From 1d2f06df6dc7ea84412564b8cca46e211155f50c Mon Sep 17 00:00:00 2001 From: Liu Jiaming Date: Tue, 2 Dec 2014 15:22:11 +0800 Subject: [PATCH 001/360] Fix std::list splice usage error --- data_structures/lru_cache.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/lru_cache.hpp b/data_structures/lru_cache.hpp index cdbeb389c..b7296eeb6 100644 --- a/data_structures/lru_cache.hpp +++ b/data_structures/lru_cache.hpp @@ -86,7 +86,7 @@ template class LRUCache result = e.value; // move to front - itemsInCache.splice(positionMap.find(key)->second, itemsInCache, itemsInCache.begin()); + itemsInCache.splice(itemsInCache.begin(), itemsInCache, positionMap.find(key)->second); positionMap.find(key)->second = itemsInCache.begin(); return true; } From 59e9a67abd717c22f4e73b3aa562d91e61e6f4c4 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 24 Nov 2014 17:55:45 +0100 Subject: [PATCH 002/360] rename and remove include header files for stabilized lib API --- data_structures/Coordinate.cpp => DataStructures/coordinate.cpp | 0 Include/osrm/{Coordinate.h => coordinate.hpp} | 0 {data_structures => Include/osrm}/json_container.hpp | 0 Include/osrm/{RouteParameters.h => route_parameters.hpp} | 0 Include/osrm/{ServerPaths.h => server_paths.hpp} | 0 {third_party => Include}/variant/optional.hpp | 0 {third_party => Include}/variant/recursive_wrapper.hpp | 0 {third_party => Include}/variant/variant.hpp | 0 {Include/osrm => Server/Http}/Header.h | 0 {Include/osrm => Server/Http}/Reply.h | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename data_structures/Coordinate.cpp => DataStructures/coordinate.cpp (100%) rename Include/osrm/{Coordinate.h => coordinate.hpp} (100%) rename {data_structures => Include/osrm}/json_container.hpp (100%) rename Include/osrm/{RouteParameters.h => route_parameters.hpp} (100%) rename Include/osrm/{ServerPaths.h => server_paths.hpp} (100%) rename {third_party => Include}/variant/optional.hpp (100%) rename {third_party => Include}/variant/recursive_wrapper.hpp (100%) rename {third_party => Include}/variant/variant.hpp (100%) rename {Include/osrm => Server/Http}/Header.h (100%) rename {Include/osrm => Server/Http}/Reply.h (100%) diff --git a/data_structures/Coordinate.cpp b/DataStructures/coordinate.cpp similarity index 100% rename from data_structures/Coordinate.cpp rename to DataStructures/coordinate.cpp diff --git a/Include/osrm/Coordinate.h b/Include/osrm/coordinate.hpp similarity index 100% rename from Include/osrm/Coordinate.h rename to Include/osrm/coordinate.hpp diff --git a/data_structures/json_container.hpp b/Include/osrm/json_container.hpp similarity index 100% rename from data_structures/json_container.hpp rename to Include/osrm/json_container.hpp diff --git a/Include/osrm/RouteParameters.h b/Include/osrm/route_parameters.hpp similarity index 100% rename from Include/osrm/RouteParameters.h rename to Include/osrm/route_parameters.hpp diff --git a/Include/osrm/ServerPaths.h b/Include/osrm/server_paths.hpp similarity index 100% rename from Include/osrm/ServerPaths.h rename to Include/osrm/server_paths.hpp diff --git a/third_party/variant/optional.hpp b/Include/variant/optional.hpp similarity index 100% rename from third_party/variant/optional.hpp rename to Include/variant/optional.hpp diff --git a/third_party/variant/recursive_wrapper.hpp b/Include/variant/recursive_wrapper.hpp similarity index 100% rename from third_party/variant/recursive_wrapper.hpp rename to Include/variant/recursive_wrapper.hpp diff --git a/third_party/variant/variant.hpp b/Include/variant/variant.hpp similarity index 100% rename from third_party/variant/variant.hpp rename to Include/variant/variant.hpp diff --git a/Include/osrm/Header.h b/Server/Http/Header.h similarity index 100% rename from Include/osrm/Header.h rename to Server/Http/Header.h diff --git a/Include/osrm/Reply.h b/Server/Http/Reply.h similarity index 100% rename from Include/osrm/Reply.h rename to Server/Http/Reply.h From b50a907ca3e4d235c5fdd1b3bafeb9de809f9f45 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 24 Nov 2014 17:57:01 +0100 Subject: [PATCH 003/360] fix changed include paths --- DataStructures/coordinate.cpp | 3 +- Include/osrm/coordinate.hpp | 8 +- Include/osrm/route_parameters.hpp | 4 +- Library/OSRM.h | 2 +- Library/OSRM_impl.cpp | 5 + Library/OSRM_impl.h | 2 +- Server/Connection.h | 3 +- Server/DataStructures/BaseDataFacade.h | 2 +- Server/DataStructures/InternalDataFacade.h | 4 +- Server/Http/Reply.cpp | 2 +- Server/RequestHandler.cpp | 6 +- Server/RequestParser.h | 2 +- UnitTests/Algorithms/DouglasPeuckerTest.cpp | 3 +- UnitTests/data_structures/StaticRTreeTest.cpp | 4 +- Util/DataStoreOptions.h | 2 +- Util/ProgramOptions.h | 4 +- Util/compute_angle.cpp | 3 +- Util/json_renderer.hpp | 3 +- Util/xml_renderer.hpp | 3 +- algorithms/douglas_peucker.cpp | 2 +- algorithms/polyline_compressor.cpp | 2 +- algorithms/polyline_formatter.cpp | 2 +- algorithms/polyline_formatter.hpp | 2 +- algorithms/tiny_components.hpp | 2 +- benchmarks/static_rtree.cpp | 12 +- data_structures/edge_based_node.hpp | 4 +- data_structures/hilbert_value.cpp | 2 +- data_structures/phantom_node.hpp | 5 +- data_structures/query_node.hpp | 4 +- data_structures/raw_route_data.hpp | 2 +- data_structures/route_parameters.cpp | 4 +- data_structures/segment_information.hpp | 2 +- data_structures/static_rtree.hpp | 2 +- datastore.cpp | 2 +- descriptors/description_factory.cpp | 2 - descriptors/description_factory.hpp | 4 +- descriptors/descriptor_base.hpp | 3 - descriptors/gpx_descriptor.hpp | 3 +- descriptors/json_descriptor.hpp | 788 +++++++++--------- extractor/extractor_callbacks.cpp | 2 +- extractor/internal_extractor_edge.hpp | 2 + plugins/distance_table.hpp | 3 +- plugins/hello_world.hpp | 2 + plugins/locate.hpp | 3 +- plugins/nearest.hpp | 3 +- plugins/plugin_base.hpp | 8 +- plugins/timestamp.hpp | 3 +- plugins/viaroute.hpp | 2 + 48 files changed, 481 insertions(+), 461 deletions(-) diff --git a/DataStructures/coordinate.cpp b/DataStructures/coordinate.cpp index 4305256ef..0b76a4306 100644 --- a/DataStructures/coordinate.cpp +++ b/DataStructures/coordinate.cpp @@ -25,7 +25,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include "../Util/MercatorUtil.h" #ifndef NDEBUG #include "../Util/simple_logger.hpp" @@ -34,6 +33,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include + #ifndef NDEBUG #include #endif diff --git a/Include/osrm/coordinate.hpp b/Include/osrm/coordinate.hpp index baac61f94..3229f256f 100644 --- a/Include/osrm/coordinate.hpp +++ b/Include/osrm/coordinate.hpp @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef FIXED_POINT_COORDINATE_H_ -#define FIXED_POINT_COORDINATE_H_ +#ifndef COORDINATE_HPP_ +#define COORDINATE_HPP_ #include //for std::ostream #include @@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace { -constexpr float COORDINATE_PRECISION = 1000000.f; +constexpr static const float COORDINATE_PRECISION = 1000000.f; } struct FixedPointCoordinate { @@ -110,4 +110,4 @@ inline std::ostream &operator<<(std::ostream &out_stream, FixedPointCoordinate c return out_stream; } -#endif /* FIXED_POINT_COORDINATE_H_ */ +#endif /* COORDINATE_HPP_ */ diff --git a/Include/osrm/route_parameters.hpp b/Include/osrm/route_parameters.hpp index fd570a1ef..0a450d571 100644 --- a/Include/osrm/route_parameters.hpp +++ b/Include/osrm/route_parameters.hpp @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ROUTE_PARAMETERS_H #define ROUTE_PARAMETERS_H -#include +#include #include @@ -40,7 +40,7 @@ struct RouteParameters RouteParameters(); void setZoomLevel(const short level); - + void setNumberOfResults(const short number); void setAlternateRouteFlag(const bool flag); diff --git a/Library/OSRM.h b/Library/OSRM.h index 372e82c39..cfa84ae27 100644 --- a/Library/OSRM.h +++ b/Library/OSRM.h @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef OSRM_H #define OSRM_H -#include +#include #include diff --git a/Library/OSRM_impl.cpp b/Library/OSRM_impl.cpp index 40fef682c..991a57f51 100644 --- a/Library/OSRM_impl.cpp +++ b/Library/OSRM_impl.cpp @@ -44,6 +44,8 @@ namespace boost { namespace interprocess { class named_mutex; } } #include "../Server/DataStructures/InternalDataFacade.h" #include "../Server/DataStructures/SharedBarriers.h" #include "../Server/DataStructures/SharedDataFacade.h" +//TODO: remove +#include "../Server/Http/Reply.h" #include "../Util/make_unique.hpp" #include "../Util/ProgramOptions.h" #include "../Util/simple_logger.hpp" @@ -52,6 +54,9 @@ namespace boost { namespace interprocess { class named_mutex; } } #include #include +#include +#include + #include #include #include diff --git a/Library/OSRM_impl.h b/Library/OSRM_impl.h index e8b47df56..b7d4bfed7 100644 --- a/Library/OSRM_impl.h +++ b/Library/OSRM_impl.h @@ -32,7 +32,7 @@ class BasePlugin; namespace http { class Reply; } struct RouteParameters; -#include +#include #include "../data_structures/query_edge.hpp" diff --git a/Server/Connection.h b/Server/Connection.h index 41b06d3a2..54e4e6305 100644 --- a/Server/Connection.h +++ b/Server/Connection.h @@ -30,10 +30,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #include "RequestParser.h" #include "Http/CompressionType.h" +#include "Http/Reply.h" #include "Http/Request.h" -#include - #include #include #include diff --git a/Server/DataStructures/BaseDataFacade.h b/Server/DataStructures/BaseDataFacade.h index 3ea391cab..9ba454f19 100644 --- a/Server/DataStructures/BaseDataFacade.h +++ b/Server/DataStructures/BaseDataFacade.h @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../Util/string_util.hpp" #include "../../typedefs.h" -#include +#include #include diff --git a/Server/DataStructures/InternalDataFacade.h b/Server/DataStructures/InternalDataFacade.h index d4f715c61..15927c785 100644 --- a/Server/DataStructures/InternalDataFacade.h +++ b/Server/DataStructures/InternalDataFacade.h @@ -43,8 +43,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../Util/graph_loader.hpp" #include "../../Util/simple_logger.hpp" -#include -#include +#include +#include template class InternalDataFacade : public BaseDataFacade { diff --git a/Server/Http/Reply.cpp b/Server/Http/Reply.cpp index e2cf0aecf..a03bf38e9 100644 --- a/Server/Http/Reply.cpp +++ b/Server/Http/Reply.cpp @@ -25,7 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include "Reply.h" #include "../../Util/cast.hpp" diff --git a/Server/RequestHandler.cpp b/Server/RequestHandler.cpp index b1178ba2b..50449d561 100644 --- a/Server/RequestHandler.cpp +++ b/Server/RequestHandler.cpp @@ -28,17 +28,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "RequestHandler.h" #include "APIGrammar.h" +#include "Http/Reply.h" #include "Http/Request.h" -#include "../data_structures/json_container.hpp" #include "../Library/OSRM.h" #include "../Util/json_renderer.hpp" #include "../Util/simple_logger.hpp" #include "../Util/string_util.hpp" #include "../typedefs.h" -#include -#include +#include +#include #include diff --git a/Server/RequestParser.h b/Server/RequestParser.h index 7f302a257..07cdd86da 100644 --- a/Server/RequestParser.h +++ b/Server/RequestParser.h @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define REQUEST_PARSER_H #include "Http/CompressionType.h" -#include +#include "Http/Header.h" #include #include diff --git a/UnitTests/Algorithms/DouglasPeuckerTest.cpp b/UnitTests/Algorithms/DouglasPeuckerTest.cpp index 27818e596..93e2aee8e 100644 --- a/UnitTests/Algorithms/DouglasPeuckerTest.cpp +++ b/UnitTests/Algorithms/DouglasPeuckerTest.cpp @@ -27,12 +27,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../algorithms/douglas_peucker.hpp" #include "../../data_structures/segment_information.hpp" -#include "../../Include/osrm/Coordinate.h" #include #include #include +#include + #include BOOST_AUTO_TEST_SUITE(douglas_peucker) diff --git a/UnitTests/data_structures/StaticRTreeTest.cpp b/UnitTests/data_structures/StaticRTreeTest.cpp index cf3dfd0b2..25e4cea51 100644 --- a/UnitTests/data_structures/StaticRTreeTest.cpp +++ b/UnitTests/data_structures/StaticRTreeTest.cpp @@ -31,12 +31,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../Util/floating_point.hpp" #include "../../typedefs.h" -#include - #include #include #include +#include + #include #include diff --git a/Util/DataStoreOptions.h b/Util/DataStoreOptions.h index 389c7231a..0ad3222fc 100644 --- a/Util/DataStoreOptions.h +++ b/Util/DataStoreOptions.h @@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "osrm_exception.hpp" #include "simple_logger.hpp" -#include +#include #include #include diff --git a/Util/ProgramOptions.h b/Util/ProgramOptions.h index 3329b3108..185edb0f0 100644 --- a/Util/ProgramOptions.h +++ b/Util/ProgramOptions.h @@ -33,11 +33,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "osrm_exception.hpp" #include "simple_logger.hpp" -#include - #include #include +#include + #include #include diff --git a/Util/compute_angle.cpp b/Util/compute_angle.cpp index b6350e445..bba4773e2 100644 --- a/Util/compute_angle.cpp +++ b/Util/compute_angle.cpp @@ -29,7 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "TrigonometryTables.h" #include "../Util/MercatorUtil.h" -#include + +#include #include diff --git a/Util/json_renderer.hpp b/Util/json_renderer.hpp index dd6089c8e..a5fc239bb 100644 --- a/Util/json_renderer.hpp +++ b/Util/json_renderer.hpp @@ -31,9 +31,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef JSON_RENDERER_HPP #define JSON_RENDERER_HPP -#include "../data_structures/json_container.hpp" #include "cast.hpp" +#include + namespace JSON { struct Renderer : mapbox::util::static_visitor<> diff --git a/Util/xml_renderer.hpp b/Util/xml_renderer.hpp index 46e050115..4f08cddbe 100644 --- a/Util/xml_renderer.hpp +++ b/Util/xml_renderer.hpp @@ -28,9 +28,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef XML_RENDERER_HPP #define XML_RENDERER_HPP -#include "../data_structures/json_container.hpp" #include "cast.hpp" +#include + namespace JSON { struct XMLToArrayRenderer : mapbox::util::static_visitor<> diff --git a/algorithms/douglas_peucker.cpp b/algorithms/douglas_peucker.cpp index 362f0a5a8..bb8da99b2 100644 --- a/algorithms/douglas_peucker.cpp +++ b/algorithms/douglas_peucker.cpp @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/segment_information.hpp" #include "../Util/integer_range.hpp" -#include +#include #include diff --git a/algorithms/polyline_compressor.cpp b/algorithms/polyline_compressor.cpp index 2f2972b15..7886de91c 100644 --- a/algorithms/polyline_compressor.cpp +++ b/algorithms/polyline_compressor.cpp @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "polyline_compressor.hpp" #include "../data_structures/segment_information.hpp" -#include +#include std::string PolylineCompressor::encode_vector(std::vector &numbers) const { diff --git a/algorithms/polyline_formatter.cpp b/algorithms/polyline_formatter.cpp index d72496ad6..e491b7570 100644 --- a/algorithms/polyline_formatter.cpp +++ b/algorithms/polyline_formatter.cpp @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "polyline_compressor.hpp" #include "../data_structures/segment_information.hpp" -#include +#include JSON::String PolylineFormatter::printEncodedString(const std::vector &polyline) const diff --git a/algorithms/polyline_formatter.hpp b/algorithms/polyline_formatter.hpp index 1d4744d0a..e4018154d 100644 --- a/algorithms/polyline_formatter.hpp +++ b/algorithms/polyline_formatter.hpp @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct SegmentInformation; -#include "../data_structures/json_container.hpp" +#include #include #include diff --git a/algorithms/tiny_components.hpp b/algorithms/tiny_components.hpp index 5cf5a75c6..9fb357c10 100644 --- a/algorithms/tiny_components.hpp +++ b/algorithms/tiny_components.hpp @@ -42,7 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../Util/std_hash.hpp" #include "../Util/timing_util.hpp" -#include +#include #include diff --git a/benchmarks/static_rtree.cpp b/benchmarks/static_rtree.cpp index 7a24cfc8c..cc2ae4231 100644 --- a/benchmarks/static_rtree.cpp +++ b/benchmarks/static_rtree.cpp @@ -25,14 +25,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "../data_structures/original_edge_data.hpp" -#include "../data_structures/query_node.hpp" -#include "../data_structures/shared_memory_vector_wrapper.hpp" -#include "../data_structures/static_rtree.hpp" -#include "../data_structures/edge_based_node.hpp" +#include "../DataStructures/OriginalEdgeData.h" +#include "../DataStructures/QueryNode.h" +#include "../DataStructures/SharedMemoryVectorWrapper.h" +#include "../DataStructures/StaticRTree.h" #include "../Util/BoostFileSystemFix.h" +#include "../DataStructures/EdgeBasedNode.h" -#include +#include #include diff --git a/data_structures/edge_based_node.hpp b/data_structures/edge_based_node.hpp index 98746d9a8..2566efffb 100644 --- a/data_structures/edge_based_node.hpp +++ b/data_structures/edge_based_node.hpp @@ -31,10 +31,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/travel_mode.hpp" #include "../typedefs.h" -#include - #include +#include + #include struct EdgeBasedNode diff --git a/data_structures/hilbert_value.cpp b/data_structures/hilbert_value.cpp index 216b7c553..8487fac11 100644 --- a/data_structures/hilbert_value.cpp +++ b/data_structures/hilbert_value.cpp @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "hilbert_value.hpp" -#include +#include uint64_t HilbertCode::operator()(const FixedPointCoordinate ¤t_coordinate) const { diff --git a/data_structures/phantom_node.hpp b/data_structures/phantom_node.hpp index 9286fb9b4..620850257 100644 --- a/data_structures/phantom_node.hpp +++ b/data_structures/phantom_node.hpp @@ -28,10 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef PHANTOM_NODES_H #define PHANTOM_NODES_H -#include -#include "../data_structures/travel_mode.hpp" +#include "../DataStructures/TravelMode.h" #include "../typedefs.h" +#include + #include #include diff --git a/data_structures/query_node.hpp b/data_structures/query_node.hpp index 7705df008..18808fd95 100644 --- a/data_structures/query_node.hpp +++ b/data_structures/query_node.hpp @@ -30,10 +30,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../typedefs.h" -#include - #include +#include + #include struct QueryNode diff --git a/data_structures/raw_route_data.hpp b/data_structures/raw_route_data.hpp index f9242cfb0..bb48a94c9 100644 --- a/data_structures/raw_route_data.hpp +++ b/data_structures/raw_route_data.hpp @@ -33,7 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/turn_instructions.hpp" #include "../typedefs.h" -#include +#include #include diff --git a/data_structures/route_parameters.cpp b/data_structures/route_parameters.cpp index 1019a9149..fa54ad6b2 100644 --- a/data_structures/route_parameters.cpp +++ b/data_structures/route_parameters.cpp @@ -25,12 +25,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include - #include #include #include +#include + RouteParameters::RouteParameters() : zoom_level(18), print_instructions(false), alternate_route(true), geometry(true), compression(true), deprecatedAPI(false), uturn_default(false), check_sum(-1), num_results(1) diff --git a/data_structures/segment_information.hpp b/data_structures/segment_information.hpp index dd1fc574b..117bd3972 100644 --- a/data_structures/segment_information.hpp +++ b/data_structures/segment_information.hpp @@ -33,7 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/travel_mode.hpp" #include "../typedefs.h" -#include +#include // Struct fits everything in one cache line struct SegmentInformation diff --git a/data_structures/static_rtree.hpp b/data_structures/static_rtree.hpp index f670ca34f..db7180468 100644 --- a/data_structures/static_rtree.hpp +++ b/data_structures/static_rtree.hpp @@ -44,7 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../Util/timing_util.hpp" #include "../typedefs.h" -#include +#include #include #include diff --git a/datastore.cpp b/datastore.cpp index d29200420..326081b2f 100644 --- a/datastore.cpp +++ b/datastore.cpp @@ -43,7 +43,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Util/FingerPrint.h" #include "typedefs.h" -#include +#include using RTreeLeaf = BaseDataFacade::RTreeLeaf; using RTreeNode = StaticRTree::vector, true>::TreeNode; diff --git a/descriptors/description_factory.cpp b/descriptors/description_factory.cpp index 075eff029..37ff8fb0c 100644 --- a/descriptors/description_factory.cpp +++ b/descriptors/description_factory.cpp @@ -27,8 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "description_factory.hpp" -#include - #include "../typedefs.h" #include "../algorithms/polyline_formatter.hpp" #include "../data_structures/raw_route_data.hpp" diff --git a/descriptors/description_factory.hpp b/descriptors/description_factory.hpp index 9b96dd20f..f001b9b8b 100644 --- a/descriptors/description_factory.hpp +++ b/descriptors/description_factory.hpp @@ -33,11 +33,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/json_container.hpp" #include "../data_structures/segment_information.hpp" #include "../data_structures/turn_instructions.hpp" -#include "../typedefs.h" #include -#include +#include +#include #include diff --git a/descriptors/descriptor_base.hpp b/descriptors/descriptor_base.hpp index 31c08eaf1..670f0038f 100644 --- a/descriptors/descriptor_base.hpp +++ b/descriptors/descriptor_base.hpp @@ -32,13 +32,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/raw_route_data.hpp" #include "../typedefs.h" -#include - #include #include #include - struct DescriptorTable : public std::unordered_map { unsigned get_id(const std::string &key) diff --git a/descriptors/gpx_descriptor.hpp b/descriptors/gpx_descriptor.hpp index 2dd003490..8da8759b2 100644 --- a/descriptors/gpx_descriptor.hpp +++ b/descriptors/gpx_descriptor.hpp @@ -29,9 +29,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define GPX_DESCRIPTOR_HPP #include "descriptor_base.hpp" -#include "../data_structures/json_container.hpp" #include "../Util/xml_renderer.hpp" +#include + #include template class GPXDescriptor final : public BaseDescriptor diff --git a/descriptors/json_descriptor.hpp b/descriptors/json_descriptor.hpp index 2aae939a9..f0f094246 100644 --- a/descriptors/json_descriptor.hpp +++ b/descriptors/json_descriptor.hpp @@ -1,393 +1,395 @@ -/* - -Copyright (c) 2014, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef JSON_DESCRIPTOR_HPP -#define JSON_DESCRIPTOR_HPP - -#include "descriptor_base.hpp" -#include "description_factory.hpp" -#include "../algorithms/object_encoder.hpp" -#include "../algorithms/route_name_extraction.hpp" -#include "../data_structures/json_container.hpp" -#include "../data_structures/segment_information.hpp" -#include "../data_structures/turn_instructions.hpp" -#include "../Util/bearing.hpp" -#include "../Util/integer_range.hpp" -#include "../Util/json_renderer.hpp" -#include "../Util/simple_logger.hpp" -#include "../Util/string_util.hpp" -#include "../Util/timing_util.hpp" - -#include - -template class JSONDescriptor final : public BaseDescriptor -{ - private: - DataFacadeT *facade; - DescriptorConfig config; - DescriptionFactory description_factory, alternate_description_factory; - FixedPointCoordinate current; - unsigned entered_restricted_area_count; - struct RoundAbout - { - RoundAbout() : start_index(INT_MAX), name_id(INVALID_NAMEID), leave_at_exit(INT_MAX) {} - int start_index; - unsigned name_id; - int leave_at_exit; - } round_about; - - struct Segment - { - Segment() : name_id(INVALID_NAMEID), length(-1), position(0) {} - Segment(unsigned n, int l, unsigned p) : name_id(n), length(l), position(p) {} - unsigned name_id; - int length; - unsigned position; - }; - std::vector shortest_path_segments, alternative_path_segments; - ExtractRouteNames GenerateRouteNames; - - public: - explicit JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0) {} - - void SetConfig(const DescriptorConfig &c) final { config = c; } - - unsigned DescribeLeg(const std::vector route_leg, - const PhantomNodes &leg_phantoms, - const bool target_traversed_in_reverse, - const bool is_via_leg) - { - unsigned added_element_count = 0; - // Get all the coordinates for the computed route - FixedPointCoordinate current_coordinate; - for (const PathData &path_data : route_leg) - { - current_coordinate = facade->GetCoordinateOfNode(path_data.node); - description_factory.AppendSegment(current_coordinate, path_data); - ++added_element_count; - } - description_factory.SetEndSegment( - leg_phantoms.target_phantom, target_traversed_in_reverse, is_via_leg); - ++added_element_count; - BOOST_ASSERT((route_leg.size() + 1) == added_element_count); - return added_element_count; - } - - void Run(const RawRouteData &raw_route, http::Reply &reply) final - { - JSON::Object json_result; - if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length) - { - // We do not need to do much, if there is no route ;-) - json_result.values["status"] = 207; - json_result.values["status_message"] = "Cannot find route between points"; - JSON::render(reply.content, json_result); - return; - } - - // check if first segment is non-zero - std::string road_name = facade->GetEscapedNameForNameID( - raw_route.segment_end_coordinates.front().source_phantom.name_id); - - BOOST_ASSERT(raw_route.unpacked_path_segments.size() == - raw_route.segment_end_coordinates.size()); - - description_factory.SetStartSegment( - raw_route.segment_end_coordinates.front().source_phantom, - raw_route.source_traversed_in_reverse.front()); - json_result.values["status"] = 0; - json_result.values["status_message"] = "Found route between points"; - - // for each unpacked segment add the leg to the description - for (const auto i : osrm::irange(0, raw_route.unpacked_path_segments.size())) - { -#ifndef NDEBUG - const int added_segments = -#endif - DescribeLeg(raw_route.unpacked_path_segments[i], - raw_route.segment_end_coordinates[i], - raw_route.target_traversed_in_reverse[i], - raw_route.is_via_leg(i)); - BOOST_ASSERT(0 < added_segments); - } - description_factory.Run(facade, config.zoom_level); - - if (config.geometry) - { - JSON::Value route_geometry = - description_factory.AppendGeometryString(config.encode_geometry); - json_result.values["route_geometry"] = route_geometry; - } - if (config.instructions) - { - JSON::Array json_route_instructions; - BuildTextualDescription(description_factory, - json_route_instructions, - raw_route.shortest_path_length, - shortest_path_segments); - json_result.values["route_instructions"] = json_route_instructions; - } - description_factory.BuildRouteSummary(description_factory.get_entire_length(), - raw_route.shortest_path_length); - JSON::Object json_route_summary; - json_route_summary.values["total_distance"] = description_factory.summary.distance; - json_route_summary.values["total_time"] = description_factory.summary.duration; - json_route_summary.values["start_point"] = - facade->GetEscapedNameForNameID(description_factory.summary.source_name_id); - json_route_summary.values["end_point"] = - facade->GetEscapedNameForNameID(description_factory.summary.target_name_id); - json_result.values["route_summary"] = json_route_summary; - - BOOST_ASSERT(!raw_route.segment_end_coordinates.empty()); - - JSON::Array json_via_points_array; - JSON::Array json_first_coordinate; - json_first_coordinate.values.push_back( - raw_route.segment_end_coordinates.front().source_phantom.location.lat / - COORDINATE_PRECISION); - json_first_coordinate.values.push_back( - raw_route.segment_end_coordinates.front().source_phantom.location.lon / - COORDINATE_PRECISION); - json_via_points_array.values.push_back(json_first_coordinate); - for (const PhantomNodes &nodes : raw_route.segment_end_coordinates) - { - std::string tmp; - JSON::Array json_coordinate; - json_coordinate.values.push_back(nodes.target_phantom.location.lat / - COORDINATE_PRECISION); - json_coordinate.values.push_back(nodes.target_phantom.location.lon / - COORDINATE_PRECISION); - json_via_points_array.values.push_back(json_coordinate); - } - json_result.values["via_points"] = json_via_points_array; - - JSON::Array json_via_indices_array; - - std::vector const &shortest_leg_end_indices = description_factory.GetViaIndices(); - json_via_indices_array.values.insert(json_via_indices_array.values.end(), - shortest_leg_end_indices.begin(), - shortest_leg_end_indices.end()); - json_result.values["via_indices"] = json_via_indices_array; - - // only one alternative route is computed at this time, so this is hardcoded - if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length) - { - json_result.values["found_alternative"] = JSON::True(); - BOOST_ASSERT(!raw_route.alt_source_traversed_in_reverse.empty()); - alternate_description_factory.SetStartSegment( - raw_route.segment_end_coordinates.front().source_phantom, - raw_route.alt_source_traversed_in_reverse.front()); - // Get all the coordinates for the computed route - for (const PathData &path_data : raw_route.unpacked_alternative) - { - current = facade->GetCoordinateOfNode(path_data.node); - alternate_description_factory.AppendSegment(current, path_data); - } - alternate_description_factory.SetEndSegment( - raw_route.segment_end_coordinates.back().target_phantom, - raw_route.alt_source_traversed_in_reverse.back()); - alternate_description_factory.Run(facade, config.zoom_level); - - if (config.geometry) - { - JSON::Value alternate_geometry_string = - alternate_description_factory.AppendGeometryString(config.encode_geometry); - JSON::Array json_alternate_geometries_array; - json_alternate_geometries_array.values.push_back(alternate_geometry_string); - json_result.values["alternative_geometries"] = json_alternate_geometries_array; - } - // Generate instructions for each alternative (simulated here) - JSON::Array json_alt_instructions; - JSON::Array json_current_alt_instructions; - if (config.instructions) - { - BuildTextualDescription(alternate_description_factory, - json_current_alt_instructions, - raw_route.alternative_path_length, - alternative_path_segments); - json_alt_instructions.values.push_back(json_current_alt_instructions); - json_result.values["alternative_instructions"] = json_alt_instructions; - } - alternate_description_factory.BuildRouteSummary( - alternate_description_factory.get_entire_length(), raw_route.alternative_path_length); - - JSON::Object json_alternate_route_summary; - JSON::Array json_alternate_route_summary_array; - json_alternate_route_summary.values["total_distance"] = - alternate_description_factory.summary.distance; - json_alternate_route_summary.values["total_time"] = - alternate_description_factory.summary.duration; - json_alternate_route_summary.values["start_point"] = facade->GetEscapedNameForNameID( - alternate_description_factory.summary.source_name_id); - json_alternate_route_summary.values["end_point"] = facade->GetEscapedNameForNameID( - alternate_description_factory.summary.target_name_id); - json_alternate_route_summary_array.values.push_back(json_alternate_route_summary); - json_result.values["alternative_summaries"] = json_alternate_route_summary_array; - - std::vector const &alternate_leg_end_indices = - alternate_description_factory.GetViaIndices(); - JSON::Array json_altenative_indices_array; - json_altenative_indices_array.values.insert(json_altenative_indices_array.values.end(), - alternate_leg_end_indices.begin(), - alternate_leg_end_indices.end()); - json_result.values["alternative_indices"] = json_altenative_indices_array; - } - else - { - json_result.values["found_alternative"] = JSON::False(); - } - - // Get Names for both routes - RouteNames route_names = - GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade); - JSON::Array json_route_names; - json_route_names.values.push_back(route_names.shortest_path_name_1); - json_route_names.values.push_back(route_names.shortest_path_name_2); - json_result.values["route_name"] = json_route_names; - - if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length) - { - JSON::Array json_alternate_names_array; - JSON::Array json_alternate_names; - json_alternate_names.values.push_back(route_names.alternative_path_name_1); - json_alternate_names.values.push_back(route_names.alternative_path_name_2); - json_alternate_names_array.values.push_back(json_alternate_names); - json_result.values["alternative_names"] = json_alternate_names_array; - } - - JSON::Object json_hint_object; - json_hint_object.values["checksum"] = facade->GetCheckSum(); - JSON::Array json_location_hint_array; - std::string hint; - for (const auto i : osrm::irange(0, raw_route.segment_end_coordinates.size())) - { - ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint); - json_location_hint_array.values.push_back(hint); - } - ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint); - json_location_hint_array.values.push_back(hint); - json_hint_object.values["locations"] = json_location_hint_array; - json_result.values["hint_data"] = json_hint_object; - - // render the content to the output array - TIMER_START(route_render); - JSON::render(reply.content, json_result); - TIMER_STOP(route_render); - SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render); - } - - // TODO: reorder parameters - inline void BuildTextualDescription(DescriptionFactory &description_factory, - JSON::Array &json_instruction_array, - const int route_length, - std::vector &route_segments_list) - { - // Segment information has following format: - //["instruction id","streetname",length,position,time,"length","earth_direction",azimuth] - unsigned necessary_segments_running_index = 0; - round_about.leave_at_exit = 0; - round_about.name_id = 0; - std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction; - - // Fetch data from Factory and generate a string from it. - for (const SegmentInformation &segment : description_factory.path_description) - { - JSON::Array json_instruction_row; - TurnInstruction current_instruction = segment.turn_instruction; - entered_restricted_area_count += (current_instruction != segment.turn_instruction); - if (TurnInstructionsClass::TurnIsNecessary(current_instruction)) - { - if (TurnInstruction::EnterRoundAbout == current_instruction) - { - round_about.name_id = segment.name_id; - round_about.start_index = necessary_segments_running_index; - } - else - { - std::string current_turn_instruction; - if (TurnInstruction::LeaveRoundAbout == current_instruction) - { - temp_instruction = - cast::integral_to_string(cast::enum_to_underlying(TurnInstruction::EnterRoundAbout)); - current_turn_instruction += temp_instruction; - current_turn_instruction += "-"; - temp_instruction = cast::integral_to_string(round_about.leave_at_exit + 1); - current_turn_instruction += temp_instruction; - round_about.leave_at_exit = 0; - } - else - { - temp_instruction = cast::integral_to_string(cast::enum_to_underlying(current_instruction)); - current_turn_instruction += temp_instruction; - } - json_instruction_row.values.push_back(current_turn_instruction); - - json_instruction_row.values.push_back( - facade->GetEscapedNameForNameID(segment.name_id)); - json_instruction_row.values.push_back(std::round(segment.length)); - json_instruction_row.values.push_back(necessary_segments_running_index); - json_instruction_row.values.push_back(round(segment.duration / 10)); - json_instruction_row.values.push_back( - cast::integral_to_string(static_cast(segment.length)) + "m"); - const double bearing_value = (segment.bearing / 10.); - json_instruction_row.values.push_back(Bearing::Get(bearing_value)); - json_instruction_row.values.push_back( - static_cast(round(bearing_value))); - json_instruction_row.values.push_back(segment.travel_mode); - - route_segments_list.emplace_back( - segment.name_id, - static_cast(segment.length), - static_cast(route_segments_list.size())); - json_instruction_array.values.push_back(json_instruction_row); - } - } - else if (TurnInstruction::StayOnRoundAbout == current_instruction) - { - ++round_about.leave_at_exit; - } - if (segment.necessary) - { - ++necessary_segments_running_index; - } - } - - JSON::Array json_last_instruction_row; - temp_instruction = cast::integral_to_string(cast::enum_to_underlying(TurnInstruction::ReachedYourDestination)); - json_last_instruction_row.values.push_back(temp_instruction); - json_last_instruction_row.values.push_back(""); - json_last_instruction_row.values.push_back(0); - json_last_instruction_row.values.push_back(necessary_segments_running_index - 1); - json_last_instruction_row.values.push_back(0); - json_last_instruction_row.values.push_back("0m"); - json_last_instruction_row.values.push_back(Bearing::Get(0.0)); - json_last_instruction_row.values.push_back(0.); - json_instruction_array.values.push_back(json_last_instruction_row); - } -}; - -#endif /* JSON_DESCRIPTOR_HPP */ +/* + +Copyright (c) 2014, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef JSON_DESCRIPTOR_HPP +#define JSON_DESCRIPTOR_HPP + +#include "descriptor_base.hpp" +#include "description_factory.hpp" +#include "../algorithms/object_encoder.hpp" +#include "../algorithms/route_name_extraction.hpp" +#include "../data_structures/json_container.hpp" +#include "../data_structures/segment_information.hpp" +#include "../data_structures/turn_instructions.hpp" +#include "../Util/bearing.hpp" +#include "../Util/integer_range.hpp" +#include "../Util/json_renderer.hpp" +#include "../Util/simple_logger.hpp" +#include "../Util/StringUtil.h" +#include "../Util/timing_util.hpp" + +#include + +#include + +template class JSONDescriptor final : public BaseDescriptor +{ + private: + DataFacadeT *facade; + DescriptorConfig config; + DescriptionFactory description_factory, alternate_description_factory; + FixedPointCoordinate current; + unsigned entered_restricted_area_count; + struct RoundAbout + { + RoundAbout() : start_index(INT_MAX), name_id(INVALID_NAMEID), leave_at_exit(INT_MAX) {} + int start_index; + unsigned name_id; + int leave_at_exit; + } round_about; + + struct Segment + { + Segment() : name_id(INVALID_NAMEID), length(-1), position(0) {} + Segment(unsigned n, int l, unsigned p) : name_id(n), length(l), position(p) {} + unsigned name_id; + int length; + unsigned position; + }; + std::vector shortest_path_segments, alternative_path_segments; + ExtractRouteNames GenerateRouteNames; + + public: + explicit JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0) {} + + void SetConfig(const DescriptorConfig &c) final { config = c; } + + unsigned DescribeLeg(const std::vector route_leg, + const PhantomNodes &leg_phantoms, + const bool target_traversed_in_reverse, + const bool is_via_leg) + { + unsigned added_element_count = 0; + // Get all the coordinates for the computed route + FixedPointCoordinate current_coordinate; + for (const PathData &path_data : route_leg) + { + current_coordinate = facade->GetCoordinateOfNode(path_data.node); + description_factory.AppendSegment(current_coordinate, path_data); + ++added_element_count; + } + description_factory.SetEndSegment( + leg_phantoms.target_phantom, target_traversed_in_reverse, is_via_leg); + ++added_element_count; + BOOST_ASSERT((route_leg.size() + 1) == added_element_count); + return added_element_count; + } + + void Run(const RawRouteData &raw_route, http::Reply &reply) final + { + JSON::Object json_result; + if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length) + { + // We do not need to do much, if there is no route ;-) + json_result.values["status"] = 207; + json_result.values["status_message"] = "Cannot find route between points"; + JSON::render(reply.content, json_result); + return; + } + + // check if first segment is non-zero + std::string road_name = facade->GetEscapedNameForNameID( + raw_route.segment_end_coordinates.front().source_phantom.name_id); + + BOOST_ASSERT(raw_route.unpacked_path_segments.size() == + raw_route.segment_end_coordinates.size()); + + description_factory.SetStartSegment( + raw_route.segment_end_coordinates.front().source_phantom, + raw_route.source_traversed_in_reverse.front()); + json_result.values["status"] = 0; + json_result.values["status_message"] = "Found route between points"; + + // for each unpacked segment add the leg to the description + for (const auto i : osrm::irange(0, raw_route.unpacked_path_segments.size())) + { +#ifndef NDEBUG + const int added_segments = +#endif + DescribeLeg(raw_route.unpacked_path_segments[i], + raw_route.segment_end_coordinates[i], + raw_route.target_traversed_in_reverse[i], + raw_route.is_via_leg(i)); + BOOST_ASSERT(0 < added_segments); + } + description_factory.Run(facade, config.zoom_level); + + if (config.geometry) + { + JSON::Value route_geometry = + description_factory.AppendGeometryString(config.encode_geometry); + json_result.values["route_geometry"] = route_geometry; + } + if (config.instructions) + { + JSON::Array json_route_instructions; + BuildTextualDescription(description_factory, + json_route_instructions, + raw_route.shortest_path_length, + shortest_path_segments); + json_result.values["route_instructions"] = json_route_instructions; + } + description_factory.BuildRouteSummary(description_factory.get_entire_length(), + raw_route.shortest_path_length); + JSON::Object json_route_summary; + json_route_summary.values["total_distance"] = description_factory.summary.distance; + json_route_summary.values["total_time"] = description_factory.summary.duration; + json_route_summary.values["start_point"] = + facade->GetEscapedNameForNameID(description_factory.summary.source_name_id); + json_route_summary.values["end_point"] = + facade->GetEscapedNameForNameID(description_factory.summary.target_name_id); + json_result.values["route_summary"] = json_route_summary; + + BOOST_ASSERT(!raw_route.segment_end_coordinates.empty()); + + JSON::Array json_via_points_array; + JSON::Array json_first_coordinate; + json_first_coordinate.values.push_back( + raw_route.segment_end_coordinates.front().source_phantom.location.lat / + COORDINATE_PRECISION); + json_first_coordinate.values.push_back( + raw_route.segment_end_coordinates.front().source_phantom.location.lon / + COORDINATE_PRECISION); + json_via_points_array.values.push_back(json_first_coordinate); + for (const PhantomNodes &nodes : raw_route.segment_end_coordinates) + { + std::string tmp; + JSON::Array json_coordinate; + json_coordinate.values.push_back(nodes.target_phantom.location.lat / + COORDINATE_PRECISION); + json_coordinate.values.push_back(nodes.target_phantom.location.lon / + COORDINATE_PRECISION); + json_via_points_array.values.push_back(json_coordinate); + } + json_result.values["via_points"] = json_via_points_array; + + JSON::Array json_via_indices_array; + + std::vector const &shortest_leg_end_indices = description_factory.GetViaIndices(); + json_via_indices_array.values.insert(json_via_indices_array.values.end(), + shortest_leg_end_indices.begin(), + shortest_leg_end_indices.end()); + json_result.values["via_indices"] = json_via_indices_array; + + // only one alternative route is computed at this time, so this is hardcoded + if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length) + { + json_result.values["found_alternative"] = JSON::True(); + BOOST_ASSERT(!raw_route.alt_source_traversed_in_reverse.empty()); + alternate_description_factory.SetStartSegment( + raw_route.segment_end_coordinates.front().source_phantom, + raw_route.alt_source_traversed_in_reverse.front()); + // Get all the coordinates for the computed route + for (const PathData &path_data : raw_route.unpacked_alternative) + { + current = facade->GetCoordinateOfNode(path_data.node); + alternate_description_factory.AppendSegment(current, path_data); + } + alternate_description_factory.SetEndSegment( + raw_route.segment_end_coordinates.back().target_phantom, + raw_route.alt_source_traversed_in_reverse.back()); + alternate_description_factory.Run(facade, config.zoom_level); + + if (config.geometry) + { + JSON::Value alternate_geometry_string = + alternate_description_factory.AppendGeometryString(config.encode_geometry); + JSON::Array json_alternate_geometries_array; + json_alternate_geometries_array.values.push_back(alternate_geometry_string); + json_result.values["alternative_geometries"] = json_alternate_geometries_array; + } + // Generate instructions for each alternative (simulated here) + JSON::Array json_alt_instructions; + JSON::Array json_current_alt_instructions; + if (config.instructions) + { + BuildTextualDescription(alternate_description_factory, + json_current_alt_instructions, + raw_route.alternative_path_length, + alternative_path_segments); + json_alt_instructions.values.push_back(json_current_alt_instructions); + json_result.values["alternative_instructions"] = json_alt_instructions; + } + alternate_description_factory.BuildRouteSummary( + alternate_description_factory.get_entire_length(), raw_route.alternative_path_length); + + JSON::Object json_alternate_route_summary; + JSON::Array json_alternate_route_summary_array; + json_alternate_route_summary.values["total_distance"] = + alternate_description_factory.summary.distance; + json_alternate_route_summary.values["total_time"] = + alternate_description_factory.summary.duration; + json_alternate_route_summary.values["start_point"] = facade->GetEscapedNameForNameID( + alternate_description_factory.summary.source_name_id); + json_alternate_route_summary.values["end_point"] = facade->GetEscapedNameForNameID( + alternate_description_factory.summary.target_name_id); + json_alternate_route_summary_array.values.push_back(json_alternate_route_summary); + json_result.values["alternative_summaries"] = json_alternate_route_summary_array; + + std::vector const &alternate_leg_end_indices = + alternate_description_factory.GetViaIndices(); + JSON::Array json_altenative_indices_array; + json_altenative_indices_array.values.insert(json_altenative_indices_array.values.end(), + alternate_leg_end_indices.begin(), + alternate_leg_end_indices.end()); + json_result.values["alternative_indices"] = json_altenative_indices_array; + } + else + { + json_result.values["found_alternative"] = JSON::False(); + } + + // Get Names for both routes + RouteNames route_names = + GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade); + JSON::Array json_route_names; + json_route_names.values.push_back(route_names.shortest_path_name_1); + json_route_names.values.push_back(route_names.shortest_path_name_2); + json_result.values["route_name"] = json_route_names; + + if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length) + { + JSON::Array json_alternate_names_array; + JSON::Array json_alternate_names; + json_alternate_names.values.push_back(route_names.alternative_path_name_1); + json_alternate_names.values.push_back(route_names.alternative_path_name_2); + json_alternate_names_array.values.push_back(json_alternate_names); + json_result.values["alternative_names"] = json_alternate_names_array; + } + + JSON::Object json_hint_object; + json_hint_object.values["checksum"] = facade->GetCheckSum(); + JSON::Array json_location_hint_array; + std::string hint; + for (const auto i : osrm::irange(0, raw_route.segment_end_coordinates.size())) + { + ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint); + json_location_hint_array.values.push_back(hint); + } + ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint); + json_location_hint_array.values.push_back(hint); + json_hint_object.values["locations"] = json_location_hint_array; + json_result.values["hint_data"] = json_hint_object; + + // render the content to the output array + TIMER_START(route_render); + JSON::render(reply.content, json_result); + TIMER_STOP(route_render); + SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render); + } + + // TODO: reorder parameters + inline void BuildTextualDescription(DescriptionFactory &description_factory, + JSON::Array &json_instruction_array, + const int route_length, + std::vector &route_segments_list) + { + // Segment information has following format: + //["instruction id","streetname",length,position,time,"length","earth_direction",azimuth] + unsigned necessary_segments_running_index = 0; + round_about.leave_at_exit = 0; + round_about.name_id = 0; + std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction; + + // Fetch data from Factory and generate a string from it. + for (const SegmentInformation &segment : description_factory.path_description) + { + JSON::Array json_instruction_row; + TurnInstruction current_instruction = segment.turn_instruction; + entered_restricted_area_count += (current_instruction != segment.turn_instruction); + if (TurnInstructionsClass::TurnIsNecessary(current_instruction)) + { + if (TurnInstruction::EnterRoundAbout == current_instruction) + { + round_about.name_id = segment.name_id; + round_about.start_index = necessary_segments_running_index; + } + else + { + std::string current_turn_instruction; + if (TurnInstruction::LeaveRoundAbout == current_instruction) + { + temp_instruction = + cast::integral_to_string(cast::enum_to_underlying(TurnInstruction::EnterRoundAbout)); + current_turn_instruction += temp_instruction; + current_turn_instruction += "-"; + temp_instruction = cast::integral_to_string(round_about.leave_at_exit + 1); + current_turn_instruction += temp_instruction; + round_about.leave_at_exit = 0; + } + else + { + temp_instruction = cast::integral_to_string(cast::enum_to_underlying(current_instruction)); + current_turn_instruction += temp_instruction; + } + json_instruction_row.values.push_back(current_turn_instruction); + + json_instruction_row.values.push_back( + facade->GetEscapedNameForNameID(segment.name_id)); + json_instruction_row.values.push_back(std::round(segment.length)); + json_instruction_row.values.push_back(necessary_segments_running_index); + json_instruction_row.values.push_back(round(segment.duration / 10)); + json_instruction_row.values.push_back( + cast::integral_to_string(static_cast(segment.length)) + "m"); + const double bearing_value = (segment.bearing / 10.); + json_instruction_row.values.push_back(Bearing::Get(bearing_value)); + json_instruction_row.values.push_back( + static_cast(round(bearing_value))); + json_instruction_row.values.push_back(segment.travel_mode); + + route_segments_list.emplace_back( + segment.name_id, + static_cast(segment.length), + static_cast(route_segments_list.size())); + json_instruction_array.values.push_back(json_instruction_row); + } + } + else if (TurnInstruction::StayOnRoundAbout == current_instruction) + { + ++round_about.leave_at_exit; + } + if (segment.necessary) + { + ++necessary_segments_running_index; + } + } + + JSON::Array json_last_instruction_row; + temp_instruction = cast::integral_to_string(cast::enum_to_underlying(TurnInstruction::ReachedYourDestination)); + json_last_instruction_row.values.push_back(temp_instruction); + json_last_instruction_row.values.push_back(""); + json_last_instruction_row.values.push_back(0); + json_last_instruction_row.values.push_back(necessary_segments_running_index - 1); + json_last_instruction_row.values.push_back(0); + json_last_instruction_row.values.push_back("0m"); + json_last_instruction_row.values.push_back(Bearing::Get(0.0)); + json_last_instruction_row.values.push_back(0.); + json_instruction_array.values.push_back(json_last_instruction_row); + } +}; + +#endif /* JSON_DESCRIPTOR_HPP */ diff --git a/extractor/extractor_callbacks.cpp b/extractor/extractor_callbacks.cpp index 87e4f4f0b..7ab0fc409 100644 --- a/extractor/extractor_callbacks.cpp +++ b/extractor/extractor_callbacks.cpp @@ -35,7 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../Util/container.hpp" #include "../Util/simple_logger.hpp" -#include +#include #include #include diff --git a/extractor/internal_extractor_edge.hpp b/extractor/internal_extractor_edge.hpp index ffd2d4a36..4060634c2 100644 --- a/extractor/internal_extractor_edge.hpp +++ b/extractor/internal_extractor_edge.hpp @@ -34,6 +34,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include + struct InternalExtractorEdge { InternalExtractorEdge() diff --git a/plugins/distance_table.hpp b/plugins/distance_table.hpp index 6ef90a5b8..050287980 100644 --- a/plugins/distance_table.hpp +++ b/plugins/distance_table.hpp @@ -31,7 +31,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "plugin_base.hpp" #include "../algorithms/object_encoder.hpp" -#include "../data_structures/json_container.hpp" #include "../data_structures/query_edge.hpp" #include "../data_structures/search_engine.hpp" #include "../descriptors/descriptor_base.hpp" @@ -40,6 +39,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../Util/string_util.hpp" #include "../Util/timing_util.hpp" +#include + #include #include diff --git a/plugins/hello_world.hpp b/plugins/hello_world.hpp index c8b07b081..b65231db8 100644 --- a/plugins/hello_world.hpp +++ b/plugins/hello_world.hpp @@ -34,6 +34,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../Util/cast.hpp" #include "../Util/json_renderer.hpp" +#include + #include class HelloWorldPlugin final : public BasePlugin diff --git a/plugins/locate.hpp b/plugins/locate.hpp index 6171395c4..ee2ddd1c0 100644 --- a/plugins/locate.hpp +++ b/plugins/locate.hpp @@ -30,10 +30,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "plugin_base.hpp" -#include "../data_structures/json_container.hpp" #include "../Util/json_renderer.hpp" #include "../Util/string_util.hpp" +#include + #include // locates the nearest node in the road network for a given coordinate. diff --git a/plugins/nearest.hpp b/plugins/nearest.hpp index ac1079be4..a8a4dc9fe 100644 --- a/plugins/nearest.hpp +++ b/plugins/nearest.hpp @@ -30,11 +30,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "plugin_base.hpp" -#include "../data_structures/json_container.hpp" #include "../data_structures/phantom_node.hpp" #include "../Util/integer_range.hpp" #include "../Util/json_renderer.hpp" +#include + #include /* diff --git a/plugins/plugin_base.hpp b/plugins/plugin_base.hpp index bb23a4d57..10f41e54c 100644 --- a/plugins/plugin_base.hpp +++ b/plugins/plugin_base.hpp @@ -28,9 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef BASEPLUGIN_H_ #define BASEPLUGIN_H_ -#include -#include -#include +// remove +#include "../Server/Http/Reply.h" + +#include +#include #include #include diff --git a/plugins/timestamp.hpp b/plugins/timestamp.hpp index acdf32e7c..80d9deda5 100644 --- a/plugins/timestamp.hpp +++ b/plugins/timestamp.hpp @@ -30,9 +30,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "plugin_base.hpp" -#include "../data_structures/json_container.hpp" #include "../Util/json_renderer.hpp" +#include + #include template class TimestampPlugin final : public BasePlugin diff --git a/plugins/viaroute.hpp b/plugins/viaroute.hpp index 236ee395a..883dc6480 100644 --- a/plugins/viaroute.hpp +++ b/plugins/viaroute.hpp @@ -40,6 +40,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../Util/make_unique.hpp" #include "../Util/simple_logger.hpp" +#include + #include #include From 4a6325696e5172e8e37a6c4981cc277a10db1851 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 25 Nov 2014 09:14:01 +0100 Subject: [PATCH 004/360] change library interface to expose json container as structure to exchange data --- Library/OSRM.h | 6 +++--- Library/OSRM_impl.cpp | 14 ++++++-------- Library/OSRM_impl.h | 3 ++- Server/RequestHandler.cpp | 17 +++++++++++------ descriptors/descriptor_base.hpp | 6 ++++-- descriptors/gpx_descriptor.hpp | 17 +++++++++-------- descriptors/json_descriptor.hpp | 21 ++++++++++----------- plugins/distance_table.hpp | 14 ++++++-------- plugins/hello_world.hpp | 8 ++------ plugins/locate.hpp | 10 +++------- plugins/nearest.hpp | 10 ++++------ plugins/plugin_base.hpp | 8 +++----- plugins/timestamp.hpp | 6 ++---- plugins/viaroute.hpp | 9 ++++----- 14 files changed, 69 insertions(+), 80 deletions(-) diff --git a/Library/OSRM.h b/Library/OSRM.h index cfa84ae27..421e99658 100644 --- a/Library/OSRM.h +++ b/Library/OSRM.h @@ -35,9 +35,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. class OSRM_impl; struct RouteParameters; -namespace http +namespace JSON { -class Reply; +struct Object; } class OSRM @@ -48,7 +48,7 @@ class OSRM public: explicit OSRM(ServerPaths paths, const bool use_shared_memory = false); ~OSRM(); - void RunQuery(RouteParameters &route_parameters, http::Reply &reply); + int RunQuery(RouteParameters &route_parameters, JSON::Object &json_result); }; #endif // OSRM_H diff --git a/Library/OSRM_impl.cpp b/Library/OSRM_impl.cpp index 991a57f51..7cc1ceb3c 100644 --- a/Library/OSRM_impl.cpp +++ b/Library/OSRM_impl.cpp @@ -44,8 +44,6 @@ namespace boost { namespace interprocess { class named_mutex; } } #include "../Server/DataStructures/InternalDataFacade.h" #include "../Server/DataStructures/SharedBarriers.h" #include "../Server/DataStructures/SharedDataFacade.h" -//TODO: remove -#include "../Server/Http/Reply.h" #include "../Util/make_unique.hpp" #include "../Util/ProgramOptions.h" #include "../Util/simple_logger.hpp" @@ -104,13 +102,12 @@ void OSRM_impl::RegisterPlugin(BasePlugin *plugin) plugin_map.emplace(plugin->GetDescriptor(), plugin); } -void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply) +int OSRM_impl::RunQuery(RouteParameters &route_parameters, JSON::Object &json_result) { const PluginMap::const_iterator &iter = plugin_map.find(route_parameters.service); if (plugin_map.end() != iter) { - reply.status = http::Reply::ok; if (barrier) { // lock update pending @@ -131,7 +128,7 @@ void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply) ->CheckAndReloadFacade(); } - iter->second->HandleRequest(route_parameters, reply); + iter->second->HandleRequest(route_parameters, json_result); if (barrier) { // lock query @@ -148,10 +145,11 @@ void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply) barrier->no_running_queries_condition.notify_all(); } } + return 200; } else { - reply = http::Reply::StockReply(http::Reply::badRequest); + return 400; } } @@ -164,7 +162,7 @@ OSRM::OSRM(ServerPaths paths, const bool use_shared_memory) OSRM::~OSRM() { OSRM_pimpl_.reset(); } -void OSRM::RunQuery(RouteParameters &route_parameters, http::Reply &reply) +int OSRM::RunQuery(RouteParameters &route_parameters, JSON::Object &json_result) { - OSRM_pimpl_->RunQuery(route_parameters, reply); + return OSRM_pimpl_->RunQuery(route_parameters, json_result); } diff --git a/Library/OSRM_impl.h b/Library/OSRM_impl.h index b7d4bfed7..376e11ac3 100644 --- a/Library/OSRM_impl.h +++ b/Library/OSRM_impl.h @@ -32,6 +32,7 @@ class BasePlugin; namespace http { class Reply; } struct RouteParameters; +#include #include #include "../data_structures/query_edge.hpp" @@ -52,7 +53,7 @@ class OSRM_impl OSRM_impl(ServerPaths paths, const bool use_shared_memory); OSRM_impl(const OSRM_impl &) = delete; virtual ~OSRM_impl(); - void RunQuery(RouteParameters &route_parameters, http::Reply &reply); + int RunQuery(RouteParameters &route_parameters, JSON::Object &json_result); private: void RegisterPlugin(BasePlugin *plugin); diff --git a/Server/RequestHandler.cpp b/Server/RequestHandler.cpp index 50449d561..2c7f72a08 100644 --- a/Server/RequestHandler.cpp +++ b/Server/RequestHandler.cpp @@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../Util/json_renderer.hpp" #include "../Util/simple_logger.hpp" #include "../Util/string_util.hpp" +#include "../Util/xml_renderer.hpp" #include "../typedefs.h" #include @@ -84,13 +85,14 @@ void RequestHandler::handle_request(const http::Request &req, http::Reply &reply auto iter = request.begin(); const bool result = boost::spirit::qi::parse(iter, request.end(), api_parser); + JSON::Object json_result; // check if the was an error with the request if (!result || (iter != request.end())) { reply = http::Reply::StockReply(http::Reply::badRequest); reply.content.clear(); const auto position = std::distance(request.begin(), iter); - JSON::Object json_result; + json_result.values["status"] = 400; std::string message = "Query string malformed close to position "; message += cast::integral_to_string(position); @@ -107,29 +109,32 @@ void RequestHandler::handle_request(const http::Request &req, http::Reply &reply const std::string json_p = (route_parameters.jsonp_parameter + "("); reply.content.insert(reply.content.end(), json_p.begin(), json_p.end()); } - routing_machine->RunQuery(route_parameters, reply); - if (!route_parameters.jsonp_parameter.empty()) - { // append brace to jsonp response - reply.content.push_back(')'); - } + routing_machine->RunQuery(route_parameters, json_result); // set headers reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size())); if ("gpx" == route_parameters.output_format) { // gpx file + JSON::gpx_render(reply.content, json_result.values["route"]); reply.headers.emplace_back("Content-Type", "application/gpx+xml; charset=UTF-8"); reply.headers.emplace_back("Content-Disposition", "attachment; filename=\"route.gpx\""); } else if (route_parameters.jsonp_parameter.empty()) { // json file + JSON::render(reply.content, json_result); reply.headers.emplace_back("Content-Type", "application/json; charset=UTF-8"); reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.json\""); } else { // jsonp + JSON::render(reply.content, json_result); reply.headers.emplace_back("Content-Type", "text/javascript; charset=UTF-8"); reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.js\""); } + if (!route_parameters.jsonp_parameter.empty()) + { // append brace to jsonp response + reply.content.push_back(')'); + } } catch (const std::exception &e) { diff --git a/descriptors/descriptor_base.hpp b/descriptors/descriptor_base.hpp index 670f0038f..25bebb680 100644 --- a/descriptors/descriptor_base.hpp +++ b/descriptors/descriptor_base.hpp @@ -32,6 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/raw_route_data.hpp" #include "../typedefs.h" +#include + #include #include #include @@ -77,8 +79,8 @@ template class BaseDescriptor BaseDescriptor() {} // Maybe someone can explain the pure virtual destructor thing to me (dennis) virtual ~BaseDescriptor() {} - virtual void Run(const RawRouteData &raw_route, http::Reply &reply) = 0; - virtual void SetConfig(const DescriptorConfig &config) = 0; + virtual void Run(const RawRouteData &, JSON::Object &) = 0; + virtual void SetConfig(const DescriptorConfig &) = 0; }; #endif // DESCRIPTOR_BASE_HPP diff --git a/descriptors/gpx_descriptor.hpp b/descriptors/gpx_descriptor.hpp index 8da8759b2..c58c5a7f9 100644 --- a/descriptors/gpx_descriptor.hpp +++ b/descriptors/gpx_descriptor.hpp @@ -41,7 +41,7 @@ template class GPXDescriptor final : public BaseDescriptor class GPXDescriptor final : public BaseDescriptor class GPXDescriptor final : public BaseDescriptor &path_data_vector : raw_route.unpacked_path_segments) { @@ -81,13 +81,14 @@ template class GPXDescriptor final : public BaseDescriptorGetCoordinateOfNode(path_data.node); - AddRoutePoint(current_coordinate, json_result); + AddRoutePoint(current_coordinate, json_route); } } AddRoutePoint(raw_route.segment_end_coordinates.back().target_phantom.location, - json_result); + json_route); } - JSON::gpx_render(reply.content, json_result); + // JSON::gpx_render(reply.content, json_route); + json_result.values["route"] = json_route; } }; #endif // GPX_DESCRIPTOR_HPP diff --git a/descriptors/json_descriptor.hpp b/descriptors/json_descriptor.hpp index f0f094246..39c36cd46 100644 --- a/descriptors/json_descriptor.hpp +++ b/descriptors/json_descriptor.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -99,15 +99,14 @@ template class JSONDescriptor final : public BaseDescriptor< return added_element_count; } - void Run(const RawRouteData &raw_route, http::Reply &reply) final + void Run(const RawRouteData &raw_route, JSON::Object &json_result) final { - JSON::Object json_result; if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length) { // We do not need to do much, if there is no route ;-) json_result.values["status"] = 207; json_result.values["status_message"] = "Cannot find route between points"; - JSON::render(reply.content, json_result); + // JSON::render(reply.content, json_result); return; } @@ -296,10 +295,10 @@ template class JSONDescriptor final : public BaseDescriptor< json_result.values["hint_data"] = json_hint_object; // render the content to the output array - TIMER_START(route_render); - JSON::render(reply.content, json_result); - TIMER_STOP(route_render); - SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render); + // TIMER_START(route_render); + // JSON::render(reply.content, json_result); + // TIMER_STOP(route_render); + // SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render); } // TODO: reorder parameters @@ -356,7 +355,7 @@ template class JSONDescriptor final : public BaseDescriptor< json_instruction_row.values.push_back( cast::integral_to_string(static_cast(segment.length)) + "m"); const double bearing_value = (segment.bearing / 10.); - json_instruction_row.values.push_back(Bearing::Get(bearing_value)); + json_instruction_row.values.push_back(Azimuth::Get(bearing_value)); json_instruction_row.values.push_back( static_cast(round(bearing_value))); json_instruction_row.values.push_back(segment.travel_mode); @@ -386,10 +385,10 @@ template class JSONDescriptor final : public BaseDescriptor< json_last_instruction_row.values.push_back(necessary_segments_running_index - 1); json_last_instruction_row.values.push_back(0); json_last_instruction_row.values.push_back("0m"); - json_last_instruction_row.values.push_back(Bearing::Get(0.0)); + json_last_instruction_row.values.push_back(Azimuth::Get(0.0)); json_last_instruction_row.values.push_back(0.); json_instruction_array.values.push_back(json_last_instruction_row); } }; -#endif /* JSON_DESCRIPTOR_HPP */ +#endif /* JSON_DESCRIPTOR_H_ */ diff --git a/plugins/distance_table.hpp b/plugins/distance_table.hpp index 050287980..d173651bd 100644 --- a/plugins/distance_table.hpp +++ b/plugins/distance_table.hpp @@ -64,12 +64,11 @@ template class DistanceTablePlugin final : public BasePlugin const std::string GetDescriptor() const final { return descriptor_string; } - void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final + int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final { if (!check_all_coordinates(route_parameters.coordinates)) { - reply = http::Reply::StockReply(http::Reply::badRequest); - return; + return 400; } const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); @@ -103,11 +102,9 @@ template class DistanceTablePlugin final : public BasePlugin if (!result_table) { - reply = http::Reply::StockReply(http::Reply::badRequest); - return; + return 400; } - JSON::Object json_object; JSON::Array json_array; const auto number_of_locations = phantom_node_vector.size(); for (const auto row : osrm::irange(0, number_of_locations)) @@ -118,8 +115,9 @@ template class DistanceTablePlugin final : public BasePlugin json_row.values.insert(json_row.values.end(), row_begin_iterator, row_end_iterator); json_array.values.push_back(json_row); } - json_object.values["distance_table"] = json_array; - JSON::render(reply.content, json_object); + json_result.values["distance_table"] = json_array; + // JSON::render(reply.content, json_object); + return 200; } private: diff --git a/plugins/hello_world.hpp b/plugins/hello_world.hpp index b65231db8..52dfa9884 100644 --- a/plugins/hello_world.hpp +++ b/plugins/hello_world.hpp @@ -48,11 +48,8 @@ class HelloWorldPlugin final : public BasePlugin virtual ~HelloWorldPlugin() {} const std::string GetDescriptor() const final { return descriptor_string; } - void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply) final + int HandleRequest(const RouteParameters &routeParameters, JSON::Object &json_result) final { - reply.status = http::Reply::ok; - - JSON::Object json_result; std::string temp_string; json_result.values["title"] = "Hello World"; @@ -98,8 +95,7 @@ class HelloWorldPlugin final : public BasePlugin ++counter; } json_result.values["hints"] = json_hints; - - JSON::render(reply.content, json_result); + return 200; } private: diff --git a/plugins/locate.hpp b/plugins/locate.hpp index ee2ddd1c0..7092da9b0 100644 --- a/plugins/locate.hpp +++ b/plugins/locate.hpp @@ -44,16 +44,14 @@ template class LocatePlugin final : public BasePlugin explicit LocatePlugin(DataFacadeT *facade) : descriptor_string("locate"), facade(facade) {} const std::string GetDescriptor() const final { return descriptor_string; } - void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final + int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final { // check number of parameters if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().is_valid()) { - reply = http::Reply::StockReply(http::Reply::badRequest); - return; + return 400; } - JSON::Object json_result; FixedPointCoordinate result; if (!facade->LocateClosestEndPointForCoordinate(route_parameters.coordinates.front(), result)) @@ -62,15 +60,13 @@ template class LocatePlugin final : public BasePlugin } else { - reply.status = http::Reply::ok; json_result.values["status"] = 0; JSON::Array json_coordinate; json_coordinate.values.push_back(result.lat / COORDINATE_PRECISION); json_coordinate.values.push_back(result.lon / COORDINATE_PRECISION); json_result.values["mapped_coordinate"] = json_coordinate; } - - JSON::render(reply.content, json_result); + return 200; } private: diff --git a/plugins/nearest.hpp b/plugins/nearest.hpp index a8a4dc9fe..33bed1333 100644 --- a/plugins/nearest.hpp +++ b/plugins/nearest.hpp @@ -49,13 +49,12 @@ template class NearestPlugin final : public BasePlugin const std::string GetDescriptor() const final { return descriptor_string; } - void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final + int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final { // check number of parameters if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().is_valid()) { - reply = http::Reply::StockReply(http::Reply::badRequest); - return; + return 400; } auto number_of_results = static_cast(route_parameters.num_results); std::vector phantom_node_vector; @@ -63,14 +62,13 @@ template class NearestPlugin final : public BasePlugin phantom_node_vector, static_cast(number_of_results)); - JSON::Object json_result; if (phantom_node_vector.empty() || !phantom_node_vector.front().is_valid()) { json_result.values["status"] = 207; } else { - reply.status = http::Reply::ok; + // reply.status = http::Reply::ok; json_result.values["status"] = 0; if (number_of_results > 1) @@ -107,7 +105,7 @@ template class NearestPlugin final : public BasePlugin json_result.values["name"] = temp_string; } } - JSON::render(reply.content, json_result); + return 200; } private: diff --git a/plugins/plugin_base.hpp b/plugins/plugin_base.hpp index 10f41e54c..8dc2eea6d 100644 --- a/plugins/plugin_base.hpp +++ b/plugins/plugin_base.hpp @@ -28,10 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef BASEPLUGIN_H_ #define BASEPLUGIN_H_ -// remove -#include "../Server/Http/Reply.h" - #include +#include #include #include @@ -44,8 +42,8 @@ class BasePlugin // Maybe someone can explain the pure virtual destructor thing to me (dennis) virtual ~BasePlugin() {} virtual const std::string GetDescriptor() const = 0; - virtual void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply) = 0; - virtual bool check_all_coordinates(const std::vector coordinates) const final + virtual int HandleRequest(const RouteParameters &, JSON::Object &) = 0; + virtual bool check_all_coordinates(const std::vector &coordinates) const final { if (2 > coordinates.size() || std::any_of(std::begin(coordinates), diff --git a/plugins/timestamp.hpp b/plugins/timestamp.hpp index 80d9deda5..181efbf7b 100644 --- a/plugins/timestamp.hpp +++ b/plugins/timestamp.hpp @@ -44,14 +44,12 @@ template class TimestampPlugin final : public BasePlugin { } const std::string GetDescriptor() const final { return descriptor_string; } - void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final + int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final { - reply.status = http::Reply::ok; - JSON::Object json_result; json_result.values["status"] = 0; const std::string timestamp = facade->GetTimestamp(); json_result.values["timestamp"] = timestamp; - JSON::render(reply.content, json_result); + return 200; } private: diff --git a/plugins/viaroute.hpp b/plugins/viaroute.hpp index 883dc6480..a36328109 100644 --- a/plugins/viaroute.hpp +++ b/plugins/viaroute.hpp @@ -71,14 +71,12 @@ template class ViaRoutePlugin final : public BasePlugin const std::string GetDescriptor() const final { return descriptor_string; } - void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final + int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final { if (!check_all_coordinates(route_parameters.coordinates)) { - reply = http::Reply::StockReply(http::Reply::badRequest); - return; + return 400; } - reply.status = http::Reply::ok; std::vector phantom_node_pair_list(route_parameters.coordinates.size()); const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); @@ -185,7 +183,8 @@ template class ViaRoutePlugin final : public BasePlugin } descriptor->SetConfig(route_parameters); - descriptor->Run(raw_route, reply); + descriptor->Run(raw_route, json_result); + return 200; } }; From 8bd7d57dd818ec6e9f5769dbb3c2c8fbd1a6fffe Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 25 Nov 2014 10:04:12 +0100 Subject: [PATCH 005/360] fixed compilation of simple client - adapted to new lib interface - fixed return codes of command line parsing - reformatted code --- tools/simpleclient.cpp | 61 ++++++++++-------------------------------- 1 file changed, 14 insertions(+), 47 deletions(-) diff --git a/tools/simpleclient.cpp b/tools/simpleclient.cpp index d9c8217b9..801bd36eb 100644 --- a/tools/simpleclient.cpp +++ b/tools/simpleclient.cpp @@ -27,37 +27,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../Library/OSRM.h" #include "../Util/git_sha.hpp" +#include "../Util/json_renderer.hpp" #include "../Util/ProgramOptions.h" #include "../Util/simple_logger.hpp" -#include -#include -#include +#include +#include +#include -#include -#include - -#include -#include #include -#include - -// Dude, real recursions on the OS stack? You must be brave... -void print_tree(boost::property_tree::ptree const &property_tree, const unsigned recursion_depth) -{ - auto end = property_tree.end(); - for (auto tree_iterator = property_tree.begin(); tree_iterator != end; ++tree_iterator) - { - for (unsigned current_recursion = 0; current_recursion < recursion_depth; - ++current_recursion) - { - std::cout << " " << std::flush; - } - std::cout << tree_iterator->first << ": " << tree_iterator->second.get_value() - << std::endl; - print_tree(tree_iterator->second, recursion_depth + 1); - } -} int main(int argc, const char *argv[]) { @@ -68,7 +46,6 @@ int main(int argc, const char *argv[]) int ip_port, requested_thread_num; bool use_shared_memory = false, trial_run = false; ServerPaths server_paths; - const unsigned init_result = GenerateServerProgramOptions(argc, argv, server_paths, @@ -78,11 +55,14 @@ int main(int argc, const char *argv[]) use_shared_memory, trial_run); - if (init_result == INIT_FAILED) + if (init_result == INIT_OK_DO_NOT_START_ENGINE) { return 0; } - + if (init_result == INIT_FAILED) + { + return 1; + } SimpleLogger().Write() << "starting up engines, " << g_GIT_DESCRIPTION; OSRM routing_machine(server_paths, use_shared_memory); @@ -93,7 +73,7 @@ int main(int argc, const char *argv[]) route_parameters.alternate_route = true; // get an alternate route, too route_parameters.geometry = true; // retrieve geometry of route route_parameters.compression = true; // polyline encoding - route_parameters.check_sum = UINT_MAX; // see wiki + route_parameters.check_sum = -1; // see wiki route_parameters.service = "viaroute"; // that's routing route_parameters.output_format = "json"; route_parameters.jsonp_parameter = ""; // set for jsonp wrapping @@ -106,23 +86,10 @@ int main(int argc, const char *argv[]) // target_coordinate route_parameters.coordinates.emplace_back(52.513191 * COORDINATE_PRECISION, 13.415852 * COORDINATE_PRECISION); - http::Reply osrm_reply; - routing_machine.RunQuery(route_parameters, osrm_reply); - - // attention: super-inefficient hack below: - - std::stringstream my_stream; - for (const auto &element : osrm_reply.content) - { - std::cout << element; - my_stream << element; - } - std::cout << std::endl; - - boost::property_tree::ptree property_tree; - boost::property_tree::read_json(my_stream, property_tree); - - print_tree(property_tree, 0); + JSON::Object json_result; + const int result_code = routing_machine.RunQuery(route_parameters, json_result); + SimpleLogger().Write() << "http code: " << result_code; + JSON::render(SimpleLogger().Write(), json_result); } catch (std::exception ¤t_exception) { From 1b10f53eff86223aa5bba81dd28b93fd97a29e84 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 25 Nov 2014 16:30:43 +0100 Subject: [PATCH 006/360] DataStructures/RawRouteData.h -> DataStructures/internal_route_result.hpp, implements #1238 --- .../internal_route_result.hpp | 18 +++++++++--------- descriptors/descriptor_base.hpp | 2 +- descriptors/gpx_descriptor.hpp | 2 +- descriptors/json_descriptor.hpp | 2 +- plugins/viaroute.hpp | 2 +- routing_algorithms/alternative_path.hpp | 2 +- routing_algorithms/shortest_path.hpp | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) rename data_structures/raw_route_data.hpp => DataStructures/internal_route_result.hpp (89%) diff --git a/data_structures/raw_route_data.hpp b/DataStructures/internal_route_result.hpp similarity index 89% rename from data_structures/raw_route_data.hpp rename to DataStructures/internal_route_result.hpp index bb48a94c9..2df529604 100644 --- a/data_structures/raw_route_data.hpp +++ b/DataStructures/internal_route_result.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,12 +25,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef RAW_ROUTE_DATA_HPP -#define RAW_ROUTE_DATA_HPP +#ifndef RAW_ROUTE_DATA_H +#define RAW_ROUTE_DATA_H -#include "../data_structures/phantom_node.hpp" -#include "../data_structures/travel_mode.hpp" -#include "../data_structures/turn_instructions.hpp" +#include "../DataStructures/phantom_node.hpp" +#include "../DataStructures/TravelMode.h" +#include "../DataStructures/TurnInstructions.h" #include "../typedefs.h" #include @@ -63,7 +63,7 @@ struct PathData TravelMode travel_mode : 4; }; -struct RawRouteData +struct InternalRouteResult { std::vector> unpacked_path_segments; std::vector unpacked_alternative; @@ -80,11 +80,11 @@ struct RawRouteData return (leg != unpacked_path_segments.size() - 1); } - RawRouteData() : + InternalRouteResult() : shortest_path_length(INVALID_EDGE_WEIGHT), alternative_path_length(INVALID_EDGE_WEIGHT) { } }; -#endif // RAW_ROUTE_DATA_HPP +#endif // RAW_ROUTE_DATA_H diff --git a/descriptors/descriptor_base.hpp b/descriptors/descriptor_base.hpp index 25bebb680..c8a24b8f4 100644 --- a/descriptors/descriptor_base.hpp +++ b/descriptors/descriptor_base.hpp @@ -79,7 +79,7 @@ template class BaseDescriptor BaseDescriptor() {} // Maybe someone can explain the pure virtual destructor thing to me (dennis) virtual ~BaseDescriptor() {} - virtual void Run(const RawRouteData &, JSON::Object &) = 0; + virtual void Run(const InternalRouteResult &, JSON::Object &) = 0; virtual void SetConfig(const DescriptorConfig &) = 0; }; diff --git a/descriptors/gpx_descriptor.hpp b/descriptors/gpx_descriptor.hpp index c58c5a7f9..0c7557917 100644 --- a/descriptors/gpx_descriptor.hpp +++ b/descriptors/gpx_descriptor.hpp @@ -67,7 +67,7 @@ template class GPXDescriptor final : public BaseDescriptor class JSONDescriptor final : public BaseDescriptor< return added_element_count; } - void Run(const RawRouteData &raw_route, JSON::Object &json_result) final + void Run(const InternalRouteResult &raw_route, JSON::Object &json_result) final { if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length) { diff --git a/plugins/viaroute.hpp b/plugins/viaroute.hpp index a36328109..bf6891163 100644 --- a/plugins/viaroute.hpp +++ b/plugins/viaroute.hpp @@ -143,7 +143,7 @@ template class ViaRoutePlugin final : public BasePlugin swap_phantom_from_big_cc_into_front); } - RawRouteData raw_route; + InternalRouteResult raw_route; auto build_phantom_pairs = [&raw_route](const phantom_node_pair &first_pair, const phantom_node_pair &second_pair) { diff --git a/routing_algorithms/alternative_path.hpp b/routing_algorithms/alternative_path.hpp index 84b5856fb..ae1f62338 100644 --- a/routing_algorithms/alternative_path.hpp +++ b/routing_algorithms/alternative_path.hpp @@ -78,7 +78,7 @@ template class AlternativeRouting final : private BasicRouti virtual ~AlternativeRouting() {} - void operator()(const PhantomNodes &phantom_node_pair, RawRouteData &raw_route_data) + void operator()(const PhantomNodes &phantom_node_pair, InternalRouteResult &raw_route_data) { std::vector alternative_path; std::vector via_node_candidate_list; diff --git a/routing_algorithms/shortest_path.hpp b/routing_algorithms/shortest_path.hpp index cab09ab9f..f09d2cff6 100644 --- a/routing_algorithms/shortest_path.hpp +++ b/routing_algorithms/shortest_path.hpp @@ -51,7 +51,7 @@ template class ShortestPathRouting final : public BasicRouti void operator()(const std::vector &phantom_nodes_vector, const std::vector &uturn_indicators, - RawRouteData &raw_route_data) const + InternalRouteResult &raw_route_data) const { int distance1 = 0; int distance2 = 0; From 89dd0c4a404f8d9f1bce2432c504356e5cee97e7 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 25 Nov 2014 16:57:26 +0100 Subject: [PATCH 007/360] install headers with .hpp suffix --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b6a40f916..081373475 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -321,7 +321,7 @@ if(WITH_TOOLS OR BUILD_TOOLS) install(TARGETS osrm-springclean DESTINATION bin) endif() -file(GLOB InstallGlob Include/osrm/*.h Library/OSRM.h) +file(GLOB InstallGlob Include/osrm/*.hpp Library/OSRM.h) # Add RPATH info to executables so that when they are run after being installed # (i.e., from /usr/local/bin/) the linker can find library dependencies. For From 06f82d5e8a995093f33fa297762ee1febafc2839 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 25 Nov 2014 17:06:10 +0100 Subject: [PATCH 008/360] install variant by default --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 081373475..2c478790e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -322,6 +322,7 @@ if(WITH_TOOLS OR BUILD_TOOLS) endif() file(GLOB InstallGlob Include/osrm/*.hpp Library/OSRM.h) +file(GLOB VariantGlob Include/variant/*.hpp) # Add RPATH info to executables so that when they are run after being installed # (i.e., from /usr/local/bin/) the linker can find library dependencies. For @@ -332,6 +333,7 @@ set_property(TARGET osrm-datastore PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE) set_property(TARGET osrm-routed PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE) install(FILES ${InstallGlob} DESTINATION include/osrm) +install(FILES ${VariantGlob} DESTINATION include/variant) install(TARGETS osrm-extract DESTINATION bin) install(TARGETS osrm-prepare DESTINATION bin) install(TARGETS osrm-datastore DESTINATION bin) From 6da33cafe56ea9db6eb53297ecb27175eda7a4e2 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 17 Dec 2014 19:02:48 +0100 Subject: [PATCH 009/360] rebase branch onto latest develop, report changes. hurt a little --- CMakeLists.txt | 4 +- Library/OSRM_impl.cpp | 4 - .../coordinate.cpp | 968 +++++++++--------- .../internal_route_result.hpp | 6 +- data_structures/phantom_node.hpp | 2 +- descriptors/description_factory.cpp | 2 +- descriptors/description_factory.hpp | 1 - descriptors/descriptor_base.hpp | 2 +- descriptors/json_descriptor.hpp | 5 +- extractor/internal_extractor_edge.hpp | 1 - plugins/hello_world.hpp | 1 - routing_algorithms/routing_base.hpp | 4 +- 12 files changed, 496 insertions(+), 504 deletions(-) rename {DataStructures => data_structures}/coordinate.cpp (96%) rename {DataStructures => data_structures}/internal_route_result.hpp (95%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c478790e..dc8264cb5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,7 +71,7 @@ file(GLOB ServerGlob Server/*.cpp) file(GLOB DescriptorGlob descriptors/*.cpp) file(GLOB DatastructureGlob data_structures/search_engine_data.cpp data_structures/route_parameters.cpp Util/bearing.cpp) list(REMOVE_ITEM DatastructureGlob data_structures/Coordinate.cpp) -file(GLOB CoordinateGlob data_structures/Coordinate.cpp) +file(GLOB CoordinateGlob data_structures/coordinate.cpp) file(GLOB AlgorithmGlob algorithms/*.cpp) file(GLOB HttpGlob Server/Http/*.cpp) file(GLOB LibOSRMGlob Library/*.cpp) @@ -299,7 +299,7 @@ if(WITH_TOOLS OR BUILD_TOOLS) else() message(FATAL_ERROR "libgdal and/or development headers not found") endif() - add_executable(osrm-cli tools/simpleclient.cpp $ $) + add_executable(osrm-cli tools/simpleclient.cpp $ $ $) target_link_libraries(osrm-cli ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM) target_link_libraries(osrm-cli ${TBB_LIBRARIES}) add_executable(osrm-io-benchmark tools/io-benchmark.cpp $ $ $) diff --git a/Library/OSRM_impl.cpp b/Library/OSRM_impl.cpp index 7cc1ceb3c..ea8ac8319 100644 --- a/Library/OSRM_impl.cpp +++ b/Library/OSRM_impl.cpp @@ -30,10 +30,6 @@ namespace boost { namespace interprocess { class named_mutex; } } #include "OSRM_impl.h" #include "OSRM.h" -#include -#include -#include - #include "../plugins/distance_table.hpp" #include "../plugins/hello_world.hpp" #include "../plugins/locate.hpp" diff --git a/DataStructures/coordinate.cpp b/data_structures/coordinate.cpp similarity index 96% rename from DataStructures/coordinate.cpp rename to data_structures/coordinate.cpp index 0b76a4306..c2563b663 100644 --- a/DataStructures/coordinate.cpp +++ b/data_structures/coordinate.cpp @@ -1,484 +1,484 @@ -/* - -Copyright (c) 2013, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "../Util/MercatorUtil.h" -#ifndef NDEBUG -#include "../Util/simple_logger.hpp" -#endif -#include "../Util/string_util.hpp" - -#include - -#include - -#ifndef NDEBUG -#include -#endif -#include -#include - -FixedPointCoordinate::FixedPointCoordinate() - : lat(std::numeric_limits::min()), lon(std::numeric_limits::min()) -{ -} - -FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon) -{ -#ifndef NDEBUG - if (0 != (std::abs(lat) >> 30)) - { - std::bitset<32> y_coordinate_vector(lat); - SimpleLogger().Write(logDEBUG) << "broken lat: " << lat - << ", bits: " << y_coordinate_vector; - } - if (0 != (std::abs(lon) >> 30)) - { - std::bitset<32> x_coordinate_vector(lon); - SimpleLogger().Write(logDEBUG) << "broken lon: " << lon - << ", bits: " << x_coordinate_vector; - } -#endif -} - -void FixedPointCoordinate::Reset() -{ - lat = std::numeric_limits::min(); - lon = std::numeric_limits::min(); -} -bool FixedPointCoordinate::isSet() const -{ - return (std::numeric_limits::min() != lat) && (std::numeric_limits::min() != lon); -} -bool FixedPointCoordinate::is_valid() const -{ - if (lat > 90 * COORDINATE_PRECISION || lat < -90 * COORDINATE_PRECISION || - lon > 180 * COORDINATE_PRECISION || lon < -180 * COORDINATE_PRECISION) - { - return false; - } - return true; -} -bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const -{ - return lat == other.lat && lon == other.lon; -} - -double FixedPointCoordinate::ApproximateDistance(const int lat1, - const int lon1, - const int lat2, - const int lon2) -{ - BOOST_ASSERT(lat1 != std::numeric_limits::min()); - BOOST_ASSERT(lon1 != std::numeric_limits::min()); - BOOST_ASSERT(lat2 != std::numeric_limits::min()); - BOOST_ASSERT(lon2 != std::numeric_limits::min()); - double RAD = 0.017453292519943295769236907684886; - double lt1 = lat1 / COORDINATE_PRECISION; - double ln1 = lon1 / COORDINATE_PRECISION; - double lt2 = lat2 / COORDINATE_PRECISION; - double ln2 = lon2 / COORDINATE_PRECISION; - double dlat1 = lt1 * (RAD); - - double dlong1 = ln1 * (RAD); - double dlat2 = lt2 * (RAD); - double dlong2 = ln2 * (RAD); - - double dLong = dlong1 - dlong2; - double dLat = dlat1 - dlat2; - - double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2); - double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv)); - // earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi) - // The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles) - const double earth = 6372797.560856; - return earth * cHarv; -} - -double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &coordinate_1, - const FixedPointCoordinate &coordinate_2) -{ - return ApproximateDistance( - coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon); -} - -float FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &coordinate_1, - const FixedPointCoordinate &coordinate_2) -{ - return ApproximateEuclideanDistance( - coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon); -} - -float FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1, - const int lon1, - const int lat2, - const int lon2) -{ - BOOST_ASSERT(lat1 != std::numeric_limits::min()); - BOOST_ASSERT(lon1 != std::numeric_limits::min()); - BOOST_ASSERT(lat2 != std::numeric_limits::min()); - BOOST_ASSERT(lon2 != std::numeric_limits::min()); - - const float RAD = 0.017453292519943295769236907684886f; - const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD; - const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD; - const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD; - const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD; - - const float x_value = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.f); - const float y_value = float_lat2 - float_lat1; - const float earth_radius = 6372797.560856f; - return sqrt(x_value * x_value + y_value * y_value) * earth_radius; -} - -float -FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate, - const FixedPointCoordinate &target_coordinate, - const FixedPointCoordinate &point) -{ - // initialize values - const float x_value = static_cast(lat2y(point.lat / COORDINATE_PRECISION)); - const float y_value = point.lon / COORDINATE_PRECISION; - float a = static_cast(lat2y(source_coordinate.lat / COORDINATE_PRECISION)); - float b = source_coordinate.lon / COORDINATE_PRECISION; - float c = static_cast(lat2y(target_coordinate.lat / COORDINATE_PRECISION)); - float d = target_coordinate.lon / COORDINATE_PRECISION; - float p, q; - if (std::abs(a - c) > std::numeric_limits::epsilon()) - { - const float slope = (d - b) / (c - a); // slope - // Projection of (x,y) on line joining (a,b) and (c,d) - p = ((x_value + (slope * y_value)) + (slope * slope * a - slope * b)) / - (1.f + slope * slope); - q = b + slope * (p - a); - } - else - { - p = c; - q = y_value; - } - - float ratio; - bool inverse_ratio = false; - - // straight line segment on equator - if (std::abs(c) < std::numeric_limits::epsilon() && - std::abs(a) < std::numeric_limits::epsilon()) - { - ratio = (q - b) / (d - b); - } - else - { - if (std::abs(c) < std::numeric_limits::epsilon()) - { - // swap start/end - std::swap(a, c); - std::swap(b, d); - inverse_ratio = true; - } - - float nY = (d * p - c * q) / (a * d - b * c); - // discretize the result to coordinate precision. it's a hack! - if (std::abs(nY) < (1.f / COORDINATE_PRECISION)) - { - nY = 0.f; - } - - // compute ratio - ratio = (p - nY * a) / c; - } - - if (std::isnan(ratio)) - { - ratio = (target_coordinate == point ? 1.f : 0.f); - } - else if (std::abs(ratio) <= std::numeric_limits::epsilon()) - { - ratio = 0.f; - } - else if (std::abs(ratio - 1.f) <= std::numeric_limits::epsilon()) - { - ratio = 1.f; - } - - // we need to do this, if we switched start/end coordinates - if (inverse_ratio) - { - ratio = 1.0f - ratio; - } - - // compute the nearest location - FixedPointCoordinate nearest_location; - BOOST_ASSERT(!std::isnan(ratio)); - if (ratio <= 0.f) - { // point is "left" of edge - nearest_location = source_coordinate; - } - else if (ratio >= 1.f) - { // point is "right" of edge - nearest_location = target_coordinate; - } - else - { // point lies in between - nearest_location.lat = static_cast(y2lat(p) * COORDINATE_PRECISION); - nearest_location.lon = static_cast(q * COORDINATE_PRECISION); - } - - BOOST_ASSERT(nearest_location.is_valid()); - return FixedPointCoordinate::ApproximateEuclideanDistance(point, nearest_location); -} - -float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &segment_source, - const FixedPointCoordinate &segment_target, - const FixedPointCoordinate &query_location, - FixedPointCoordinate &nearest_location, - float &ratio) -{ - BOOST_ASSERT(query_location.is_valid()); - - // initialize values - const double x = lat2y(query_location.lat / COORDINATE_PRECISION); - const double y = query_location.lon / COORDINATE_PRECISION; - const double a = lat2y(segment_source.lat / COORDINATE_PRECISION); - const double b = segment_source.lon / COORDINATE_PRECISION; - const double c = lat2y(segment_target.lat / COORDINATE_PRECISION); - const double d = segment_target.lon / COORDINATE_PRECISION; - double p, q /*,mX*/, nY; - if (std::abs(a - c) > std::numeric_limits::epsilon()) - { - const double m = (d - b) / (c - a); // slope - // Projection of (x,y) on line joining (a,b) and (c,d) - p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m); - q = b + m * (p - a); - } - else - { - p = c; - q = y; - } - nY = (d * p - c * q) / (a * d - b * c); - - // discretize the result to coordinate precision. it's a hack! - if (std::abs(nY) < (1.f / COORDINATE_PRECISION)) - { - nY = 0.f; - } - - // compute ratio - ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need - // not calculate the explicit values of m an n as we - // are just interested in the ratio - if (std::isnan(ratio)) - { - ratio = (segment_target == query_location ? 1.f : 0.f); - } - else if (std::abs(ratio) <= std::numeric_limits::epsilon()) - { - ratio = 0.f; - } - else if (std::abs(ratio - 1.f) <= std::numeric_limits::epsilon()) - { - ratio = 1.f; - } - - // compute nearest location - BOOST_ASSERT(!std::isnan(ratio)); - if (ratio <= 0.f) - { - nearest_location = segment_source; - } - else if (ratio >= 1.f) - { - nearest_location = segment_target; - } - else - { - // point lies in between - nearest_location.lat = static_cast(y2lat(p) * COORDINATE_PRECISION); - nearest_location.lon = static_cast(q * COORDINATE_PRECISION); - } - BOOST_ASSERT(nearest_location.is_valid()); - - const float approximate_distance = - FixedPointCoordinate::ApproximateEuclideanDistance(query_location, nearest_location); - BOOST_ASSERT(0. <= approximate_distance); - return approximate_distance; -} - -void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output) -{ - char buffer[12]; - buffer[11] = 0; // zero termination - output = printInt<11, 6>(buffer, value); -} - -void FixedPointCoordinate::convertInternalCoordinateToString(const FixedPointCoordinate &coord, - std::string &output) -{ - std::string tmp; - tmp.reserve(23); - convertInternalLatLonToString(coord.lon, tmp); - output = tmp; - output += ","; - convertInternalLatLonToString(coord.lat, tmp); - output += tmp; -} - -void -FixedPointCoordinate::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord, - std::string &output) -{ - std::string tmp; - tmp.reserve(23); - convertInternalLatLonToString(coord.lat, tmp); - output = tmp; - output += ","; - convertInternalLatLonToString(coord.lon, tmp); - output += tmp; -} - -void FixedPointCoordinate::Output(std::ostream &out) const -{ - out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")"; -} - -float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &first_coordinate, - const FixedPointCoordinate &second_coordinate) -{ - const float lon_diff = - second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION; - const float lon_delta = DegreeToRadian(lon_diff); - const float lat1 = DegreeToRadian(first_coordinate.lat / COORDINATE_PRECISION); - const float lat2 = DegreeToRadian(second_coordinate.lat / COORDINATE_PRECISION); - const float y = sin(lon_delta) * cos(lat2); - const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon_delta); - float result = RadianToDegree(std::atan2(y, x)); - while (result < 0.f) - { - result += 360.f; - } - - while (result >= 360.f) - { - result -= 360.f; - } - return result; -} - -float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const -{ - const float lon_delta = - DegreeToRadian(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION); - const float lat1 = DegreeToRadian(other.lat / COORDINATE_PRECISION); - const float lat2 = DegreeToRadian(lat / COORDINATE_PRECISION); - const float y_value = std::sin(lon_delta) * std::cos(lat2); - const float x_value = - std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta); - float result = RadianToDegree(std::atan2(y_value, x_value)); - - while (result < 0.f) - { - result += 360.f; - } - - while (result >= 360.f) - { - result -= 360.f; - } - return result; -} - -float FixedPointCoordinate::DegreeToRadian(const float degree) -{ - return degree * (static_cast(M_PI) / 180.f); -} - -float FixedPointCoordinate::RadianToDegree(const float radian) -{ - return radian * (180.f * static_cast(M_1_PI)); -} - -// This distance computation does integer arithmetic only and is a lot faster than -// the other distance function which are numerically correct('ish). -// It preserves some order among the elements that make it useful for certain purposes -int FixedPointCoordinate::OrderedPerpendicularDistanceApproximation( - const FixedPointCoordinate &input_point, - const FixedPointCoordinate &segment_source, - const FixedPointCoordinate &segment_target) -{ - // initialize values - const float x = static_cast(lat2y(input_point.lat / COORDINATE_PRECISION)); - const float y = input_point.lon / COORDINATE_PRECISION; - const float a = static_cast(lat2y(segment_source.lat / COORDINATE_PRECISION)); - const float b = segment_source.lon / COORDINATE_PRECISION; - const float c = static_cast(lat2y(segment_target.lat / COORDINATE_PRECISION)); - const float d = segment_target.lon / COORDINATE_PRECISION; - - float p, q; - if (a == c) - { - p = c; - q = y; - } - else - { - const float m = (d - b) / (c - a); // slope - // Projection of (x,y) on line joining (a,b) and (c,d) - p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m); - q = b + m * (p - a); - } - - const float nY = (d * p - c * q) / (a * d - b * c); - float ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need - // not calculate the explicit values of m an n as we - // are just interested in the ratio - if (std::isnan(ratio)) - { - ratio = (segment_target == input_point) ? 1.f : 0.f; - } - - // compute target quasi-location - int dx, dy; - if (ratio < 0.f) - { - dx = input_point.lon - segment_source.lon; - dy = input_point.lat - segment_source.lat; - } - else if (ratio > 1.f) - { - dx = input_point.lon - segment_target.lon; - dy = input_point.lat - segment_target.lat; - } - else - { - // point lies in between - dx = input_point.lon - static_cast(q * COORDINATE_PRECISION); - dy = input_point.lat - static_cast(y2lat(p) * COORDINATE_PRECISION); - } - - // return an approximation in the plane - return static_cast(sqrt(dx * dx + dy * dy)); -} +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "../Util/MercatorUtil.h" +#ifndef NDEBUG +#include "../Util/simple_logger.hpp" +#endif +#include "../Util/string_util.hpp" + +#include + +#include + +#ifndef NDEBUG +#include +#endif +#include +#include + +FixedPointCoordinate::FixedPointCoordinate() + : lat(std::numeric_limits::min()), lon(std::numeric_limits::min()) +{ +} + +FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon) +{ +#ifndef NDEBUG + if (0 != (std::abs(lat) >> 30)) + { + std::bitset<32> y_coordinate_vector(lat); + SimpleLogger().Write(logDEBUG) << "broken lat: " << lat + << ", bits: " << y_coordinate_vector; + } + if (0 != (std::abs(lon) >> 30)) + { + std::bitset<32> x_coordinate_vector(lon); + SimpleLogger().Write(logDEBUG) << "broken lon: " << lon + << ", bits: " << x_coordinate_vector; + } +#endif +} + +void FixedPointCoordinate::Reset() +{ + lat = std::numeric_limits::min(); + lon = std::numeric_limits::min(); +} +bool FixedPointCoordinate::isSet() const +{ + return (std::numeric_limits::min() != lat) && (std::numeric_limits::min() != lon); +} +bool FixedPointCoordinate::is_valid() const +{ + if (lat > 90 * COORDINATE_PRECISION || lat < -90 * COORDINATE_PRECISION || + lon > 180 * COORDINATE_PRECISION || lon < -180 * COORDINATE_PRECISION) + { + return false; + } + return true; +} +bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const +{ + return lat == other.lat && lon == other.lon; +} + +double FixedPointCoordinate::ApproximateDistance(const int lat1, + const int lon1, + const int lat2, + const int lon2) +{ + BOOST_ASSERT(lat1 != std::numeric_limits::min()); + BOOST_ASSERT(lon1 != std::numeric_limits::min()); + BOOST_ASSERT(lat2 != std::numeric_limits::min()); + BOOST_ASSERT(lon2 != std::numeric_limits::min()); + double RAD = 0.017453292519943295769236907684886; + double lt1 = lat1 / COORDINATE_PRECISION; + double ln1 = lon1 / COORDINATE_PRECISION; + double lt2 = lat2 / COORDINATE_PRECISION; + double ln2 = lon2 / COORDINATE_PRECISION; + double dlat1 = lt1 * (RAD); + + double dlong1 = ln1 * (RAD); + double dlat2 = lt2 * (RAD); + double dlong2 = ln2 * (RAD); + + double dLong = dlong1 - dlong2; + double dLat = dlat1 - dlat2; + + double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2); + double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv)); + // earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi) + // The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles) + const double earth = 6372797.560856; + return earth * cHarv; +} + +double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &coordinate_1, + const FixedPointCoordinate &coordinate_2) +{ + return ApproximateDistance( + coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon); +} + +float FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &coordinate_1, + const FixedPointCoordinate &coordinate_2) +{ + return ApproximateEuclideanDistance( + coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon); +} + +float FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1, + const int lon1, + const int lat2, + const int lon2) +{ + BOOST_ASSERT(lat1 != std::numeric_limits::min()); + BOOST_ASSERT(lon1 != std::numeric_limits::min()); + BOOST_ASSERT(lat2 != std::numeric_limits::min()); + BOOST_ASSERT(lon2 != std::numeric_limits::min()); + + const float RAD = 0.017453292519943295769236907684886f; + const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD; + const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD; + const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD; + const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD; + + const float x_value = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.f); + const float y_value = float_lat2 - float_lat1; + const float earth_radius = 6372797.560856f; + return sqrt(x_value * x_value + y_value * y_value) * earth_radius; +} + +float +FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate, + const FixedPointCoordinate &target_coordinate, + const FixedPointCoordinate &point) +{ + // initialize values + const float x_value = static_cast(lat2y(point.lat / COORDINATE_PRECISION)); + const float y_value = point.lon / COORDINATE_PRECISION; + float a = static_cast(lat2y(source_coordinate.lat / COORDINATE_PRECISION)); + float b = source_coordinate.lon / COORDINATE_PRECISION; + float c = static_cast(lat2y(target_coordinate.lat / COORDINATE_PRECISION)); + float d = target_coordinate.lon / COORDINATE_PRECISION; + float p, q; + if (std::abs(a - c) > std::numeric_limits::epsilon()) + { + const float slope = (d - b) / (c - a); // slope + // Projection of (x,y) on line joining (a,b) and (c,d) + p = ((x_value + (slope * y_value)) + (slope * slope * a - slope * b)) / + (1.f + slope * slope); + q = b + slope * (p - a); + } + else + { + p = c; + q = y_value; + } + + float ratio; + bool inverse_ratio = false; + + // straight line segment on equator + if (std::abs(c) < std::numeric_limits::epsilon() && + std::abs(a) < std::numeric_limits::epsilon()) + { + ratio = (q - b) / (d - b); + } + else + { + if (std::abs(c) < std::numeric_limits::epsilon()) + { + // swap start/end + std::swap(a, c); + std::swap(b, d); + inverse_ratio = true; + } + + float nY = (d * p - c * q) / (a * d - b * c); + // discretize the result to coordinate precision. it's a hack! + if (std::abs(nY) < (1.f / COORDINATE_PRECISION)) + { + nY = 0.f; + } + + // compute ratio + ratio = (p - nY * a) / c; + } + + if (std::isnan(ratio)) + { + ratio = (target_coordinate == point ? 1.f : 0.f); + } + else if (std::abs(ratio) <= std::numeric_limits::epsilon()) + { + ratio = 0.f; + } + else if (std::abs(ratio - 1.f) <= std::numeric_limits::epsilon()) + { + ratio = 1.f; + } + + // we need to do this, if we switched start/end coordinates + if (inverse_ratio) + { + ratio = 1.0f - ratio; + } + + // compute the nearest location + FixedPointCoordinate nearest_location; + BOOST_ASSERT(!std::isnan(ratio)); + if (ratio <= 0.f) + { // point is "left" of edge + nearest_location = source_coordinate; + } + else if (ratio >= 1.f) + { // point is "right" of edge + nearest_location = target_coordinate; + } + else + { // point lies in between + nearest_location.lat = static_cast(y2lat(p) * COORDINATE_PRECISION); + nearest_location.lon = static_cast(q * COORDINATE_PRECISION); + } + + BOOST_ASSERT(nearest_location.is_valid()); + return FixedPointCoordinate::ApproximateEuclideanDistance(point, nearest_location); +} + +float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target, + const FixedPointCoordinate &query_location, + FixedPointCoordinate &nearest_location, + float &ratio) +{ + BOOST_ASSERT(query_location.is_valid()); + + // initialize values + const double x = lat2y(query_location.lat / COORDINATE_PRECISION); + const double y = query_location.lon / COORDINATE_PRECISION; + const double a = lat2y(segment_source.lat / COORDINATE_PRECISION); + const double b = segment_source.lon / COORDINATE_PRECISION; + const double c = lat2y(segment_target.lat / COORDINATE_PRECISION); + const double d = segment_target.lon / COORDINATE_PRECISION; + double p, q /*,mX*/, nY; + if (std::abs(a - c) > std::numeric_limits::epsilon()) + { + const double m = (d - b) / (c - a); // slope + // Projection of (x,y) on line joining (a,b) and (c,d) + p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m); + q = b + m * (p - a); + } + else + { + p = c; + q = y; + } + nY = (d * p - c * q) / (a * d - b * c); + + // discretize the result to coordinate precision. it's a hack! + if (std::abs(nY) < (1.f / COORDINATE_PRECISION)) + { + nY = 0.f; + } + + // compute ratio + ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need + // not calculate the explicit values of m an n as we + // are just interested in the ratio + if (std::isnan(ratio)) + { + ratio = (segment_target == query_location ? 1.f : 0.f); + } + else if (std::abs(ratio) <= std::numeric_limits::epsilon()) + { + ratio = 0.f; + } + else if (std::abs(ratio - 1.f) <= std::numeric_limits::epsilon()) + { + ratio = 1.f; + } + + // compute nearest location + BOOST_ASSERT(!std::isnan(ratio)); + if (ratio <= 0.f) + { + nearest_location = segment_source; + } + else if (ratio >= 1.f) + { + nearest_location = segment_target; + } + else + { + // point lies in between + nearest_location.lat = static_cast(y2lat(p) * COORDINATE_PRECISION); + nearest_location.lon = static_cast(q * COORDINATE_PRECISION); + } + BOOST_ASSERT(nearest_location.is_valid()); + + const float approximate_distance = + FixedPointCoordinate::ApproximateEuclideanDistance(query_location, nearest_location); + BOOST_ASSERT(0. <= approximate_distance); + return approximate_distance; +} + +void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output) +{ + char buffer[12]; + buffer[11] = 0; // zero termination + output = printInt<11, 6>(buffer, value); +} + +void FixedPointCoordinate::convertInternalCoordinateToString(const FixedPointCoordinate &coord, + std::string &output) +{ + std::string tmp; + tmp.reserve(23); + convertInternalLatLonToString(coord.lon, tmp); + output = tmp; + output += ","; + convertInternalLatLonToString(coord.lat, tmp); + output += tmp; +} + +void +FixedPointCoordinate::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord, + std::string &output) +{ + std::string tmp; + tmp.reserve(23); + convertInternalLatLonToString(coord.lat, tmp); + output = tmp; + output += ","; + convertInternalLatLonToString(coord.lon, tmp); + output += tmp; +} + +void FixedPointCoordinate::Output(std::ostream &out) const +{ + out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")"; +} + +float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &first_coordinate, + const FixedPointCoordinate &second_coordinate) +{ + const float lon_diff = + second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION; + const float lon_delta = DegreeToRadian(lon_diff); + const float lat1 = DegreeToRadian(first_coordinate.lat / COORDINATE_PRECISION); + const float lat2 = DegreeToRadian(second_coordinate.lat / COORDINATE_PRECISION); + const float y = sin(lon_delta) * cos(lat2); + const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon_delta); + float result = RadianToDegree(std::atan2(y, x)); + while (result < 0.f) + { + result += 360.f; + } + + while (result >= 360.f) + { + result -= 360.f; + } + return result; +} + +float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const +{ + const float lon_delta = + DegreeToRadian(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION); + const float lat1 = DegreeToRadian(other.lat / COORDINATE_PRECISION); + const float lat2 = DegreeToRadian(lat / COORDINATE_PRECISION); + const float y_value = std::sin(lon_delta) * std::cos(lat2); + const float x_value = + std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta); + float result = RadianToDegree(std::atan2(y_value, x_value)); + + while (result < 0.f) + { + result += 360.f; + } + + while (result >= 360.f) + { + result -= 360.f; + } + return result; +} + +float FixedPointCoordinate::DegreeToRadian(const float degree) +{ + return degree * (static_cast(M_PI) / 180.f); +} + +float FixedPointCoordinate::RadianToDegree(const float radian) +{ + return radian * (180.f * static_cast(M_1_PI)); +} + +// This distance computation does integer arithmetic only and is a lot faster than +// the other distance function which are numerically correct('ish). +// It preserves some order among the elements that make it useful for certain purposes +int FixedPointCoordinate::OrderedPerpendicularDistanceApproximation( + const FixedPointCoordinate &input_point, + const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target) +{ + // initialize values + const float x = static_cast(lat2y(input_point.lat / COORDINATE_PRECISION)); + const float y = input_point.lon / COORDINATE_PRECISION; + const float a = static_cast(lat2y(segment_source.lat / COORDINATE_PRECISION)); + const float b = segment_source.lon / COORDINATE_PRECISION; + const float c = static_cast(lat2y(segment_target.lat / COORDINATE_PRECISION)); + const float d = segment_target.lon / COORDINATE_PRECISION; + + float p, q; + if (a == c) + { + p = c; + q = y; + } + else + { + const float m = (d - b) / (c - a); // slope + // Projection of (x,y) on line joining (a,b) and (c,d) + p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m); + q = b + m * (p - a); + } + + const float nY = (d * p - c * q) / (a * d - b * c); + float ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need + // not calculate the explicit values of m an n as we + // are just interested in the ratio + if (std::isnan(ratio)) + { + ratio = (segment_target == input_point) ? 1.f : 0.f; + } + + // compute target quasi-location + int dx, dy; + if (ratio < 0.f) + { + dx = input_point.lon - segment_source.lon; + dy = input_point.lat - segment_source.lat; + } + else if (ratio > 1.f) + { + dx = input_point.lon - segment_target.lon; + dy = input_point.lat - segment_target.lat; + } + else + { + // point lies in between + dx = input_point.lon - static_cast(q * COORDINATE_PRECISION); + dy = input_point.lat - static_cast(y2lat(p) * COORDINATE_PRECISION); + } + + // return an approximation in the plane + return static_cast(sqrt(dx * dx + dy * dy)); +} diff --git a/DataStructures/internal_route_result.hpp b/data_structures/internal_route_result.hpp similarity index 95% rename from DataStructures/internal_route_result.hpp rename to data_structures/internal_route_result.hpp index 2df529604..629e50d8a 100644 --- a/DataStructures/internal_route_result.hpp +++ b/data_structures/internal_route_result.hpp @@ -28,9 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef RAW_ROUTE_DATA_H #define RAW_ROUTE_DATA_H -#include "../DataStructures/phantom_node.hpp" -#include "../DataStructures/TravelMode.h" -#include "../DataStructures/TurnInstructions.h" +#include "../data_structures/phantom_node.hpp" +#include "../data_structures/travel_mode.hpp" +#include "../data_structures/turn_instructions.hpp" #include "../typedefs.h" #include diff --git a/data_structures/phantom_node.hpp b/data_structures/phantom_node.hpp index 620850257..3cc1f510d 100644 --- a/data_structures/phantom_node.hpp +++ b/data_structures/phantom_node.hpp @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef PHANTOM_NODES_H #define PHANTOM_NODES_H -#include "../DataStructures/TravelMode.h" +#include "travel_mode.hpp" #include "../typedefs.h" #include diff --git a/descriptors/description_factory.cpp b/descriptors/description_factory.cpp index 37ff8fb0c..e92aacd6c 100644 --- a/descriptors/description_factory.cpp +++ b/descriptors/description_factory.cpp @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../typedefs.h" #include "../algorithms/polyline_formatter.hpp" -#include "../data_structures/raw_route_data.hpp" +#include "../data_structures/internal_route_result.hpp" #include "../data_structures/turn_instructions.hpp" DescriptionFactory::DescriptionFactory() : entire_length(0) { via_indices.push_back(0); } diff --git a/descriptors/description_factory.hpp b/descriptors/description_factory.hpp index f001b9b8b..406e0530c 100644 --- a/descriptors/description_factory.hpp +++ b/descriptors/description_factory.hpp @@ -30,7 +30,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../algorithms/douglas_peucker.hpp" #include "../data_structures/phantom_node.hpp" -#include "../data_structures/json_container.hpp" #include "../data_structures/segment_information.hpp" #include "../data_structures/turn_instructions.hpp" diff --git a/descriptors/descriptor_base.hpp b/descriptors/descriptor_base.hpp index c8a24b8f4..393d84440 100644 --- a/descriptors/descriptor_base.hpp +++ b/descriptors/descriptor_base.hpp @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef DESCRIPTOR_BASE_HPP #define DESCRIPTOR_BASE_HPP +#include "../data_structures/internal_route_result.hpp" #include "../data_structures/phantom_node.hpp" -#include "../data_structures/raw_route_data.hpp" #include "../typedefs.h" #include diff --git a/descriptors/json_descriptor.hpp b/descriptors/json_descriptor.hpp index bb841d823..f67b47424 100644 --- a/descriptors/json_descriptor.hpp +++ b/descriptors/json_descriptor.hpp @@ -32,7 +32,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "description_factory.hpp" #include "../algorithms/object_encoder.hpp" #include "../algorithms/route_name_extraction.hpp" -#include "../data_structures/json_container.hpp" #include "../data_structures/segment_information.hpp" #include "../data_structures/turn_instructions.hpp" #include "../Util/bearing.hpp" @@ -355,7 +354,7 @@ template class JSONDescriptor final : public BaseDescriptor< json_instruction_row.values.push_back( cast::integral_to_string(static_cast(segment.length)) + "m"); const double bearing_value = (segment.bearing / 10.); - json_instruction_row.values.push_back(Azimuth::Get(bearing_value)); + json_instruction_row.values.push_back(Bearing::Get(bearing_value)); json_instruction_row.values.push_back( static_cast(round(bearing_value))); json_instruction_row.values.push_back(segment.travel_mode); @@ -385,7 +384,7 @@ template class JSONDescriptor final : public BaseDescriptor< json_last_instruction_row.values.push_back(necessary_segments_running_index - 1); json_last_instruction_row.values.push_back(0); json_last_instruction_row.values.push_back("0m"); - json_last_instruction_row.values.push_back(Azimuth::Get(0.0)); + json_last_instruction_row.values.push_back(Bearing::Get(0.0)); json_last_instruction_row.values.push_back(0.); json_instruction_array.values.push_back(json_last_instruction_row); } diff --git a/extractor/internal_extractor_edge.hpp b/extractor/internal_extractor_edge.hpp index 4060634c2..a852a905c 100644 --- a/extractor/internal_extractor_edge.hpp +++ b/extractor/internal_extractor_edge.hpp @@ -30,7 +30,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../typedefs.h" #include "../data_structures/travel_mode.hpp" -#include #include diff --git a/plugins/hello_world.hpp b/plugins/hello_world.hpp index 52dfa9884..d0f1e9092 100644 --- a/plugins/hello_world.hpp +++ b/plugins/hello_world.hpp @@ -30,7 +30,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "plugin_base.hpp" -#include "../data_structures/json_container.hpp" #include "../Util/cast.hpp" #include "../Util/json_renderer.hpp" diff --git a/routing_algorithms/routing_base.hpp b/routing_algorithms/routing_base.hpp index 20610ea17..a120d9717 100644 --- a/routing_algorithms/routing_base.hpp +++ b/routing_algorithms/routing_base.hpp @@ -28,10 +28,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ROUTING_BASE_HPP #define ROUTING_BASE_HPP -#include "../data_structures/raw_route_data.hpp" +#include "../data_structures/internal_route_result.hpp" #include "../data_structures/search_engine_data.hpp" #include "../data_structures/turn_instructions.hpp" -// #include "../Util/simple_logger.hpp.h" +// #include "../Util/simple_logger.hpp" #include From a11a8429bbab99face45a5ffe27163b2db16ebbb Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 18 Dec 2014 09:13:22 +0100 Subject: [PATCH 010/360] remove unneeded header file --- data_structures/InputReaderFactory.h | 123 --------------------------- 1 file changed, 123 deletions(-) delete mode 100644 data_structures/InputReaderFactory.h diff --git a/data_structures/InputReaderFactory.h b/data_structures/InputReaderFactory.h deleted file mode 100644 index 3f6aa3c63..000000000 --- a/data_structures/InputReaderFactory.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - -Copyright (c) 2013, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef INPUT_READER_FACTORY_H -#define INPUT_READER_FACTORY_H - -#include - -#include -#include - -struct BZ2Context -{ - FILE *file; - BZFILE *bz2; - int error; - int nUnused; - char unused[BZ_MAX_UNUSED]; -}; - -int readFromBz2Stream(void *pointer, char *buffer, int len) -{ - void *unusedTmpVoid = nullptr; - char *unusedTmp = nullptr; - BZ2Context *context = (BZ2Context *)pointer; - int read = 0; - while (0 == read && - !(BZ_STREAM_END == context->error && 0 == context->nUnused && feof(context->file))) - { - read = BZ2_bzRead(&context->error, context->bz2, buffer, len); - if (BZ_OK == context->error) - { - return read; - } - else if (BZ_STREAM_END == context->error) - { - BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused); - BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadGetUnused"); - unusedTmp = (char *)unusedTmpVoid; - for (int i = 0; i < context->nUnused; i++) - { - context->unused[i] = unusedTmp[i]; - } - BZ2_bzReadClose(&context->error, context->bz2); - BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadClose"); - context->error = BZ_STREAM_END; // set to the stream end for next call to this function - if (0 == context->nUnused && feof(context->file)) - { - return read; - } - else - { - context->bz2 = BZ2_bzReadOpen( - &context->error, context->file, 0, 0, context->unused, context->nUnused); - BOOST_ASSERT_MSG(nullptr != context->bz2, "Could not open file"); - } - } - else - { - BOOST_ASSERT_MSG(false, "Could not read bz2 file"); - } - } - return read; -} - -int closeBz2Stream(void *pointer) -{ - BZ2Context *context = (BZ2Context *)pointer; - fclose(context->file); - delete context; - return 0; -} - -xmlTextReaderPtr inputReaderFactory(const char *name) -{ - std::string inputName(name); - - if (inputName.find(".osm.bz2") != std::string::npos) - { - BZ2Context *context = new BZ2Context(); - context->error = false; - context->file = fopen(name, "r"); - int error; - context->bz2 = - BZ2_bzReadOpen(&error, context->file, 0, 0, context->unused, context->nUnused); - if (context->bz2 == nullptr || context->file == nullptr) - { - delete context; - return nullptr; - } - return xmlReaderForIO(readFromBz2Stream, closeBz2Stream, (void *)context, nullptr, nullptr, 0); - } - else - { - return xmlNewTextReaderFilename(name); - } -} - -#endif // INPUT_READER_FACTORY_H From 4d27366ead1fa3e8a3ece5fb2b6806e989e12b1d Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 18 Dec 2014 09:13:45 +0100 Subject: [PATCH 011/360] fix compilation of benchmark tests --- benchmarks/static_rtree.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/benchmarks/static_rtree.cpp b/benchmarks/static_rtree.cpp index cc2ae4231..83a94ae9b 100644 --- a/benchmarks/static_rtree.cpp +++ b/benchmarks/static_rtree.cpp @@ -25,12 +25,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "../DataStructures/OriginalEdgeData.h" -#include "../DataStructures/QueryNode.h" -#include "../DataStructures/SharedMemoryVectorWrapper.h" -#include "../DataStructures/StaticRTree.h" +#include "../data_structures/original_edge_data.hpp" +#include "../data_structures/query_node.hpp" +#include "../data_structures/shared_memory_vector_wrapper.hpp" +#include "../data_structures/static_rtree.hpp" #include "../Util/BoostFileSystemFix.h" -#include "../DataStructures/EdgeBasedNode.h" +#include "../data_structures/edge_based_node.hpp" #include From dea9c37d99b70721aa889631b32768bf08371707 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 18 Dec 2014 10:46:08 +0100 Subject: [PATCH 012/360] fix bad request error message --- Server/RequestHandler.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Server/RequestHandler.cpp b/Server/RequestHandler.cpp index 2c7f72a08..277298dea 100644 --- a/Server/RequestHandler.cpp +++ b/Server/RequestHandler.cpp @@ -109,8 +109,17 @@ void RequestHandler::handle_request(const http::Request &req, http::Reply &reply const std::string json_p = (route_parameters.jsonp_parameter + "("); reply.content.insert(reply.content.end(), json_p.begin(), json_p.end()); } - routing_machine->RunQuery(route_parameters, json_result); - + const auto return_code = routing_machine->RunQuery(route_parameters, json_result); + if (200 != return_code) + { + reply = http::Reply::StockReply(http::Reply::badRequest); + reply.content.clear(); + json_result.values["status"] = 400; + std::string message = "Bad Request"; + json_result.values["status_message"] = message; + JSON::render(reply.content, json_result); + return; + } // set headers reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size())); if ("gpx" == route_parameters.output_format) From be63939441fc6e939ee4663053a71e84bff9414a Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 6 Jan 2015 13:35:36 +0100 Subject: [PATCH 013/360] fix includes --- descriptors/json_descriptor.hpp | 2 +- tools/components.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/descriptors/json_descriptor.hpp b/descriptors/json_descriptor.hpp index f67b47424..8365d576d 100644 --- a/descriptors/json_descriptor.hpp +++ b/descriptors/json_descriptor.hpp @@ -38,7 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../Util/integer_range.hpp" #include "../Util/json_renderer.hpp" #include "../Util/simple_logger.hpp" -#include "../Util/StringUtil.h" +#include "../Util/string_util.hpp" #include "../Util/timing_util.hpp" #include diff --git a/tools/components.cpp b/tools/components.cpp index 607d86b60..27dda38ab 100644 --- a/tools/components.cpp +++ b/tools/components.cpp @@ -44,7 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #endif -#include +#include #include #include From e2605c2838ad937030da50f828b9ba114a8c75f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Rodrigo?= Date: Thu, 27 Nov 2014 12:09:07 +0100 Subject: [PATCH 014/360] Add a commande line option to osrm-routed for max locations supported in distance table query --- Library/OSRM.h | 2 +- Library/OSRM_impl.cpp | 8 ++++---- Library/OSRM_impl.h | 2 +- Util/ProgramOptions.h | 13 +++++++++++-- plugins/distance_table.hpp | 9 ++++++--- routed.cpp | 7 ++++--- tools/simpleclient.cpp | 5 +++-- 7 files changed, 30 insertions(+), 16 deletions(-) diff --git a/Library/OSRM.h b/Library/OSRM.h index 372e82c39..6bfa845a6 100644 --- a/Library/OSRM.h +++ b/Library/OSRM.h @@ -46,7 +46,7 @@ class OSRM std::unique_ptr OSRM_pimpl_; public: - explicit OSRM(ServerPaths paths, const bool use_shared_memory = false); + explicit OSRM(ServerPaths paths, const bool use_shared_memory = false, const int max_locations_distance_table = 100); ~OSRM(); void RunQuery(RouteParameters &route_parameters, http::Reply &reply); }; diff --git a/Library/OSRM_impl.cpp b/Library/OSRM_impl.cpp index 40fef682c..b0e7f013d 100644 --- a/Library/OSRM_impl.cpp +++ b/Library/OSRM_impl.cpp @@ -57,7 +57,7 @@ namespace boost { namespace interprocess { class named_mutex; } } #include #include -OSRM_impl::OSRM_impl(ServerPaths server_paths, const bool use_shared_memory) +OSRM_impl::OSRM_impl(ServerPaths server_paths, const bool use_shared_memory, const int max_locations_distance_table) { if (use_shared_memory) { @@ -72,7 +72,7 @@ OSRM_impl::OSRM_impl(ServerPaths server_paths, const bool use_shared_memory) } // The following plugins handle all requests. - RegisterPlugin(new DistanceTablePlugin>(query_data_facade)); + RegisterPlugin(new DistanceTablePlugin>(query_data_facade, max_locations_distance_table)); RegisterPlugin(new HelloWorldPlugin()); RegisterPlugin(new LocatePlugin>(query_data_facade)); RegisterPlugin(new NearestPlugin>(query_data_facade)); @@ -152,8 +152,8 @@ void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply) // proxy code for compilation firewall -OSRM::OSRM(ServerPaths paths, const bool use_shared_memory) - : OSRM_pimpl_(osrm::make_unique(paths, use_shared_memory)) +OSRM::OSRM(ServerPaths paths, const bool use_shared_memory, const int max_locations_distance_table) + : OSRM_pimpl_(osrm::make_unique(paths, use_shared_memory, max_locations_distance_table)) { } diff --git a/Library/OSRM_impl.h b/Library/OSRM_impl.h index e8b47df56..56dc137d9 100644 --- a/Library/OSRM_impl.h +++ b/Library/OSRM_impl.h @@ -49,7 +49,7 @@ class OSRM_impl using PluginMap = std::unordered_map; public: - OSRM_impl(ServerPaths paths, const bool use_shared_memory); + OSRM_impl(ServerPaths paths, const bool use_shared_memory, const int max_locations_distance_table); OSRM_impl(const OSRM_impl &) = delete; virtual ~OSRM_impl(); void RunQuery(RouteParameters &route_parameters, http::Reply &reply); diff --git a/Util/ProgramOptions.h b/Util/ProgramOptions.h index 3329b3108..1f9a2404b 100644 --- a/Util/ProgramOptions.h +++ b/Util/ProgramOptions.h @@ -151,7 +151,8 @@ inline unsigned GenerateServerProgramOptions(const int argc, int &ip_port, int &requested_num_threads, bool &use_shared_memory, - bool &trial) + bool &trial, + int &max_locations_distance_table) { // declare a group of options that will be allowed only on command line boost::program_options::options_description generic_options("Options"); @@ -198,7 +199,10 @@ inline unsigned GenerateServerProgramOptions(const int argc, "Number of threads to use")( "sharedmemory,s", boost::program_options::value(&use_shared_memory)->implicit_value(true), - "Load data from shared memory"); + "Load data from shared memory")( + "max_locations_distance_table", + boost::program_options::value(&max_locations_distance_table)->default_value(100), + "Max locations supported in distance table query"); // hidden options, will be allowed both on command line and in config // file, but will not be shown to the user @@ -272,6 +276,11 @@ inline unsigned GenerateServerProgramOptions(const int argc, { return INIT_OK_START_ENGINE; } + if (1 > max_locations_distance_table) + { + throw OSRMException("Max location for distance table must be a positive number"); + } + SimpleLogger().Write() << visible_options; return INIT_OK_DO_NOT_START_ENGINE; } diff --git a/plugins/distance_table.hpp b/plugins/distance_table.hpp index 6ef90a5b8..33dd7cb0b 100644 --- a/plugins/distance_table.hpp +++ b/plugins/distance_table.hpp @@ -52,9 +52,11 @@ template class DistanceTablePlugin final : public BasePlugin { private: std::unique_ptr> search_engine_ptr; + int max_locations_distance_table; public: - explicit DistanceTablePlugin(DataFacadeT *facade) : descriptor_string("table"), facade(facade) + explicit DistanceTablePlugin(DataFacadeT *facade, const int max_locations_distance_table) : + max_locations_distance_table(max_locations_distance_table), descriptor_string("table"), facade(facade) { search_engine_ptr = osrm::make_unique>(facade); } @@ -72,8 +74,9 @@ template class DistanceTablePlugin final : public BasePlugin } const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); - unsigned max_locations = - std::min(100u, static_cast(route_parameters.coordinates.size())); + unsigned max_locations = std::min(static_cast(max_locations_distance_table), + static_cast(route_parameters.coordinates.size())); + PhantomNodeArray phantom_node_vector(max_locations); for (const auto i : osrm::irange(0u, max_locations)) { diff --git a/routed.cpp b/routed.cpp index 1be6dd805..26a39ef12 100644 --- a/routed.cpp +++ b/routed.cpp @@ -71,7 +71,7 @@ int main(int argc, const char *argv[]) bool use_shared_memory = false, trial_run = false; std::string ip_address; - int ip_port, requested_thread_num; + int ip_port, requested_thread_num, max_locations_distance_table; ServerPaths server_paths; @@ -82,7 +82,8 @@ int main(int argc, const char *argv[]) ip_port, requested_thread_num, use_shared_memory, - trial_run); + trial_run, + max_locations_distance_table); if (init_result == INIT_OK_DO_NOT_START_ENGINE) { return 0; @@ -117,7 +118,7 @@ int main(int argc, const char *argv[]) pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask); #endif - OSRM osrm_lib(server_paths, use_shared_memory); + OSRM osrm_lib(server_paths, use_shared_memory, max_locations_distance_table); auto routing_server = Server::CreateServer(ip_address, ip_port, requested_thread_num); diff --git a/tools/simpleclient.cpp b/tools/simpleclient.cpp index d9c8217b9..fb26d4ba9 100644 --- a/tools/simpleclient.cpp +++ b/tools/simpleclient.cpp @@ -65,7 +65,7 @@ int main(int argc, const char *argv[]) try { std::string ip_address; - int ip_port, requested_thread_num; + int ip_port, requested_thread_num, max_locations_distance_table; bool use_shared_memory = false, trial_run = false; ServerPaths server_paths; @@ -76,7 +76,8 @@ int main(int argc, const char *argv[]) ip_port, requested_thread_num, use_shared_memory, - trial_run); + trial_run, + max_locations_distance_table); if (init_result == INIT_FAILED) { From 7075a8a8ef66f0dd8ec0f0b3f7aab701e3232354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Rodrigo?= Date: Tue, 23 Dec 2014 15:33:53 +0100 Subject: [PATCH 015/360] Fix tests for new option --max_locations_distance_table --- features/options/routed/help.feature | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/features/options/routed/help.feature b/features/options/routed/help.feature index 9603c40dd..f11787d6c 100644 --- a/features/options/routed/help.feature +++ b/features/options/routed/help.feature @@ -25,7 +25,8 @@ Feature: osrm-routed command line options: help And stdout should contain "--port" And stdout should contain "--threads" And stdout should contain "--sharedmemory" - And stdout should contain 22 lines + And stdout should contain "--max_locations_distance_table" + And stdout should contain 25 lines And it should exit with code 0 Scenario: osrm-routed - Help, short @@ -49,7 +50,8 @@ Feature: osrm-routed command line options: help And stdout should contain "--port" And stdout should contain "--threads" And stdout should contain "--sharedmemory" - And stdout should contain 22 lines + And stdout should contain "--max_locations_distance_table" + And stdout should contain 25 lines And it should exit with code 0 Scenario: osrm-routed - Help, long @@ -73,5 +75,6 @@ Feature: osrm-routed command line options: help And stdout should contain "--port" And stdout should contain "--threads" And stdout should contain "--sharedmemory" - And stdout should contain 22 lines + And stdout should contain "--max_locations_distance_table" + And stdout should contain 25 lines And it should exit with code 0 From ced64d7a0986fb45493d6ce20f9e61d8025c0750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Rodrigo?= Date: Tue, 23 Dec 2014 15:34:54 +0100 Subject: [PATCH 016/360] Move server configuration from method parameter to a struct --- Include/osrm/ServerConfig.h | 48 +++++++++++++++++++++++++++++++ Library/OSRM.h | 4 +-- Library/OSRM_impl.cpp | 17 +++++------ Library/OSRM_impl.h | 5 ++-- data_structures/server_config.hpp | 39 +++++++++++++++++++++++++ routed.cpp | 6 +++- 6 files changed, 106 insertions(+), 13 deletions(-) create mode 100644 Include/osrm/ServerConfig.h create mode 100644 data_structures/server_config.hpp diff --git a/Include/osrm/ServerConfig.h b/Include/osrm/ServerConfig.h new file mode 100644 index 000000000..4c6b52a1d --- /dev/null +++ b/Include/osrm/ServerConfig.h @@ -0,0 +1,48 @@ +/* + +Copyright (c) 2014, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef SERVER_CONFIG_H +#define SERVER_CONFIG_H + +#include + +struct ServerConfig +{ + ServerConfig(); + + void setServerPaths(const ServerPaths paths); + + void setUseSharedMemory(const bool use_shared_memory); + + void setMaxLocationsDistanceTable(const int max_locations_distance_table); + + ServerPaths server_paths; + bool use_shared_memory; + int max_locations_distance_table; +}; + +#endif // SERVER_CONFIG_H diff --git a/Library/OSRM.h b/Library/OSRM.h index 6bfa845a6..3c9c4d5e5 100644 --- a/Library/OSRM.h +++ b/Library/OSRM.h @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef OSRM_H #define OSRM_H -#include +#include #include @@ -46,7 +46,7 @@ class OSRM std::unique_ptr OSRM_pimpl_; public: - explicit OSRM(ServerPaths paths, const bool use_shared_memory = false, const int max_locations_distance_table = 100); + explicit OSRM(ServerConfig serverConfig); ~OSRM(); void RunQuery(RouteParameters &route_parameters, http::Reply &reply); }; diff --git a/Library/OSRM_impl.cpp b/Library/OSRM_impl.cpp index b0e7f013d..8604878ae 100644 --- a/Library/OSRM_impl.cpp +++ b/Library/OSRM_impl.cpp @@ -32,7 +32,7 @@ namespace boost { namespace interprocess { class named_mutex; } } #include #include -#include +#include #include "../plugins/distance_table.hpp" #include "../plugins/hello_world.hpp" @@ -57,9 +57,9 @@ namespace boost { namespace interprocess { class named_mutex; } } #include #include -OSRM_impl::OSRM_impl(ServerPaths server_paths, const bool use_shared_memory, const int max_locations_distance_table) +OSRM_impl::OSRM_impl(ServerConfig serverConfig) { - if (use_shared_memory) + if (serverConfig.use_shared_memory) { barrier = osrm::make_unique(); query_data_facade = new SharedDataFacade(); @@ -67,12 +67,13 @@ OSRM_impl::OSRM_impl(ServerPaths server_paths, const bool use_shared_memory, con else { // populate base path - populate_base_path(server_paths); - query_data_facade = new InternalDataFacade(server_paths); + populate_base_path(serverConfig.server_paths); + query_data_facade = new InternalDataFacade(serverConfig.server_paths); } // The following plugins handle all requests. - RegisterPlugin(new DistanceTablePlugin>(query_data_facade, max_locations_distance_table)); + RegisterPlugin(new DistanceTablePlugin>(query_data_facade, + serverConfig.max_locations_distance_table)); RegisterPlugin(new HelloWorldPlugin()); RegisterPlugin(new LocatePlugin>(query_data_facade)); RegisterPlugin(new NearestPlugin>(query_data_facade)); @@ -152,8 +153,8 @@ void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply) // proxy code for compilation firewall -OSRM::OSRM(ServerPaths paths, const bool use_shared_memory, const int max_locations_distance_table) - : OSRM_pimpl_(osrm::make_unique(paths, use_shared_memory, max_locations_distance_table)) +OSRM::OSRM(ServerConfig server_config) + : OSRM_pimpl_(osrm::make_unique(server_config)) { } diff --git a/Library/OSRM_impl.h b/Library/OSRM_impl.h index 56dc137d9..2b9639fb8 100644 --- a/Library/OSRM_impl.h +++ b/Library/OSRM_impl.h @@ -32,8 +32,9 @@ class BasePlugin; namespace http { class Reply; } struct RouteParameters; -#include +#include +#include "../data_structures/server_config.hpp" #include "../data_structures/query_edge.hpp" #include @@ -49,7 +50,7 @@ class OSRM_impl using PluginMap = std::unordered_map; public: - OSRM_impl(ServerPaths paths, const bool use_shared_memory, const int max_locations_distance_table); + OSRM_impl(ServerConfig serverConfig); OSRM_impl(const OSRM_impl &) = delete; virtual ~OSRM_impl(); void RunQuery(RouteParameters &route_parameters, http::Reply &reply); diff --git a/data_structures/server_config.hpp b/data_structures/server_config.hpp new file mode 100644 index 000000000..7adbd5694 --- /dev/null +++ b/data_structures/server_config.hpp @@ -0,0 +1,39 @@ +/* + +Copyright (c) 2014, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include + +ServerConfig::ServerConfig() + : use_shared_memory(false), max_locations_distance_table(100) +{ +} + +void ServerConfig::setServerPaths(const ServerPaths object) { server_paths = object; } + +void ServerConfig::setUseSharedMemory(const bool flag) { use_shared_memory = flag; } + +void ServerConfig::setMaxLocationsDistanceTable(const int max) { max_locations_distance_table = max; } diff --git a/routed.cpp b/routed.cpp index 26a39ef12..6133577fc 100644 --- a/routed.cpp +++ b/routed.cpp @@ -118,7 +118,11 @@ int main(int argc, const char *argv[]) pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask); #endif - OSRM osrm_lib(server_paths, use_shared_memory, max_locations_distance_table); + ServerConfig server_config; + server_config.setServerPaths(server_paths); + server_config.setUseSharedMemory(use_shared_memory); + server_config.setMaxLocationsDistanceTable(max_locations_distance_table); + OSRM osrm_lib(server_config); auto routing_server = Server::CreateServer(ip_address, ip_port, requested_thread_num); From 598f5519d109903861d234f94e4a2484e4aedc54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Rodrigo?= Date: Mon, 5 Jan 2015 15:48:24 +0100 Subject: [PATCH 017/360] Remove setters from structures server_config --- Include/osrm/ServerConfig.h | 15 +++++++----- Library/OSRM_impl.h | 1 - data_structures/server_config.hpp | 39 ------------------------------- routed.cpp | 5 +--- 4 files changed, 10 insertions(+), 50 deletions(-) delete mode 100644 data_structures/server_config.hpp diff --git a/Include/osrm/ServerConfig.h b/Include/osrm/ServerConfig.h index 4c6b52a1d..a3ffb11e2 100644 --- a/Include/osrm/ServerConfig.h +++ b/Include/osrm/ServerConfig.h @@ -32,13 +32,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct ServerConfig { - ServerConfig(); + ServerConfig() + : use_shared_memory(false) + , max_locations_distance_table(100) + {} - void setServerPaths(const ServerPaths paths); - - void setUseSharedMemory(const bool use_shared_memory); - - void setMaxLocationsDistanceTable(const int max_locations_distance_table); + ServerConfig(const ServerPaths paths, const bool flag, const int max) + : server_paths(paths) + , use_shared_memory(flag) + , max_locations_distance_table(max) + {} ServerPaths server_paths; bool use_shared_memory; diff --git a/Library/OSRM_impl.h b/Library/OSRM_impl.h index 2b9639fb8..bf28c8bf9 100644 --- a/Library/OSRM_impl.h +++ b/Library/OSRM_impl.h @@ -34,7 +34,6 @@ struct RouteParameters; #include -#include "../data_structures/server_config.hpp" #include "../data_structures/query_edge.hpp" #include diff --git a/data_structures/server_config.hpp b/data_structures/server_config.hpp deleted file mode 100644 index 7adbd5694..000000000 --- a/data_structures/server_config.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - -Copyright (c) 2014, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include - -ServerConfig::ServerConfig() - : use_shared_memory(false), max_locations_distance_table(100) -{ -} - -void ServerConfig::setServerPaths(const ServerPaths object) { server_paths = object; } - -void ServerConfig::setUseSharedMemory(const bool flag) { use_shared_memory = flag; } - -void ServerConfig::setMaxLocationsDistanceTable(const int max) { max_locations_distance_table = max; } diff --git a/routed.cpp b/routed.cpp index 6133577fc..8224c2e7b 100644 --- a/routed.cpp +++ b/routed.cpp @@ -118,10 +118,7 @@ int main(int argc, const char *argv[]) pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask); #endif - ServerConfig server_config; - server_config.setServerPaths(server_paths); - server_config.setUseSharedMemory(use_shared_memory); - server_config.setMaxLocationsDistanceTable(max_locations_distance_table); + ServerConfig server_config(server_paths, use_shared_memory, max_locations_distance_table); OSRM osrm_lib(server_config); auto routing_server = Server::CreateServer(ip_address, ip_port, requested_thread_num); From b53e8bf5012f7f9be4f65323492c38840a85629c Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 6 Jan 2015 15:29:51 +0100 Subject: [PATCH 018/360] remove implicit conversion --- UnitTests/data_structures/StaticRTreeTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UnitTests/data_structures/StaticRTreeTest.cpp b/UnitTests/data_structures/StaticRTreeTest.cpp index 25e4cea51..905e58a55 100644 --- a/UnitTests/data_structures/StaticRTreeTest.cpp +++ b/UnitTests/data_structures/StaticRTreeTest.cpp @@ -334,7 +334,7 @@ void build_rtree(const std::string &prefix, const std::string coords_path = prefix + ".nodes"; boost::filesystem::ofstream node_stream(coords_path, std::ios::binary); - const unsigned num_nodes = fixture->nodes.size(); + const auto num_nodes = static_cast(fixture->nodes.size()); node_stream.write((char *)&num_nodes, sizeof(unsigned)); node_stream.write((char *)&(fixture->nodes[0]), num_nodes * sizeof(QueryNode)); node_stream.close(); From 12f2acc9ff917d60af23fe1786c0bce8c402a305 Mon Sep 17 00:00:00 2001 From: Frederic Rodrigo Date: Tue, 6 Jan 2015 15:33:57 +0000 Subject: [PATCH 019/360] Order ServerPaths members by memory size, pass ServerPaths by ref --- Include/osrm/ServerConfig.h | 12 ++++++------ Library/OSRM_impl.cpp | 2 +- Library/OSRM_impl.h | 2 +- Util/ProgramOptions.h | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Include/osrm/ServerConfig.h b/Include/osrm/ServerConfig.h index a3ffb11e2..3c48f3c56 100644 --- a/Include/osrm/ServerConfig.h +++ b/Include/osrm/ServerConfig.h @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -33,19 +33,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct ServerConfig { ServerConfig() - : use_shared_memory(false) - , max_locations_distance_table(100) + : max_locations_distance_table(100) + , use_shared_memory(false) {} - ServerConfig(const ServerPaths paths, const bool flag, const int max) + ServerConfig(const ServerPaths &paths, const bool flag, const int max) : server_paths(paths) - , use_shared_memory(flag) , max_locations_distance_table(max) + , use_shared_memory(flag) {} ServerPaths server_paths; - bool use_shared_memory; int max_locations_distance_table; + bool use_shared_memory; }; #endif // SERVER_CONFIG_H diff --git a/Library/OSRM_impl.cpp b/Library/OSRM_impl.cpp index 8604878ae..6b3a2e11f 100644 --- a/Library/OSRM_impl.cpp +++ b/Library/OSRM_impl.cpp @@ -57,7 +57,7 @@ namespace boost { namespace interprocess { class named_mutex; } } #include #include -OSRM_impl::OSRM_impl(ServerConfig serverConfig) +OSRM_impl::OSRM_impl(ServerConfig &serverConfig) { if (serverConfig.use_shared_memory) { diff --git a/Library/OSRM_impl.h b/Library/OSRM_impl.h index bf28c8bf9..94aa123a9 100644 --- a/Library/OSRM_impl.h +++ b/Library/OSRM_impl.h @@ -49,7 +49,7 @@ class OSRM_impl using PluginMap = std::unordered_map; public: - OSRM_impl(ServerConfig serverConfig); + OSRM_impl(ServerConfig &serverConfig); OSRM_impl(const OSRM_impl &) = delete; virtual ~OSRM_impl(); void RunQuery(RouteParameters &route_parameters, http::Reply &reply); diff --git a/Util/ProgramOptions.h b/Util/ProgramOptions.h index 1f9a2404b..ae50cd97f 100644 --- a/Util/ProgramOptions.h +++ b/Util/ProgramOptions.h @@ -278,7 +278,7 @@ inline unsigned GenerateServerProgramOptions(const int argc, } if (1 > max_locations_distance_table) { - throw OSRMException("Max location for distance table must be a positive number"); + throw osrm::exception("Max location for distance table must be a positive number"); } SimpleLogger().Write() << visible_options; From 66fc6768586bd4f02942c9afb06e08cb4ee8067f Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 6 Jan 2015 20:05:33 +0100 Subject: [PATCH 020/360] remove unused parameter, move previously templated function into compile unit --- descriptors/description_factory.cpp | 132 +++++++++++++++++++++++++++- descriptors/description_factory.hpp | 128 +-------------------------- descriptors/json_descriptor.hpp | 6 +- 3 files changed, 134 insertions(+), 132 deletions(-) diff --git a/descriptors/description_factory.cpp b/descriptors/description_factory.cpp index e92aacd6c..87af445e5 100644 --- a/descriptors/description_factory.cpp +++ b/descriptors/description_factory.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -27,10 +27,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "description_factory.hpp" -#include "../typedefs.h" #include "../algorithms/polyline_formatter.hpp" #include "../data_structures/internal_route_result.hpp" #include "../data_structures/turn_instructions.hpp" +#include "../typedefs.h" DescriptionFactory::DescriptionFactory() : entire_length(0) { via_indices.push_back(0); } @@ -120,3 +120,131 @@ void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned summary.target_name_id = target_phantom.name_id; summary.BuildDurationAndLengthStrings(distance, time); } + +void DescriptionFactory::Run(const unsigned zoom_level) +{ + if (path_description.empty()) + { + return; + } + + /** starts at index 1 */ + path_description[0].length = 0; + for (unsigned i = 1; i < path_description.size(); ++i) + { + // move down names by one, q&d hack + path_description[i - 1].name_id = path_description[i].name_id; + path_description[i].length = FixedPointCoordinate::ApproximateEuclideanDistance( + path_description[i - 1].location, path_description[i].location); + } + + /*Simplify turn instructions + Input : + 10. Turn left on B 36 for 20 km + 11. Continue on B 35; B 36 for 2 km + 12. Continue on B 36 for 13 km + + becomes: + 10. Turn left on B 36 for 35 km + */ + // TODO: rework to check only end and start of string. + // stl string is way to expensive + + // unsigned lastTurn = 0; + // for(unsigned i = 1; i < path_description.size(); ++i) { + // string1 = sEngine.GetEscapedNameForNameID(path_description[i].name_id); + // if(TurnInstruction::GoStraight == path_description[i].turn_instruction) { + // if(std::string::npos != string0.find(string1+";") + // || std::string::npos != string0.find(";"+string1) + // || std::string::npos != string0.find(string1+" ;") + // || std::string::npos != string0.find("; "+string1) + // ){ + // SimpleLogger().Write() << "->next correct: " << string0 << " contains " << + // string1; + // for(; lastTurn != i; ++lastTurn) + // path_description[lastTurn].name_id = path_description[i].name_id; + // path_description[i].turn_instruction = TurnInstruction::NoTurn; + // } else if(std::string::npos != string1.find(string0+";") + // || std::string::npos != string1.find(";"+string0) + // || std::string::npos != string1.find(string0+" ;") + // || std::string::npos != string1.find("; "+string0) + // ){ + // SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << + // string0; + // path_description[i].name_id = path_description[i-1].name_id; + // path_description[i].turn_instruction = TurnInstruction::NoTurn; + // } + // } + // if (TurnInstruction::NoTurn != path_description[i].turn_instruction) { + // lastTurn = i; + // } + // string0 = string1; + // } + + float segment_length = 0.; + unsigned segment_duration = 0; + unsigned segment_start_index = 0; + + for (unsigned i = 1; i < path_description.size(); ++i) + { + entire_length += path_description[i].length; + segment_length += path_description[i].length; + segment_duration += path_description[i].duration; + path_description[segment_start_index].length = segment_length; + path_description[segment_start_index].duration = segment_duration; + + if (TurnInstruction::NoTurn != path_description[i].turn_instruction) + { + BOOST_ASSERT(path_description[i].necessary); + segment_length = 0; + segment_duration = 0; + segment_start_index = i; + } + } + + // Post-processing to remove empty or nearly empty path segments + if (std::numeric_limits::epsilon() > path_description.back().length) + { + if (path_description.size() > 2) + { + path_description.pop_back(); + path_description.back().necessary = true; + path_description.back().turn_instruction = TurnInstruction::NoTurn; + target_phantom.name_id = (path_description.end() - 2)->name_id; + } + } + if (std::numeric_limits::epsilon() > path_description.front().length) + { + if (path_description.size() > 2) + { + path_description.erase(path_description.begin()); + path_description.front().turn_instruction = TurnInstruction::HeadOn; + path_description.front().necessary = true; + start_phantom.name_id = path_description.front().name_id; + } + } + + // Generalize poly line + polyline_generalizer.Run(path_description.begin(), path_description.end(), zoom_level); + + // fix what needs to be fixed else + unsigned necessary_pieces = 0; // a running index that counts the necessary pieces + for (unsigned i = 0; i < path_description.size() - 1 && path_description.size() >= 2; ++i) + { + if (path_description[i].necessary) + { + ++necessary_pieces; + if (path_description[i].is_via_location) + { // mark the end of a leg + via_indices.push_back(necessary_pieces); + } + const double angle = + path_description[i + 1].location.GetBearing(path_description[i].location); + path_description[i].bearing = static_cast(angle * 10); + } + } + via_indices.push_back(necessary_pieces + 1); + BOOST_ASSERT(via_indices.size() >= 2); + // BOOST_ASSERT(0 != necessary_pieces || path_description.empty()); + return; +} diff --git a/descriptors/description_factory.hpp b/descriptors/description_factory.hpp index 406e0530c..cb24b13c8 100644 --- a/descriptors/description_factory.hpp +++ b/descriptors/description_factory.hpp @@ -93,133 +93,7 @@ class DescriptionFactory return entire_length; } - template void Run(const DataFacadeT *facade, const unsigned zoomLevel) - { - if (path_description.empty()) - { - return; - } - - /** starts at index 1 */ - path_description[0].length = 0; - for (unsigned i = 1; i < path_description.size(); ++i) - { - // move down names by one, q&d hack - path_description[i - 1].name_id = path_description[i].name_id; - path_description[i].length = FixedPointCoordinate::ApproximateEuclideanDistance( - path_description[i - 1].location, path_description[i].location); - } - - /*Simplify turn instructions - Input : - 10. Turn left on B 36 for 20 km - 11. Continue on B 35; B 36 for 2 km - 12. Continue on B 36 for 13 km - - becomes: - 10. Turn left on B 36 for 35 km - */ - // TODO: rework to check only end and start of string. - // stl string is way to expensive - - // unsigned lastTurn = 0; - // for(unsigned i = 1; i < path_description.size(); ++i) { - // string1 = sEngine.GetEscapedNameForNameID(path_description[i].name_id); - // if(TurnInstruction::GoStraight == path_description[i].turn_instruction) { - // if(std::string::npos != string0.find(string1+";") - // || std::string::npos != string0.find(";"+string1) - // || std::string::npos != string0.find(string1+" ;") - // || std::string::npos != string0.find("; "+string1) - // ){ - // SimpleLogger().Write() << "->next correct: " << string0 << " contains " << - // string1; - // for(; lastTurn != i; ++lastTurn) - // path_description[lastTurn].name_id = path_description[i].name_id; - // path_description[i].turn_instruction = TurnInstruction::NoTurn; - // } else if(std::string::npos != string1.find(string0+";") - // || std::string::npos != string1.find(";"+string0) - // || std::string::npos != string1.find(string0+" ;") - // || std::string::npos != string1.find("; "+string0) - // ){ - // SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << - // string0; - // path_description[i].name_id = path_description[i-1].name_id; - // path_description[i].turn_instruction = TurnInstruction::NoTurn; - // } - // } - // if (TurnInstruction::NoTurn != path_description[i].turn_instruction) { - // lastTurn = i; - // } - // string0 = string1; - // } - - float segment_length = 0.; - unsigned segment_duration = 0; - unsigned segment_start_index = 0; - - for (unsigned i = 1; i < path_description.size(); ++i) - { - entire_length += path_description[i].length; - segment_length += path_description[i].length; - segment_duration += path_description[i].duration; - path_description[segment_start_index].length = segment_length; - path_description[segment_start_index].duration = segment_duration; - - if (TurnInstruction::NoTurn != path_description[i].turn_instruction) - { - BOOST_ASSERT(path_description[i].necessary); - segment_length = 0; - segment_duration = 0; - segment_start_index = i; - } - } - - // Post-processing to remove empty or nearly empty path segments - if (std::numeric_limits::epsilon() > path_description.back().length) - { - if (path_description.size() > 2) - { - path_description.pop_back(); - path_description.back().necessary = true; - path_description.back().turn_instruction = TurnInstruction::NoTurn; - target_phantom.name_id = (path_description.end() - 2)->name_id; - } - } - if (std::numeric_limits::epsilon() > path_description.front().length) - { - if (path_description.size() > 2) - { - path_description.erase(path_description.begin()); - path_description.front().turn_instruction = TurnInstruction::HeadOn; - path_description.front().necessary = true; - start_phantom.name_id = path_description.front().name_id; - } - } - - // Generalize poly line - polyline_generalizer.Run(path_description.begin(), path_description.end(), zoomLevel); - - // fix what needs to be fixed else - unsigned necessary_pieces = 0; // a running index that counts the necessary pieces - for (unsigned i = 0; i < path_description.size() - 1 && path_description.size() >= 2; ++i) - { - if (path_description[i].necessary) - { - ++necessary_pieces; - if (path_description[i].is_via_location) - { // mark the end of a leg - via_indices.push_back(necessary_pieces); - } - const double angle = - path_description[i + 1].location.GetBearing(path_description[i].location); - path_description[i].bearing = static_cast(angle * 10); - } - } - via_indices.push_back(necessary_pieces + 1); - BOOST_ASSERT(via_indices.size() >= 2); - // BOOST_ASSERT(0 != necessary_pieces || path_description.empty()); - return; - } + void Run(const unsigned zoom_level); }; #endif /* DESCRIPTION_FACTORY_HPP */ diff --git a/descriptors/json_descriptor.hpp b/descriptors/json_descriptor.hpp index 8365d576d..74850d8f5 100644 --- a/descriptors/json_descriptor.hpp +++ b/descriptors/json_descriptor.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -134,7 +134,7 @@ template class JSONDescriptor final : public BaseDescriptor< raw_route.is_via_leg(i)); BOOST_ASSERT(0 < added_segments); } - description_factory.Run(facade, config.zoom_level); + description_factory.Run(config.zoom_level); if (config.geometry) { @@ -210,7 +210,7 @@ template class JSONDescriptor final : public BaseDescriptor< alternate_description_factory.SetEndSegment( raw_route.segment_end_coordinates.back().target_phantom, raw_route.alt_source_traversed_in_reverse.back()); - alternate_description_factory.Run(facade, config.zoom_level); + alternate_description_factory.Run(config.zoom_level); if (config.geometry) { From 0ccdd4b6ad83ca611a36b898156ef88c33e6a9d1 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 7 Jan 2015 12:26:09 +0100 Subject: [PATCH 021/360] fix implicit conversion that _may_ lose integer precision --- algorithms/tiny_components.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algorithms/tiny_components.hpp b/algorithms/tiny_components.hpp index 9fb357c10..04f380a1b 100644 --- a/algorithms/tiny_components.hpp +++ b/algorithms/tiny_components.hpp @@ -80,7 +80,7 @@ class TarjanSCC std::shared_ptr m_node_based_graph; std::unordered_set barrier_node_set; RestrictionMap m_restriction_map; - unsigned size_one_counter; + std::size_t size_one_counter; public: template From d896a9efeccfb26f338d327fc00de57d989f856c Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 7 Jan 2015 12:26:49 +0100 Subject: [PATCH 022/360] remove superflous inline keywords as this DeallocatingVector is header-defined, also remove ignored const keywords --- data_structures/deallocating_vector.hpp | 45 +++++++++++-------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/data_structures/deallocating_vector.hpp b/data_structures/deallocating_vector.hpp index 415fa69d3..facf56ec8 100644 --- a/data_structures/deallocating_vector.hpp +++ b/data_structures/deallocating_vector.hpp @@ -50,7 +50,7 @@ template struct DeallocatingVectorIteratorState std::size_t index; std::vector *bucket_list; - inline DeallocatingVectorIteratorState &operator=(const DeallocatingVectorIteratorState &other) + DeallocatingVectorIteratorState &operator=(const DeallocatingVectorIteratorState &other) { index = other.index; bucket_list = other.bucket_list; @@ -175,13 +175,13 @@ class DeallocatingVector ~DeallocatingVector() { clear(); } - inline void swap(DeallocatingVector &other) + void swap(DeallocatingVector &other) { std::swap(current_size, other.current_size); bucket_list.swap(other.bucket_list); } - inline void clear() + void clear() { // Delete[]'ing ptr's to all Buckets for (auto bucket : bucket_list) @@ -196,7 +196,7 @@ class DeallocatingVector current_size = 0; } - inline void push_back(const ElementT &element) + void push_back(const ElementT &element) { const std::size_t current_capacity = capacity(); if (current_size == current_capacity) @@ -209,7 +209,7 @@ class DeallocatingVector ++current_size; } - template inline void emplace_back(Ts &&... element) + template void emplace_back(Ts &&... element) { const std::size_t current_capacity = capacity(); if (current_size == current_capacity) @@ -222,9 +222,9 @@ class DeallocatingVector ++current_size; } - inline void reserve(const std::size_t) const { /* don't do anything */ } + void reserve(const std::size_t) const { /* don't do anything */ } - inline void resize(const std::size_t new_size) + void resize(const std::size_t new_size) { if (new_size >= current_size) { @@ -248,50 +248,43 @@ class DeallocatingVector current_size = new_size; } - inline std::size_t size() const { return current_size; } + std::size_t size() const { return current_size; } - inline std::size_t capacity() const { return bucket_list.size() * ELEMENTS_PER_BLOCK; } + std::size_t capacity() const { return bucket_list.size() * ELEMENTS_PER_BLOCK; } - inline iterator begin() { return iterator(static_cast(0), &bucket_list); } + iterator begin() { return iterator(static_cast(0), &bucket_list); } - inline iterator end() { return iterator(size(), &bucket_list); } + iterator end() { return iterator(size(), &bucket_list); } - inline deallocation_iterator dbegin() + deallocation_iterator dbegin() { return deallocation_iterator(static_cast(0), &bucket_list); } - inline deallocation_iterator dend() { return deallocation_iterator(size(), &bucket_list); } + deallocation_iterator dend() { return deallocation_iterator(size(), &bucket_list); } - inline const_iterator begin() const + const_iterator begin() const { return const_iterator(static_cast(0), &bucket_list); } - inline const_iterator end() const { return const_iterator(size(), &bucket_list); } + const_iterator end() const { return const_iterator(size(), &bucket_list); } - inline ElementT &operator[](const std::size_t index) + ElementT &operator[](const std::size_t index) { const std::size_t _bucket = index / ELEMENTS_PER_BLOCK; const std::size_t _index = index % ELEMENTS_PER_BLOCK; return (bucket_list[_bucket][_index]); } - const inline ElementT &operator[](const std::size_t index) const + ElementT &operator[](const std::size_t index) const { const std::size_t _bucket = index / ELEMENTS_PER_BLOCK; const std::size_t _index = index % ELEMENTS_PER_BLOCK; return (bucket_list[_bucket][_index]); } - inline ElementT &back() - { - const std::size_t _bucket = current_size / ELEMENTS_PER_BLOCK; - const std::size_t _index = current_size % ELEMENTS_PER_BLOCK; - return (bucket_list[_bucket][_index]); - } - - const inline ElementT &back() const + ElementT &back() const { const std::size_t _bucket = current_size / ELEMENTS_PER_BLOCK; const std::size_t _index = current_size % ELEMENTS_PER_BLOCK; @@ -299,7 +292,7 @@ class DeallocatingVector } template - const inline void append(InputIterator first, const InputIterator last) + void append(InputIterator first, const InputIterator last) { InputIterator position = first; while (position != last) From 10672786a1183849627d3b07f5454001bb327455 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 7 Jan 2015 12:28:26 +0100 Subject: [PATCH 023/360] fix copyright year and include guard --- data_structures/deallocating_vector.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data_structures/deallocating_vector.hpp b/data_structures/deallocating_vector.hpp index facf56ec8..e2f82cfb0 100644 --- a/data_structures/deallocating_vector.hpp +++ b/data_structures/deallocating_vector.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DEALLOCATINGVECTOR_H_ -#define DEALLOCATINGVECTOR_H_ +#ifndef DEALLOCATING_VECTOR_HPP +#define DEALLOCATING_VECTOR_HPP #include "../Util/integer_range.hpp" @@ -303,4 +303,4 @@ class DeallocatingVector } }; -#endif /* DEALLOCATINGVECTOR_H_ */ +#endif /* DEALLOCATING_VECTOR_HPP */ From 88c1e622dd17d684c3b43922f4d4758d7ecd65c7 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 7 Jan 2015 12:29:13 +0100 Subject: [PATCH 024/360] fix copyright year --- descriptors/description_factory.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/descriptors/description_factory.hpp b/descriptors/description_factory.hpp index cb24b13c8..18a9f169b 100644 --- a/descriptors/description_factory.hpp +++ b/descriptors/description_factory.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, From 1328be2b614f48d288e8c01b5c5bf33b857c3ad5 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 7 Jan 2015 12:30:01 +0100 Subject: [PATCH 025/360] move structs into anon namespace, move containers in function scope --- tools/components.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/components.cpp b/tools/components.cpp index 27dda38ab..f6ad3dd12 100644 --- a/tools/components.cpp +++ b/tools/components.cpp @@ -51,10 +51,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -std::vector coordinate_list; -std::vector restriction_list; -std::vector bollard_node_list; -std::vector traffic_lights_list; +namespace { struct TarjanEdgeData { @@ -74,9 +71,15 @@ void DeleteFileIfExists(const std::string &file_name) boost::filesystem::remove(file_name); } } +} int main(int argc, char *argv[]) { + std::vector coordinate_list; + std::vector restriction_list; + std::vector bollard_node_list; + std::vector traffic_lights_list; + LogPolicy::GetInstance().Unmute(); try { From c6bb7c5993fcd3c525f29b1d8b0689c2e5997212 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 8 Jan 2015 15:05:54 +0100 Subject: [PATCH 026/360] renamed: Include/osrm/ServerConfig.h -> Include/osrm/libosrm_config.hpp pass lib config object by reference --- .../osrm/{ServerConfig.h => libosrm_config.hpp} | 7 ++++--- Library/OSRM.h | 4 ++-- Library/OSRM_impl.cpp | 14 +++++++------- Library/OSRM_impl.h | 4 ++-- routed.cpp | 17 ++++++++--------- tools/simpleclient.cpp | 12 ++++++------ 6 files changed, 29 insertions(+), 29 deletions(-) rename Include/osrm/{ServerConfig.h => libosrm_config.hpp} (90%) diff --git a/Include/osrm/ServerConfig.h b/Include/osrm/libosrm_config.hpp similarity index 90% rename from Include/osrm/ServerConfig.h rename to Include/osrm/libosrm_config.hpp index bcd561d69..078c28f8f 100644 --- a/Include/osrm/ServerConfig.h +++ b/Include/osrm/libosrm_config.hpp @@ -30,14 +30,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -struct ServerConfig +struct libosrm_config { - ServerConfig() + libosrm_config(const libosrm_config&) = delete; + libosrm_config() : max_locations_distance_table(100) , use_shared_memory(false) {} - ServerConfig(const ServerPaths &paths, const bool flag, const int max) + libosrm_config(const ServerPaths &paths, const bool flag, const int max) : server_paths(paths) , max_locations_distance_table(max) , use_shared_memory(flag) diff --git a/Library/OSRM.h b/Library/OSRM.h index 1f35ec272..d51f8dcee 100644 --- a/Library/OSRM.h +++ b/Library/OSRM.h @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef OSRM_H #define OSRM_H -#include +#include #include @@ -46,7 +46,7 @@ class OSRM std::unique_ptr OSRM_pimpl_; public: - explicit OSRM(ServerConfig serverConfig); + explicit OSRM(libosrm_config &lib_config); ~OSRM(); int RunQuery(RouteParameters &route_parameters, JSON::Object &json_result); }; diff --git a/Library/OSRM_impl.cpp b/Library/OSRM_impl.cpp index a557aa66a..38f5fd1d9 100644 --- a/Library/OSRM_impl.cpp +++ b/Library/OSRM_impl.cpp @@ -55,9 +55,9 @@ namespace boost { namespace interprocess { class named_mutex; } } #include #include -OSRM_impl::OSRM_impl(ServerConfig &serverConfig) +OSRM_impl::OSRM_impl(libosrm_config &lib_config) { - if (serverConfig.use_shared_memory) + if (lib_config.use_shared_memory) { barrier = osrm::make_unique(); query_data_facade = new SharedDataFacade(); @@ -65,13 +65,13 @@ OSRM_impl::OSRM_impl(ServerConfig &serverConfig) else { // populate base path - populate_base_path(serverConfig.server_paths); - query_data_facade = new InternalDataFacade(serverConfig.server_paths); + populate_base_path(lib_config.server_paths); + query_data_facade = new InternalDataFacade(lib_config.server_paths); } // The following plugins handle all requests. RegisterPlugin(new DistanceTablePlugin>(query_data_facade, - serverConfig.max_locations_distance_table)); + lib_config.max_locations_distance_table)); RegisterPlugin(new HelloWorldPlugin()); RegisterPlugin(new LocatePlugin>(query_data_facade)); RegisterPlugin(new NearestPlugin>(query_data_facade)); @@ -151,8 +151,8 @@ int OSRM_impl::RunQuery(RouteParameters &route_parameters, JSON::Object &json_re // proxy code for compilation firewall -OSRM::OSRM(ServerConfig server_config) - : OSRM_pimpl_(osrm::make_unique(server_config)) +OSRM::OSRM(libosrm_config &lib_config) + : OSRM_pimpl_(osrm::make_unique(lib_config)) { } diff --git a/Library/OSRM_impl.h b/Library/OSRM_impl.h index 519686277..176ede688 100644 --- a/Library/OSRM_impl.h +++ b/Library/OSRM_impl.h @@ -35,7 +35,7 @@ struct RouteParameters; #include "../data_structures/query_edge.hpp" #include -#include +#include #include #include @@ -50,7 +50,7 @@ class OSRM_impl using PluginMap = std::unordered_map; public: - OSRM_impl(ServerConfig &serverConfig); + OSRM_impl(libosrm_config &lib_config); OSRM_impl(const OSRM_impl &) = delete; virtual ~OSRM_impl(); int RunQuery(RouteParameters &route_parameters, JSON::Object &json_result); diff --git a/routed.cpp b/routed.cpp index 8224c2e7b..a0caac1f4 100644 --- a/routed.cpp +++ b/routed.cpp @@ -69,21 +69,21 @@ int main(int argc, const char *argv[]) { LogPolicy::GetInstance().Unmute(); - bool use_shared_memory = false, trial_run = false; + bool trial_run = false; std::string ip_address; - int ip_port, requested_thread_num, max_locations_distance_table; + int ip_port, requested_thread_num; - ServerPaths server_paths; + libosrm_config lib_config; const unsigned init_result = GenerateServerProgramOptions(argc, argv, - server_paths, + lib_config.server_paths, ip_address, ip_port, requested_thread_num, - use_shared_memory, + lib_config.use_shared_memory, trial_run, - max_locations_distance_table); + lib_config.max_locations_distance_table); if (init_result == INIT_OK_DO_NOT_START_ENGINE) { return 0; @@ -102,7 +102,7 @@ int main(int argc, const char *argv[]) #endif SimpleLogger().Write() << "starting up engines, " << g_GIT_DESCRIPTION; - if (use_shared_memory) + if (lib_config.use_shared_memory) { SimpleLogger().Write(logDEBUG) << "Loading from shared memory"; } @@ -118,8 +118,7 @@ int main(int argc, const char *argv[]) pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask); #endif - ServerConfig server_config(server_paths, use_shared_memory, max_locations_distance_table); - OSRM osrm_lib(server_config); + OSRM osrm_lib(lib_config); auto routing_server = Server::CreateServer(ip_address, ip_port, requested_thread_num); diff --git a/tools/simpleclient.cpp b/tools/simpleclient.cpp index 0a736d8b7..0bb47599b 100644 --- a/tools/simpleclient.cpp +++ b/tools/simpleclient.cpp @@ -32,8 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../Util/simple_logger.hpp" #include +#include #include -#include #include @@ -45,16 +45,16 @@ int main(int argc, const char *argv[]) std::string ip_address; int ip_port, requested_thread_num; bool trial_run = false; - ServerConfig server_config; + libosrm_config lib_config; const unsigned init_result = GenerateServerProgramOptions(argc, argv, - server_config.server_paths, + lib_config.server_paths, ip_address, ip_port, requested_thread_num, - server_config.use_shared_memory, + lib_config.use_shared_memory, trial_run, - server_config.max_locations_distance_table); + lib_config.max_locations_distance_table); if (init_result == INIT_OK_DO_NOT_START_ENGINE) { @@ -66,7 +66,7 @@ int main(int argc, const char *argv[]) } SimpleLogger().Write() << "starting up engines, " << g_GIT_DESCRIPTION; - OSRM routing_machine(server_config); + OSRM routing_machine(lib_config); RouteParameters route_parameters; route_parameters.zoom_level = 18; // no generalization From 91a89399f8d28b2687c4f4d2372f6393087e058c Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 8 Jan 2015 15:07:01 +0100 Subject: [PATCH 027/360] fix copyright year --- Library/OSRM.h | 2 +- Library/OSRM_impl.cpp | 2 +- Library/OSRM_impl.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Library/OSRM.h b/Library/OSRM.h index d51f8dcee..1f0acebfa 100644 --- a/Library/OSRM.h +++ b/Library/OSRM.h @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/Library/OSRM_impl.cpp b/Library/OSRM_impl.cpp index 38f5fd1d9..6b67a675d 100644 --- a/Library/OSRM_impl.cpp +++ b/Library/OSRM_impl.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/Library/OSRM_impl.h b/Library/OSRM_impl.h index 176ede688..625fc19ca 100644 --- a/Library/OSRM_impl.h +++ b/Library/OSRM_impl.h @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, From b1a12768e10df76e4d12b84da041dc561c45c85c Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 8 Jan 2015 17:27:36 +0100 Subject: [PATCH 028/360] fix parameter name for maximum number of location in distance table plugin --- Util/ProgramOptions.h | 6 +++--- features/options/routed/help.feature | 18 +++++++++--------- features/support/launch.rb | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Util/ProgramOptions.h b/Util/ProgramOptions.h index b766c5519..3e2471189 100644 --- a/Util/ProgramOptions.h +++ b/Util/ProgramOptions.h @@ -197,12 +197,12 @@ inline unsigned GenerateServerProgramOptions(const int argc, "threads,t", boost::program_options::value(&requested_num_threads)->default_value(8), "Number of threads to use")( - "sharedmemory,s", + "shared-memory,s", boost::program_options::value(&use_shared_memory)->implicit_value(true), "Load data from shared memory")( - "max_locations_distance_table", + "max-table-size,m", boost::program_options::value(&max_locations_distance_table)->default_value(100), - "Max locations supported in distance table query"); + "Max. locations supported in distance table query"); // hidden options, will be allowed both on command line and in config // file, but will not be shown to the user diff --git a/features/options/routed/help.feature b/features/options/routed/help.feature index f11787d6c..4b89dcb24 100644 --- a/features/options/routed/help.feature +++ b/features/options/routed/help.feature @@ -24,9 +24,9 @@ Feature: osrm-routed command line options: help And stdout should contain "--ip" And stdout should contain "--port" And stdout should contain "--threads" - And stdout should contain "--sharedmemory" - And stdout should contain "--max_locations_distance_table" - And stdout should contain 25 lines + And stdout should contain "--shared-memory" + And stdout should contain "--max-table-size" + And stdout should contain 24 lines And it should exit with code 0 Scenario: osrm-routed - Help, short @@ -49,9 +49,9 @@ Feature: osrm-routed command line options: help And stdout should contain "--ip" And stdout should contain "--port" And stdout should contain "--threads" - And stdout should contain "--sharedmemory" - And stdout should contain "--max_locations_distance_table" - And stdout should contain 25 lines + And stdout should contain "--shared-memory" + And stdout should contain "--max-table-size" + And stdout should contain 24 lines And it should exit with code 0 Scenario: osrm-routed - Help, long @@ -74,7 +74,7 @@ Feature: osrm-routed command line options: help And stdout should contain "--ip" And stdout should contain "--port" And stdout should contain "--threads" - And stdout should contain "--sharedmemory" - And stdout should contain "--max_locations_distance_table" - And stdout should contain 25 lines + And stdout should contain "--shared-memory" + And stdout should contain "--max-table-size" + And stdout should contain 24 lines And it should exit with code 0 diff --git a/features/support/launch.rb b/features/support/launch.rb index 0f983c151..d8d23aeaa 100644 --- a/features/support/launch.rb +++ b/features/support/launch.rb @@ -4,7 +4,7 @@ require 'json' # Only one isntance of osrm-routed is ever launched, to avoid collisions. # The default is to keep osrm-routed running and load data with datastore. -# however, osrm-routed it shut down and relaunched for each scenario thats +# however, osrm-routed it shut down and relaunched for each scenario thats # loads data directly. class OSRMLoader @@ -118,7 +118,7 @@ class OSRMLoader def osrm_up return if osrm_up? - @@pid = Process.spawn("#{BIN_PATH}/osrm-routed --sharedmemory=1 --port #{OSRM_PORT}",:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE) + @@pid = Process.spawn("#{BIN_PATH}/osrm-routed --shared-memory=1 --port #{OSRM_PORT}",:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE) Process.detach(@@pid) # avoid zombie processes end end From 26f7ac9ca133c5d1f4caf1ad94f26810bb16a349 Mon Sep 17 00:00:00 2001 From: Frederic Rodrigo Date: Fri, 9 Jan 2015 17:06:14 +0000 Subject: [PATCH 029/360] Black list access=psv for car profile --- features/car/access.feature | 2 ++ profiles/car.lua | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/features/car/access.feature b/features/car/access.feature index 37dfed4c6..5fd56f395 100644 --- a/features/car/access.feature +++ b/features/car/access.feature @@ -93,6 +93,7 @@ Feature: Car - Restricted access | private | | | agricultural | | | forestry | | + | psv | | | some_tag | x | @@ -106,6 +107,7 @@ Feature: Car - Restricted access | private | | | agricultural | | | forestry | | + | psv | | | some_tag | x | Scenario: Car - Access tags on both node and way diff --git a/profiles/car.lua b/profiles/car.lua index cd1f06bd4..ca27c8068 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -3,7 +3,7 @@ barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["checkpoint"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true, ["entrance"] = true } access_tag_whitelist = { ["yes"] = true, ["motorcar"] = true, ["motor_vehicle"] = true, ["vehicle"] = true, ["permissive"] = true, ["designated"] = true } -access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true, ["emergency"] = true } +access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true, ["emergency"] = true, ["psv"] = true } access_tag_restricted = { ["destination"] = true, ["delivery"] = true } access_tags = { "motorcar", "motor_vehicle", "vehicle" } access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" } From 64c17c4ecdb55079856926b1fab4b7ba3b379299 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 9 Jan 2015 18:53:15 +0100 Subject: [PATCH 030/360] remove explicit appveyor os spec to get scheduled on hyper-v --- appveyor.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index e650e1ae1..afb8dd406 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,9 +9,6 @@ branches: only: - develop -# Operating system (build VM template) -os: Windows Server 2012 R2 - # scripts that are called at very beginning, before repo cloning init: - git config --global core.autocrlf input From bea4b520c00dd5560eec08a497b137909de104be Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 9 Jan 2015 19:15:00 +0100 Subject: [PATCH 031/360] Revert "Revert "fix #1255 assume lift gates are passable"" This reverts commit cec3d1488a63e31589f70d807e4c37cc8d8afa1e. *sigh* --- features/car/barrier.feature | 1 + profiles/car.lua | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/features/car/barrier.feature b/features/car/barrier.feature index e63704986..7c89688c9 100644 --- a/features/car/barrier.feature +++ b/features/car/barrier.feature @@ -10,6 +10,7 @@ Feature: Car - Barriers | | x | | bollard | | | gate | x | + | lift_gate | x | | cattle_grid | x | | border_control | x | | toll_booth | x | diff --git a/profiles/car.lua b/profiles/car.lua index cd1f06bd4..ad5009636 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -1,7 +1,7 @@ -- Begin of globals --require("lib/access") --function temporarily inlined -barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["checkpoint"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true, ["entrance"] = true } +barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["checkpoint"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["lift_gate"] = true, ["no"] = true, ["entrance"] = true } access_tag_whitelist = { ["yes"] = true, ["motorcar"] = true, ["motor_vehicle"] = true, ["vehicle"] = true, ["permissive"] = true, ["designated"] = true } access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true, ["emergency"] = true } access_tag_restricted = { ["destination"] = true, ["delivery"] = true } From eebf3a54e2699a7880c2bfd8345567f821fc1631 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Mon, 12 Jan 2015 13:56:43 +0100 Subject: [PATCH 032/360] cuke: abort if bins are missing, closes #1341 --- Util/FingerPrint.cpp | 103 ++++++++++++++++++++++++++++++++++++++++ Util/GitDescription.cpp | 29 +++++++++++ features/support/env.rb | 18 +++++-- 3 files changed, 147 insertions(+), 3 deletions(-) create mode 100644 Util/FingerPrint.cpp create mode 100644 Util/GitDescription.cpp diff --git a/Util/FingerPrint.cpp b/Util/FingerPrint.cpp new file mode 100644 index 000000000..bf02504e7 --- /dev/null +++ b/Util/FingerPrint.cpp @@ -0,0 +1,103 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "FingerPrint.h" + +#include "OSRMException.h" + +#include + +#include +#include + +#define HAS64BITS 0 +#define MD5PREPARE "2a7459472965fa17443822b826aa61f8" +#define MD5RTREE "74e5d04195aebe6500db7b61603f1d69" +#define MD5GRAPH "53ec17ab0e1fc4737fc7599b3467928a" +#define MD5OBJECTS "434731cd393154817166fcec8b0ceab0" + +FingerPrint::FingerPrint() : magic_number(1297240911) +{ + md5_prepare[32] = md5_tree[32] = md5_graph[32] = md5_objects[32] = '\0'; + + boost::uuids::name_generator gen(named_uuid); + std::string temp_string; + + std::memcpy(md5_prepare, MD5PREPARE, strlen(MD5PREPARE)); + temp_string += md5_prepare; + std::memcpy(md5_tree, MD5RTREE, 32); + temp_string += md5_tree; + std::memcpy(md5_graph, MD5GRAPH, 32); + temp_string += md5_graph; + std::memcpy(md5_objects, MD5OBJECTS, 32); + temp_string += md5_objects; + + named_uuid = gen(temp_string); + has_64_bits = HAS64BITS; +} + +FingerPrint::~FingerPrint() {} + +const boost::uuids::uuid &FingerPrint::GetFingerPrint() const { return named_uuid; } + +bool FingerPrint::IsMagicNumberOK() const { return 1297240911 == magic_number; } + +bool FingerPrint::TestGraphUtil(const FingerPrint &other) const +{ + if (!other.IsMagicNumberOK()) + { + throw OSRMException("hsgr input file misses magic number. Check or reprocess the file"); + } + return std::equal(md5_graph, md5_graph + 32, other.md5_graph); +} + +bool FingerPrint::TestPrepare(const FingerPrint &other) const +{ + if (!other.IsMagicNumberOK()) + { + throw OSRMException("osrm input file misses magic number. Check or reprocess the file"); + } + return std::equal(md5_prepare, md5_prepare + 32, other.md5_prepare); +} + +bool FingerPrint::TestRTree(const FingerPrint &other) const +{ + if (!other.IsMagicNumberOK()) + { + throw OSRMException("r-tree input file misses magic number. Check or reprocess the file"); + } + return std::equal(md5_tree, md5_tree + 32, other.md5_tree); +} + +bool FingerPrint::TestQueryObjects(const FingerPrint &other) const +{ + if (!other.IsMagicNumberOK()) + { + throw OSRMException("missing magic number. Check or reprocess the file"); + } + return std::equal(md5_objects, md5_objects + 32, other.md5_objects); +} diff --git a/Util/GitDescription.cpp b/Util/GitDescription.cpp new file mode 100644 index 000000000..a593aeb82 --- /dev/null +++ b/Util/GitDescription.cpp @@ -0,0 +1,29 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#define GIT_DESCRIPTION "v0.4.3-234-g8eccfaa" +char g_GIT_DESCRIPTION[] = GIT_DESCRIPTION; diff --git a/features/support/env.rb b/features/support/env.rb index a01341dd6..f9a4fe436 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -64,6 +64,19 @@ unless File.exists? TEST_FOLDER raise "*** Test folder #{TEST_FOLDER} doesn't exist." end +def verify_osrm_is_not_running + if OSRMLoader::OSRMBaseLoader.new.osrm_up? + raise "*** osrm-routed is already running." + end +end + +def verify_existance_of_binaries + ["osrm-extract", "osrm-prepare", "osrm-routed"].each do |bin| + unless File.exists? "#{BIN_PATH}/#{bin}" + raise "*** #{BIN_PATH}/#{bin} is missing. Build failed?" + end + end +end if ENV['OS']=~/Windows.*/ then EXE='.exe' @@ -74,10 +87,9 @@ else end AfterConfiguration do |config| - if OSRMLoader::OSRMBaseLoader.new.osrm_up? - raise "*** osrm-routed is already running." - end clear_log_files + verify_osrm_is_not_running + verify_existance_of_binaries end at_exit do From a28395b1163bfb4d44ff5544cf2193a0d37a4d51 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Mon, 12 Jan 2015 13:58:32 +0100 Subject: [PATCH 033/360] remove accidentally added files --- Util/FingerPrint.cpp | 103 ---------------------------------------- Util/GitDescription.cpp | 29 ----------- 2 files changed, 132 deletions(-) delete mode 100644 Util/FingerPrint.cpp delete mode 100644 Util/GitDescription.cpp diff --git a/Util/FingerPrint.cpp b/Util/FingerPrint.cpp deleted file mode 100644 index bf02504e7..000000000 --- a/Util/FingerPrint.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - -Copyright (c) 2013, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "FingerPrint.h" - -#include "OSRMException.h" - -#include - -#include -#include - -#define HAS64BITS 0 -#define MD5PREPARE "2a7459472965fa17443822b826aa61f8" -#define MD5RTREE "74e5d04195aebe6500db7b61603f1d69" -#define MD5GRAPH "53ec17ab0e1fc4737fc7599b3467928a" -#define MD5OBJECTS "434731cd393154817166fcec8b0ceab0" - -FingerPrint::FingerPrint() : magic_number(1297240911) -{ - md5_prepare[32] = md5_tree[32] = md5_graph[32] = md5_objects[32] = '\0'; - - boost::uuids::name_generator gen(named_uuid); - std::string temp_string; - - std::memcpy(md5_prepare, MD5PREPARE, strlen(MD5PREPARE)); - temp_string += md5_prepare; - std::memcpy(md5_tree, MD5RTREE, 32); - temp_string += md5_tree; - std::memcpy(md5_graph, MD5GRAPH, 32); - temp_string += md5_graph; - std::memcpy(md5_objects, MD5OBJECTS, 32); - temp_string += md5_objects; - - named_uuid = gen(temp_string); - has_64_bits = HAS64BITS; -} - -FingerPrint::~FingerPrint() {} - -const boost::uuids::uuid &FingerPrint::GetFingerPrint() const { return named_uuid; } - -bool FingerPrint::IsMagicNumberOK() const { return 1297240911 == magic_number; } - -bool FingerPrint::TestGraphUtil(const FingerPrint &other) const -{ - if (!other.IsMagicNumberOK()) - { - throw OSRMException("hsgr input file misses magic number. Check or reprocess the file"); - } - return std::equal(md5_graph, md5_graph + 32, other.md5_graph); -} - -bool FingerPrint::TestPrepare(const FingerPrint &other) const -{ - if (!other.IsMagicNumberOK()) - { - throw OSRMException("osrm input file misses magic number. Check or reprocess the file"); - } - return std::equal(md5_prepare, md5_prepare + 32, other.md5_prepare); -} - -bool FingerPrint::TestRTree(const FingerPrint &other) const -{ - if (!other.IsMagicNumberOK()) - { - throw OSRMException("r-tree input file misses magic number. Check or reprocess the file"); - } - return std::equal(md5_tree, md5_tree + 32, other.md5_tree); -} - -bool FingerPrint::TestQueryObjects(const FingerPrint &other) const -{ - if (!other.IsMagicNumberOK()) - { - throw OSRMException("missing magic number. Check or reprocess the file"); - } - return std::equal(md5_objects, md5_objects + 32, other.md5_objects); -} diff --git a/Util/GitDescription.cpp b/Util/GitDescription.cpp deleted file mode 100644 index a593aeb82..000000000 --- a/Util/GitDescription.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - -Copyright (c) 2013, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#define GIT_DESCRIPTION "v0.4.3-234-g8eccfaa" -char g_GIT_DESCRIPTION[] = GIT_DESCRIPTION; From 67f3111cc0207e9f776b9cd1a77a471afc2d8067 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 13 Jan 2015 11:05:22 +0100 Subject: [PATCH 034/360] renamed: Util/FingerPrint.h -> Util/finger_print.hpp --- Util/finger_print.cpp.in | 4 ++-- Util/{FingerPrint.h => finger_print.hpp} | 2 +- Util/graph_loader.hpp | 8 ++++---- datastore.cpp | 2 +- extractor/extraction_containers.hpp | 4 ++-- tools/components.cpp | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) rename Util/{FingerPrint.h => finger_print.hpp} (97%) diff --git a/Util/finger_print.cpp.in b/Util/finger_print.cpp.in index c73756ece..989138417 100644 --- a/Util/finger_print.cpp.in +++ b/Util/finger_print.cpp.in @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,7 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "FingerPrint.h" +#include "finger_print.hpp" #include "osrm_exception.hpp" diff --git a/Util/FingerPrint.h b/Util/finger_print.hpp similarity index 97% rename from Util/FingerPrint.h rename to Util/finger_print.hpp index 5fd04b60e..43a811deb 100644 --- a/Util/FingerPrint.h +++ b/Util/finger_print.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/Util/graph_loader.hpp b/Util/graph_loader.hpp index 5ab8eba83..948b1ec39 100644 --- a/Util/graph_loader.hpp +++ b/Util/graph_loader.hpp @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GRAPHLOADER_H -#define GRAPHLOADER_H +#ifndef GRAPH_LOADER_HPP +#define GRAPH_LOADER_HPP #include "osrm_exception.hpp" #include "../data_structures/external_memory_node.hpp" @@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/query_node.hpp" #include "../data_structures/restriction.hpp" #include "../Util/simple_logger.hpp" -#include "../Util/FingerPrint.h" +#include "../Util/finger_print.hpp" #include "../typedefs.h" #include @@ -322,4 +322,4 @@ unsigned readHSGRFromStream(const boost::filesystem::path &hsgr_file, return number_of_nodes; } -#endif // GRAPHLOADER_H +#endif // GRAPH_LOADER_HPP diff --git a/datastore.cpp b/datastore.cpp index 326081b2f..758013b44 100644 --- a/datastore.cpp +++ b/datastore.cpp @@ -40,7 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Util/DataStoreOptions.h" #include "Util/simple_logger.hpp" #include "Util/osrm_exception.hpp" -#include "Util/FingerPrint.h" +#include "Util/finger_print.hpp" #include "typedefs.h" #include diff --git a/extractor/extraction_containers.hpp b/extractor/extraction_containers.hpp index 8a1df8c36..2dfbcd523 100644 --- a/extractor/extraction_containers.hpp +++ b/extractor/extraction_containers.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "first_and_last_segment_of_way.hpp" #include "../data_structures/external_memory_node.hpp" #include "../data_structures/restriction.hpp" -#include "../Util/FingerPrint.h" +#include "../Util/finger_print.hpp" #include diff --git a/tools/components.cpp b/tools/components.cpp index f6ad3dd12..79d301762 100644 --- a/tools/components.cpp +++ b/tools/components.cpp @@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../Util/make_unique.hpp" #include "../Util/osrm_exception.hpp" #include "../Util/simple_logger.hpp" -#include "../Util/FingerPrint.h" +#include "../Util/finger_print.hpp" #include From ef9074f8e478467078c22ac30e546d4c06ade114 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 13 Jan 2015 11:16:13 +0100 Subject: [PATCH 035/360] renamed: Util/finger_print.* -> Util/fingerprint.* thx @emiltin --- .gitignore | 2 +- CMakeLists.txt | 10 +++++----- Util/{finger_print.cpp.in => fingerprint.cpp.in} | 2 +- Util/{finger_print.hpp => fingerprint.hpp} | 0 Util/graph_loader.hpp | 2 +- cmake/FingerPrint-Config.cmake | 4 ++-- datastore.cpp | 2 +- extractor/extraction_containers.hpp | 2 +- tools/components.cpp | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) rename Util/{finger_print.cpp.in => fingerprint.cpp.in} (99%) rename Util/{finger_print.hpp => fingerprint.hpp} (100%) diff --git a/.gitignore b/.gitignore index b905eeafb..6a154a4b3 100644 --- a/.gitignore +++ b/.gitignore @@ -36,7 +36,7 @@ Thumbs.db # build related files # ####################### /build/ -/Util/finger_print.cpp +/Util/fingerprint.cpp /Util/git_sha.cpp /cmake/postinst diff --git a/CMakeLists.txt b/CMakeLists.txt index dc8264cb5..02a353564 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,15 +33,15 @@ OPTION(BUILD_TOOLS "Build OSRM tools" OFF) include_directories(${CMAKE_SOURCE_DIR}/Include/) include_directories(${CMAKE_SOURCE_DIR}/third_party/) -add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/finger_print.cpp finger_print.cpp.alwaysbuild +add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/fingerprint.cpp fingerprint.cpp.alwaysbuild COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FingerPrint-Config.cmake DEPENDS - ${CMAKE_SOURCE_DIR}/Util/finger_print.cpp.in - COMMENT "Configuring finger_print.cpp" + ${CMAKE_SOURCE_DIR}/Util/fingerprint.cpp.in + COMMENT "Configuring fingerprint.cpp" VERBATIM) -add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/finger_print.cpp) +add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/fingerprint.cpp) add_custom_target(tests DEPENDS datastructure-tests algorithm-tests) add_custom_target(benchmarks DEPENDS rtree-bench) @@ -88,7 +88,7 @@ set( ${HttpGlob} ) add_library(COORDINATE OBJECT ${CoordinateGlob}) -add_library(FINGERPRINT OBJECT Util/finger_print.cpp) +add_library(FINGERPRINT OBJECT Util/fingerprint.cpp) add_library(GITDESCRIPTION OBJECT Util/git_sha.cpp) add_library(OSRM ${OSRMSources} $ $ $ $ $ $) add_dependencies(FINGERPRINT FingerPrintConfigure) diff --git a/Util/finger_print.cpp.in b/Util/fingerprint.cpp.in similarity index 99% rename from Util/finger_print.cpp.in rename to Util/fingerprint.cpp.in index 989138417..6f9a6658f 100644 --- a/Util/finger_print.cpp.in +++ b/Util/fingerprint.cpp.in @@ -25,7 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "finger_print.hpp" +#include "fingerprint.hpp" #include "osrm_exception.hpp" diff --git a/Util/finger_print.hpp b/Util/fingerprint.hpp similarity index 100% rename from Util/finger_print.hpp rename to Util/fingerprint.hpp diff --git a/Util/graph_loader.hpp b/Util/graph_loader.hpp index 948b1ec39..bbf9d5fbb 100644 --- a/Util/graph_loader.hpp +++ b/Util/graph_loader.hpp @@ -33,8 +33,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/import_edge.hpp" #include "../data_structures/query_node.hpp" #include "../data_structures/restriction.hpp" +#include "../Util/fingerprint.hpp" #include "../Util/simple_logger.hpp" -#include "../Util/finger_print.hpp" #include "../typedefs.h" #include diff --git a/cmake/FingerPrint-Config.cmake b/cmake/FingerPrint-Config.cmake index 710368d7b..7d0de9122 100644 --- a/cmake/FingerPrint-Config.cmake +++ b/cmake/FingerPrint-Config.cmake @@ -1,4 +1,4 @@ -set(OLDFILE ${SOURCE_DIR}/Util/FingerPrint.cpp) +set(OLDFILE ${SOURCE_DIR}/Util/fingerprint.cpp) if (EXISTS ${OLDFILE}) file(REMOVE_RECURSE ${OLDFILE}) endif() @@ -7,4 +7,4 @@ file(MD5 ${SOURCE_DIR}/data_structures/static_rtree.hpp MD5RTREE) file(MD5 ${SOURCE_DIR}/Util/graph_loader.hpp MD5GRAPH) file(MD5 ${SOURCE_DIR}/Server/DataStructures/InternalDataFacade.h MD5OBJECTS) -CONFIGURE_FILE( ${SOURCE_DIR}/Util/finger_print.cpp.in ${SOURCE_DIR}/Util/finger_print.cpp ) +CONFIGURE_FILE( ${SOURCE_DIR}/Util/fingerprint.cpp.in ${SOURCE_DIR}/Util/fingerprint.cpp ) diff --git a/datastore.cpp b/datastore.cpp index 758013b44..011fa09b6 100644 --- a/datastore.cpp +++ b/datastore.cpp @@ -40,7 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Util/DataStoreOptions.h" #include "Util/simple_logger.hpp" #include "Util/osrm_exception.hpp" -#include "Util/finger_print.hpp" +#include "Util/fingerprint.hpp" #include "typedefs.h" #include diff --git a/extractor/extraction_containers.hpp b/extractor/extraction_containers.hpp index 2dfbcd523..68df14cff 100644 --- a/extractor/extraction_containers.hpp +++ b/extractor/extraction_containers.hpp @@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "first_and_last_segment_of_way.hpp" #include "../data_structures/external_memory_node.hpp" #include "../data_structures/restriction.hpp" -#include "../Util/finger_print.hpp" +#include "../Util/fingerprint.hpp" #include diff --git a/tools/components.cpp b/tools/components.cpp index 79d301762..3618258ee 100644 --- a/tools/components.cpp +++ b/tools/components.cpp @@ -28,11 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../typedefs.h" #include "../algorithms/tiny_components.hpp" #include "../data_structures/dynamic_graph.hpp" +#include "../Util/fingerprint.hpp" #include "../Util/graph_loader.hpp" #include "../Util/make_unique.hpp" #include "../Util/osrm_exception.hpp" #include "../Util/simple_logger.hpp" -#include "../Util/finger_print.hpp" #include From fbce104f3b2d5385e0bfc04cfa29f1f7dbc2cb3c Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 12 Jan 2015 18:53:26 +0100 Subject: [PATCH 036/360] use static graph for component exploration, closes #1288 --- tools/components.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/components.cpp b/tools/components.cpp index 3618258ee..59035ba89 100644 --- a/tools/components.cpp +++ b/tools/components.cpp @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../typedefs.h" #include "../algorithms/tiny_components.hpp" -#include "../data_structures/dynamic_graph.hpp" +#include "../data_structures/static_graph.hpp" #include "../Util/fingerprint.hpp" #include "../Util/graph_loader.hpp" #include "../Util/make_unique.hpp" @@ -61,8 +61,8 @@ struct TarjanEdgeData unsigned name_id; }; -using TarjanDynamicGraph = DynamicGraph; -using TarjanEdge = TarjanDynamicGraph::InputEdge; +using TarjanGraph = StaticGraph; +using TarjanEdge = TarjanGraph::InputEdge; void DeleteFileIfExists(const std::string &file_name) { @@ -148,7 +148,7 @@ int main(int argc, char *argv[]) traffic_lights_list.shrink_to_fit(); // Building an node-based graph - DeallocatingVector graph_edge_list; + std::vector graph_edge_list; for (const NodeBasedEdge &input_edge : edge_list) { if (input_edge.source == input_edge.target) @@ -177,14 +177,14 @@ int main(int argc, char *argv[]) "input edge vector not properly deallocated"); tbb::parallel_sort(graph_edge_list.begin(), graph_edge_list.end()); - auto graph = std::make_shared(number_of_nodes, graph_edge_list); + auto graph = std::make_shared(number_of_nodes, graph_edge_list); edge_list.clear(); edge_list.shrink_to_fit(); SimpleLogger().Write() << "Starting SCC graph traversal"; RestrictionMap restriction_map(restriction_list); - auto tarjan = osrm::make_unique>(graph, + auto tarjan = osrm::make_unique>(graph, restriction_map, bollard_node_list); tarjan->run(); @@ -238,7 +238,7 @@ int main(int argc, char *argv[]) p.printIncrement(); for (const auto current_edge : graph->GetAdjacentEdgeRange(source)) { - const TarjanDynamicGraph::NodeIterator target = graph->GetTarget(current_edge); + const TarjanGraph::NodeIterator target = graph->GetTarget(current_edge); if (source < target || graph->EndEdges(target) == graph->FindEdge(target, source)) { From bf71781ee935d84449fd7db678f1a6f039fa9fca Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 13 Jan 2015 14:56:46 +0100 Subject: [PATCH 037/360] new file: Util/mercator.cpp renamed: Util/MercatorUtil.h -> Util/mercator.hpp --- CMakeLists.txt | 11 ++++---- Util/compute_angle.cpp | 8 +++--- Util/{MercatorUtil.h => mercator.cpp} | 11 +++----- Util/mercator.hpp | 38 +++++++++++++++++++++++++++ data_structures/coordinate.cpp | 26 +++++++++--------- data_structures/static_rtree.hpp | 4 +-- 6 files changed, 67 insertions(+), 31 deletions(-) rename Util/{MercatorUtil.h => mercator.cpp} (87%) create mode 100644 Util/mercator.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 02a353564..bccab776e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,15 +57,16 @@ add_library(IMPORT OBJECT ${ImporterGlob}) add_library(LOGGER OBJECT Util/simple_logger.cpp) add_library(PHANTOMNODE OBJECT data_structures/phantom_node.cpp) add_library(EXCEPTION OBJECT Util/osrm_exception.cpp) +add_library(MERCATOR OBJECT Util/mercator.cpp) set(ExtractorSources extract.cpp ${ExtractorGlob}) -add_executable(osrm-extract ${ExtractorSources} $ $ $ $ $ $) +add_executable(osrm-extract ${ExtractorSources} $ $ $ $ $ $ $) add_library(RESTRICTION OBJECT data_structures/restriction_map.cpp) file(GLOB PrepareGlob contractor/*.cpp data_structures/hilbert_value.cpp Util/compute_angle.cpp {RestrictionMapGlob}) set(PrepareSources prepare.cpp ${PrepareGlob}) -add_executable(osrm-prepare ${PrepareSources} $ $ $ $ $ $ $) +add_executable(osrm-prepare ${PrepareSources} $ $ $ $ $ $ $ $) file(GLOB ServerGlob Server/*.cpp) file(GLOB DescriptorGlob descriptors/*.cpp) @@ -90,11 +91,11 @@ set( add_library(COORDINATE OBJECT ${CoordinateGlob}) add_library(FINGERPRINT OBJECT Util/fingerprint.cpp) add_library(GITDESCRIPTION OBJECT Util/git_sha.cpp) -add_library(OSRM ${OSRMSources} $ $ $ $ $ $) +add_library(OSRM ${OSRMSources} $ $ $ $ $ $ $) add_dependencies(FINGERPRINT FingerPrintConfigure) add_executable(osrm-routed routed.cpp ${ServerGlob} $) -add_executable(osrm-datastore datastore.cpp $ $ $ $ $) +add_executable(osrm-datastore datastore.cpp $ $ $ $ $ $) # Unit tests add_executable(datastructure-tests EXCLUDE_FROM_ALL UnitTests/datastructure_tests.cpp ${DataStructureTestsGlob} $ $ $ $) @@ -289,7 +290,7 @@ if(WITH_TOOLS OR BUILD_TOOLS) message(STATUS "Activating OSRM internal tools") find_package(GDAL) if(GDAL_FOUND) - add_executable(osrm-components tools/components.cpp $ $ $ $ $ $) + add_executable(osrm-components tools/components.cpp $ $ $ $ $ $ $) target_link_libraries(osrm-components ${TBB_LIBRARIES}) include_directories(${GDAL_INCLUDE_DIR}) target_link_libraries( diff --git a/Util/compute_angle.cpp b/Util/compute_angle.cpp index bba4773e2..ca9d18980 100644 --- a/Util/compute_angle.cpp +++ b/Util/compute_angle.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "compute_angle.hpp" #include "TrigonometryTables.h" -#include "../Util/MercatorUtil.h" +#include "../Util/mercator.hpp" #include @@ -39,9 +39,9 @@ double ComputeAngle::OfThreeFixedPointCoordinates(const FixedPointCoordinate &A, const FixedPointCoordinate &B) { const double v1x = (A.lon - C.lon) / COORDINATE_PRECISION; - const double v1y = lat2y(A.lat / COORDINATE_PRECISION) - lat2y(C.lat / COORDINATE_PRECISION); + const double v1y = mercator::lat2y(A.lat / COORDINATE_PRECISION) - mercator::lat2y(C.lat / COORDINATE_PRECISION); const double v2x = (B.lon - C.lon) / COORDINATE_PRECISION; - const double v2y = lat2y(B.lat / COORDINATE_PRECISION) - lat2y(C.lat / COORDINATE_PRECISION); + const double v2y = mercator::lat2y(B.lat / COORDINATE_PRECISION) - mercator::lat2y(C.lat / COORDINATE_PRECISION); double angle = (atan2_lookup(v2y, v2x) - atan2_lookup(v1y, v1x)) * 180. / M_PI; while (angle < 0.) diff --git a/Util/MercatorUtil.h b/Util/mercator.cpp similarity index 87% rename from Util/MercatorUtil.h rename to Util/mercator.cpp index b4a15b779..707fd5535 100644 --- a/Util/MercatorUtil.h +++ b/Util/mercator.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,19 +25,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef MERCATOR_UTIL_H -#define MERCATOR_UTIL_H +#include "mercator.hpp" #include -inline double y2lat(const double a) +double mercator::y2lat(const double a) { return 180. * M_1_PI * (2. * std::atan(std::exp(a * M_PI / 180.)) - M_PI_2); } -inline double lat2y(const double a) +double mercator::lat2y(const double a) { return 180. * M_1_PI * std::log(std::tan(M_PI_4 + a * (M_PI / 180.) / 2.)); } - -#endif // MERCATOR_UTIL_H diff --git a/Util/mercator.hpp b/Util/mercator.hpp new file mode 100644 index 000000000..0ea22d034 --- /dev/null +++ b/Util/mercator.hpp @@ -0,0 +1,38 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef MERCATOR_HPP +#define MERCATOR_HPP + +struct mercator +{ + static double y2lat(const double a); + + static double lat2y(const double a); +}; + +#endif // MERCATOR_HPP diff --git a/data_structures/coordinate.cpp b/data_structures/coordinate.cpp index c2563b663..2d045e195 100644 --- a/data_structures/coordinate.cpp +++ b/data_structures/coordinate.cpp @@ -25,7 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "../Util/MercatorUtil.h" +#include "../Util/mercator.hpp" #ifndef NDEBUG #include "../Util/simple_logger.hpp" #endif @@ -160,11 +160,11 @@ FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &s const FixedPointCoordinate &point) { // initialize values - const float x_value = static_cast(lat2y(point.lat / COORDINATE_PRECISION)); + const float x_value = static_cast(mercator::lat2y(point.lat / COORDINATE_PRECISION)); const float y_value = point.lon / COORDINATE_PRECISION; - float a = static_cast(lat2y(source_coordinate.lat / COORDINATE_PRECISION)); + float a = static_cast(mercator::lat2y(source_coordinate.lat / COORDINATE_PRECISION)); float b = source_coordinate.lon / COORDINATE_PRECISION; - float c = static_cast(lat2y(target_coordinate.lat / COORDINATE_PRECISION)); + float c = static_cast(mercator::lat2y(target_coordinate.lat / COORDINATE_PRECISION)); float d = target_coordinate.lon / COORDINATE_PRECISION; float p, q; if (std::abs(a - c) > std::numeric_limits::epsilon()) @@ -243,7 +243,7 @@ FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &s } else { // point lies in between - nearest_location.lat = static_cast(y2lat(p) * COORDINATE_PRECISION); + nearest_location.lat = static_cast(mercator::y2lat(p) * COORDINATE_PRECISION); nearest_location.lon = static_cast(q * COORDINATE_PRECISION); } @@ -260,11 +260,11 @@ float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordin BOOST_ASSERT(query_location.is_valid()); // initialize values - const double x = lat2y(query_location.lat / COORDINATE_PRECISION); + const double x = mercator::lat2y(query_location.lat / COORDINATE_PRECISION); const double y = query_location.lon / COORDINATE_PRECISION; - const double a = lat2y(segment_source.lat / COORDINATE_PRECISION); + const double a = mercator::lat2y(segment_source.lat / COORDINATE_PRECISION); const double b = segment_source.lon / COORDINATE_PRECISION; - const double c = lat2y(segment_target.lat / COORDINATE_PRECISION); + const double c = mercator::lat2y(segment_target.lat / COORDINATE_PRECISION); const double d = segment_target.lon / COORDINATE_PRECISION; double p, q /*,mX*/, nY; if (std::abs(a - c) > std::numeric_limits::epsilon()) @@ -317,7 +317,7 @@ float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordin else { // point lies in between - nearest_location.lat = static_cast(y2lat(p) * COORDINATE_PRECISION); + nearest_location.lat = static_cast(mercator::y2lat(p) * COORDINATE_PRECISION); nearest_location.lon = static_cast(q * COORDINATE_PRECISION); } BOOST_ASSERT(nearest_location.is_valid()); @@ -430,11 +430,11 @@ int FixedPointCoordinate::OrderedPerpendicularDistanceApproximation( const FixedPointCoordinate &segment_target) { // initialize values - const float x = static_cast(lat2y(input_point.lat / COORDINATE_PRECISION)); + const float x = static_cast(mercator::lat2y(input_point.lat / COORDINATE_PRECISION)); const float y = input_point.lon / COORDINATE_PRECISION; - const float a = static_cast(lat2y(segment_source.lat / COORDINATE_PRECISION)); + const float a = static_cast(mercator::lat2y(segment_source.lat / COORDINATE_PRECISION)); const float b = segment_source.lon / COORDINATE_PRECISION; - const float c = static_cast(lat2y(segment_target.lat / COORDINATE_PRECISION)); + const float c = static_cast(mercator::lat2y(segment_target.lat / COORDINATE_PRECISION)); const float d = segment_target.lon / COORDINATE_PRECISION; float p, q; @@ -476,7 +476,7 @@ int FixedPointCoordinate::OrderedPerpendicularDistanceApproximation( { // point lies in between dx = input_point.lon - static_cast(q * COORDINATE_PRECISION); - dy = input_point.lat - static_cast(y2lat(p) * COORDINATE_PRECISION); + dy = input_point.lat - static_cast(mercator::y2lat(p) * COORDINATE_PRECISION); } // return an approximation in the plane diff --git a/data_structures/static_rtree.hpp b/data_structures/static_rtree.hpp index db7180468..a8cccd1bf 100644 --- a/data_structures/static_rtree.hpp +++ b/data_structures/static_rtree.hpp @@ -38,7 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../Util/floating_point.hpp" #include "../Util/integer_range.hpp" -#include "../Util/MercatorUtil.h" +#include "../Util/mercator.hpp" #include "../Util/osrm_exception.hpp" #include "../Util/simple_logger.hpp" #include "../Util/timing_util.hpp" @@ -377,7 +377,7 @@ class StaticRTree FixedPointCoordinate(coordinate_list.at(current_element.v).lat, coordinate_list.at(current_element.v).lon)); current_centroid.lat = - COORDINATE_PRECISION * lat2y(current_centroid.lat / COORDINATE_PRECISION); + COORDINATE_PRECISION * mercator::lat2y(current_centroid.lat / COORDINATE_PRECISION); current_wrapper.m_hilbert_value = get_hilbert_number(current_centroid); } From d0c99f1999cca560795d99b1f0db55f91bb2da3d Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 13 Jan 2015 15:45:27 +0100 Subject: [PATCH 038/360] fix linking of benchmarks and tests --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bccab776e..8d11858b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,11 +98,11 @@ add_executable(osrm-routed routed.cpp ${ServerGlob} $) add_executable(osrm-datastore datastore.cpp $ $ $ $ $ $) # Unit tests -add_executable(datastructure-tests EXCLUDE_FROM_ALL UnitTests/datastructure_tests.cpp ${DataStructureTestsGlob} $ $ $ $) +add_executable(datastructure-tests EXCLUDE_FROM_ALL UnitTests/datastructure_tests.cpp ${DataStructureTestsGlob} $ $ $ $ $) add_executable(algorithm-tests EXCLUDE_FROM_ALL UnitTests/algorithm_tests.cpp ${AlgorithmTestsGlob} $ $ $ $) # Benchmarks -add_executable(rtree-bench EXCLUDE_FROM_ALL benchmarks/static_rtree.cpp $ $ $ $) +add_executable(rtree-bench EXCLUDE_FROM_ALL benchmarks/static_rtree.cpp $ $ $ $ $) # Check the release mode if(NOT CMAKE_BUILD_TYPE MATCHES Debug) From 5f28a7db0d3243c559fd5006680b66ea7d3169ca Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 13 Jan 2015 15:52:24 +0100 Subject: [PATCH 039/360] add some whitespace --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d11858b7..b5bd1779e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,6 +88,7 @@ set( ${AlgorithmGlob} ${HttpGlob} ) + add_library(COORDINATE OBJECT ${CoordinateGlob}) add_library(FINGERPRINT OBJECT Util/fingerprint.cpp) add_library(GITDESCRIPTION OBJECT Util/git_sha.cpp) From 347cbd37ca652b7e517243fc34706ae0359af2a3 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 13 Jan 2015 16:02:02 +0100 Subject: [PATCH 040/360] fix include guard naming in plugin base --- plugins/plugin_base.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/plugin_base.hpp b/plugins/plugin_base.hpp index 8dc2eea6d..37d32b5b2 100644 --- a/plugins/plugin_base.hpp +++ b/plugins/plugin_base.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BASEPLUGIN_H_ -#define BASEPLUGIN_H_ +#ifndef BASE_PLUGIN_HPP +#define BASE_PLUGIN_HPP #include #include @@ -59,4 +59,4 @@ class BasePlugin } }; -#endif /* BASEPLUGIN_H_ */ +#endif /* BASE_PLUGIN_HPP */ From ebbc168f3f8a5e0c89d53db10d871c728d32bd04 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 13 Jan 2015 16:46:44 +0100 Subject: [PATCH 041/360] fix implicit integer cast, reorder includes --- algorithms/douglas_peucker.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/algorithms/douglas_peucker.cpp b/algorithms/douglas_peucker.cpp index bb8da99b2..20f698d8f 100644 --- a/algorithms/douglas_peucker.cpp +++ b/algorithms/douglas_peucker.cpp @@ -30,12 +30,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/segment_information.hpp" #include "../Util/integer_range.hpp" +#include #include -#include - #include - #include namespace @@ -90,7 +88,7 @@ void DouglasPeucker::Run(std::vector &input_geometry, const void DouglasPeucker::Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level) { - unsigned size = std::distance(begin, end); + const auto size = std::distance(begin, end); if (size < 2) { return; From d6946a8aae62ddcd1370d6e18306497fe35ea9d8 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 13 Jan 2015 16:50:31 +0100 Subject: [PATCH 042/360] remove copy of libosmium, to be replaced by a subtree --- third_party/osmium/area/assembler.hpp | 783 --------------- .../osmium/area/detail/node_ref_segment.hpp | 262 ----- third_party/osmium/area/detail/proto_ring.hpp | 274 ----- .../osmium/area/detail/segment_list.hpp | 216 ---- .../osmium/area/multipolygon_collector.hpp | 212 ---- third_party/osmium/area/problem_reporter.hpp | 149 --- .../area/problem_reporter_exception.hpp | 96 -- .../osmium/area/problem_reporter_ogr.hpp | 206 ---- .../osmium/area/problem_reporter_stream.hpp | 96 -- third_party/osmium/builder/builder.hpp | 220 ---- third_party/osmium/builder/builder_helper.hpp | 103 -- .../osmium/builder/osm_object_builder.hpp | 283 ------ third_party/osmium/config/constexpr.hpp | 43 - third_party/osmium/diff_handler.hpp | 67 -- third_party/osmium/diff_iterator.hpp | 129 --- third_party/osmium/diff_visitor.hpp | 104 -- third_party/osmium/dynamic_handler.hpp | 195 ---- .../osmium/experimental/flex_reader.hpp | 131 --- third_party/osmium/geom/coordinates.hpp | 97 -- third_party/osmium/geom/factory.hpp | 328 ------ third_party/osmium/geom/geojson.hpp | 152 --- third_party/osmium/geom/geos.hpp | 224 ----- third_party/osmium/geom/haversine.hpp | 94 -- .../osmium/geom/mercator_projection.hpp | 109 -- third_party/osmium/geom/ogr.hpp | 179 ---- third_party/osmium/geom/projection.hpp | 159 --- third_party/osmium/geom/relations.hpp | 57 -- third_party/osmium/geom/util.hpp | 75 -- third_party/osmium/geom/wkb.hpp | 279 ------ third_party/osmium/geom/wkt.hpp | 148 --- third_party/osmium/handler.hpp | 101 -- third_party/osmium/handler/chain.hpp | 128 --- third_party/osmium/handler/disk_store.hpp | 111 -- third_party/osmium/handler/dump.hpp | 294 ------ .../handler/node_locations_for_ways.hpp | 177 ---- .../osmium/handler/object_relations.hpp | 106 -- .../osmium/index/detail/mmap_vector_anon.hpp | 78 -- .../osmium/index/detail/mmap_vector_base.hpp | 183 ---- .../osmium/index/detail/mmap_vector_file.hpp | 82 -- third_party/osmium/index/detail/tmpfile.hpp | 62 -- .../osmium/index/detail/typed_mmap.hpp | 229 ----- third_party/osmium/index/index.hpp | 100 -- third_party/osmium/index/map.hpp | 155 --- third_party/osmium/index/map/dummy.hpp | 87 -- .../osmium/index/map/mmap_vector_anon.hpp | 61 -- .../osmium/index/map/mmap_vector_file.hpp | 57 -- third_party/osmium/index/map/sparse_table.hpp | 140 --- third_party/osmium/index/map/stl_map.hpp | 112 --- third_party/osmium/index/map/stl_vector.hpp | 61 -- third_party/osmium/index/map/vector.hpp | 208 ---- third_party/osmium/index/multimap.hpp | 129 --- third_party/osmium/index/multimap/hybrid.hpp | 199 ---- .../index/multimap/mmap_vector_anon.hpp | 58 -- .../index/multimap/mmap_vector_file.hpp | 54 - .../osmium/index/multimap/stl_multimap.hpp | 151 --- .../osmium/index/multimap/stl_vector.hpp | 58 -- third_party/osmium/index/multimap/vector.hpp | 151 --- third_party/osmium/io/any_compression.hpp | 39 - third_party/osmium/io/any_input.hpp | 41 - third_party/osmium/io/any_output.hpp | 42 - third_party/osmium/io/bzip2_compression.hpp | 277 ----- third_party/osmium/io/compression.hpp | 279 ------ third_party/osmium/io/detail/input_format.hpp | 160 --- .../osmium/io/detail/opl_output_format.hpp | 315 ------ .../osmium/io/detail/output_format.hpp | 156 --- third_party/osmium/io/detail/pbf.hpp | 100 -- .../osmium/io/detail/pbf_input_format.hpp | 240 ----- .../osmium/io/detail/pbf_output_format.hpp | 944 ------------------ third_party/osmium/io/detail/pbf_parser.hpp | 449 --------- .../osmium/io/detail/pbf_stringtable.hpp | 204 ---- third_party/osmium/io/detail/read_thread.hpp | 106 -- third_party/osmium/io/detail/read_write.hpp | 156 --- third_party/osmium/io/detail/write_thread.hpp | 86 -- .../osmium/io/detail/xml_input_format.hpp | 726 -------------- .../osmium/io/detail/xml_output_format.hpp | 481 --------- third_party/osmium/io/detail/zlib.hpp | 99 -- third_party/osmium/io/error.hpp | 57 -- third_party/osmium/io/file.hpp | 343 ------- third_party/osmium/io/file_compression.hpp | 72 -- third_party/osmium/io/file_format.hpp | 78 -- third_party/osmium/io/gzip_compression.hpp | 238 ----- third_party/osmium/io/header.hpp | 122 --- third_party/osmium/io/input_iterator.hpp | 139 --- third_party/osmium/io/opl_output.hpp | 39 - third_party/osmium/io/output_iterator.hpp | 116 --- third_party/osmium/io/overwrite.hpp | 52 - third_party/osmium/io/pbf_input.hpp | 39 - third_party/osmium/io/pbf_output.hpp | 39 - third_party/osmium/io/reader.hpp | 303 ------ third_party/osmium/io/reader_iterator.hpp | 51 - third_party/osmium/io/writer.hpp | 145 --- third_party/osmium/io/xml_input.hpp | 39 - third_party/osmium/io/xml_output.hpp | 39 - third_party/osmium/memory/buffer.hpp | 534 ---------- third_party/osmium/memory/collection.hpp | 153 --- third_party/osmium/memory/item.hpp | 179 ---- third_party/osmium/memory/item_iterator.hpp | 234 ----- .../osmium/object_pointer_collection.hpp | 112 --- third_party/osmium/osm.hpp | 48 - third_party/osmium/osm/area.hpp | 193 ---- third_party/osmium/osm/box.hpp | 207 ---- third_party/osmium/osm/changeset.hpp | 336 ------- third_party/osmium/osm/diff_object.hpp | 156 --- third_party/osmium/osm/entity.hpp | 74 -- third_party/osmium/osm/entity_bits.hpp | 99 -- third_party/osmium/osm/item_type.hpp | 173 ---- third_party/osmium/osm/location.hpp | 285 ------ third_party/osmium/osm/node.hpp | 76 -- third_party/osmium/osm/node_ref.hpp | 173 ---- third_party/osmium/osm/node_ref_list.hpp | 135 --- third_party/osmium/osm/object.hpp | 437 -------- third_party/osmium/osm/object_comparisons.hpp | 110 -- third_party/osmium/osm/relation.hpp | 189 ---- third_party/osmium/osm/segment.hpp | 105 -- third_party/osmium/osm/tag.hpp | 140 --- third_party/osmium/osm/timestamp.hpp | 169 ---- third_party/osmium/osm/types.hpp | 83 -- third_party/osmium/osm/undirected_segment.hpp | 100 -- third_party/osmium/osm/way.hpp | 115 --- third_party/osmium/relations/collector.hpp | 544 ---------- .../osmium/relations/detail/member_meta.hpp | 158 --- .../osmium/relations/detail/relation_meta.hpp | 136 --- third_party/osmium/tags/filter.hpp | 148 --- third_party/osmium/tags/regex_filter.hpp | 58 -- third_party/osmium/tags/taglist.hpp | 67 -- third_party/osmium/thread/checked_task.hpp | 106 -- .../osmium/thread/function_wrapper.hpp | 110 -- third_party/osmium/thread/name.hpp | 61 -- third_party/osmium/thread/pool.hpp | 180 ---- third_party/osmium/thread/queue.hpp | 178 ---- third_party/osmium/thread/sorted_queue.hpp | 159 --- third_party/osmium/thread/util.hpp | 87 -- third_party/osmium/util/cast.hpp | 72 -- third_party/osmium/util/compatibility.hpp | 47 - third_party/osmium/util/config.hpp | 73 -- third_party/osmium/util/double.hpp | 91 -- third_party/osmium/util/options.hpp | 155 --- third_party/osmium/util/verbose_output.hpp | 139 --- third_party/osmium/visitor.hpp | 255 ----- 139 files changed, 23052 deletions(-) delete mode 100644 third_party/osmium/area/assembler.hpp delete mode 100644 third_party/osmium/area/detail/node_ref_segment.hpp delete mode 100644 third_party/osmium/area/detail/proto_ring.hpp delete mode 100644 third_party/osmium/area/detail/segment_list.hpp delete mode 100644 third_party/osmium/area/multipolygon_collector.hpp delete mode 100644 third_party/osmium/area/problem_reporter.hpp delete mode 100644 third_party/osmium/area/problem_reporter_exception.hpp delete mode 100644 third_party/osmium/area/problem_reporter_ogr.hpp delete mode 100644 third_party/osmium/area/problem_reporter_stream.hpp delete mode 100644 third_party/osmium/builder/builder.hpp delete mode 100644 third_party/osmium/builder/builder_helper.hpp delete mode 100644 third_party/osmium/builder/osm_object_builder.hpp delete mode 100644 third_party/osmium/config/constexpr.hpp delete mode 100644 third_party/osmium/diff_handler.hpp delete mode 100644 third_party/osmium/diff_iterator.hpp delete mode 100644 third_party/osmium/diff_visitor.hpp delete mode 100644 third_party/osmium/dynamic_handler.hpp delete mode 100644 third_party/osmium/experimental/flex_reader.hpp delete mode 100644 third_party/osmium/geom/coordinates.hpp delete mode 100644 third_party/osmium/geom/factory.hpp delete mode 100644 third_party/osmium/geom/geojson.hpp delete mode 100644 third_party/osmium/geom/geos.hpp delete mode 100644 third_party/osmium/geom/haversine.hpp delete mode 100644 third_party/osmium/geom/mercator_projection.hpp delete mode 100644 third_party/osmium/geom/ogr.hpp delete mode 100644 third_party/osmium/geom/projection.hpp delete mode 100644 third_party/osmium/geom/relations.hpp delete mode 100644 third_party/osmium/geom/util.hpp delete mode 100644 third_party/osmium/geom/wkb.hpp delete mode 100644 third_party/osmium/geom/wkt.hpp delete mode 100644 third_party/osmium/handler.hpp delete mode 100644 third_party/osmium/handler/chain.hpp delete mode 100644 third_party/osmium/handler/disk_store.hpp delete mode 100644 third_party/osmium/handler/dump.hpp delete mode 100644 third_party/osmium/handler/node_locations_for_ways.hpp delete mode 100644 third_party/osmium/handler/object_relations.hpp delete mode 100644 third_party/osmium/index/detail/mmap_vector_anon.hpp delete mode 100644 third_party/osmium/index/detail/mmap_vector_base.hpp delete mode 100644 third_party/osmium/index/detail/mmap_vector_file.hpp delete mode 100644 third_party/osmium/index/detail/tmpfile.hpp delete mode 100644 third_party/osmium/index/detail/typed_mmap.hpp delete mode 100644 third_party/osmium/index/index.hpp delete mode 100644 third_party/osmium/index/map.hpp delete mode 100644 third_party/osmium/index/map/dummy.hpp delete mode 100644 third_party/osmium/index/map/mmap_vector_anon.hpp delete mode 100644 third_party/osmium/index/map/mmap_vector_file.hpp delete mode 100644 third_party/osmium/index/map/sparse_table.hpp delete mode 100644 third_party/osmium/index/map/stl_map.hpp delete mode 100644 third_party/osmium/index/map/stl_vector.hpp delete mode 100644 third_party/osmium/index/map/vector.hpp delete mode 100644 third_party/osmium/index/multimap.hpp delete mode 100644 third_party/osmium/index/multimap/hybrid.hpp delete mode 100644 third_party/osmium/index/multimap/mmap_vector_anon.hpp delete mode 100644 third_party/osmium/index/multimap/mmap_vector_file.hpp delete mode 100644 third_party/osmium/index/multimap/stl_multimap.hpp delete mode 100644 third_party/osmium/index/multimap/stl_vector.hpp delete mode 100644 third_party/osmium/index/multimap/vector.hpp delete mode 100644 third_party/osmium/io/any_compression.hpp delete mode 100644 third_party/osmium/io/any_input.hpp delete mode 100644 third_party/osmium/io/any_output.hpp delete mode 100644 third_party/osmium/io/bzip2_compression.hpp delete mode 100644 third_party/osmium/io/compression.hpp delete mode 100644 third_party/osmium/io/detail/input_format.hpp delete mode 100644 third_party/osmium/io/detail/opl_output_format.hpp delete mode 100644 third_party/osmium/io/detail/output_format.hpp delete mode 100644 third_party/osmium/io/detail/pbf.hpp delete mode 100644 third_party/osmium/io/detail/pbf_input_format.hpp delete mode 100644 third_party/osmium/io/detail/pbf_output_format.hpp delete mode 100644 third_party/osmium/io/detail/pbf_parser.hpp delete mode 100644 third_party/osmium/io/detail/pbf_stringtable.hpp delete mode 100644 third_party/osmium/io/detail/read_thread.hpp delete mode 100644 third_party/osmium/io/detail/read_write.hpp delete mode 100644 third_party/osmium/io/detail/write_thread.hpp delete mode 100644 third_party/osmium/io/detail/xml_input_format.hpp delete mode 100644 third_party/osmium/io/detail/xml_output_format.hpp delete mode 100644 third_party/osmium/io/detail/zlib.hpp delete mode 100644 third_party/osmium/io/error.hpp delete mode 100644 third_party/osmium/io/file.hpp delete mode 100644 third_party/osmium/io/file_compression.hpp delete mode 100644 third_party/osmium/io/file_format.hpp delete mode 100644 third_party/osmium/io/gzip_compression.hpp delete mode 100644 third_party/osmium/io/header.hpp delete mode 100644 third_party/osmium/io/input_iterator.hpp delete mode 100644 third_party/osmium/io/opl_output.hpp delete mode 100644 third_party/osmium/io/output_iterator.hpp delete mode 100644 third_party/osmium/io/overwrite.hpp delete mode 100644 third_party/osmium/io/pbf_input.hpp delete mode 100644 third_party/osmium/io/pbf_output.hpp delete mode 100644 third_party/osmium/io/reader.hpp delete mode 100644 third_party/osmium/io/reader_iterator.hpp delete mode 100644 third_party/osmium/io/writer.hpp delete mode 100644 third_party/osmium/io/xml_input.hpp delete mode 100644 third_party/osmium/io/xml_output.hpp delete mode 100644 third_party/osmium/memory/buffer.hpp delete mode 100644 third_party/osmium/memory/collection.hpp delete mode 100644 third_party/osmium/memory/item.hpp delete mode 100644 third_party/osmium/memory/item_iterator.hpp delete mode 100644 third_party/osmium/object_pointer_collection.hpp delete mode 100644 third_party/osmium/osm.hpp delete mode 100644 third_party/osmium/osm/area.hpp delete mode 100644 third_party/osmium/osm/box.hpp delete mode 100644 third_party/osmium/osm/changeset.hpp delete mode 100644 third_party/osmium/osm/diff_object.hpp delete mode 100644 third_party/osmium/osm/entity.hpp delete mode 100644 third_party/osmium/osm/entity_bits.hpp delete mode 100644 third_party/osmium/osm/item_type.hpp delete mode 100644 third_party/osmium/osm/location.hpp delete mode 100644 third_party/osmium/osm/node.hpp delete mode 100644 third_party/osmium/osm/node_ref.hpp delete mode 100644 third_party/osmium/osm/node_ref_list.hpp delete mode 100644 third_party/osmium/osm/object.hpp delete mode 100644 third_party/osmium/osm/object_comparisons.hpp delete mode 100644 third_party/osmium/osm/relation.hpp delete mode 100644 third_party/osmium/osm/segment.hpp delete mode 100644 third_party/osmium/osm/tag.hpp delete mode 100644 third_party/osmium/osm/timestamp.hpp delete mode 100644 third_party/osmium/osm/types.hpp delete mode 100644 third_party/osmium/osm/undirected_segment.hpp delete mode 100644 third_party/osmium/osm/way.hpp delete mode 100644 third_party/osmium/relations/collector.hpp delete mode 100644 third_party/osmium/relations/detail/member_meta.hpp delete mode 100644 third_party/osmium/relations/detail/relation_meta.hpp delete mode 100644 third_party/osmium/tags/filter.hpp delete mode 100644 third_party/osmium/tags/regex_filter.hpp delete mode 100644 third_party/osmium/tags/taglist.hpp delete mode 100644 third_party/osmium/thread/checked_task.hpp delete mode 100644 third_party/osmium/thread/function_wrapper.hpp delete mode 100644 third_party/osmium/thread/name.hpp delete mode 100644 third_party/osmium/thread/pool.hpp delete mode 100644 third_party/osmium/thread/queue.hpp delete mode 100644 third_party/osmium/thread/sorted_queue.hpp delete mode 100644 third_party/osmium/thread/util.hpp delete mode 100644 third_party/osmium/util/cast.hpp delete mode 100644 third_party/osmium/util/compatibility.hpp delete mode 100644 third_party/osmium/util/config.hpp delete mode 100644 third_party/osmium/util/double.hpp delete mode 100644 third_party/osmium/util/options.hpp delete mode 100644 third_party/osmium/util/verbose_output.hpp delete mode 100644 third_party/osmium/visitor.hpp diff --git a/third_party/osmium/area/assembler.hpp b/third_party/osmium/area/assembler.hpp deleted file mode 100644 index 155fa24c2..000000000 --- a/third_party/osmium/area/assembler.hpp +++ /dev/null @@ -1,783 +0,0 @@ -#ifndef OSMIUM_AREA_ASSEMBLER_HPP -#define OSMIUM_AREA_ASSEMBLER_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2014 Jochen Topf 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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace osmium { - - namespace area { - - using osmium::area::detail::ProtoRing; - - struct AssemblerConfig { - - osmium::area::ProblemReporter* problem_reporter; - - // Enables debug output to stderr - bool debug; - - explicit AssemblerConfig(osmium::area::ProblemReporter* pr = nullptr, bool d=false) : - problem_reporter(pr), - debug(d) { - } - - /** - * Enable or disable debug output to stderr. This is for Osmium - * developers only. - */ - void enable_debug_output(bool d=true) { - debug = d; - } - - }; // struct AssemblerConfig - - /** - * Assembles area objects from multipolygon relations and their - * members. This is called by the MultipolygonCollector object - * after all members have been collected. - */ - class Assembler { - - const AssemblerConfig m_config; - - // The way segments - osmium::area::detail::SegmentList m_segment_list; - - // The rings we are building from the way segments - std::list m_rings; - - std::vector m_outer_rings; - std::vector m_inner_rings; - - int m_inner_outer_mismatches { 0 }; - - bool debug() const { - return m_config.debug; - } - - /** - * Checks whether the given NodeRefs have the same location. - * Uses the actual location for the test, not the id. If both - * have the same location, but not the same id, a problem - * point will be added to the list of problem points. - */ - bool has_same_location(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) { - if (nr1.location() != nr2.location()) { - return false; - } - if (nr1.ref() != nr2.ref()) { - if (m_config.problem_reporter) { - m_config.problem_reporter->report_duplicate_node(nr1.ref(), nr2.ref(), nr1.location()); - } - } - return true; - } - - void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Way& way) const { - osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder); - for (const osmium::Tag& tag : way.tags()) { - tl_builder.add_tag(tag.key(), tag.value()); - } - } - - void add_common_tags(osmium::builder::TagListBuilder& tl_builder, std::set& ways) const { - std::map counter; - for (const osmium::Way* way : ways) { - for (const auto& tag : way->tags()) { - std::string kv {tag.key()}; - kv.append(1, '\0'); - kv.append(tag.value()); - ++counter[kv]; - } - } - - size_t num_ways = ways.size(); - for (const auto& t_c : counter) { - if (debug()) { - std::cerr << " tag " << t_c.first << " is used " << t_c.second << " times in " << num_ways << " ways\n"; - } - if (t_c.second == num_ways) { - size_t len = std::strlen(t_c.first.c_str()); - tl_builder.add_tag(t_c.first.c_str(), t_c.first.c_str() + len + 1); - } - } - } - - struct MPFilter : public osmium::tags::KeyFilter { - - MPFilter() : osmium::tags::KeyFilter(true) { - add(false, "type"); - add(false, "created_by"); - add(false, "source"); - add(false, "note"); - add(false, "test:id"); - add(false, "test:section"); - } - - }; // struct MPFilter - - static MPFilter& filter() { - static MPFilter filter; - return filter; - } - - void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Relation& relation) const { - auto count = std::count_if(relation.tags().begin(), relation.tags().end(), filter()); - - if (debug()) { - std::cerr << " found " << count << " tags on relation (without ignored ones)\n"; - } - - if (count > 0) { - if (debug()) { - std::cerr << " use tags from relation\n"; - } - - // write out all tags except type=* - osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder); - for (const osmium::Tag& tag : relation.tags()) { - if (strcmp(tag.key(), "type")) { - tl_builder.add_tag(tag.key(), tag.value()); - } - } - } else { - if (debug()) { - std::cerr << " use tags from outer ways\n"; - } - std::set ways; - for (const auto& ring : m_outer_rings) { - ring->get_ways(ways); - } - if (ways.size() == 1) { - if (debug()) { - std::cerr << " only one outer way\n"; - } - osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder); - for (const osmium::Tag& tag : (*ways.begin())->tags()) { - tl_builder.add_tag(tag.key(), tag.value()); - } - } else { - if (debug()) { - std::cerr << " multiple outer ways, get common tags\n"; - } - osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder); - add_common_tags(tl_builder, ways); - } - } - } - - /** - * Go through all the rings and find rings that are not closed. - * Problems are reported through the problem reporter. - * - * @returns true if any rings were not closed, false otherwise - */ - bool check_for_open_rings() { - bool open_rings = false; - - for (const auto& ring : m_rings) { - if (!ring.closed()) { - open_rings = true; - if (m_config.problem_reporter) { - m_config.problem_reporter->report_ring_not_closed(ring.get_segment_front().first().location(), ring.get_segment_back().second().location()); - } - } - } - - return open_rings; - } - - /** - * Check whether there are any rings that can be combined with the - * given ring to one larger ring by appending the other ring to - * the end of this ring. - * If the rings can be combined they are and the function returns - * true. - */ - bool possibly_combine_rings_back(ProtoRing& ring) { - const osmium::NodeRef& nr = ring.get_segment_back().second(); - - if (debug()) { - std::cerr << " possibly_combine_rings_back()\n"; - } - for (auto it = m_rings.begin(); it != m_rings.end(); ++it) { - if (&*it != &ring && !it->closed()) { - if (has_same_location(nr, it->get_segment_front().first())) { - if (debug()) { - std::cerr << " ring.last=it->first\n"; - } - ring.merge_ring(*it, debug()); - m_rings.erase(it); - return true; - } - if (has_same_location(nr, it->get_segment_back().second())) { - if (debug()) { - std::cerr << " ring.last=it->last\n"; - } - ring.merge_ring_reverse(*it, debug()); - m_rings.erase(it); - return true; - } - } - } - return false; - } - - /** - * Check whether there are any rings that can be combined with the - * given ring to one larger ring by prepending the other ring to - * the start of this ring. - * If the rings can be combined they are and the function returns - * true. - */ - bool possibly_combine_rings_front(ProtoRing& ring) { - const osmium::NodeRef& nr = ring.get_segment_front().first(); - - if (debug()) { - std::cerr << " possibly_combine_rings_front()\n"; - } - for (auto it = m_rings.begin(); it != m_rings.end(); ++it) { - if (&*it != &ring && !it->closed()) { - if (has_same_location(nr, it->get_segment_back().second())) { - if (debug()) { - std::cerr << " ring.first=it->last\n"; - } - ring.swap_segments(*it); - ring.merge_ring(*it, debug()); - m_rings.erase(it); - return true; - } - if (has_same_location(nr, it->get_segment_front().first())) { - if (debug()) { - std::cerr << " ring.first=it->first\n"; - } - ring.reverse(); - ring.merge_ring(*it, debug()); - m_rings.erase(it); - return true; - } - } - } - return false; - } - - void split_off_subring(osmium::area::detail::ProtoRing& ring, osmium::area::detail::ProtoRing::segments_type::iterator it, osmium::area::detail::ProtoRing::segments_type::iterator it_begin, osmium::area::detail::ProtoRing::segments_type::iterator it_end) { - if (debug()) { - std::cerr << " subring found at: " << *it << "\n"; - } - ProtoRing new_ring(it_begin, it_end); - ring.remove_segments(it_begin, it_end); - if (debug()) { - std::cerr << " split into two rings:\n"; - std::cerr << " " << new_ring << "\n"; - std::cerr << " " << ring << "\n"; - } - m_rings.push_back(std::move(new_ring)); - } - - bool has_closed_subring_back(ProtoRing& ring, const NodeRef& nr) { - if (ring.segments().size() < 3) { - return false; - } - if (debug()) { - std::cerr << " has_closed_subring_back()\n"; - } - auto end = ring.segments().end(); - for (auto it = ring.segments().begin() + 1; it != end - 1; ++it) { - if (has_same_location(nr, it->first())) { - split_off_subring(ring, it, it, end); - return true; - } - } - return false; - } - - bool has_closed_subring_front(ProtoRing& ring, const NodeRef& nr) { - if (ring.segments().size() < 3) { - return false; - } - if (debug()) { - std::cerr << " has_closed_subring_front()\n"; - } - auto end = ring.segments().end(); - for (auto it = ring.segments().begin() + 1; it != end - 1; ++it) { - if (has_same_location(nr, it->second())) { - split_off_subring(ring, it, ring.segments().begin(), it+1); - return true; - } - } - return false; - } - - bool check_for_closed_subring(ProtoRing& ring) { - if (debug()) { - std::cerr << " check_for_closed_subring()\n"; - } - - osmium::area::detail::ProtoRing::segments_type segments(ring.segments().size()); - std::copy(ring.segments().begin(), ring.segments().end(), segments.begin()); - std::sort(segments.begin(), segments.end()); - auto it = std::adjacent_find(segments.begin(), segments.end(), [this](const osmium::area::detail::NodeRefSegment& s1, const osmium::area::detail::NodeRefSegment& s2) { - return has_same_location(s1.first(), s2.first()); - }); - if (it == segments.end()) { - return false; - } - auto r1 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it, it+1); - assert(r1 != ring.segments().end()); - auto r2 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it+1, it+2); - assert(r2 != ring.segments().end()); - - if (debug()) { - std::cerr << " found subring in ring " << ring << " at " << it->first() << "\n"; - } - - auto m = std::minmax(r1, r2); - - ProtoRing new_ring(m.first, m.second); - ring.remove_segments(m.first, m.second); - - if (debug()) { - std::cerr << " split ring1=" << new_ring << "\n"; - std::cerr << " split ring2=" << ring << "\n"; - } - - m_rings.emplace_back(new_ring); - - return true; - } - - void combine_rings_front(const osmium::area::detail::NodeRefSegment& segment, ProtoRing& ring) { - if (debug()) { - std::cerr << " => match at front of ring\n"; - } - ring.add_segment_front(segment); - has_closed_subring_front(ring, segment.first()); - if (possibly_combine_rings_front(ring)) { - check_for_closed_subring(ring); - } - } - - void combine_rings_back(const osmium::area::detail::NodeRefSegment& segment, ProtoRing& ring) { - if (debug()) { - std::cerr << " => match at back of ring\n"; - } - ring.add_segment_back(segment); - has_closed_subring_back(ring, segment.second()); - if (possibly_combine_rings_back(ring)) { - check_for_closed_subring(ring); - } - } - - /** - * Append each outer ring together with its inner rings to the - * area in the buffer. - */ - void add_rings_to_area(osmium::builder::AreaBuilder& builder) const { - for (const ProtoRing* ring : m_outer_rings) { - if (debug()) { - std::cerr << " ring " << *ring << " is outer\n"; - } - { - osmium::builder::OuterRingBuilder ring_builder(builder.buffer(), &builder); - ring_builder.add_node_ref(ring->get_segment_front().first()); - for (const auto& segment : ring->segments()) { - ring_builder.add_node_ref(segment.second()); - } - } - for (ProtoRing* inner : ring->inner_rings()) { - osmium::builder::InnerRingBuilder ring_builder(builder.buffer(), &builder); - ring_builder.add_node_ref(inner->get_segment_front().first()); - for (const auto& segment : inner->segments()) { - ring_builder.add_node_ref(segment.second()); - } - } - } - } - - bool add_to_existing_ring(osmium::area::detail::NodeRefSegment segment) { - int n=0; - for (auto& ring : m_rings) { - if (debug()) { - std::cerr << " check against ring " << n << " " << ring; - } - if (ring.closed()) { - if (debug()) { - std::cerr << " => ring CLOSED\n"; - } - } else { - if (has_same_location(ring.get_segment_back().second(), segment.first())) { - combine_rings_back(segment, ring); - return true; - } - if (has_same_location(ring.get_segment_back().second(), segment.second())) { - segment.swap_locations(); - combine_rings_back(segment, ring); - return true; - } - if (has_same_location(ring.get_segment_front().first(), segment.first())) { - segment.swap_locations(); - combine_rings_front(segment, ring); - return true; - } - if (has_same_location(ring.get_segment_front().first(), segment.second())) { - combine_rings_front(segment, ring); - return true; - } - if (debug()) { - std::cerr << " => no match\n"; - } - } - - ++n; - } - return false; - } - - void check_inner_outer(ProtoRing& ring) { - const osmium::NodeRef& min_node = ring.min_node(); - if (debug()) { - std::cerr << " check_inner_outer min_node=" << min_node << "\n"; - } - - int count = 0; - int above = 0; - - for (auto it = m_segment_list.begin(); it != m_segment_list.end() && it->first().location().x() <= min_node.location().x(); ++it) { - if (!ring.contains(*it)) { - if (debug()) { - std::cerr << " segments for count: " << *it; - } - if (it->to_left_of(min_node.location())) { - ++count; - if (debug()) { - std::cerr << " counted\n"; - } - } else { - if (debug()) { - std::cerr << " not counted\n"; - } - } - if (it->first().location() == min_node.location()) { - if (it->second().location().y() > min_node.location().y()) { - ++above; - } - } - if (it->second().location() == min_node.location()) { - if (it->first().location().y() > min_node.location().y()) { - ++above; - } - } - } - } - - if (debug()) { - std::cerr << " count=" << count << " above=" << above << "\n"; - } - - count += above % 2; - - if (count % 2) { - ring.set_inner(); - } - } - - void check_inner_outer_roles() { - if (debug()) { - std::cerr << " check_inner_outer_roles\n"; - } - - for (const auto ringptr : m_outer_rings) { - for (const auto segment : ringptr->segments()) { - if (!segment.role_outer()) { - ++m_inner_outer_mismatches; - if (debug()) { - std::cerr << " segment " << segment << " from way " << segment.way()->id() << " should have role 'outer'\n"; - } - if (m_config.problem_reporter) { - m_config.problem_reporter->report_role_should_be_outer(segment.way()->id(), segment.first().location(), segment.second().location()); - } - } - } - } - for (const auto ringptr : m_inner_rings) { - for (const auto segment : ringptr->segments()) { - if (!segment.role_inner()) { - ++m_inner_outer_mismatches; - if (debug()) { - std::cerr << " segment " << segment << " from way " << segment.way()->id() << " should have role 'inner'\n"; - } - if (m_config.problem_reporter) { - m_config.problem_reporter->report_role_should_be_inner(segment.way()->id(), segment.first().location(), segment.second().location()); - } - } - } - } - } - - /** - * Create rings from segments. - */ - bool create_rings() { - m_segment_list.sort(); - m_segment_list.erase_duplicate_segments(); - - // Now we look for segments crossing each other. If there are - // any, the multipolygon is invalid. - // In the future this could be improved by trying to fix those - // cases. - if (m_segment_list.find_intersections(m_config.problem_reporter)) { - return false; - } - - // Now iterator over all segments and add them to rings. Each segment - // is tacked on to either end of an existing ring if possible, or a - // new ring is started with it. - for (const auto& segment : m_segment_list) { - if (debug()) { - std::cerr << " checking segment " << segment << "\n"; - } - if (!add_to_existing_ring(segment)) { - if (debug()) { - std::cerr << " new ring for segment " << segment << "\n"; - } - m_rings.emplace_back(segment); - } - } - - if (debug()) { - std::cerr << " Rings:\n"; - for (const auto& ring : m_rings) { - std::cerr << " " << ring; - if (ring.closed()) { - std::cerr << " (closed)"; - } - std::cerr << "\n"; - } - } - - if (check_for_open_rings()) { - if (debug()) { - std::cerr << " not all rings are closed\n"; - } - return false; - } - - if (debug()) { - std::cerr << " Find inner/outer...\n"; - } - - if (m_rings.size() == 1) { - m_outer_rings.push_back(&m_rings.front()); - } else { - for (auto& ring : m_rings) { - check_inner_outer(ring); - if (ring.outer()) { - if (!ring.is_cw()) { - ring.reverse(); - } - m_outer_rings.push_back(&ring); - } else { - if (ring.is_cw()) { - ring.reverse(); - } - m_inner_rings.push_back(&ring); - } - } - - if (m_outer_rings.size() == 1) { - for (auto inner : m_inner_rings) { - m_outer_rings.front()->add_inner_ring(inner); - } - } else { - // sort outer rings by size, smallest first - std::sort(m_outer_rings.begin(), m_outer_rings.end(), [](ProtoRing* a, ProtoRing* b) { - return a->area() < b->area(); - }); - for (auto inner : m_inner_rings) { - for (auto outer : m_outer_rings) { - if (inner->is_in(outer)) { - outer->add_inner_ring(inner); - break; - } - } - } - } - } - - check_inner_outer_roles(); - - return true; - } - - public: - - typedef osmium::area::AssemblerConfig config_type; - - explicit Assembler(const config_type& config) : - m_config(config), - m_segment_list(config.debug) { - } - - ~Assembler() = default; - - /** - * Assemble an area from the given way. - * The resulting area is put into the out_buffer. - */ - void operator()(const osmium::Way& way, osmium::memory::Buffer& out_buffer) { - if (m_config.problem_reporter) { - m_config.problem_reporter->set_object(osmium::item_type::way, way.id()); - } - - if (!way.ends_have_same_id()) { - if (m_config.problem_reporter) { - m_config.problem_reporter->report_duplicate_node(way.nodes().front().ref(), way.nodes().back().ref(), way.nodes().front().location()); - } - } - - m_segment_list.extract_segments_from_way(way, "outer"); - - if (debug()) { - std::cerr << "\nBuild way id()=" << way.id() << " segments.size()=" << m_segment_list.size() << "\n"; - } - - // Now create the Area object and add the attributes and tags - // from the relation. - { - osmium::builder::AreaBuilder builder(out_buffer); - builder.initialize_from_object(way); - - if (create_rings()) { - add_tags_to_area(builder, way); - add_rings_to_area(builder); - } - } - out_buffer.commit(); - } - - /** - * Assemble an area from the given relation and its members. - * All members are to be found in the in_buffer at the offsets - * given by the members parameter. - * The resulting area is put into the out_buffer. - */ - void operator()(const osmium::Relation& relation, const std::vector& members, const osmium::memory::Buffer& in_buffer, osmium::memory::Buffer& out_buffer) { - if (m_config.problem_reporter) { - m_config.problem_reporter->set_object(osmium::item_type::relation, relation.id()); - } - - m_segment_list.extract_segments_from_ways(relation, members, in_buffer); - - if (debug()) { - std::cerr << "\nBuild relation id()=" << relation.id() << " members.size()=" << members.size() << " segments.size()=" << m_segment_list.size() << "\n"; - } - - size_t area_offset = out_buffer.committed(); - - // Now create the Area object and add the attributes and tags - // from the relation. - { - osmium::builder::AreaBuilder builder(out_buffer); - builder.initialize_from_object(relation); - - if (create_rings()) { - add_tags_to_area(builder, relation); - add_rings_to_area(builder); - } - } - out_buffer.commit(); - - const osmium::TagList& area_tags = out_buffer.get(area_offset).tags(); // tags of the area we just built - - // Find all closed ways that are inner rings and check their - // tags. If they are not the same as the tags of the area we - // just built, add them to a list and later build areas for - // them, too. - std::vector ways_that_should_be_areas; - if (m_inner_outer_mismatches == 0) { - auto memit = relation.members().begin(); - for (size_t offset : members) { - if (!std::strcmp(memit->role(), "inner")) { - const osmium::Way& way = in_buffer.get(offset); - if (way.is_closed() && way.tags().size() > 0) { - auto d = std::count_if(way.tags().begin(), way.tags().end(), filter()); - if (d > 0) { - osmium::tags::KeyFilter::iterator way_fi_begin(filter(), way.tags().begin(), way.tags().end()); - osmium::tags::KeyFilter::iterator way_fi_end(filter(), way.tags().end(), way.tags().end()); - osmium::tags::KeyFilter::iterator area_fi_begin(filter(), area_tags.begin(), area_tags.end()); - osmium::tags::KeyFilter::iterator area_fi_end(filter(), area_tags.end(), area_tags.end()); - - if (!std::equal(way_fi_begin, way_fi_end, area_fi_begin) || d != std::distance(area_fi_begin, area_fi_end)) { - ways_that_should_be_areas.push_back(&way); - } - } - } - } - ++memit; - } - } - - // Now build areas for all ways found in the last step. - for (const osmium::Way* way : ways_that_should_be_areas) { - Assembler assembler(m_config); - assembler(*way, out_buffer); - } - } - - }; // class Assembler - - } // namespace area - -} // namespace osmium - -#endif // OSMIUM_AREA_ASSEMBLER_HPP diff --git a/third_party/osmium/area/detail/node_ref_segment.hpp b/third_party/osmium/area/detail/node_ref_segment.hpp deleted file mode 100644 index 5b251bb5b..000000000 --- a/third_party/osmium/area/detail/node_ref_segment.hpp +++ /dev/null @@ -1,262 +0,0 @@ -#ifndef OSMIUM_AREA_DETAIL_NODE_REF_SEGMENT_HPP -#define OSMIUM_AREA_DETAIL_NODE_REF_SEGMENT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2014 Jochen Topf 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 -#include -#include -#include -#include - -#include -#include - -namespace osmium { - - class Way; - - namespace area { - - /** - * @brief Namespace for Osmium internal use - */ - namespace detail { - - /** - * This helper class for the Assembler class models a segment. - * Segments are the connection between - * two nodes and they all have their smaller coordinate at the - * beginning of the segment. Smaller, in this case, means smaller x - * coordinate, and if they are the same smaller y coordinate. - */ - class NodeRefSegment { - - osmium::NodeRef m_first; - osmium::NodeRef m_second; - - /// Role of the member this segment was from. - const char* m_role; - - /// Way this segment was from. - const osmium::Way* m_way; - - public: - - void swap_locations() { - using std::swap; - swap(m_first, m_second); - } - - explicit NodeRefSegment() noexcept : - m_first(), - m_second(), - m_role(nullptr), - m_way(nullptr) { - } - - explicit NodeRefSegment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2, const char* role, const osmium::Way* way) : - m_first(nr1), - m_second(nr2), - m_role(role), - m_way(way) { - if (nr2.location() < nr1.location()) { - swap_locations(); - } - } - - NodeRefSegment(const NodeRefSegment&) = default; - NodeRefSegment(NodeRefSegment&&) = default; - - NodeRefSegment& operator=(const NodeRefSegment&) = default; - NodeRefSegment& operator=(NodeRefSegment&&) = default; - - ~NodeRefSegment() = default; - - /// Return first NodeRef of Segment according to sorting order (bottom left to top right). - const osmium::NodeRef& first() const noexcept { - return m_first; - } - - /// Return second NodeRef of Segment according to sorting order (bottom left to top right). - const osmium::NodeRef& second() const noexcept { - return m_second; - } - - bool to_left_of(const osmium::Location location) const { - // std::cerr << "segment " << first() << "--" << second() << " to_left_of(" << location << "\n"; - - if (first().location() == location || second().location() == location) { - return false; - } - - const std::pair mm = std::minmax(first().location(), second().location(), [](const osmium::Location a, const osmium::Location b) { - return a.y() < b.y(); - }); - - if (mm.first.y() >= location.y() || mm.second.y() < location.y() || first().location().x() > location.x()) { - // std::cerr << " false\n"; - return false; - } - - int64_t ax = mm.first.x(); - int64_t bx = mm.second.x(); - int64_t lx = location.x(); - int64_t ay = mm.first.y(); - int64_t by = mm.second.y(); - int64_t ly = location.y(); - return ((bx - ax)*(ly - ay) - (by - ay)*(lx - ax)) <= 0; - } - - bool role_outer() const noexcept { - return !strcmp(m_role, "outer"); - } - - bool role_inner() const noexcept { - return !strcmp(m_role, "inner"); - } - - const osmium::Way* way() const noexcept { - return m_way; - } - - }; // class NodeRefSegment - - /// NodeRefSegments are equal if both their locations are equal - inline bool operator==(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept { - return lhs.first().location() == rhs.first().location() && lhs.second().location() == rhs.second().location(); - } - - inline bool operator!=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept { - return ! (lhs == rhs); - } - - /** - * NodeRefSegments are "smaller" if they are to the left and down of another - * segment. The first() location is checked first() and only if they have the - * same first() location the second() location is taken into account. - */ - inline bool operator<(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept { - return (lhs.first().location() == rhs.first().location() && lhs.second().location() < rhs.second().location()) || lhs.first().location() < rhs.first().location(); - } - - inline bool operator>(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept { - return rhs < lhs; - } - - inline bool operator<=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept { - return ! (rhs < lhs); - } - - inline bool operator>=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept { - return ! (lhs < rhs); - } - - template - inline std::basic_ostream& operator<<(std::basic_ostream& out, const NodeRefSegment& segment) { - return out << segment.first() << "--" << segment.second(); - } - - inline bool outside_x_range(const NodeRefSegment& s1, const NodeRefSegment& s2) noexcept { - if (s1.first().location().x() > s2.second().location().x()) { - return true; - } - return false; - } - - inline bool y_range_overlap(const NodeRefSegment& s1, const NodeRefSegment& s2) { - auto m1 = std::minmax(s1.first().location().y(), s1.second().location().y()); - auto m2 = std::minmax(s2.first().location().y(), s2.second().location().y()); - if (m1.first > m2.second || m2.first > m1.second) { - return false; - } - return true; - } - - /** - * Calculate the intersection between to NodeRefSegments. The result is returned - * as a Location. Note that because the Location uses integers with limited - * precision internally, the result might be slightly different than the - * numerically correct location. - * - * If the segments touch in one of their endpoints, it doesn't count as an - * intersection. - * - * If the segments intersect not in a single point but in multiple points, ie - * if they overlap, this is NOT detected. - * - * @returns Undefined osmium::Location if there is no intersection or a defined - * Location if the segments intersect. - */ - inline osmium::Location calculate_intersection(const NodeRefSegment& s1, const NodeRefSegment& s2) { - if (s1.first().location() == s2.first().location() || - s1.first().location() == s2.second().location() || - s1.second().location() == s2.first().location() || - s1.second().location() == s2.second().location()) { - return osmium::Location(); - } - - auto d = (static_cast(s2.second().y()) - static_cast(s2.first().y())) * - (static_cast(s1.second().x()) - static_cast(s1.first().x())) - - (static_cast(s2.second().x()) - static_cast(s2.first().x())) * - (static_cast(s1.second().y()) - static_cast(s1.first().y())); - - if (d != 0) { - double denom = ((s2.second().lat() - s2.first().lat())*(s1.second().lon() - s1.first().lon())) - - ((s2.second().lon() - s2.first().lon())*(s1.second().lat() - s1.first().lat())); - - double nume_a = ((s2.second().lon() - s2.first().lon())*(s1.first().lat() - s2.first().lat())) - - ((s2.second().lat() - s2.first().lat())*(s1.first().lon() - s2.first().lon())); - - double nume_b = ((s1.second().lon() - s1.first().lon())*(s1.first().lat() - s2.first().lat())) - - ((s1.second().lat() - s1.first().lat())*(s1.first().lon() - s2.first().lon())); - - if ((denom > 0 && nume_a >= 0 && nume_a <= denom && nume_b >= 0 && nume_b <= denom) || - (denom < 0 && nume_a <= 0 && nume_a >= denom && nume_b <= 0 && nume_b >= denom)) { - double ua = nume_a / denom; - double ix = s1.first().lon() + ua*(s1.second().lon() - s1.first().lon()); - double iy = s1.first().lat() + ua*(s1.second().lat() - s1.first().lat()); - return osmium::Location(ix, iy); - } - } - - return osmium::Location(); - } - - } // namespace detail - - } // namespace area - -} // namespace osmium - -#endif // OSMIUM_AREA_DETAIL_NODE_REF_SEGMENT_HPP diff --git a/third_party/osmium/area/detail/proto_ring.hpp b/third_party/osmium/area/detail/proto_ring.hpp deleted file mode 100644 index 63fec5b79..000000000 --- a/third_party/osmium/area/detail/proto_ring.hpp +++ /dev/null @@ -1,274 +0,0 @@ -#ifndef OSMIUM_AREA_DETAIL_PROTO_RING_HPP -#define OSMIUM_AREA_DETAIL_PROTO_RING_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2014 Jochen Topf 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 -#include -#include -#include -#include -#include - -#include -#include - -namespace osmium { - - namespace area { - - namespace detail { - - /** - * A ring in the process of being built by the Assembler object. - */ - class ProtoRing { - - public: - - typedef std::vector segments_type; - - private: - - // segments in this ring - segments_type m_segments; - - bool m_outer {true}; - - // if this is an outer ring, these point to it's inner rings (if any) - std::vector m_inner; - - public: - - explicit ProtoRing(const NodeRefSegment& segment) noexcept : - m_segments() { - add_segment_back(segment); - } - - explicit ProtoRing(segments_type::const_iterator sbegin, segments_type::const_iterator send) : - m_segments(static_cast(std::distance(sbegin, send))) { - std::copy(sbegin, send, m_segments.begin()); - } - - bool outer() const noexcept { - return m_outer; - } - - void set_inner() noexcept { - m_outer = false; - } - - segments_type& segments() noexcept { - return m_segments; - } - - const segments_type& segments() const noexcept { - return m_segments; - } - - void remove_segments(segments_type::iterator sbegin, segments_type::iterator send) { - m_segments.erase(sbegin, send); - } - - void add_segment_front(const NodeRefSegment& segment) { - m_segments.insert(m_segments.begin(), segment); - } - - void add_segment_back(const NodeRefSegment& segment) { - m_segments.push_back(segment); - } - - const NodeRefSegment& get_segment_front() const { - return m_segments.front(); - } - - NodeRefSegment& get_segment_front() { - return m_segments.front(); - } - - const NodeRefSegment& get_segment_back() const { - return m_segments.back(); - } - - NodeRefSegment& get_segment_back() { - return m_segments.back(); - } - - bool closed() const { - return m_segments.front().first().location() == m_segments.back().second().location(); - } - - int64_t sum() const { - int64_t sum = 0; - - for (const auto& segment : m_segments) { - sum += static_cast(segment.first().location().x()) * static_cast(segment.second().location().y()) - - static_cast(segment.second().location().x()) * static_cast(segment.first().location().y()); - } - - return sum; - } - - bool is_cw() const { - return sum() <= 0; - } - - int64_t area() const { - return std::abs(sum()) / 2; - } - - void swap_segments(ProtoRing& other) { - std::swap(m_segments, other.m_segments); - } - - void add_inner_ring(ProtoRing* ring) { - m_inner.push_back(ring); - } - - const std::vector inner_rings() const { - return m_inner; - } - - void print(std::ostream& out) const { - out << "["; - bool first = true; - for (const auto& segment : m_segments) { - if (first) { - out << segment.first().ref(); - } - out << ',' << segment.second().ref(); - first = false; - } - out << "]"; - } - - void reverse() { - std::for_each(m_segments.begin(), m_segments.end(), [](NodeRefSegment& segment) { - segment.swap_locations(); - }); - std::reverse(m_segments.begin(), m_segments.end()); - } - - /** - * Merge other ring to end of this ring. - */ - void merge_ring(const ProtoRing& other, bool debug) { - if (debug) { - std::cerr << " MERGE rings "; - print(std::cerr); - std::cerr << " to "; - other.print(std::cerr); - std::cerr << "\n"; - } - m_segments.insert(m_segments.end(), other.m_segments.begin(), other.m_segments.end()); - if (debug) { - std::cerr << " result ring: "; - print(std::cerr); - std::cerr << "\n"; - } - } - - void merge_ring_reverse(const ProtoRing& other, bool debug) { - if (debug) { - std::cerr << " MERGE rings (reverse) "; - print(std::cerr); - std::cerr << " to "; - other.print(std::cerr); - std::cerr << "\n"; - } - size_t n = m_segments.size(); - m_segments.resize(n + other.m_segments.size()); - std::transform(other.m_segments.rbegin(), other.m_segments.rend(), m_segments.begin() + static_cast(n), [](NodeRefSegment segment) { - segment.swap_locations(); - return segment; - }); - if (debug) { - std::cerr << " result ring: "; - print(std::cerr); - std::cerr << "\n"; - } - } - - const NodeRef& min_node() const { - auto it = std::min_element(m_segments.begin(), m_segments.end()); - if (location_less()(it->first(), it->second())) { - return it->first(); - } else { - return it->second(); - } - } - - bool is_in(ProtoRing* outer) { - osmium::Location testpoint = segments().front().first().location(); - bool is_in = false; - - for (size_t i = 0, j = outer->segments().size()-1; i < outer->segments().size(); j = i++) { - if (((outer->segments()[i].first().location().y() > testpoint.y()) != (outer->segments()[j].first().location().y() > testpoint.y())) && - (testpoint.x() < (outer->segments()[j].first().location().x() - outer->segments()[i].first().location().x()) * (testpoint.y() - outer->segments()[i].first().location().y()) / (outer->segments()[j].first().location().y() - outer->segments()[i].first().location().y()) + outer->segments()[i].first().location().x()) ) { - is_in = !is_in; - } - } - - return is_in; - } - - void get_ways(std::set& ways) { - for (const auto& segment : m_segments) { - ways.insert(segment.way()); - } - } - - bool contains(const NodeRefSegment& segment) const { - for (const auto& s : m_segments) { - if (s == segment || (s.first() == segment.second() && s.second() == segment.first())) { - return true; - } - } - return false; - } - - }; // class ProtoRing - - template - inline std::basic_ostream& operator<<(std::basic_ostream& out, const ProtoRing& ring) { - ring.print(out); - return out; - } - - } // namespace detail - - } // namespace area - -} // namespace osmium - -#endif // OSMIUM_AREA_DETAIL_PROTO_RING_HPP diff --git a/third_party/osmium/area/detail/segment_list.hpp b/third_party/osmium/area/detail/segment_list.hpp deleted file mode 100644 index a14f792e4..000000000 --- a/third_party/osmium/area/detail/segment_list.hpp +++ /dev/null @@ -1,216 +0,0 @@ -#ifndef OSMIUM_AREA_DETAIL_SEGMENT_LIST_HPP -#define OSMIUM_AREA_DETAIL_SEGMENT_LIST_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2014 Jochen Topf 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 -#include -#include -#include - -#include -#include -#include -#include -#include - -namespace osmium { - - namespace area { - - namespace detail { - - /** - * This is a helper class for the area assembler. It models - * a list of segments. - */ - class SegmentList { - - typedef std::vector slist_type; - - slist_type m_segments; - - bool m_debug; - - public: - - explicit SegmentList(bool debug) noexcept : - m_debug(debug) { - } - - ~SegmentList() = default; - - SegmentList(const SegmentList&) = delete; - SegmentList(SegmentList&&) = delete; - - SegmentList& operator=(const SegmentList&) = delete; - SegmentList& operator=(SegmentList&&) = delete; - - /// The number of segments in the list. - size_t size() const noexcept { - return m_segments.size(); - } - - bool empty() const noexcept { - return m_segments.empty(); - } - - typedef slist_type::const_iterator const_iterator; - - const_iterator begin() const noexcept { - return m_segments.begin(); - } - - const_iterator end() const noexcept { - return m_segments.end(); - } - - /** - * Enable or disable debug output to stderr. This is for Osmium - * developers only. - */ - void enable_debug_output(bool debug=true) noexcept { - m_debug = debug; - } - - /// Clear the list of segments. All segments are removed. - void clear() { - m_segments.clear(); - } - - /// Sort the list of segments. - void sort() { - std::sort(m_segments.begin(), m_segments.end()); - } - - /** - * Extract segments from given way and add them to the list. - * - * Segments connecting two nodes with the same location (ie same - * node or different node with same location) are removed. - * - * XXX should two nodes with same location be reported? - */ - void extract_segments_from_way(const osmium::Way& way, const char* role) { - osmium::NodeRef last_nr; - for (const osmium::NodeRef& nr : way.nodes()) { - if (last_nr.location() && last_nr.location() != nr.location()) { - m_segments.emplace_back(last_nr, nr, role, &way); - } - last_nr = nr; - } - } - - /** - * Extract all segments from all ways that make up this - * multipolygon relation and add them to the list. - */ - void extract_segments_from_ways(const osmium::Relation& relation, const std::vector& members, const osmium::memory::Buffer& in_buffer) { - auto member_it = relation.members().begin(); - for (size_t offset : members) { - const osmium::Way& way = in_buffer.get(offset); - extract_segments_from_way(way, member_it->role()); - ++member_it; - } - } - - /** - * Find duplicate segments (ie same start and end point) in the - * list and remove them. This will always remove pairs of the same - * segment. So if there are three, for instance, two will be - * removed and one will be left. - */ - void erase_duplicate_segments() { - while (true) { - auto it = std::adjacent_find(m_segments.begin(), m_segments.end()); - if (it == m_segments.end()) { - return; - } - if (m_debug) { - std::cerr << " erase duplicate segment: " << *it << "\n"; - } - m_segments.erase(it, it+2); - } - } - - /** - * Find intersection between segments. - * - * @param problem_reporter Any intersections found are reported to this object. - * @returns true if there are intersections. - */ - bool find_intersections(osmium::area::ProblemReporter* problem_reporter) const { - if (m_segments.empty()) { - return false; - } - - bool found_intersections = false; - - for (auto it1 = m_segments.begin(); it1 != m_segments.end()-1; ++it1) { - const NodeRefSegment& s1 = *it1; - for (auto it2 = it1+1; it2 != m_segments.end(); ++it2) { - const NodeRefSegment& s2 = *it2; - - assert(s1 != s2); // erase_duplicate_segments() should have made sure of that - - if (outside_x_range(s2, s1)) { - break; - } - - if (y_range_overlap(s1, s2)) { - osmium::Location intersection = calculate_intersection(s1, s2); - if (intersection) { - found_intersections = true; - if (m_debug) { - std::cerr << " segments " << s1 << " and " << s2 << " intersecting at " << intersection << "\n"; - } - if (problem_reporter) { - problem_reporter->report_intersection(s1.way()->id(), s1.first().location(), s1.second().location(), s2.way()->id(), s2.first().location(), s2.second().location(), intersection); - } - } - } - } - } - - return found_intersections; - } - - }; // class SegmentList - - } // namespace detail - - } // namespace area - -} // namespace osmium - -#endif // OSMIUM_AREA_DETAIL_SEGMENT_LIST_HPP diff --git a/third_party/osmium/area/multipolygon_collector.hpp b/third_party/osmium/area/multipolygon_collector.hpp deleted file mode 100644 index af48176d4..000000000 --- a/third_party/osmium/area/multipolygon_collector.hpp +++ /dev/null @@ -1,212 +0,0 @@ -#ifndef OSMIUM_AREA_MULTIPOLYGON_COLLECTOR_HPP -#define OSMIUM_AREA_MULTIPOLYGON_COLLECTOR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2014 Jochen Topf 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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace osmium { - - struct invalid_location; - - namespace relations { - class RelationMeta; - } - - /** - * @brief Code related to the building of areas (multipolygons) from relations. - */ - namespace area { - - /** - * This class collects all data needed for creating areas from - * relations tagged with type=multipolygon or type=boundary. - * Most of its functionality is derived from the parent class - * osmium::relations::Collector. - * - * The actual assembling of the areas is done by the assembler - * class given as template argument. - * - * @tparam TAssembler Multipolygon Assembler class. - */ - template - class MultipolygonCollector : public osmium::relations::Collector, false, true, false> { - - typedef typename osmium::relations::Collector, false, true, false> collector_type; - - typedef typename TAssembler::config_type assembler_config_type; - const assembler_config_type m_assembler_config; - - osmium::memory::Buffer m_output_buffer; - - static constexpr size_t initial_output_buffer_size = 1024 * 1024; - static constexpr size_t max_buffer_size_for_flush = 100 * 1024; - - void flush_output_buffer() { - if (this->callback()) { - osmium::memory::Buffer buffer(initial_output_buffer_size); - std::swap(buffer, m_output_buffer); - this->callback()(std::move(buffer)); - } - } - - void possibly_flush_output_buffer() { - if (m_output_buffer.committed() > max_buffer_size_for_flush) { - flush_output_buffer(); - } - } - - public: - - explicit MultipolygonCollector(const assembler_config_type& assembler_config) : - collector_type(), - m_assembler_config(assembler_config), - m_output_buffer(initial_output_buffer_size, osmium::memory::Buffer::auto_grow::yes) { - } - - /** - * We are interested in all relations tagged with type=multipolygon or - * type=boundary. - * - * Overwritten from the base class. - */ - bool keep_relation(const osmium::Relation& relation) const { - const char* type = relation.tags().get_value_by_key("type"); - - // ignore relations without "type" tag - if (!type) { - return false; - } - - if ((!strcmp(type, "multipolygon")) || (!strcmp(type, "boundary"))) { - return true; - } - - return false; - } - - /** - * Overwritten from the base class. - */ - bool keep_member(const osmium::relations::RelationMeta& /*relation_meta*/, const osmium::RelationMember& member) const { - // We are only interested in members of type way. - return member.type() == osmium::item_type::way; - } - - /** - * This is called when a way is not in any multipolygon - * relation. - * - * Overwritten from the base class. - */ - void way_not_in_any_relation(const osmium::Way& way) { - if (way.ends_have_same_location() && way.nodes().size() > 3) { - // way is closed and has enough nodes, build simple multipolygon - try { - TAssembler assembler(m_assembler_config); - assembler(way, m_output_buffer); - possibly_flush_output_buffer(); - } catch (osmium::invalid_location&) { - // XXX ignore - } - } - } - - void complete_relation(osmium::relations::RelationMeta& relation_meta) { - const osmium::Relation& relation = this->get_relation(relation_meta); - std::vector offsets; - for (const auto& member : relation.members()) { - if (member.ref() != 0) { - offsets.push_back(this->get_offset(member.type(), member.ref())); - } - } - try { - TAssembler assembler(m_assembler_config); - assembler(relation, offsets, this->members_buffer(), m_output_buffer); - possibly_flush_output_buffer(); - } catch (osmium::invalid_location&) { - // XXX ignore - } - - // clear member metas - for (const auto& member : relation.members()) { - if (member.ref() != 0) { - auto& mmv = this->member_meta(member.type()); - auto range = std::equal_range(mmv.begin(), mmv.end(), osmium::relations::MemberMeta(member.ref())); - assert(range.first != range.second); - - // if this is the last time this object was needed - // then mark it as removed - if (osmium::relations::count_not_removed(range.first, range.second) == 1) { - this->get_member(range.first->buffer_offset()).set_removed(true); - } - - for (auto it = range.first; it != range.second; ++it) { - if (!it->removed() && relation.id() == this->get_relation(it->relation_pos()).id()) { - it->remove(); - break; - } - } - } - } - } - - void flush() { - flush_output_buffer(); - } - - osmium::memory::Buffer read() { - osmium::memory::Buffer buffer(initial_output_buffer_size, osmium::memory::Buffer::auto_grow::yes); - std::swap(buffer, m_output_buffer); - return buffer; - } - - }; // class MultipolygonCollector - - } // namespace area - -} // namespace osmium - -#endif // OSMIUM_AREA_MULTIPOLYGON_COLLECTOR_HPP diff --git a/third_party/osmium/area/problem_reporter.hpp b/third_party/osmium/area/problem_reporter.hpp deleted file mode 100644 index 5e255db50..000000000 --- a/third_party/osmium/area/problem_reporter.hpp +++ /dev/null @@ -1,149 +0,0 @@ -#ifndef OSMIUM_AREA_PROBLEM_REPORTER_HPP -#define OSMIUM_AREA_PROBLEM_REPORTER_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2014 Jochen Topf 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 -#include -#include - -namespace osmium { - - namespace area { - - /** - * When assembling a multipolygon/area from a multipolygon relation - * or a closed way several problems can be detected. This includes - * intersections between lines, wrong role attributes on relation - * members etc. These problems are reported by the area::Assembler - * class to the ProblemReporter class or one of its child classes. - * - * This is the parent class which does nothing with the reports. - * Child classes are expected to implement different ways of - * reporting the problems. - */ - class ProblemReporter { - - protected: - - // Type of object we are currently working on - osmium::item_type m_object_type; - - // ID of the relation/way we are currently working on - osmium::object_id_type m_object_id; - - public: - - ProblemReporter() = default; - - virtual ~ProblemReporter() = default; - - /** - * Set the object the next problem reports will be on. - * - * @param object_type The type of the object. - * @param object_id The ID of the object. - */ - void set_object(osmium::item_type object_type, osmium::object_id_type object_id) noexcept { - m_object_type = object_type; - m_object_id = object_id; - } - -// Disable "unused-parameter" warning, so that the compiler will not complain. -// We can't remove the parameter names, because then doxygen will complain. -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" - - /** - * Report a duplicate node, ie. two nodes with the same location. - * - * @param node_id1 ID of the first node. - * @param node_id2 ID of the second node. - * @param location Location of both nodes. - */ - virtual void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location) { - } - - /** - * Report an intersection between two segments. - * - * @param way1_id ID of the first involved way. - * @param way1_seg_start Location where the segment of the first way with the intersection starts - * @param way1_seg_end Location where the segment of the first way with the intersection ends - * @param way2_id ID of the second involved way. - * @param way2_seg_start Location where the segment of the second way with the intersection starts - * @param way2_seg_end Location where the segment of the second way with the intersection ends - * @param intersection Location of the intersection. This might be slightly off the correct location due to rounding. - */ - virtual void report_intersection(osmium::object_id_type way1_id, osmium::Location way1_seg_start, osmium::Location way1_seg_end, - osmium::object_id_type way2_id, osmium::Location way2_seg_start, osmium::Location way2_seg_end, osmium::Location intersection) { - } - - /** - * Report an open ring. - * - * @param end1 Location of the first open end. - * @param end2 Location of the second open end. - */ - virtual void report_ring_not_closed(osmium::Location end1, osmium::Location end2) { - } - - /** - * Report a segment that should have role "outer", but has a different role. - * - * @param way_id ID of the way this segment is in. - * @param seg_start Start of the segment with the wrong role. - * @param seg_end End of the segment with the wrong role. - */ - virtual void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) { - } - - /** - * Report a segment that should have role "inner", but has a different role. - * - * @param way_id ID of the way this segment is in. - * @param seg_start Start of the segment with the wrong role. - * @param seg_end End of the segment with the wrong role. - */ - virtual void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) { - } - -#pragma GCC diagnostic pop - - }; // class ProblemReporter - - } // namespace area - -} // namespace osmium - -#endif // OSMIUM_AREA_PROBLEM_REPORTER_HPP diff --git a/third_party/osmium/area/problem_reporter_exception.hpp b/third_party/osmium/area/problem_reporter_exception.hpp deleted file mode 100644 index 29c7ad429..000000000 --- a/third_party/osmium/area/problem_reporter_exception.hpp +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef OSMIUM_AREA_PROBLEM_REPORTER_EXCEPTION_HPP -#define OSMIUM_AREA_PROBLEM_REPORTER_EXCEPTION_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2014 Jochen Topf 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 -#include - -#include -#include -#include - -namespace osmium { - - namespace area { - - class ProblemReporterException : public ProblemReporterStream { - - std::stringstream m_sstream; - - public: - - ProblemReporterException() : - ProblemReporterStream(m_sstream) { - } - - virtual ~ProblemReporterException() = default; - - void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location) override { - m_sstream.str(); - ProblemReporterStream::report_duplicate_node(node_id1, node_id2, location); - throw std::runtime_error(m_sstream.str()); - } - - void report_intersection(osmium::object_id_type way1_id, osmium::Location way1_seg_start, osmium::Location way1_seg_end, - osmium::object_id_type way2_id, osmium::Location way2_seg_start, osmium::Location way2_seg_end, osmium::Location intersection) override { - m_sstream.str(); - ProblemReporterStream::report_intersection(way1_id, way1_seg_start, way1_seg_end, way2_id, way2_seg_start, way2_seg_end, intersection); - throw std::runtime_error(m_sstream.str()); - } - - void report_ring_not_closed(osmium::Location end1, osmium::Location end2) override { - m_sstream.str(); - ProblemReporterStream::report_ring_not_closed(end1, end2); - throw std::runtime_error(m_sstream.str()); - } - - void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override { - m_sstream.str(); - ProblemReporterStream::report_role_should_be_outer(way_id, seg_start, seg_end); - throw std::runtime_error(m_sstream.str()); - } - - void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override { - m_sstream.str(); - ProblemReporterStream::report_role_should_be_inner(way_id, seg_start, seg_end); - throw std::runtime_error(m_sstream.str()); - } - - }; // class ProblemReporterException - - } // namespace area - -} // namespace osmium - -#endif // OSMIUM_AREA_PROBLEM_REPORTER_EXCEPTION_HPP diff --git a/third_party/osmium/area/problem_reporter_ogr.hpp b/third_party/osmium/area/problem_reporter_ogr.hpp deleted file mode 100644 index a9eb1359f..000000000 --- a/third_party/osmium/area/problem_reporter_ogr.hpp +++ /dev/null @@ -1,206 +0,0 @@ -#ifndef OSMIUM_AREA_PROBLEM_REPORTER_OGR_HPP -#define OSMIUM_AREA_PROBLEM_REPORTER_OGR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2014 Jochen Topf 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. - -*/ - -#define OSMIUM_COMPILE_WITH_CFLAGS_OGR `gdal-config --cflags` -#define OSMIUM_LINK_WITH_LIBS_OGR `gdal-config --libs` - -#pragma GCC diagnostic push -#ifdef __clang__ -# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" -#endif -#pragma GCC diagnostic ignored "-Wfloat-equal" -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Wpadded" -#pragma GCC diagnostic ignored "-Wredundant-decls" -#pragma GCC diagnostic ignored "-Wshadow" -# include -# include -#pragma GCC diagnostic pop - -#include -#include - -#include -#include -#include -#include - -namespace osmium { - - namespace area { - - /** - * Report problems when assembling areas by adding them to - * layers in an OGR datasource. - */ - class ProblemReporterOGR : public ProblemReporter { - - osmium::geom::OGRFactory<> m_ogr_factory; - - OGRDataSource* m_data_source; - - OGRLayer* m_layer_perror; - OGRLayer* m_layer_lerror; - - void write_point(const char* problem_type, osmium::object_id_type id1, osmium::object_id_type id2, osmium::Location location) { - OGRFeature* feature = OGRFeature::CreateFeature(m_layer_perror->GetLayerDefn()); - std::unique_ptr ogr_point = m_ogr_factory.create_point(location); - feature->SetGeometry(ogr_point.get()); - feature->SetField("id1", static_cast(id1)); - feature->SetField("id2", static_cast(id2)); - feature->SetField("problem_type", problem_type); - - if (m_layer_perror->CreateFeature(feature) != OGRERR_NONE) { - std::runtime_error("Failed to create feature on layer 'perrors'"); - } - - OGRFeature::DestroyFeature(feature); - } - - void write_line(const char* problem_type, osmium::object_id_type id1, osmium::object_id_type id2, osmium::Location loc1, osmium::Location loc2) { - std::unique_ptr ogr_point1 = m_ogr_factory.create_point(loc1); - std::unique_ptr ogr_point2 = m_ogr_factory.create_point(loc2); - std::unique_ptr ogr_linestring = std::unique_ptr(new OGRLineString()); - ogr_linestring->addPoint(ogr_point1.get()); - ogr_linestring->addPoint(ogr_point2.get()); - OGRFeature* feature = OGRFeature::CreateFeature(m_layer_lerror->GetLayerDefn()); - feature->SetGeometry(ogr_linestring.get()); - feature->SetField("id1", static_cast(id1)); - feature->SetField("id2", static_cast(id2)); - feature->SetField("problem_type", problem_type); - - if (m_layer_lerror->CreateFeature(feature) != OGRERR_NONE) { - std::runtime_error("Failed to create feature on layer 'lerrors'"); - } - - OGRFeature::DestroyFeature(feature); - } - - public: - - explicit ProblemReporterOGR(OGRDataSource* data_source) : - m_data_source(data_source) { - - OGRSpatialReference sparef; - sparef.SetWellKnownGeogCS("WGS84"); - - m_layer_perror = m_data_source->CreateLayer("perrors", &sparef, wkbPoint, nullptr); - if (!m_layer_perror) { - std::runtime_error("Layer creation failed for layer 'perrors'"); - } - - OGRFieldDefn layer_perror_field_id1("id1", OFTReal); - layer_perror_field_id1.SetWidth(10); - - if (m_layer_perror->CreateField(&layer_perror_field_id1) != OGRERR_NONE) { - std::runtime_error("Creating field 'id1' failed for layer 'perrors'"); - } - - OGRFieldDefn layer_perror_field_id2("id2", OFTReal); - layer_perror_field_id2.SetWidth(10); - - if (m_layer_perror->CreateField(&layer_perror_field_id2) != OGRERR_NONE) { - std::runtime_error("Creating field 'id2' failed for layer 'perrors'"); - } - - OGRFieldDefn layer_perror_field_problem_type("problem_type", OFTString); - layer_perror_field_problem_type.SetWidth(30); - - if (m_layer_perror->CreateField(&layer_perror_field_problem_type) != OGRERR_NONE) { - std::runtime_error("Creating field 'problem_type' failed for layer 'perrors'"); - } - - /**************/ - - m_layer_lerror = m_data_source->CreateLayer("lerrors", &sparef, wkbLineString, nullptr); - if (!m_layer_lerror) { - std::runtime_error("Layer creation failed for layer 'lerrors'"); - } - - OGRFieldDefn layer_lerror_field_id1("id1", OFTReal); - layer_lerror_field_id1.SetWidth(10); - - if (m_layer_lerror->CreateField(&layer_lerror_field_id1) != OGRERR_NONE) { - std::runtime_error("Creating field 'id1' failed for layer 'lerrors'"); - } - - OGRFieldDefn layer_lerror_field_id2("id2", OFTReal); - layer_lerror_field_id2.SetWidth(10); - - if (m_layer_lerror->CreateField(&layer_lerror_field_id2) != OGRERR_NONE) { - std::runtime_error("Creating field 'id2' failed for layer 'lerrors'"); - } - - OGRFieldDefn layer_lerror_field_problem_type("problem_type", OFTString); - layer_lerror_field_problem_type.SetWidth(30); - - if (m_layer_lerror->CreateField(&layer_lerror_field_problem_type) != OGRERR_NONE) { - std::runtime_error("Creating field 'problem_type' failed for layer 'lerrors'"); - } - } - - virtual ~ProblemReporterOGR() = default; - - void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location) override { - write_point("duplicate_node", node_id1, node_id2, location); - } - - void report_intersection(osmium::object_id_type way1_id, osmium::Location way1_seg_start, osmium::Location way1_seg_end, - osmium::object_id_type way2_id, osmium::Location way2_seg_start, osmium::Location way2_seg_end, osmium::Location intersection) override { - write_point("intersection", m_object_id, 0, intersection); - write_line("intersection", m_object_id, way1_id, way1_seg_start, way1_seg_end); - write_line("intersection", m_object_id, way2_id, way2_seg_start, way2_seg_end); - } - - void report_ring_not_closed(osmium::Location end1, osmium::Location end2) override { - write_point("ring_not_closed", m_object_id, 0, end1); - write_point("ring_not_closed", m_object_id, 0, end2); - } - - void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override { - write_line("role_should_be_outer", m_object_id, way_id, seg_start, seg_end); - } - - void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override { - write_line("role_should_be_inner", m_object_id, way_id, seg_start, seg_end); - } - - }; // class ProblemReporterOGR - - } // namespace area - -} // namespace osmium - -#endif // OSMIUM_AREA_PROBLEM_REPORTER_OGR_HPP diff --git a/third_party/osmium/area/problem_reporter_stream.hpp b/third_party/osmium/area/problem_reporter_stream.hpp deleted file mode 100644 index 6bee56816..000000000 --- a/third_party/osmium/area/problem_reporter_stream.hpp +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef OSMIUM_AREA_PROBLEM_REPORTER_STREAM_HPP -#define OSMIUM_AREA_PROBLEM_REPORTER_STREAM_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2014 Jochen Topf 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 - -#include -#include -#include -#include - -namespace osmium { - - namespace area { - - class ProblemReporterStream : public ProblemReporter { - - std::ostream* m_out; - - public: - - explicit ProblemReporterStream(std::ostream& out) : - m_out(&out) { - } - - virtual ~ProblemReporterStream() = default; - - void header(const char* msg) { - *m_out << "DATA PROBLEM: " << msg << " on " << item_type_to_char(m_object_type) << m_object_id << ": "; - } - - void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location) override { - header("duplicate node"); - *m_out << "node_id1=" << node_id1 << " node_id2=" << node_id2 << " location=" << location << "\n"; - } - - void report_intersection(osmium::object_id_type way1_id, osmium::Location way1_seg_start, osmium::Location way1_seg_end, - osmium::object_id_type way2_id, osmium::Location way2_seg_start, osmium::Location way2_seg_end, osmium::Location intersection) override { - header("intersection"); - *m_out << "way1_id=" << way1_id << " way1_seg_start=" << way1_seg_start << " way1_seg_end=" << way1_seg_end - << " way2_id=" << way2_id << " way2_seg_start=" << way2_seg_start << " way2_seg_end=" << way2_seg_end << " intersection=" << intersection << "\n"; - } - - void report_ring_not_closed(osmium::Location end1, osmium::Location end2) override { - header("ring not closed"); - *m_out << "end1=" << end1 << " end2=" << end2 << "\n"; - } - - void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override { - header("role should be outer"); - *m_out << "way_id=" << way_id << " seg_start=" << seg_start << " seg_end=" << seg_end << "\n"; - } - - void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override { - header("role should be inner"); - *m_out << "way_id=" << way_id << " seg_start=" << seg_start << " seg_end=" << seg_end << "\n"; - } - - }; // class ProblemReporterStream - - } // namespace area - -} // namespace osmium - -#endif // OSMIUM_AREA_PROBLEM_REPORTER_STREAM_HPP diff --git a/third_party/osmium/builder/builder.hpp b/third_party/osmium/builder/builder.hpp deleted file mode 100644 index 61e853e70..000000000 --- a/third_party/osmium/builder/builder.hpp +++ /dev/null @@ -1,220 +0,0 @@ -#ifndef OSMIUM_BUILDER_BUILDER_HPP -#define OSMIUM_BUILDER_BUILDER_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace osmium { - - /** - * @brief Classes for building OSM objects and other items in buffers - */ - namespace builder { - - class Builder { - - osmium::memory::Buffer& m_buffer; - Builder* m_parent; - size_t m_item_offset; - - Builder(const Builder&) = delete; - Builder(Builder&&) = delete; - - Builder& operator=(const Builder&) = delete; - Builder& operator=(Builder&&) = delete; - - protected: - - explicit Builder(osmium::memory::Buffer& buffer, Builder* parent, osmium::memory::item_size_type size) : - m_buffer(buffer), - m_parent(parent), - m_item_offset(buffer.written()) { - m_buffer.reserve_space(size); - assert(buffer.is_aligned()); - if (m_parent) { - m_parent->add_size(size); - } - } - - ~Builder() = default; - - osmium::memory::Item& item() const { - return *reinterpret_cast(m_buffer.data() + m_item_offset); - } - - public: - - /** - * Add padding to buffer (if needed) to align data properly. - * - * This calculates how many padding bytes are needed and adds - * as many zero bytes to the buffer. It also adds this number - * to the size of the current item (if the "self" param is - * true) and recursively to all the parent items. - * - * @param self If true add number of padding bytes to size - * of current item. Size is always added to - * parent item (if any). - * - */ - void add_padding(bool self=false) { - auto padding = osmium::memory::align_bytes - (size() % osmium::memory::align_bytes); - if (padding != osmium::memory::align_bytes) { - std::memset(m_buffer.reserve_space(padding), 0, padding); - if (self) { - add_size(padding); - } else if (m_parent) { - m_parent->add_size(padding); - assert(m_parent->size() % osmium::memory::align_bytes == 0); - } - } - } - - void add_size(uint32_t size) { - item().add_size(size); - if (m_parent) { - m_parent->add_size(size); - } - } - - uint32_t size() const noexcept { - return item().byte_size(); - } - - void add_item(const osmium::memory::Item* item) { - std::memcpy(m_buffer.reserve_space(item->padded_size()), item, item->padded_size()); - add_size(item->padded_size()); - } - - /** - * Reserve space for an object of class T in buffer and return - * pointer to it. - */ - template - T* reserve_space_for() { - assert(m_buffer.is_aligned()); - return reinterpret_cast(m_buffer.reserve_space(sizeof(T))); - } - - /** - * Append data to buffer. - * - * @param data Pointer to data. - * @param length Length of data in bytes. If data is a - * \0-terminated string, length must contain the - * \0 byte. - */ - osmium::memory::item_size_type append(const char* data, const osmium::memory::item_size_type length) { - std::memcpy(m_buffer.reserve_space(length), data, length); - return length; - } - - /** - * Append \0-terminated string to buffer. - */ - osmium::memory::item_size_type append(const char* str) { - return append(str, static_cast(std::strlen(str) + 1)); - } - - /// Return the buffer this builder is using. - osmium::memory::Buffer& buffer() noexcept { - return m_buffer; - } - - }; // class Builder - - template - class ObjectBuilder : public Builder { - - static_assert(std::is_base_of::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(item()); - } - - /** - * Add user name to buffer. - * - * @param user Pointer to user name. - * @param length Length of user name including \0 byte. - */ - void add_user(const char* user, const string_size_type length) { - object().set_user_size(length); - add_size(append(user, length)); - 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(std::strlen(user) + 1)); - } - - /** - * Add user name to buffer. - * - * @param user User name. - */ - void add_user(const std::string& user) { - add_user(user.data(), static_cast_with_assert(user.size() + 1)); - } - - }; // class ObjectBuilder - - } // namespace builder - -} // namespace osmium - -#endif // OSMIUM_BUILDER_BUILDER_HPP diff --git a/third_party/osmium/builder/builder_helper.hpp b/third_party/osmium/builder/builder_helper.hpp deleted file mode 100644 index 3e00f81c4..000000000 --- a/third_party/osmium/builder/builder_helper.hpp +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef OSMIUM_BUILDER_BUILDER_HELPER_HPP -#define OSMIUM_BUILDER_BUILDER_HELPER_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include - -#include -#include - -namespace osmium { - - class NodeRef; - class TagList; - class WayNodeList; - - namespace builder { - - inline const osmium::WayNodeList& build_way_node_list(osmium::memory::Buffer& buffer, const std::initializer_list& nodes) { - size_t pos = buffer.committed(); - { - osmium::builder::WayNodeListBuilder wnl_builder(buffer); - for (const auto& node_ref : nodes) { - wnl_builder.add_node_ref(node_ref); - } - } - buffer.commit(); - return buffer.get(pos); - } - - inline const osmium::TagList& build_tag_list(osmium::memory::Buffer& buffer, const std::initializer_list>& tags) { - size_t pos = buffer.committed(); - { - osmium::builder::TagListBuilder tl_builder(buffer); - for (const auto& p : tags) { - tl_builder.add_tag(p.first, p.second); - } - } - buffer.commit(); - return buffer.get(pos); - } - - inline const osmium::TagList& build_tag_list_from_map(osmium::memory::Buffer& buffer, const std::map& tags) { - size_t pos = buffer.committed(); - { - osmium::builder::TagListBuilder tl_builder(buffer); - for (const auto& p : tags) { - tl_builder.add_tag(p.first, p.second); - } - } - buffer.commit(); - return buffer.get(pos); - } - - inline const osmium::TagList& build_tag_list_from_func(osmium::memory::Buffer& buffer, std::function func) { - size_t pos = buffer.committed(); - { - osmium::builder::TagListBuilder tl_builder(buffer); - func(tl_builder); - } - buffer.commit(); - return buffer.get(pos); - } - - } // namespace builder - -} // namespace osmium - -#endif // OSMIUM_BUILDER_BUILDER_HELPER_HPP diff --git a/third_party/osmium/builder/osm_object_builder.hpp b/third_party/osmium/builder/osm_object_builder.hpp deleted file mode 100644 index 851eb85f8..000000000 --- a/third_party/osmium/builder/osm_object_builder.hpp +++ /dev/null @@ -1,283 +0,0 @@ -#ifndef OSMIUM_BUILDER_OSM_OBJECT_BUILDER_HPP -#define OSMIUM_BUILDER_OSM_OBJECT_BUILDER_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace osmium { - - namespace memory { - class Buffer; - } - - namespace builder { - - class TagListBuilder : public ObjectBuilder { - - public: - - explicit TagListBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : - ObjectBuilder(buffer, parent) { - } - - ~TagListBuilder() { - add_padding(); - } - - /** - * Add tag to buffer. - * - * @param key Tag key. - * @param value Tag value. - */ - void add_tag(const char* key, const char* value) { - add_size(append(key) + append(value)); - } - - /** - * Add tag to buffer. - * - * @param key Tag key. - * @param value Tag value. - */ - void add_tag(const std::string& key, const std::string& value) { - add_size(append(key.data(), static_cast_with_assert(key.size() + 1)) + - append(value.data(), static_cast_with_assert(value.size() + 1))); - } - - }; // class TagListBuilder - - template - class NodeRefListBuilder : public ObjectBuilder { - - public: - - explicit NodeRefListBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : - ObjectBuilder(buffer, parent) { - } - - ~NodeRefListBuilder() { - static_cast(this)->add_padding(); - } - - void add_node_ref(const NodeRef& node_ref) { - new (static_cast(this)->reserve_space_for()) osmium::NodeRef(node_ref); - static_cast(this)->add_size(sizeof(osmium::NodeRef)); - } - - void add_node_ref(const object_id_type ref, const osmium::Location location=Location()) { - add_node_ref(NodeRef(ref, location)); - } - - }; // class NodeRefListBuilder - - typedef NodeRefListBuilder WayNodeListBuilder; - typedef NodeRefListBuilder OuterRingBuilder; - typedef NodeRefListBuilder InnerRingBuilder; - - class RelationMemberListBuilder : public ObjectBuilder { - - /** - * Add role to buffer. - * - * @param member Relation member object where the length of the role - * will be set. - * @param role The role. - * @param length Length of role string including \0 termination. - */ - void add_role(osmium::RelationMember& member, const char* role, const string_size_type length) { - member.set_role_size(length); - add_size(append(role, length)); - add_padding(true); - } - - /** - * Add role to buffer. - * - * @param member Relation member object where the length of the role - * will be set. - * @param role \0-terminated role. - */ - void add_role(osmium::RelationMember& member, const char* role) { - add_role(member, role, static_cast_with_assert(std::strlen(role) + 1)); - } - - /** - * Add role to buffer. - * - * @param member Relation member object where the length of the role - * will be set. - * @param role Role. - */ - void add_role(osmium::RelationMember& member, const std::string& role) { - add_role(member, role.data(), static_cast_with_assert(role.size() + 1)); - } - - public: - - explicit RelationMemberListBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : - ObjectBuilder(buffer, parent) { - } - - ~RelationMemberListBuilder() { - add_padding(); - } - - /** - * Add a member to the relation. - * - * @param type The type (node, way, or relation). - * @param ref The ID of the member. - * @param role The role of the member. - * @param full_member Optional pointer to the member object. If it - * is available a copy will be added to the - * relation. - */ - void add_member(osmium::item_type type, object_id_type ref, const char* role, const osmium::OSMObject* full_member = nullptr) { - osmium::RelationMember* member = reserve_space_for(); - new (member) osmium::RelationMember(ref, type, full_member != nullptr); - add_size(sizeof(RelationMember)); - add_role(*member, role); - if (full_member) { - add_item(full_member); - } - } - - /** - * Add a member to the relation. - * - * @param type The type (node, way, or relation). - * @param ref The ID of the member. - * @param role The role of the member. - * @param full_member Optional pointer to the member object. If it - * is available a copy will be added to the - * relation. - */ - void add_member(osmium::item_type type, object_id_type ref, const std::string& role, const osmium::OSMObject* full_member = nullptr) { - osmium::RelationMember* member = reserve_space_for(); - new (member) osmium::RelationMember(ref, type, full_member != nullptr); - add_size(sizeof(RelationMember)); - add_role(*member, role); - if (full_member) { - add_item(full_member); - } - } - - }; // class RelationMemberListBuilder - - template - class OSMObjectBuilder : public ObjectBuilder { - - public: - - explicit OSMObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : - ObjectBuilder(buffer, parent) { - static_cast(this)->reserve_space_for(); - static_cast(this)->add_size(sizeof(string_size_type)); - } - - void add_tags(const std::initializer_list>& tags) { - osmium::builder::TagListBuilder tl_builder(static_cast(this)->buffer(), this); - for (const auto& p : tags) { - tl_builder.add_tag(p.first, p.second); - } - } - - }; // class OSMObjectBuilder - - typedef OSMObjectBuilder NodeBuilder; - typedef OSMObjectBuilder RelationBuilder; - - class WayBuilder : public OSMObjectBuilder { - - public: - - explicit WayBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : - OSMObjectBuilder(buffer, parent) { - } - - void add_node_refs(const std::initializer_list& nodes) { - osmium::builder::WayNodeListBuilder builder(buffer(), this); - for (const auto& node_ref : nodes) { - builder.add_node_ref(node_ref); - } - } - - }; // class WayBuilder - - class AreaBuilder : public OSMObjectBuilder { - - public: - - explicit AreaBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : - OSMObjectBuilder(buffer, parent) { - } - - /** - * Initialize area attributes from the attributes of the given object. - */ - void initialize_from_object(const osmium::OSMObject& source) { - osmium::Area& area = object(); - area.set_id(osmium::object_id_to_area_id(source.id(), source.type())); - area.set_version(source.version()); - area.set_changeset(source.changeset()); - area.set_timestamp(source.timestamp()); - area.set_visible(source.visible()); - area.set_uid(source.uid()); - - add_user(source.user()); - } - - }; // class AreaBuilder - - typedef ObjectBuilder ChangesetBuilder; - - } // namespace builder - -} // namespace osmium - -#endif // OSMIUM_BUILDER_OSM_OBJECT_BUILDER_HPP diff --git a/third_party/osmium/config/constexpr.hpp b/third_party/osmium/config/constexpr.hpp deleted file mode 100644 index 3eddc84a2..000000000 --- a/third_party/osmium/config/constexpr.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef OSMIUM_CONFIG_CONSTEXPR_HPP -#define OSMIUM_CONFIG_CONSTEXPR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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. - -*/ - -// Workaround for MSVC which doesn't support constexpr in all cases yet -#ifdef _MSC_VER -# define OSMIUM_CONSTEXPR -#else -# define OSMIUM_CONSTEXPR constexpr -#endif - -#endif // OSMIUM_CONFIG_CONSTEXPR_HPP diff --git a/third_party/osmium/diff_handler.hpp b/third_party/osmium/diff_handler.hpp deleted file mode 100644 index 9864df5a1..000000000 --- a/third_party/osmium/diff_handler.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef OSMIUM_DIFF_HANDLER_HPP -#define OSMIUM_DIFF_HANDLER_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 - -namespace osmium { - - /** - * @brief Osmium diff handlers provide access to differences between OSM object versions - */ - namespace diff_handler { - - class DiffHandler { - - public: - - DiffHandler() { - } - - void node(const osmium::DiffNode&) const { - } - - void way(const osmium::DiffWay&) const { - } - - void relation(const osmium::DiffRelation&) const { - } - - }; // class DiffHandler - - } // namespace diff_handler - -} // namespace osmium - -#endif // OSMIUM_DIFF_HANDLER_HPP diff --git a/third_party/osmium/diff_iterator.hpp b/third_party/osmium/diff_iterator.hpp deleted file mode 100644 index 576834c4d..000000000 --- a/third_party/osmium/diff_iterator.hpp +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef OSMIUM_DIFF_ITERATOR_HPP -#define OSMIUM_DIFF_ITERATOR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include - -#include - -namespace osmium { - - class OSMObject; - - template - class DiffIterator : public std::iterator { - - static_assert(std::is_base_of::value, "TBasicIterator::value_type must derive from osmium::OSMObject"); - - TBasicIterator m_prev; - TBasicIterator m_curr; - TBasicIterator m_next; - - const TBasicIterator m_end; - - mutable osmium::DiffObject m_diff; - - void set_diff() const { - assert(m_curr != m_end); - - TBasicIterator prev = m_prev; - if (prev->type() != m_curr->type() || prev->id() != m_curr->id()) { - prev = m_curr; - } - - TBasicIterator next = m_next; - if (next == m_end || next->type() != m_curr->type() || next->id() != m_curr->id()) { - next = m_curr; - } - - m_diff = osmium::DiffObject(*prev, *m_curr, *next); - } - - public: - - explicit DiffIterator(TBasicIterator begin, TBasicIterator end) : - m_prev(begin), - m_curr(begin), - m_next(begin == end ? begin : ++begin), - m_end(end) { - } - - DiffIterator(const DiffIterator&) = default; - DiffIterator& operator=(const DiffIterator&) = default; - - DiffIterator(DiffIterator&&) = default; - DiffIterator& operator=(DiffIterator&&) = default; - - DiffIterator& operator++() { - m_prev = std::move(m_curr); - m_curr = m_next; - - if (m_next != m_end) { - ++m_next; - } - - return *this; - } - - DiffIterator operator++(int) { - DiffIterator tmp(*this); - operator++(); - return tmp; - } - - bool operator==(const DiffIterator& rhs) const { - return m_curr == rhs.m_curr && m_end == rhs.m_end; - } - - bool operator!=(const DiffIterator& rhs) const { - return !(*this == rhs); - } - - reference operator*() const { - set_diff(); - return m_diff; - } - - pointer operator->() const { - set_diff(); - return &m_diff; - } - - }; // class DiffIterator - -} // namespace osmium - -#endif // OSMIUM_DIFF_ITERATOR_HPP diff --git a/third_party/osmium/diff_visitor.hpp b/third_party/osmium/diff_visitor.hpp deleted file mode 100644 index b8db6970b..000000000 --- a/third_party/osmium/diff_visitor.hpp +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef OSMIUM_DIFF_VISITOR_HPP -#define OSMIUM_DIFF_VISITOR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include - -namespace osmium { - - namespace detail { - - template - inline void apply_diff_iterator_recurse(const osmium::DiffObject& diff, THandler& handler) { - switch (diff.type()) { - case osmium::item_type::node: - handler.node(static_cast(diff)); - break; - case osmium::item_type::way: - handler.way(static_cast(diff)); - break; - case osmium::item_type::relation: - handler.relation(static_cast(diff)); - break; - default: - throw osmium::unknown_type(); - } - } - - template - inline void apply_diff_iterator_recurse(const osmium::DiffObject& diff, THandler& handler, TRest&... more) { - apply_diff_iterator_recurse(diff, handler); - apply_diff_iterator_recurse(diff, more...); - } - - } // namespace detail - - template - inline void apply_diff(TIterator it, TIterator end, THandlers&... handlers) { - typedef osmium::DiffIterator diff_iterator; - - diff_iterator dit(it, end); - diff_iterator dend(end, end); - - for (; dit != dend; ++dit) { - detail::apply_diff_iterator_recurse(*dit, handlers...); - } - } - - class OSMObject; - - template - inline void apply_diff(TSource& source, THandlers&... handlers) { - apply_diff(osmium::io::InputIterator {source}, - osmium::io::InputIterator {}, - handlers...); - } - - template - inline void apply_diff(osmium::memory::Buffer& buffer, THandlers&... handlers) { - apply_diff(buffer.begin(), buffer.end(), handlers...); - } - - template - inline void apply_diff(const osmium::memory::Buffer& buffer, THandlers&... handlers) { - apply_diff(buffer.cbegin(), buffer.cend(), handlers...); - } - -} // namespace osmium - -#endif // OSMIUM_DIFF_VISITOR_HPP diff --git a/third_party/osmium/dynamic_handler.hpp b/third_party/osmium/dynamic_handler.hpp deleted file mode 100644 index bc593131c..000000000 --- a/third_party/osmium/dynamic_handler.hpp +++ /dev/null @@ -1,195 +0,0 @@ -#ifndef OSMIUM_DYNAMIC_HANDLER_HPP -#define OSMIUM_DYNAMIC_HANDLER_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -#include - -namespace osmium { - - class Node; - class Way; - class Relation; - class Area; - class Changeset; - - namespace handler { - - namespace detail { - - class HandlerWrapperBase { - - public: - - virtual ~HandlerWrapperBase() { - } - - virtual void node(const osmium::Node&) { - } - - virtual void way(const osmium::Way&) { - } - - virtual void relation(const osmium::Relation&) { - } - - virtual void area(const osmium::Area&) { - } - - virtual void changeset(const osmium::Changeset&) { - } - - virtual void flush() { - } - - }; // class HandlerWrapperBase - - - // The following uses trick from - // http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-template-to-check-for-a-functions-existence - // to either call handler style functions or visitor style operator(). - -#define OSMIUM_DYNAMIC_HANDLER_DISPATCH(_name_, _type_) \ -template \ -auto _name_##_dispatch(THandler& handler, const osmium::_type_& object, int) -> decltype(handler._name_(object), void()) { \ - handler._name_(object); \ -} \ -template \ -auto _name_##_dispatch(THandler& handler, const osmium::_type_& object, long) -> decltype(handler(object), void()) { \ - handler(object); \ -} - - OSMIUM_DYNAMIC_HANDLER_DISPATCH(node, Node) - OSMIUM_DYNAMIC_HANDLER_DISPATCH(way, Way) - OSMIUM_DYNAMIC_HANDLER_DISPATCH(relation, Relation) - OSMIUM_DYNAMIC_HANDLER_DISPATCH(changeset, Changeset) - OSMIUM_DYNAMIC_HANDLER_DISPATCH(area, Area) - - template - auto flush_dispatch(THandler& handler, int) -> decltype(handler.flush(), void()) { - handler.flush(); - } - - template - void flush_dispatch(THandler&, long) {} - - template - class HandlerWrapper : public HandlerWrapperBase { - - THandler m_handler; - - public: - - template - HandlerWrapper(TArgs&&... args) : - m_handler(std::forward(args)...) { - } - - void node(const osmium::Node& node) override final { - node_dispatch(m_handler, node, 0); - } - - void way(const osmium::Way& way) override final { - way_dispatch(m_handler, way, 0); - } - - void relation(const osmium::Relation& relation) override final { - relation_dispatch(m_handler, relation, 0); - } - - void area(const osmium::Area& area) override final { - area_dispatch(m_handler, area, 0); - } - - void changeset(const osmium::Changeset& changeset) override final { - changeset_dispatch(m_handler, changeset, 0); - } - - void flush() override final { - flush_dispatch(m_handler, 0); - } - - }; // class HandlerWrapper - - } // namespace detail - - class DynamicHandler : public osmium::handler::Handler { - - typedef std::unique_ptr impl_ptr; - impl_ptr m_impl; - - public: - - DynamicHandler() : - m_impl(impl_ptr(new osmium::handler::detail::HandlerWrapperBase)) { - } - - template - void set(TArgs&&... args) { - m_impl = impl_ptr(new osmium::handler::detail::HandlerWrapper(std::forward(args)...)); - } - - void node(const osmium::Node& node) { - m_impl->node(node); - } - - void way(const osmium::Way& way) { - m_impl->way(way); - } - - void relation(const osmium::Relation& relation) { - m_impl->relation(relation); - } - - void area(const osmium::Area& area) { - m_impl->area(area); - } - - void changeset(const osmium::Changeset& changeset) { - m_impl->changeset(changeset); - } - - void flush() { - m_impl->flush(); - } - - }; // class DynamicHandler - - } // namspace handler - -} // namespace osmium - -#endif // OSMIUM_DYNAMIC_HANDLER_HPP diff --git a/third_party/osmium/experimental/flex_reader.hpp b/third_party/osmium/experimental/flex_reader.hpp deleted file mode 100644 index 8dca152ec..000000000 --- a/third_party/osmium/experimental/flex_reader.hpp +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef OSMIUM_EXPERIMENTAL_FLEX_READER_HPP -#define OSMIUM_EXPERIMENTAL_FLEX_READER_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2014 Jochen Topf 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 -#include -#include -#include - -namespace osmium { - - /** - * Experimental code that is not "officially" supported. - */ - namespace experimental { - - template - class FlexReader { - - bool m_with_areas; - osmium::osm_entity_bits::type m_entities; - - typename TLocationHandler::index_pos_type m_index_pos; - typename TLocationHandler::index_neg_type m_index_neg; - TLocationHandler m_location_handler; - - osmium::io::Reader m_reader; - osmium::area::Assembler::config_type m_assembler_config; - osmium::area::MultipolygonCollector m_collector; - - public: - - explicit FlexReader(const osmium::io::File& file, osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::nwr) : - m_with_areas(entities & osmium::osm_entity_bits::area), - m_entities((entities & ~osmium::osm_entity_bits::area) | (m_with_areas ? osmium::osm_entity_bits::node | osmium::osm_entity_bits::way : osmium::osm_entity_bits::nothing)), - m_index_pos(), - m_index_neg(), - m_location_handler(m_index_pos, m_index_neg), - m_reader(file, m_entities), - m_assembler_config(), - m_collector(m_assembler_config) - { - m_location_handler.ignore_errors(); - if (m_with_areas) { - osmium::io::Reader reader(file, osmium::osm_entity_bits::relation); - m_collector.read_relations(reader); - reader.close(); - } - } - - explicit FlexReader(const std::string& filename, osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::nwr) : - FlexReader(osmium::io::File(filename), entities) { - } - - explicit FlexReader(const char* filename, osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::nwr) : - FlexReader(osmium::io::File(filename), entities) { - } - - std::vector read() { - std::vector buffers; - - osmium::memory::Buffer buffer = m_reader.read(); - - if (buffer) { - buffers.push_back(std::move(buffer)); - if (m_with_areas) { - osmium::apply(buffers[0], m_location_handler, m_collector.handler([&buffers](osmium::memory::Buffer&& area_buffer) { - buffers.push_back(std::move(area_buffer)); - })); - } else if (m_entities & (osmium::osm_entity_bits::node | osmium::osm_entity_bits::way)) { - osmium::apply(buffers[0], m_location_handler); - } - } - - return buffers; - } - - osmium::io::Header header() const { - return m_reader.header(); - } - - void close() { - return m_reader.close(); - } - - bool eof() const { - return m_reader.eof(); - } - - const osmium::area::MultipolygonCollector& collector() const { - return m_collector; - } - - }; // class FlexReader - - } // namespace experimental - -} // namespace osmium - -#endif // OSMIUM_EXPERIMENTAL_FLEX_READER_HPP diff --git a/third_party/osmium/geom/coordinates.hpp b/third_party/osmium/geom/coordinates.hpp deleted file mode 100644 index 1ff27fea4..000000000 --- a/third_party/osmium/geom/coordinates.hpp +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef OSMIUM_GEOM_COORDINATES_HPP -#define OSMIUM_GEOM_COORDINATES_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include - -#include -#include - -namespace osmium { - - namespace geom { - - struct Coordinates { - - double x; - double y; - - explicit Coordinates(double cx, double cy) noexcept : x(cx), y(cy) { - } - - Coordinates(const osmium::Location& location) : x(location.lon()), y(location.lat()) { - } - - void append_to_string(std::string& s, const char infix, int precision) const { - osmium::util::double2string(s, x, precision); - s += infix; - osmium::util::double2string(s, y, precision); - } - - void append_to_string(std::string& s, const char prefix, const char infix, const char suffix, int precision) const { - s += prefix; - append_to_string(s, infix, precision); - s += suffix; - } - - }; // struct coordinates - - /** - * Compare whether two Coordinates are identical. Might not give the - * right result if the coordinates have been the result of some - * calculation that introduced rounding errors. - */ - inline bool operator==(const Coordinates& lhs, const Coordinates& rhs) noexcept { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wfloat-equal" - return lhs.x == rhs.x && lhs.y == rhs.y; -#pragma GCC diagnostic pop - } - - inline bool operator!=(const Coordinates& lhs, const Coordinates& rhs) noexcept { - return ! operator==(lhs, rhs); - } - - template - inline std::basic_ostream& operator<<(std::basic_ostream& out, const Coordinates& c) { - return out << '(' << c.x << ',' << c.y << ')'; - } - - } // namespace geom - -} // namespace osmium - -#endif // OSMIUM_GEOM_COORDINATES_HPP diff --git a/third_party/osmium/geom/factory.hpp b/third_party/osmium/geom/factory.hpp deleted file mode 100644 index 4097b5dac..000000000 --- a/third_party/osmium/geom/factory.hpp +++ /dev/null @@ -1,328 +0,0 @@ -#ifndef OSMIUM_GEOM_FACTORY_HPP -#define OSMIUM_GEOM_FACTORY_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace osmium { - - /** - * Exception thrown when an invalid geometry is encountered. An example - * would be a linestring with less than two points. - */ - struct geometry_error : public std::runtime_error { - - geometry_error(const std::string& what) : - std::runtime_error(what) { - } - - geometry_error(const char* what) : - std::runtime_error(what) { - } - - }; // struct geometry_error - - /** - * @brief Everything related to geometry handling. - */ - namespace geom { - - /** - * Which nodes of a way to use for a linestring. - */ - enum class use_nodes : bool { - unique = true, ///< Remove consecutive nodes with same location. - all = false ///< Use all nodes. - }; // enum class use_nodes - - /** - * Which direction the linestring created from a way - * should have. - */ - enum class direction : bool { - backward = true, ///< Linestring has reverse direction. - forward = false ///< Linestring has same direction as way. - }; // enum class direction - - /** - * This pseudo projection just returns its WGS84 input unchanged. - * Used as a template parameter if a real projection is not needed. - */ - class IdentityProjection { - - public: - - Coordinates operator()(osmium::Location location) const { - return Coordinates{location.lon(), location.lat()}; - } - - int epsg() const noexcept { - return 4326; - } - - std::string proj_string() const { - return "+proj=longlat +datum=WGS84 +no_defs"; - } - - }; // class IdentityProjection - - /** - * Geometry factory. - */ - template - class GeometryFactory { - - /** - * Add all points of an outer or inner ring to a multipolygon. - */ - void add_points(const osmium::OuterRing& nodes) { - osmium::Location last_location; - for (const osmium::NodeRef& node_ref : nodes) { - if (last_location != node_ref.location()) { - last_location = node_ref.location(); - m_impl.multipolygon_add_location(m_projection(last_location)); - } - } - } - - TProjection m_projection; - TGeomImpl m_impl; - - public: - - /** - * Constructor for default initialized projection. - */ - template - GeometryFactory(TArgs&&... args) : - m_projection(), - m_impl(std::forward(args)...) { - } - - /** - * Constructor for explicitly initialized projection. Note that the - * projection is moved into the GeometryFactory. - */ - template - GeometryFactory(TProjection&& projection, TArgs&&... args) : - m_projection(std::move(projection)), - m_impl(std::forward(args)...) { - } - - typedef typename TGeomImpl::point_type point_type; - typedef typename TGeomImpl::linestring_type linestring_type; - typedef typename TGeomImpl::polygon_type polygon_type; - typedef typename TGeomImpl::multipolygon_type multipolygon_type; - typedef typename TGeomImpl::ring_type ring_type; - - int epsg() const { - return m_projection.epsg(); - } - - std::string proj_string() const { - return m_projection.proj_string(); - } - - /* Point */ - - point_type create_point(const osmium::Location location) const { - return m_impl.make_point(m_projection(location)); - } - - point_type create_point(const osmium::Node& node) { - return create_point(node.location()); - } - - point_type create_point(const osmium::NodeRef& node_ref) { - return create_point(node_ref.location()); - } - - /* LineString */ - - void linestring_start() { - m_impl.linestring_start(); - } - - template - size_t fill_linestring(TIter it, TIter end) { - size_t num_points = 0; - for (; it != end; ++it, ++num_points) { - m_impl.linestring_add_location(m_projection(it->location())); - } - return num_points; - } - - template - size_t fill_linestring_unique(TIter it, TIter end) { - size_t num_points = 0; - osmium::Location last_location; - for (; it != end; ++it) { - if (last_location != it->location()) { - last_location = it->location(); - m_impl.linestring_add_location(m_projection(last_location)); - ++num_points; - } - } - return num_points; - } - - linestring_type linestring_finish(size_t num_points) { - return m_impl.linestring_finish(num_points); - } - - linestring_type create_linestring(const osmium::WayNodeList& wnl, use_nodes un=use_nodes::unique, direction dir=direction::forward) { - linestring_start(); - size_t num_points = 0; - - if (un == use_nodes::unique) { - osmium::Location last_location; - switch (dir) { - case direction::forward: - num_points = fill_linestring_unique(wnl.cbegin(), wnl.cend()); - break; - case direction::backward: - num_points = fill_linestring_unique(wnl.crbegin(), wnl.crend()); - break; - } - } else { - switch (dir) { - case direction::forward: - num_points = fill_linestring(wnl.cbegin(), wnl.cend()); - break; - case direction::backward: - num_points = fill_linestring(wnl.crbegin(), wnl.crend()); - break; - } - } - - if (num_points < 2) { - throw osmium::geometry_error("not enough points for linestring"); - } - - return linestring_finish(num_points); - } - - linestring_type create_linestring(const osmium::Way& way, use_nodes un=use_nodes::unique, direction dir=direction::forward) { - return create_linestring(way.nodes(), un, dir); - } - - /* Polygon */ - - void polygon_start() { - m_impl.polygon_start(); - } - - template - size_t fill_polygon(TIter it, TIter end) { - size_t num_points = 0; - for (; it != end; ++it, ++num_points) { - m_impl.polygon_add_location(m_projection(it->location())); - } - return num_points; - } - - template - size_t fill_polygon_unique(TIter it, TIter end) { - size_t num_points = 0; - osmium::Location last_location; - for (; it != end; ++it) { - if (last_location != it->location()) { - last_location = it->location(); - m_impl.polygon_add_location(m_projection(last_location)); - ++num_points; - } - } - return num_points; - } - - polygon_type polygon_finish(size_t num_points) { - return m_impl.polygon_finish(num_points); - } - - /* MultiPolygon */ - - multipolygon_type create_multipolygon(const osmium::Area& area) { - size_t num_polygons = 0; - size_t num_rings = 0; - m_impl.multipolygon_start(); - - for (auto it = area.cbegin(); it != area.cend(); ++it) { - const osmium::OuterRing& ring = static_cast(*it); - if (it->type() == osmium::item_type::outer_ring) { - if (num_polygons > 0) { - m_impl.multipolygon_polygon_finish(); - } - m_impl.multipolygon_polygon_start(); - m_impl.multipolygon_outer_ring_start(); - add_points(ring); - m_impl.multipolygon_outer_ring_finish(); - ++num_rings; - ++num_polygons; - } else if (it->type() == osmium::item_type::inner_ring) { - m_impl.multipolygon_inner_ring_start(); - add_points(ring); - m_impl.multipolygon_inner_ring_finish(); - ++num_rings; - } - } - - // if there are no rings, this area is invalid - if (num_rings == 0) { - throw osmium::geometry_error("invalid area"); - } - - m_impl.multipolygon_polygon_finish(); - return m_impl.multipolygon_finish(); - } - - }; // class GeometryFactory - - } // namespace geom - -} // namespace osmium - -#endif // OSMIUM_GEOM_FACTORY_HPP diff --git a/third_party/osmium/geom/geojson.hpp b/third_party/osmium/geom/geojson.hpp deleted file mode 100644 index f6d7ee6e4..000000000 --- a/third_party/osmium/geom/geojson.hpp +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef OSMIUM_GEOM_GEOJSON_HPP -#define OSMIUM_GEOM_GEOJSON_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include - -#include -#include - -namespace osmium { - - namespace geom { - - namespace detail { - - class GeoJSONFactoryImpl { - - std::string m_str; - int m_precision; - - public: - - typedef std::string point_type; - typedef std::string linestring_type; - typedef std::string polygon_type; - typedef std::string multipolygon_type; - typedef std::string ring_type; - - GeoJSONFactoryImpl(int precision = 7) : - m_precision(precision) { - } - - /* Point */ - - // { "type": "Point", "coordinates": [100.0, 0.0] } - point_type make_point(const osmium::geom::Coordinates& xy) const { - std::string str {"{\"type\":\"Point\",\"coordinates\":"}; - xy.append_to_string(str, '[', ',', ']', m_precision); - str += "}"; - return str; - } - - /* LineString */ - - // { "type": "LineString", "coordinates": [ [100.0, 0.0], [101.0, 1.0] ] } - void linestring_start() { - m_str = "{\"type\":\"LineString\",\"coordinates\":["; - } - - void linestring_add_location(const osmium::geom::Coordinates& xy) { - xy.append_to_string(m_str, '[', ',', ']', m_precision); - m_str += ','; - } - - linestring_type linestring_finish(size_t /* num_points */) { - assert(!m_str.empty()); - std::string str; - std::swap(str, m_str); - str.back() = ']'; - str += "}"; - return str; - } - - /* MultiPolygon */ - - void multipolygon_start() { - m_str = "{\"type\":\"MultiPolygon\",\"coordinates\":["; - } - - void multipolygon_polygon_start() { - m_str += '['; - } - - void multipolygon_polygon_finish() { - m_str += "],"; - } - - void multipolygon_outer_ring_start() { - m_str += '['; - } - - void multipolygon_outer_ring_finish() { - assert(!m_str.empty()); - m_str.back() = ']'; - } - - void multipolygon_inner_ring_start() { - m_str += ",["; - } - - void multipolygon_inner_ring_finish() { - assert(!m_str.empty()); - m_str.back() = ']'; - } - - void multipolygon_add_location(const osmium::geom::Coordinates& xy) { - xy.append_to_string(m_str, '[', ',', ']', m_precision); - m_str += ','; - } - - multipolygon_type multipolygon_finish() { - assert(!m_str.empty()); - m_str.back() = ']'; - m_str += "}"; - return std::move(m_str); - } - - }; // class GeoJSONFactoryImpl - - } // namespace detail - - template - using GeoJSONFactory = GeometryFactory; - - } // namespace geom - -} // namespace osmium - -#endif // OSMIUM_GEOM_GEOJSON_HPP diff --git a/third_party/osmium/geom/geos.hpp b/third_party/osmium/geom/geos.hpp deleted file mode 100644 index 877520b2c..000000000 --- a/third_party/osmium/geom/geos.hpp +++ /dev/null @@ -1,224 +0,0 @@ -#ifndef OSMIUM_GEOM_GEOS_HPP -#define OSMIUM_GEOM_GEOS_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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. - -*/ - -#define OSMIUM_COMPILE_WITH_CFLAGS_GEOS `geos-config --cflags` -#define OSMIUM_LINK_WITH_LIBS_GEOS `geos-config --libs` - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -// MSVC doesn't support throw_with_nested yet -#ifdef _MSC_VER -# define THROW throw -#else -# define THROW std::throw_with_nested -#endif - -namespace osmium { - - struct geos_geometry_error : public geometry_error { - - geos_geometry_error() : - geometry_error("geometry creation failed in GEOS library, see nested exception for details") { - } - - }; // struct geos_geometry_error - - namespace geom { - - namespace detail { - - class GEOSFactoryImpl { - - geos::geom::PrecisionModel m_precision_model; - geos::geom::GeometryFactory m_geos_factory; - - std::unique_ptr m_coordinate_sequence; - std::vector> m_rings; - std::vector> m_polygons; - - public: - - typedef std::unique_ptr point_type; - typedef std::unique_ptr linestring_type; - typedef std::unique_ptr polygon_type; - typedef std::unique_ptr multipolygon_type; - typedef std::unique_ptr ring_type; - - explicit GEOSFactoryImpl(int srid = -1) : - m_precision_model(), - m_geos_factory(&m_precision_model, srid) { - } - - /* Point */ - - point_type make_point(const osmium::geom::Coordinates& xy) const { - try { - return point_type(m_geos_factory.createPoint(geos::geom::Coordinate(xy.x, xy.y))); - } catch (geos::util::GEOSException&) { - THROW(osmium::geos_geometry_error()); - } - } - - /* LineString */ - - void linestring_start() { - try { - m_coordinate_sequence.reset(m_geos_factory.getCoordinateSequenceFactory()->create(static_cast(0), 2)); - } catch (geos::util::GEOSException&) { - THROW(osmium::geos_geometry_error()); - } - } - - void linestring_add_location(const osmium::geom::Coordinates& xy) { - try { - m_coordinate_sequence->add(geos::geom::Coordinate(xy.x, xy.y)); - } catch (geos::util::GEOSException&) { - THROW(osmium::geos_geometry_error()); - } - } - - linestring_type linestring_finish(size_t /* num_points */) { - try { - return linestring_type(m_geos_factory.createLineString(m_coordinate_sequence.release())); - } catch (geos::util::GEOSException&) { - THROW(osmium::geos_geometry_error()); - } - } - - /* MultiPolygon */ - - void multipolygon_start() { - m_polygons.clear(); - } - - void multipolygon_polygon_start() { - m_rings.clear(); - } - - void multipolygon_polygon_finish() { - try { - assert(!m_rings.empty()); - auto inner_rings = new std::vector; - std::transform(std::next(m_rings.begin(), 1), m_rings.end(), std::back_inserter(*inner_rings), [](std::unique_ptr& r) { - return r.release(); - }); - m_polygons.emplace_back(m_geos_factory.createPolygon(m_rings[0].release(), inner_rings)); - m_rings.clear(); - } catch (geos::util::GEOSException&) { - THROW(osmium::geos_geometry_error()); - } - } - - void multipolygon_outer_ring_start() { - try { - m_coordinate_sequence.reset(m_geos_factory.getCoordinateSequenceFactory()->create(static_cast(0), 2)); - } catch (geos::util::GEOSException&) { - THROW(osmium::geos_geometry_error()); - } - } - - void multipolygon_outer_ring_finish() { - try { - m_rings.emplace_back(m_geos_factory.createLinearRing(m_coordinate_sequence.release())); - } catch (geos::util::GEOSException&) { - THROW(osmium::geos_geometry_error()); - } - } - - void multipolygon_inner_ring_start() { - try { - m_coordinate_sequence.reset(m_geos_factory.getCoordinateSequenceFactory()->create(static_cast(0), 2)); - } catch (geos::util::GEOSException&) { - THROW(osmium::geos_geometry_error()); - } - } - - void multipolygon_inner_ring_finish() { - try { - m_rings.emplace_back(m_geos_factory.createLinearRing(m_coordinate_sequence.release())); - } catch (geos::util::GEOSException&) { - THROW(osmium::geos_geometry_error()); - } - } - - void multipolygon_add_location(const osmium::geom::Coordinates& xy) { - try { - m_coordinate_sequence->add(geos::geom::Coordinate(xy.x, xy.y)); - } catch (geos::util::GEOSException&) { - THROW(osmium::geos_geometry_error()); - } - } - - multipolygon_type multipolygon_finish() { - try { - auto polygons = new std::vector; - std::transform(m_polygons.begin(), m_polygons.end(), std::back_inserter(*polygons), [](std::unique_ptr& p) { - return p.release(); - }); - m_polygons.clear(); - return multipolygon_type(m_geos_factory.createMultiPolygon(polygons)); - } catch (geos::util::GEOSException&) { - THROW(osmium::geos_geometry_error()); - } - } - - }; // class GEOSFactoryImpl - - } // namespace detail - - template - using GEOSFactory = GeometryFactory; - - } // namespace geom - -} // namespace osmium - -#undef THROW - -#endif // OSMIUM_GEOM_GEOS_HPP diff --git a/third_party/osmium/geom/haversine.hpp b/third_party/osmium/geom/haversine.hpp deleted file mode 100644 index b8d013492..000000000 --- a/third_party/osmium/geom/haversine.hpp +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef OSMIUM_GEOM_HAVERSINE_HPP -#define OSMIUM_GEOM_HAVERSINE_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -#include -#include -#include -#include - -namespace osmium { - - namespace geom { - - /** - * @brief Functions to calculate arc distance on Earth using the haversine formula. - * - * See http://en.wikipedia.org/wiki/Haversine_formula - * - * Implementation derived from - * http://blog.julien.cayzac.name/2008/10/arc-and-distance-between-two-points-on.html - */ - namespace haversine { - - /// @brief Earth's quadratic mean radius for WGS84 - constexpr double EARTH_RADIUS_IN_METERS = 6372797.560856; - - /** - * Calculate distance in meters between two sets of coordinates. - */ - inline double distance(const osmium::geom::Coordinates& c1, const osmium::geom::Coordinates& c2) { - double lonh = sin(deg_to_rad(c1.x - c2.x) * 0.5); - lonh *= lonh; - double lath = sin(deg_to_rad(c1.y - c2.y) * 0.5); - lath *= lath; - const double tmp = cos(deg_to_rad(c1.y)) * cos(deg_to_rad(c2.y)); - return 2.0 * EARTH_RADIUS_IN_METERS * asin(sqrt(lath + tmp*lonh)); - } - - /** - * Calculate length of way. - */ - inline double distance(const osmium::WayNodeList& wnl) { - double sum_length=0; - - for (auto it = wnl.begin(); it != wnl.end(); ++it) { - if (std::next(it) != wnl.end()) { - sum_length += distance(it->location(), std::next(it)->location()); - } - } - - return sum_length; - } - - } // namespace haversine - - } // namespace geom - -} // namespace osmium - -#endif // OSMIUM_GEOM_HAVERSINE_HPP diff --git a/third_party/osmium/geom/mercator_projection.hpp b/third_party/osmium/geom/mercator_projection.hpp deleted file mode 100644 index d17001717..000000000 --- a/third_party/osmium/geom/mercator_projection.hpp +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef OSMIUM_GEOM_MERCATOR_PROJECTION_HPP -#define OSMIUM_GEOM_MERCATOR_PROJECTION_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -#include -#include -#include - -namespace osmium { - - namespace geom { - - namespace detail { - - constexpr double earth_radius_for_epsg3857 = 6378137.0; - - constexpr inline double lon_to_x(double lon) { - return earth_radius_for_epsg3857 * deg_to_rad(lon); - } - - inline double lat_to_y(double lat) { // not constexpr because math functions aren't - return earth_radius_for_epsg3857 * std::log(std::tan(osmium::geom::PI/4 + deg_to_rad(lat)/2)); - } - - constexpr inline double x_to_lon(double x) { - return rad_to_deg(x) / earth_radius_for_epsg3857; - } - - inline double y_to_lat(double y) { // not constexpr because math functions aren't - return rad_to_deg(2 * std::atan(std::exp(y / earth_radius_for_epsg3857)) - osmium::geom::PI/2); - } - - } // namespace detail - - /** - * The maximum latitude that can be projected with the Web Mercator - * (EPSG:3857) projection. - */ - constexpr double MERCATOR_MAX_LAT = 85.0511288; - - inline Coordinates lonlat_to_mercator(const Coordinates& c) { - return Coordinates(detail::lon_to_x(c.x), detail::lat_to_y(c.y)); - } - - inline Coordinates mercator_to_lonlat(const Coordinates& c) { - return Coordinates(detail::x_to_lon(c.x), detail::y_to_lat(c.y)); - } - - /** - * Functor that does projection from WGS84 (EPSG:4326) to "Web - * Mercator" (EPSG:3857) - */ - class MercatorProjection { - - public: - - Coordinates operator()(osmium::Location location) const { - return Coordinates {detail::lon_to_x(location.lon()), detail::lat_to_y(location.lat())}; - } - - int epsg() const noexcept { - return 3857; - } - - std::string proj_string() const { - return "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"; - } - - }; // class MercatorProjection - - } // namespace geom - -} // namespace osmium - -#endif // OSMIUM_GEOM_MERCATOR_PROJECTION_HPP diff --git a/third_party/osmium/geom/ogr.hpp b/third_party/osmium/geom/ogr.hpp deleted file mode 100644 index 2727f2fd8..000000000 --- a/third_party/osmium/geom/ogr.hpp +++ /dev/null @@ -1,179 +0,0 @@ -#ifndef OSMIUM_GEOM_OGR_HPP -#define OSMIUM_GEOM_OGR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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. - -*/ - -#define OSMIUM_COMPILE_WITH_CFLAGS_OGR `gdal-config --cflags` -#define OSMIUM_LINK_WITH_LIBS_OGR `gdal-config --libs` - -#include -#include -#include -#include - -#pragma GCC diagnostic push -#ifdef __clang__ -# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" -#endif -#pragma GCC diagnostic ignored "-Wfloat-equal" -#pragma GCC diagnostic ignored "-Wpadded" -# include -#pragma GCC diagnostic pop - -#include -#include - -namespace osmium { - - namespace geom { - - namespace detail { - - class OGRFactoryImpl { - - public: - - typedef std::unique_ptr point_type; - typedef std::unique_ptr linestring_type; - typedef std::unique_ptr polygon_type; - typedef std::unique_ptr multipolygon_type; - typedef std::unique_ptr ring_type; - - private: - - linestring_type m_linestring; - multipolygon_type m_multipolygon; - polygon_type m_polygon; - ring_type m_ring; - - public: - - OGRFactoryImpl() = default; - - /* Point */ - - point_type make_point(const osmium::geom::Coordinates& xy) const { - return point_type(new OGRPoint(xy.x, xy.y)); - } - - /* LineString */ - - void linestring_start() { - m_linestring = std::unique_ptr(new OGRLineString()); - } - - void linestring_add_location(const osmium::geom::Coordinates& xy) { - assert(!!m_linestring); - m_linestring->addPoint(xy.x, xy.y); - } - - linestring_type linestring_finish(size_t /* num_points */) { - return std::move(m_linestring); - } - - /* Polygon */ - - void polygon_start() { - m_ring = std::unique_ptr(new OGRLinearRing()); - } - - void polygon_add_location(const osmium::geom::Coordinates& xy) { - assert(!!m_ring); - m_ring->addPoint(xy.x, xy.y); - } - - polygon_type polygon_finish(size_t /* num_points */) { - std::unique_ptr polygon = std::unique_ptr(new OGRPolygon()); - polygon->addRingDirectly(m_ring.release()); - return polygon; - } - - /* MultiPolygon */ - - void multipolygon_start() { - m_multipolygon.reset(new OGRMultiPolygon()); - } - - void multipolygon_polygon_start() { - m_polygon.reset(new OGRPolygon()); - } - - void multipolygon_polygon_finish() { - assert(!!m_multipolygon); - assert(!!m_polygon); - m_multipolygon->addGeometryDirectly(m_polygon.release()); - } - - void multipolygon_outer_ring_start() { - m_ring.reset(new OGRLinearRing()); - } - - void multipolygon_outer_ring_finish() { - assert(!!m_polygon); - assert(!!m_ring); - m_polygon->addRingDirectly(m_ring.release()); - } - - void multipolygon_inner_ring_start() { - m_ring.reset(new OGRLinearRing()); - } - - void multipolygon_inner_ring_finish() { - assert(!!m_polygon); - assert(!!m_ring); - m_polygon->addRingDirectly(m_ring.release()); - } - - void multipolygon_add_location(const osmium::geom::Coordinates& xy) { - assert(!!m_polygon); - assert(!!m_ring); - m_ring->addPoint(xy.x, xy.y); - } - - multipolygon_type multipolygon_finish() { - assert(!!m_multipolygon); - return std::move(m_multipolygon); - } - - }; // class OGRFactoryImpl - - } // namespace detail - - template - using OGRFactory = GeometryFactory; - - } // namespace geom - -} // namespace osmium - -#endif // OSMIUM_GEOM_OGR_HPP diff --git a/third_party/osmium/geom/projection.hpp b/third_party/osmium/geom/projection.hpp deleted file mode 100644 index 72ff945e9..000000000 --- a/third_party/osmium/geom/projection.hpp +++ /dev/null @@ -1,159 +0,0 @@ -#ifndef OSMIUM_GEOM_PROJECTION_HPP -#define OSMIUM_GEOM_PROJECTION_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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. - -*/ - -#define OSMIUM_LINK_WITH_LIBS_PROJ -lproj - -#include -#include - -#include - -#include -#include -#include - -namespace osmium { - - namespace geom { - - /** - * C++ wrapper for a Coordinate Reference System of the proj library. - */ - class CRS { - - struct ProjCRSDeleter { - void operator()(void* crs) { - pj_free(crs); - } - }; // struct ProjCRSDeleter - - std::unique_ptr m_crs; - - projPJ get() const { - return m_crs.get(); - } - - public: - - CRS(const std::string& crs) : - m_crs(pj_init_plus(crs.c_str()), ProjCRSDeleter()) { - if (!m_crs) { - throw osmium::projection_error(std::string("creation of CRS failed: ") + pj_strerrno(*pj_get_errno_ref())); - } - } - - CRS(int epsg) : - CRS(std::string("+init=epsg:") + std::to_string(epsg)) { - } - - bool is_latlong() const { - return pj_is_latlong(m_crs.get()); - } - - bool is_geocent() const { - return pj_is_geocent(m_crs.get()); - } - - /** - * Transform coordinates from one CRS into another. Wraps the same function - * of the proj library. - * - * Coordinates have to be in radians and are produced in radians. - * - * @throws osmmium::projection_error if the projection fails - */ - friend Coordinates transform(const CRS& src, const CRS& dest, Coordinates c) { - int result = pj_transform(src.get(), dest.get(), 1, 1, &c.x, &c.y, nullptr); - if (result != 0) { - throw osmium::projection_error(std::string("projection failed: ") + pj_strerrno(result)); - } - return c; - } - - }; // class CRS - - /** - * Functor that does projection from WGS84 (EPSG:4326) in to the given - * CRS. - */ - class Projection { - - int m_epsg; - std::string m_proj_string; - CRS m_crs_wgs84 {4326}; - CRS m_crs_user; - - public: - - Projection(const std::string& proj_string) : - m_epsg(-1), - m_proj_string(proj_string), - m_crs_user(proj_string) { - } - - Projection(int epsg) : - m_epsg(epsg), - m_proj_string(std::string("+init=epsg:") + std::to_string(epsg)), - m_crs_user(epsg) { - } - - Coordinates operator()(osmium::Location location) const { - if (m_epsg == 4326) { - return Coordinates(location.lon(), location.lat()); - } else { - Coordinates c = transform(m_crs_wgs84, m_crs_user, Coordinates(deg_to_rad(location.lon()), deg_to_rad(location.lat()))); - if (m_crs_user.is_latlong()) { - c.x = rad_to_deg(c.x); - c.y = rad_to_deg(c.y); - } - return c; - } - } - - int epsg() const noexcept { - return m_epsg; - } - - std::string proj_string() const { - return m_proj_string; - } - - }; // class Projection - - } // namespace geom - -} // namespace osmium - -#endif // OSMIUM_GEOM_PROJECTION_HPP diff --git a/third_party/osmium/geom/relations.hpp b/third_party/osmium/geom/relations.hpp deleted file mode 100644 index e57e2f4c9..000000000 --- a/third_party/osmium/geom/relations.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef OSMIUM_GEOM_RELATIONS_HPP -#define OSMIUM_GEOM_RELATIONS_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -namespace osmium { - - namespace geom { - - /** - * Check whether one geometry contains another. - */ - inline bool contains(const osmium::Box& a, const osmium::Box& b) { - return ((a.bottom_left().x() >= b.bottom_left().x()) && - (a.top_right().x() <= b.top_right().x()) && - (a.bottom_left().y() >= b.bottom_left().y()) && - (a.top_right().y() <= b.top_right().y())); - } - - } // namespace geom - -} // namespace osmium - -#endif // OSMIUM_GEOM_RELATIONS_HPP diff --git a/third_party/osmium/geom/util.hpp b/third_party/osmium/geom/util.hpp deleted file mode 100644 index 1f1a50dc8..000000000 --- a/third_party/osmium/geom/util.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef OSMIUM_GEOM_UTIL_HPP -#define OSMIUM_GEOM_UTIL_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -namespace osmium { - - /** - * Exception thrown when a projection object can not be initialized or the - * projection of some coordinates can not be calculated. - */ - struct projection_error : public std::runtime_error { - - projection_error(const std::string& what) : - std::runtime_error(what) { - } - - projection_error(const char* what) : - std::runtime_error(what) { - } - - }; // struct projection_error - - namespace geom { - - constexpr double PI = 3.14159265358979323846; - - /// Convert angle from degrees to radians. - inline constexpr double deg_to_rad(double degree) noexcept { - return degree * (PI / 180.0); - } - - /// Convert angle from radians to degrees. - inline constexpr double rad_to_deg(double radians) noexcept { - return radians * (180.0 / PI); - } - - } // namespace geom - -} // namespace osmium - -#endif // OSMIUM_GEOM_UTIL_HPP diff --git a/third_party/osmium/geom/wkb.hpp b/third_party/osmium/geom/wkb.hpp deleted file mode 100644 index 0748ede54..000000000 --- a/third_party/osmium/geom/wkb.hpp +++ /dev/null @@ -1,279 +0,0 @@ -#ifndef OSMIUM_GEOM_WKB_HPP -#define OSMIUM_GEOM_WKB_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include - -// Windows is only available for little endian architectures -// http://stackoverflow.com/questions/6449468/can-i-safely-assume-that-windows-installations-will-always-be-little-endian -#if !defined(_WIN32) && !defined(__APPLE__) -# include -#else -# define __LITTLE_ENDIAN 1234 -# define __BYTE_ORDER __LITTLE_ENDIAN -#endif - -#include -#include -#include - -namespace osmium { - - namespace geom { - - enum class wkb_type : bool { - wkb = false, - ewkb = true - }; // enum class wkb_type - - enum class out_type : bool { - binary = false, - hex = true - }; // enum class out_type - - namespace detail { - - template - inline void str_push(std::string& str, T data) { - size_t size = str.size(); - str.resize(size + sizeof(T)); - std::memcpy(const_cast(&str[size]), reinterpret_cast(&data), sizeof(T)); - } - - inline std::string convert_to_hex(std::string& str) { - static const char* lookup_hex = "0123456789ABCDEF"; - std::string out; - - for (char c : str) { - out += lookup_hex[(c >> 4) & 0xf]; - out += lookup_hex[c & 0xf]; - } - - return out; - } - - class WKBFactoryImpl { - - /// OSM data always uses SRID 4326 (WGS84). - static constexpr uint32_t srid = 4326; - - /** - * Type of WKB geometry. - * These definitions are from - * 99-049_OpenGIS_Simple_Features_Specification_For_SQL_Rev_1.1.pdf (for WKB) - * and http://trac.osgeo.org/postgis/browser/trunk/doc/ZMSgeoms.txt (for EWKB). - * They are used to encode geometries into the WKB format. - */ - enum wkbGeometryType : uint32_t { - wkbPoint = 1, - wkbLineString = 2, - wkbPolygon = 3, - wkbMultiPoint = 4, - wkbMultiLineString = 5, - wkbMultiPolygon = 6, - wkbGeometryCollection = 7, - - // SRID-presence flag (EWKB) - wkbSRID = 0x20000000 - }; // enum wkbGeometryType - - /** - * Byte order marker in WKB geometry. - */ - enum class wkb_byte_order_type : uint8_t { - XDR = 0, // Big Endian - NDR = 1 // Little Endian - }; // enum class wkb_byte_order_type - - std::string m_data; - uint32_t m_points {0}; - wkb_type m_wkb_type; - out_type m_out_type; - - size_t m_linestring_size_offset = 0; - size_t m_polygons = 0; - size_t m_rings = 0; - size_t m_multipolygon_size_offset = 0; - size_t m_polygon_size_offset = 0; - size_t m_ring_size_offset = 0; - - size_t header(std::string& str, wkbGeometryType type, bool add_length) const { -#if __BYTE_ORDER == __LITTLE_ENDIAN - str_push(str, wkb_byte_order_type::NDR); -#else - str_push(str, wkb_byte_order_type::XDR); -#endif - if (m_wkb_type == wkb_type::ewkb) { - str_push(str, type | wkbSRID); - str_push(str, srid); - } else { - str_push(str, type); - } - size_t offset = str.size(); - if (add_length) { - str_push(str, static_cast(0)); - } - return offset; - } - - void set_size(const size_t offset, const size_t size) { - const uint32_t s = static_cast_with_assert(size); - memcpy(&m_data[offset], &s, sizeof(uint32_t)); - } - - public: - - typedef std::string point_type; - typedef std::string linestring_type; - typedef std::string polygon_type; - typedef std::string multipolygon_type; - typedef std::string ring_type; - - explicit WKBFactoryImpl(wkb_type wtype=wkb_type::wkb, out_type otype=out_type::binary) : - m_wkb_type(wtype), - m_out_type(otype) { - } - - /* Point */ - - point_type make_point(const osmium::geom::Coordinates& xy) const { - std::string data; - header(data, wkbPoint, false); - str_push(data, xy.x); - str_push(data, xy.y); - - if (m_out_type == out_type::hex) { - return convert_to_hex(data); - } else { - return data; - } - } - - /* LineString */ - - void linestring_start() { - m_data.clear(); - m_linestring_size_offset = header(m_data, wkbLineString, true); - } - - void linestring_add_location(const osmium::geom::Coordinates& xy) { - str_push(m_data, xy.x); - str_push(m_data, xy.y); - } - - linestring_type linestring_finish(size_t num_points) { - set_size(m_linestring_size_offset, num_points); - std::string data; - std::swap(data, m_data); - - if (m_out_type == out_type::hex) { - return convert_to_hex(data); - } else { - return data; - } - } - - /* MultiPolygon */ - - void multipolygon_start() { - m_data.clear(); - m_polygons = 0; - m_multipolygon_size_offset = header(m_data, wkbMultiPolygon, true); - } - - void multipolygon_polygon_start() { - ++m_polygons; - m_rings = 0; - m_polygon_size_offset = header(m_data, wkbPolygon, true); - } - - void multipolygon_polygon_finish() { - set_size(m_polygon_size_offset, m_rings); - } - - void multipolygon_outer_ring_start() { - ++m_rings; - m_points = 0; - m_ring_size_offset = m_data.size(); - str_push(m_data, static_cast(0)); - } - - void multipolygon_outer_ring_finish() { - set_size(m_ring_size_offset, m_points); - } - - void multipolygon_inner_ring_start() { - ++m_rings; - m_points = 0; - m_ring_size_offset = m_data.size(); - str_push(m_data, static_cast(0)); - } - - void multipolygon_inner_ring_finish() { - set_size(m_ring_size_offset, m_points); - } - - void multipolygon_add_location(const osmium::geom::Coordinates& xy) { - str_push(m_data, xy.x); - str_push(m_data, xy.y); - ++m_points; - } - - multipolygon_type multipolygon_finish() { - set_size(m_multipolygon_size_offset, m_polygons); - std::string data; - std::swap(data, m_data); - - if (m_out_type == out_type::hex) { - return convert_to_hex(data); - } else { - return data; - } - } - - }; // class WKBFactoryImpl - - } // namespace detail - - template - using WKBFactory = GeometryFactory; - - } // namespace geom - -} // namespace osmium - -#endif // OSMIUM_GEOM_WKB_HPP diff --git a/third_party/osmium/geom/wkt.hpp b/third_party/osmium/geom/wkt.hpp deleted file mode 100644 index 0ef304a86..000000000 --- a/third_party/osmium/geom/wkt.hpp +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef OSMIUM_GEOM_WKT_HPP -#define OSMIUM_GEOM_WKT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include - -#include -#include - -namespace osmium { - - namespace geom { - - namespace detail { - - class WKTFactoryImpl { - - std::string m_str; - int m_precision; - - public: - - typedef std::string point_type; - typedef std::string linestring_type; - typedef std::string polygon_type; - typedef std::string multipolygon_type; - typedef std::string ring_type; - - WKTFactoryImpl(int precision = 7) : - m_precision(precision) { - } - - /* Point */ - - point_type make_point(const osmium::geom::Coordinates& xy) const { - std::string str {"POINT"}; - xy.append_to_string(str, '(', ' ', ')', m_precision); - return str; - } - - /* LineString */ - - void linestring_start() { - m_str = "LINESTRING("; - } - - void linestring_add_location(const osmium::geom::Coordinates& xy) { - xy.append_to_string(m_str, ' ', m_precision); - m_str += ','; - } - - linestring_type linestring_finish(size_t /* num_points */) { - assert(!m_str.empty()); - std::string str; - std::swap(str, m_str); - str.back() = ')'; - return str; - } - - /* MultiPolygon */ - - void multipolygon_start() { - m_str = "MULTIPOLYGON("; - } - - void multipolygon_polygon_start() { - m_str += '('; - } - - void multipolygon_polygon_finish() { - m_str += "),"; - } - - void multipolygon_outer_ring_start() { - m_str += '('; - } - - void multipolygon_outer_ring_finish() { - assert(!m_str.empty()); - m_str.back() = ')'; - } - - void multipolygon_inner_ring_start() { - m_str += ",("; - } - - void multipolygon_inner_ring_finish() { - assert(!m_str.empty()); - m_str.back() = ')'; - } - - void multipolygon_add_location(const osmium::geom::Coordinates& xy) { - xy.append_to_string(m_str, ' ', m_precision); - m_str += ','; - } - - multipolygon_type multipolygon_finish() { - assert(!m_str.empty()); - m_str.back() = ')'; - return std::move(m_str); - } - - }; // class WKTFactoryImpl - - } // namespace detail - - template - using WKTFactory = GeometryFactory; - - } // namespace geom - -} // namespace osmium - -#endif // OSMIUM_GEOM_WKT_HPP diff --git a/third_party/osmium/handler.hpp b/third_party/osmium/handler.hpp deleted file mode 100644 index 62e59f80a..000000000 --- a/third_party/osmium/handler.hpp +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef OSMIUM_HANDLER_HPP -#define OSMIUM_HANDLER_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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. - -*/ - -namespace osmium { - - class OSMObject; - class Node; - class Way; - class Relation; - class Area; - class Changeset; - class TagList; - class WayNodeList; - class RelationMemberList; - class OuterRing; - class InnerRing; - - /** - * @brief Osmium handlers provide callbacks for OSM objects - */ - namespace handler { - - class Handler { - - public: - - void osm_object(const osmium::OSMObject&) const { - } - - void node(const osmium::Node&) const { - } - - void way(const osmium::Way&) const { - } - - void relation(const osmium::Relation&) const { - } - - void area(const osmium::Area&) const { - } - - void changeset(const osmium::Changeset&) const { - } - - void tag_list(const osmium::TagList&) const { - } - - void way_node_list(const osmium::WayNodeList&) const { - } - - void relation_member_list(const osmium::RelationMemberList&) const { - } - - void outer_ring(const osmium::OuterRing&) const { - } - - void inner_ring(const osmium::InnerRing&) const { - } - - void flush() const { - } - - }; // class Handler - - } // namspace handler - -} // namespace osmium - -#endif // OSMIUM_HANDLER_HPP diff --git a/third_party/osmium/handler/chain.hpp b/third_party/osmium/handler/chain.hpp deleted file mode 100644 index 868632d7e..000000000 --- a/third_party/osmium/handler/chain.hpp +++ /dev/null @@ -1,128 +0,0 @@ -#ifndef OSMIUM_HANDLER_CHAIN_HPP -#define OSMIUM_HANDLER_CHAIN_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2014 Jochen Topf 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 - -#include - -#define OSMIUM_CHAIN_HANDLER_CALL(_func_, _type_) \ - template \ - struct call_ ## _func_ { \ - void operator()(THandlers& handlers, osmium::_type_& object) { \ - std::get(handlers)._func_(object); \ - call_ ## _func_()(handlers, object); \ - } \ - }; \ - template \ - struct call_ ## _func_ { \ - void operator()(THandlers&, osmium::_type_&) {} \ - }; - -namespace osmium { - - class Node; - class Way; - class Relation; - class Area; - class Changeset; - - namespace handler { - - /** - * This handler allows chaining of any number of handlers into a single - * handler. - */ - template - class ChainHandler : public osmium::handler::Handler { - - typedef std::tuple handlers_type; - handlers_type m_handlers; - - template - struct call_flush { - void operator()(THandlers& handlers) { - std::get(handlers).flush(); - call_flush()(handlers); - } - }; // struct call_flush - - template - struct call_flush { - void operator()(THandlers&) {} - }; // struct call_flush - - OSMIUM_CHAIN_HANDLER_CALL(node, Node) - OSMIUM_CHAIN_HANDLER_CALL(way, Way) - OSMIUM_CHAIN_HANDLER_CALL(relation, Relation) - OSMIUM_CHAIN_HANDLER_CALL(changeset, Changeset) - OSMIUM_CHAIN_HANDLER_CALL(area, Area) - - public: - - explicit ChainHandler(THandler&... handlers) : - m_handlers(handlers...) { - } - - void node(osmium::Node& node) { - call_node<0, sizeof...(THandler), handlers_type>()(m_handlers, node); - } - - void way(osmium::Way& way) { - call_way<0, sizeof...(THandler), handlers_type>()(m_handlers, way); - } - - void relation(osmium::Relation& relation) { - call_relation<0, sizeof...(THandler), handlers_type>()(m_handlers, relation); - } - - void changeset( osmium::Changeset& changeset) { - call_changeset<0, sizeof...(THandler), handlers_type>()(m_handlers, changeset); - } - - void area(osmium::Area& area) { - call_area<0, sizeof...(THandler), handlers_type>()(m_handlers, area); - } - - void flush() { - call_flush<0, sizeof...(THandler), handlers_type>()(m_handlers); - } - - }; // class ChainHandler - - } // namespace handler - -} // namespace osmium - -#endif // OSMIUM_HANDLER_CHAIN_HPP diff --git a/third_party/osmium/handler/disk_store.hpp b/third_party/osmium/handler/disk_store.hpp deleted file mode 100644 index 2b7ffcff6..000000000 --- a/third_party/osmium/handler/disk_store.hpp +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef OSMIUM_HANDLER_DISK_STORE_HPP -#define OSMIUM_HANDLER_DISK_STORE_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace osmium { - - namespace handler { - - /** - * - * Note: This handler will only work if either all object IDs are - * positive or all object IDs are negative. - */ - class DiskStore : public osmium::handler::Handler { - - typedef osmium::index::map::Map offset_index_type; - - size_t m_offset = 0; - int m_data_fd; - - offset_index_type& m_node_index; - offset_index_type& m_way_index; - offset_index_type& m_relation_index; - - public: - - explicit DiskStore(int data_fd, offset_index_type& node_index, offset_index_type& way_index, offset_index_type& relation_index) : - m_data_fd(data_fd), - m_node_index(node_index), - m_way_index(way_index), - m_relation_index(relation_index) { - } - - DiskStore(const DiskStore&) = delete; - DiskStore& operator=(const DiskStore&) = delete; - - ~DiskStore() noexcept = default; - - void node(const osmium::Node& node) { - m_node_index.set(node.positive_id(), m_offset); - m_offset += node.byte_size(); - } - - void way(const osmium::Way& way) { - m_way_index.set(way.positive_id(), m_offset); - m_offset += way.byte_size(); - } - - void relation(const osmium::Relation& relation) { - m_relation_index.set(relation.positive_id(), m_offset); - m_offset += relation.byte_size(); - } - - // XXX - void operator()(const osmium::memory::Buffer& buffer) { - osmium::io::detail::reliable_write(m_data_fd, buffer.data(), buffer.committed()); - - osmium::apply(buffer.begin(), buffer.end(), *this); - } - - }; // class DiskStore - - } // namespace handler - -} // namespace osmium - -#endif // OSMIUM_HANDLER_DISK_STORE_HPP diff --git a/third_party/osmium/handler/dump.hpp b/third_party/osmium/handler/dump.hpp deleted file mode 100644 index e62c4b071..000000000 --- a/third_party/osmium/handler/dump.hpp +++ /dev/null @@ -1,294 +0,0 @@ -#ifndef OSMIUM_HANDLER_DUMP_HPP -#define OSMIUM_HANDLER_DUMP_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace osmium { - - namespace handler { - - class Dump : public osmium::handler::Handler { - - std::ostream* m_out; - bool m_with_size; - std::string m_prefix; - - void print_title(const char* title, const osmium::memory::Item& item) { - *m_out << m_prefix - << title - << ":"; - - if (m_with_size) { - *m_out << " [" - << item.byte_size() - << "]"; - } - - *m_out << "\n"; - } - - void print_meta(const osmium::OSMObject& object) { - *m_out << m_prefix - << " id=" - << object.id() - << "\n"; - *m_out << m_prefix - << " version=" - << object.version() - << "\n"; - *m_out << m_prefix - << " uid=" - << object.uid() - << "\n"; - *m_out << m_prefix - << " user=|" - << object.user() - << "|\n"; - *m_out << m_prefix - << " changeset=" - << object.changeset() - << "\n"; - *m_out << m_prefix - << " timestamp=" - << object.timestamp().to_iso() - << "\n"; - *m_out << m_prefix - << " visible=" - << (object.visible() ? "yes" : "no") - << "\n"; - - Dump dump(*m_out, m_with_size, m_prefix + " "); - osmium::apply(object.cbegin(), object.cend(), dump); - } - - void print_location(const osmium::Node& node) { - const osmium::Location& location = node.location(); - - if (location) { - *m_out << m_prefix - << " lon=" - << std::fixed - << std::setprecision(7) - << location.lon_without_check() - << "\n"; - *m_out << m_prefix - << " lat=" - << location.lat_without_check() - << "\n"; - } else { - *m_out << m_prefix - << " lon=\n" - << m_prefix - << " lat=\n"; - } - } - - public: - - explicit Dump(std::ostream& out, bool with_size=true, const std::string& prefix="") : - m_out(&out), - m_with_size(with_size), - m_prefix(prefix) { - } - - void tag_list(const osmium::TagList& tags) { - print_title("TAGS", tags); - for (const auto& tag : tags) { - *m_out << m_prefix - << " k=|" - << tag.key() - << "| v=|" - << tag.value() - << "|" - << "\n"; - } - } - - void way_node_list(const osmium::WayNodeList& wnl) { - print_title("NODES", wnl); - for (const auto& node_ref : wnl) { - *m_out << m_prefix - << " ref=" - << node_ref.ref(); - if (node_ref.location()) { - *m_out << " pos=" - << node_ref.location(); - } - *m_out << "\n"; - } - } - - void relation_member_list(const osmium::RelationMemberList& rml) { - print_title("MEMBERS", rml); - for (const auto& member : rml) { - *m_out << m_prefix - << " type=" - << item_type_to_name(member.type()) - << " ref=" - << member.ref() - << " role=|" - << member.role() - << "|\n"; - if (member.full_member()) { - Dump dump(*m_out, m_with_size, m_prefix + " | "); - osmium::apply_item(member.get_object(), dump); - } - } - } - - void outer_ring(const osmium::OuterRing& ring) { - print_title("OUTER RING", ring); - for (const auto& node_ref : ring) { - *m_out << m_prefix - << " ref=" - << node_ref.ref(); - if (node_ref.location()) { - *m_out << " pos=" - << node_ref.location(); - } - *m_out << "\n"; - } - } - - void inner_ring(const osmium::InnerRing& ring) { - print_title("INNER RING", ring); - for (const auto& node_ref : ring) { - *m_out << m_prefix - << " ref=" - << node_ref.ref(); - if (node_ref.location()) { - *m_out << " pos=" - << node_ref.location(); - } - *m_out << "\n"; - } - } - - void node(const osmium::Node& node) { - print_title("NODE", node); - print_meta(node); - print_location(node); - } - - void way(const osmium::Way& way) { - print_title("WAY", way); - print_meta(way); - } - - void relation(const osmium::Relation& relation) { - print_title("RELATION", relation); - print_meta(relation); - } - - void area(const osmium::Area& area) { - print_title("AREA", area); - print_meta(area); - } - - void changeset(const osmium::Changeset& changeset) { - print_title("CHANGESET", changeset); - *m_out << m_prefix - << " id=" - << changeset.id() - << "\n"; - *m_out << m_prefix - << " num_changes=" - << changeset.num_changes() - << "\n"; - *m_out << m_prefix - << " uid=" - << changeset.uid() - << "\n"; - *m_out << m_prefix - << " user=|" - << changeset.user() - << "|\n"; - *m_out << m_prefix - << " created_at=" - << changeset.created_at().to_iso() - << "\n"; - *m_out << m_prefix - << " closed_at=" - << changeset.closed_at().to_iso() - << "\n"; - *m_out << m_prefix - << " bounds="; - - if (changeset.bounds()) { - *m_out << '(' - << changeset.bounds().bottom_left().lon_without_check() - << ',' - << changeset.bounds().bottom_left().lat_without_check() - << ',' - << changeset.bounds().top_right().lon_without_check() - << ',' - << changeset.bounds().top_right().lat_without_check() - << ')'; - } else { - *m_out << "(undefined)"; - } - - *m_out << "\n"; - - Dump dump(*m_out, m_with_size, m_prefix + " "); - osmium::apply(changeset.cbegin(), changeset.cend(), dump); - } - - }; // class Dump - - } // namespace handler - -} // namespace osmium - -#endif // OSMIUM_HANDLER_DUMP_HPP diff --git a/third_party/osmium/handler/node_locations_for_ways.hpp b/third_party/osmium/handler/node_locations_for_ways.hpp deleted file mode 100644 index a273082b0..000000000 --- a/third_party/osmium/handler/node_locations_for_ways.hpp +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef OSMIUM_HANDLER_NODE_LOCATIONS_FOR_WAYS_HPP -#define OSMIUM_HANDLER_NODE_LOCATIONS_FOR_WAYS_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace osmium { - - namespace handler { - - typedef osmium::index::map::Dummy dummy_type; - - /** - * Handler to retrieve locations from nodes and add them to ways. - * - * @tparam TStoragePosIDs Class that handles the actual storage of the node locations - * (for positive IDs). It must support the set(id, value) and - * get(id) methods. - * @tparam TStorageNegIDs Same but for negative IDs. - */ - template - class NodeLocationsForWays : public osmium::handler::Handler { - - static_assert(std::is_base_of, TStoragePosIDs>::value, - "Index class must be derived from osmium::index::map::Map"); - - static_assert(std::is_base_of, TStorageNegIDs>::value, - "Index class must be derived from osmium::index::map::Map"); - - public: - - typedef TStoragePosIDs index_pos_type; - typedef TStorageNegIDs index_neg_type; - - private: - - /// Object that handles the actual storage of the node locations (with positive IDs). - TStoragePosIDs& m_storage_pos; - - /// Object that handles the actual storage of the node locations (with negative IDs). - TStorageNegIDs& m_storage_neg; - - bool m_ignore_errors {false}; - - bool m_must_sort {false}; - - // It is okay to have this static dummy instance, even when using several threads, - // because it is read-only. - static dummy_type& get_dummy() { - static dummy_type instance; - return instance; - } - - public: - - explicit NodeLocationsForWays(TStoragePosIDs& storage_pos, - TStorageNegIDs& storage_neg = get_dummy()) : - m_storage_pos(storage_pos), - m_storage_neg(storage_neg) { - } - - NodeLocationsForWays(const NodeLocationsForWays&) = delete; - NodeLocationsForWays& operator=(const NodeLocationsForWays&) = delete; - - ~NodeLocationsForWays() noexcept = default; - - void ignore_errors() { - m_ignore_errors = true; - } - - /** - * Store the location of the node in the storage. - */ - void node(const osmium::Node& node) { - m_must_sort = true; - const osmium::object_id_type id = node.id(); - if (id >= 0) { - m_storage_pos.set(static_cast( id), node.location()); - } else { - m_storage_neg.set(static_cast(-id), node.location()); - } - } - - /** - * Get location of node with given id. - */ - osmium::Location get_node_location(const osmium::object_id_type id) const { - if (id >= 0) { - return m_storage_pos.get(static_cast( id)); - } else { - return m_storage_neg.get(static_cast(-id)); - } - } - - /** - * Retrieve locations of all nodes in the way from storage and add - * them to the way object. - */ - void way(osmium::Way& way) { - if (m_must_sort) { - m_storage_pos.sort(); - m_storage_neg.sort(); - m_must_sort = false; - } - bool error = false; - for (auto& node_ref : way.nodes()) { - try { - node_ref.set_location(get_node_location(node_ref.ref())); - if (!node_ref.location()) { - error = true; - } - } catch (osmium::not_found&) { - error = true; - } - } - if (error && !m_ignore_errors) { - throw osmium::not_found("location for one or more nodes not found in node location index"); - } - } - - /** - * Call clear on the location indexes. Makes the - * NodeLocationsForWays handler unusable. Used to explicitly free - * memory if thats needed. - */ - void clear() { - m_storage_pos.clear(); - m_storage_neg.clear(); - } - - }; // class NodeLocationsForWays - - } // namespace handler - -} // namespace osmium - -#endif // OSMIUM_HANDLER_NODE_LOCATIONS_FOR_WAYS_HPP diff --git a/third_party/osmium/handler/object_relations.hpp b/third_party/osmium/handler/object_relations.hpp deleted file mode 100644 index e73ce87fc..000000000 --- a/third_party/osmium/handler/object_relations.hpp +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef OSMIUM_HANDLER_OBJECT_RELATIONS_HPP -#define OSMIUM_HANDLER_OBJECT_RELATIONS_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include -#include - -namespace osmium { - - namespace handler { - - /** - * - * Note: This handler will only work if either all object IDs are - * positive or all object IDs are negative. - */ - class ObjectRelations : public osmium::handler::Handler { - - typedef osmium::index::multimap::Multimap index_type; - - index_type& m_index_n2w; - index_type& m_index_n2r; - index_type& m_index_w2r; - index_type& m_index_r2r; - - public: - - explicit ObjectRelations(index_type& n2w, index_type& n2r, index_type& w2r, index_type& r2r) : - m_index_n2w(n2w), - m_index_n2r(n2r), - m_index_w2r(w2r), - m_index_r2r(r2r) { - } - - ObjectRelations(const ObjectRelations&) = delete; - ObjectRelations& operator=(const ObjectRelations&) = delete; - - ~ObjectRelations() noexcept = default; - - void way(const osmium::Way& way) { - for (const auto& node_ref : way.nodes()) { - m_index_n2w.set(node_ref.positive_ref(), way.positive_id()); - } - } - - void relation(const osmium::Relation& relation) { - for (const auto& member : relation.members()) { - switch (member.type()) { - case osmium::item_type::node: - m_index_n2r.set(member.positive_ref(), relation.positive_id()); - break; - case osmium::item_type::way: - m_index_w2r.set(member.positive_ref(), relation.positive_id()); - break; - case osmium::item_type::relation: - m_index_r2r.set(member.positive_ref(), relation.positive_id()); - break; - default: - break; - } - } - } - - }; // class ObjectRelations - - } // namespace handler - -} // namespace osmium - -#endif // OSMIUM_HANDLER_OBJECT_RELATIONS_HPP diff --git a/third_party/osmium/index/detail/mmap_vector_anon.hpp b/third_party/osmium/index/detail/mmap_vector_anon.hpp deleted file mode 100644 index f06696150..000000000 --- a/third_party/osmium/index/detail/mmap_vector_anon.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef OSMIUM_DETAIL_MMAP_VECTOR_ANON_HPP -#define OSMIUM_DETAIL_MMAP_VECTOR_ANON_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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. - -*/ - -#ifdef __linux__ - -#include - -#include -#include - -namespace osmium { - - namespace detail { - - /** - * This class looks and behaves like STL vector, but uses mmap internally. - */ - template - class mmap_vector_anon : public mmap_vector_base { - - public: - - mmap_vector_anon() : - mmap_vector_base( - -1, - osmium::detail::mmap_vector_size_increment, - 0, - osmium::detail::typed_mmap::map(osmium::detail::mmap_vector_size_increment)) { - } - - void reserve(size_t new_capacity) { - if (new_capacity > this->capacity()) { - this->data(osmium::detail::typed_mmap::remap(this->data(), this->capacity(), new_capacity)); - this->m_capacity = new_capacity; - } - } - - }; // class mmap_vector_anon - - } // namespace detail - -} // namespace osmium - -#endif // __linux__ - -#endif // OSMIUM_DETAIL_MMAP_VECTOR_ANON_HPP diff --git a/third_party/osmium/index/detail/mmap_vector_base.hpp b/third_party/osmium/index/detail/mmap_vector_base.hpp deleted file mode 100644 index fc96b271a..000000000 --- a/third_party/osmium/index/detail/mmap_vector_base.hpp +++ /dev/null @@ -1,183 +0,0 @@ -#ifndef OSMIUM_DETAIL_MMAP_VECTOR_BASE_HPP -#define OSMIUM_DETAIL_MMAP_VECTOR_BASE_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include - -#include - -namespace osmium { - - namespace detail { - - constexpr size_t mmap_vector_size_increment = 1024 * 1024; - - /** - * This is a base class for implementing classes that look like - * STL vector but use mmap internally. This class can not be used - * on it's own. Use the derived classes mmap_vector_anon or - * mmap_vector_file. - */ - template class TDerived> - class mmap_vector_base { - - protected: - - int m_fd; - size_t m_capacity; - size_t m_size; - T* m_data; - - explicit mmap_vector_base(int fd, size_t capacity, size_t size, T* data) noexcept : - m_fd(fd), - m_capacity(capacity), - m_size(size), - m_data(data) { - } - - explicit mmap_vector_base(int fd, size_t capacity, size_t size) : - m_fd(fd), - m_capacity(capacity), - m_size(size), - m_data(osmium::detail::typed_mmap::grow_and_map(capacity, m_fd)) { - } - - void data(T* data) { - m_data = data; - } - - public: - - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; - typedef T* iterator; - typedef const T* const_iterator; - - ~mmap_vector_base() { - osmium::detail::typed_mmap::unmap(m_data, m_capacity); - } - - size_t capacity() const noexcept { - return m_capacity; - } - - size_t size() const noexcept { - return m_size; - } - - bool empty() const noexcept { - return m_size == 0; - } - - const T* data() const noexcept { - return m_data; - } - - T* data() noexcept { - return m_data; - } - - T& operator[](size_t n) { - return m_data[n]; - } - - T at(size_t n) const { - if (n >= m_size) { - throw std::out_of_range("out of range"); - } - return m_data[n]; - } - - void clear() noexcept { - m_size = 0; - } - - void shrink_to_fit() { - // XXX do something here - } - - void push_back(const T& value) { - if (m_size >= m_capacity) { - resize(m_size+1); - } - m_data[m_size] = value; - ++m_size; - } - - void resize(size_t new_size) { - if (new_size > capacity()) { - static_cast*>(this)->reserve(new_size + osmium::detail::mmap_vector_size_increment); - } - if (new_size > size()) { - new (data() + size()) T[new_size - size()]; - } - m_size = new_size; - } - - iterator begin() noexcept { - return m_data; - } - - iterator end() noexcept { - return m_data + m_size; - } - - const_iterator begin() const noexcept { - return m_data; - } - - const_iterator end() const noexcept { - return m_data + m_size; - } - - const_iterator cbegin() noexcept { - return m_data; - } - - const_iterator cend() noexcept { - return m_data + m_size; - } - - }; // class mmap_vector_base - - } // namespace detail - -} // namespace osmium - -#endif // OSMIUM_DETAIL_MMAP_VECTOR_BASE_HPP diff --git a/third_party/osmium/index/detail/mmap_vector_file.hpp b/third_party/osmium/index/detail/mmap_vector_file.hpp deleted file mode 100644 index ca8f0ebfa..000000000 --- a/third_party/osmium/index/detail/mmap_vector_file.hpp +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef OSMIUM_DETAIL_MMAP_VECTOR_FILE_HPP -#define OSMIUM_DETAIL_MMAP_VECTOR_FILE_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 - -#include -#include -#include - -namespace osmium { - - namespace detail { - - /** - * This class looks and behaves like STL vector, but mmap's a file internally. - */ - template - class mmap_vector_file : public mmap_vector_base { - - public: - - explicit mmap_vector_file() : - mmap_vector_base( - osmium::detail::create_tmp_file(), - osmium::detail::mmap_vector_size_increment, - 0) { - } - - explicit mmap_vector_file(int fd) : - mmap_vector_base( - fd, - osmium::detail::typed_mmap::file_size(fd) == 0 ? osmium::detail::mmap_vector_size_increment : osmium::detail::typed_mmap::file_size(fd), - osmium::detail::typed_mmap::file_size(fd)) { - } - - void reserve(size_t new_capacity) { - if (new_capacity > this->capacity()) { - osmium::detail::typed_mmap::unmap(this->data(), this->capacity()); - this->data(osmium::detail::typed_mmap::grow_and_map(new_capacity, this->m_fd)); - this->m_capacity = new_capacity; - } - } - - }; // class mmap_vector_file - - } // namespace detail - -} // namespace osmium - -#endif // OSMIUM_DETAIL_MMAP_VECTOR_FILE_HPP diff --git a/third_party/osmium/index/detail/tmpfile.hpp b/third_party/osmium/index/detail/tmpfile.hpp deleted file mode 100644 index 3d00c5017..000000000 --- a/third_party/osmium/index/detail/tmpfile.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef OSMIUM_DETAIL_TMPFILE_HPP -#define OSMIUM_DETAIL_TMPFILE_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include - -namespace osmium { - - namespace detail { - - /** - * Create and open a temporary file. It is removed after opening. - * - * @returns File descriptor of temporary file. - * @throws std::system_error if something went wrong. - */ - inline int create_tmp_file() { - FILE* file = ::tmpfile(); - if (!file) { - throw std::system_error(errno, std::system_category(), "tempfile failed"); - } - return fileno(file); - } - - } // namespace detail - -} // namespace osmium - -#endif // OSMIUM_DETAIL_TMPFILE diff --git a/third_party/osmium/index/detail/typed_mmap.hpp b/third_party/osmium/index/detail/typed_mmap.hpp deleted file mode 100644 index 8a952a4e0..000000000 --- a/third_party/osmium/index/detail/typed_mmap.hpp +++ /dev/null @@ -1,229 +0,0 @@ -#ifndef OSMIUM_DETAIL_TYPED_MMAP_HPP -#define OSMIUM_DETAIL_TYPED_MMAP_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include - -#include - -#ifndef _WIN32 -# include -#else -# include -#endif - -#ifndef _MSC_VER -# include -#else -# define ftruncate _chsize -#endif - -// for bsd systems -#ifndef MAP_ANONYMOUS -# define MAP_ANONYMOUS MAP_ANON -#endif - -#include - -namespace osmium { - - /** - * @brief Namespace for Osmium internal use - */ - namespace detail { - - /** - * This is a helper class for working with memory mapped files and - * anonymous shared memory. It wraps the necessary system calls - * adding: - * - error checking: all functions throw exceptions where needed - * - internal casts and size calculations allow use with user defined - * type T instead of void* - * - * This class only contains static functions. It should never be - * instantiated. - * - * @tparam T Type of objects we want to store. - */ - template - class typed_mmap { - - public: - - /** - * Create anonymous private memory mapping with enough space for size - * objects of type T. - * - * Note that no constructor is called for any of the objects in this memory! - * - * @param size Number of objects of type T that should fit into this memory - * @returns Pointer to mapped memory - * @throws std::system_error If mmap(2) failed - */ - static T* map(size_t size) { - void* addr = ::mmap(nullptr, sizeof(T) * size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" - if (addr == MAP_FAILED) { - throw std::system_error(errno, std::system_category(), "mmap failed"); - } -#pragma GCC diagnostic pop - return reinterpret_cast(addr); - } - - /** - * Create shared memory mapping of a file with enough space for size - * objects of type T. The file must already have at least the - * required size. - * - * Note that no constructor is called for any of the objects in this memory! - * - * @param size Number of objects of type T that should fit into this memory - * @param fd File descriptor - * @param write True if data should be writable - * @returns Pointer to mapped memory - * @throws std::system_error If mmap(2) failed - */ - static T* map(size_t size, int fd, bool write = false) { - int prot = PROT_READ; - if (write) { - prot |= PROT_WRITE; - } - void* addr = ::mmap(nullptr, sizeof(T) * size, prot, MAP_SHARED, fd, 0); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" - if (addr == MAP_FAILED) { - throw std::system_error(errno, std::system_category(), "mmap failed"); - } -#pragma GCC diagnostic pop - return reinterpret_cast(addr); - } - -// mremap(2) is only available on linux systems -#ifdef __linux__ - /** - * Grow memory mapping created with map(). - * - * Note that no constructor is called for any of the objects in this memory! - * - * @param data Pointer to current mapping (as returned by typed_mmap()) - * @param old_size Number of objects currently stored in this memory - * @param new_size Number of objects we want to have space for - * @throws std::system_error If mremap(2) call failed - */ - static T* remap(T* data, size_t old_size, size_t new_size) { - void* addr = ::mremap(reinterpret_cast(data), sizeof(T) * old_size, sizeof(T) * new_size, MREMAP_MAYMOVE); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" - if (addr == MAP_FAILED) { - throw std::system_error(errno, std::system_category(), "mremap failed"); - } -#pragma GCC diagnostic pop - return reinterpret_cast(addr); - } -#endif - - /** - * Release memory from map() call. - * - * Note that no destructor is called for the objects in this memory! - * - * @param data Pointer to the data - * @param size Number of objects of type T stored - * @throws std::system_error If munmap(2) call failed - */ - static void unmap(T* data, size_t size) { - if (::munmap(reinterpret_cast(data), sizeof(T) * size) != 0) { - throw std::system_error(errno, std::system_category(), "munmap failed"); - } - } - - /** - * Get number of objects of type T that would fit into a file. - * - * @param fd File descriptor - * @returns Number of objects of type T in this file - * @throws std::system_error If fstat(2) call failed - * @throws std::length_error If size of the file isn't a multiple of sizeof(T) - */ - static size_t file_size(int fd) { - struct stat s; - if (fstat(fd, &s) < 0) { - throw std::system_error(errno, std::system_category(), "fstat failed"); - } - if (static_cast(s.st_size) % sizeof(T) != 0) { - throw std::length_error("file size has to be multiple of object size"); - } - return static_cast(s.st_size) / sizeof(T); - } - - /** - * Grow file so there is enough space for at least new_size objects - * of type T. If the file is large enough already, nothing is done. - * The file is never shrunk. - * - * @param new_size Number of objects of type T that should fit into this file - * @param fd File descriptor - * @throws std::system_error If ftruncate(2) call failed - */ - static void grow_file(size_t new_size, int fd) { - if (file_size(fd) < new_size) { - if (::ftruncate(fd, static_cast_with_assert(sizeof(T) * new_size)) < 0) { - throw std::system_error(errno, std::system_category(), "ftruncate failed"); - } - } - } - - /** - * Grow file to given size (if it is smaller) and mmap it. - * - * @param size Number of objects of type T that should fit into this file - * @param fd File descriptor - * @throws Errors thrown by grow_file() or map() - */ - static T* grow_and_map(size_t size, int fd) { - grow_file(size, fd); - return map(size, fd, true); - } - - }; // class typed_mmap - - } // namespace detail - -} // namespace osmium - -#endif // OSMIUM_DETAIL_TYPED_MMAP_HPP diff --git a/third_party/osmium/index/index.hpp b/third_party/osmium/index/index.hpp deleted file mode 100644 index ece8ec444..000000000 --- a/third_party/osmium/index/index.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef OSMIUM_INDEX_INDEX_HPP -#define OSMIUM_INDEX_INDEX_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include - -#include - -namespace osmium { - - /** - * Exception signaling that an element could not be - * found in an index. - */ - struct not_found : public std::runtime_error { - - not_found(const std::string& what) : - std::runtime_error(what) { - } - - not_found(const char* what) : - std::runtime_error(what) { - } - - }; // struct not_found - - /** - * @brief Indexing of OSM data, Locations, etc. - */ - namespace index { - - template - OSMIUM_NORETURN void not_found_error(TKey key) { - std::stringstream s; - s << "id " << key << " no found"; - throw not_found(s.str()); - } - - /** - * Some of the index classes need an "empty" value that can - * never appear in real data. This function must return this - * empty value for any class used as a value in an index. - * The default implementation returns a default constructed - * object, but it can be specialized. - */ - template - inline constexpr T empty_value() { - return T{}; - } - - /** - * The size_t value in indexes is usually used for offsets - * into a buffer or file. It is unlikely that we ever need - * the full range, so the max value is a good "empty" value. - */ - template <> - inline OSMIUM_CONSTEXPR size_t empty_value() { - return std::numeric_limits::max(); - } - - } // namespace index - -} // namespace osmium - -#endif // OSMIUM_INDEX_INDEX_HPP diff --git a/third_party/osmium/index/map.hpp b/third_party/osmium/index/map.hpp deleted file mode 100644 index 92b880f47..000000000 --- a/third_party/osmium/index/map.hpp +++ /dev/null @@ -1,155 +0,0 @@ -#ifndef OSMIUM_INDEX_MAP_HPP -#define OSMIUM_INDEX_MAP_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -#include // IWYU pragma: export - -namespace osmium { - - namespace index { - - /** - * @brief Key-value containers with unique integer values for a key - */ - namespace map { - - /** - * This abstract class defines an interface to storage classes - * intended for storing small pieces of data (such as coordinates) - * indexed by a positive integer (such as an object ID). The - * storage must be very space efficient and able to scale to billions - * of objects. - * - * Subclasses have different implementations that store the - * data in different ways in memory and/or on disk. Some storage - * classes are better suited when working with the whole planet, - * some are better for data extracts. - * - * Note that these classes are not required to track "empty" fields. - * When reading data you have to be sure you have put something in - * there before. - * - * A typical use for this and derived classes is storage of node - * locations indexed by node ID. These indexes will only work - * on 64 bit systems if used in this case. 32 bit systems just - * can't address that much memory! - * - * @tparam TId Id type, usually osmium::unsigned_object_id_type, - * must be an unsigned integral type. - * @tparam TValue Value type, usually osmium::Location or size_t. - * Copied by value, so should be "small" type. - */ - template - class Map { - - static_assert(std::is_integral::value && std::is_unsigned::value, - "TId template parameter for class Map must be unsigned integral type"); - - Map(const Map&) = delete; - Map& operator=(const Map&) = delete; - - protected: - - Map(Map&&) = default; - Map& operator=(Map&&) = default; - - public: - - /// The "key" type, usually osmium::unsigned_object_id_type. - typedef TId key_type; - - /// The "value" type, usually a Location or size_t. - typedef TValue value_type; - - Map() = default; - - virtual ~Map() = default; - - virtual void reserve(const size_t) { - // default implementation is empty - } - - /// Set the field with id to value. - virtual void set(const TId id, const TValue value) = 0; - - /// Retrieve value by id. Does not check for overflow or empty fields. - virtual const TValue get(const TId id) const = 0; - - /** - * Get the approximate number of items in the storage. The storage - * might allocate memory in blocks, so this size might not be - * accurate. You can not use this to find out how much memory the - * storage uses. Use used_memory() for that. - */ - virtual size_t size() const = 0; - - /** - * Get the memory used for this storage in bytes. Note that this - * is not necessarily entirely accurate but an approximation. - * For storage classes that store the data in memory, this is - * the main memory used, for storage classes storing data on disk - * this is the memory used on disk. - */ - virtual size_t used_memory() const = 0; - - /** - * Clear memory used for this storage. After this you can not - * use the storage container any more. - */ - virtual void clear() = 0; - - /** - * Sort data in map. Call this after writing all data and - * before reading. Not all implementations need this. - */ - virtual void sort() { - // default implementation is empty - } - - virtual void dump_as_list(int /*fd*/) const { - std::runtime_error("can't dump as list"); - } - - }; // class Map - - } // namespace map - - } // namespace index - -} // namespace osmium - -#endif // OSMIUM_INDEX_MAP_HPP diff --git a/third_party/osmium/index/map/dummy.hpp b/third_party/osmium/index/map/dummy.hpp deleted file mode 100644 index bafb81008..000000000 --- a/third_party/osmium/index/map/dummy.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef OSMIUM_INDEX_MAP_DUMMY_HPP -#define OSMIUM_INDEX_MAP_DUMMY_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 - -#include - -namespace osmium { - - namespace index { - - namespace map { - - /** - * Pseudo map. - * Use this class if you don't need a map, but you - * need an object that behaves like one. - */ - template - class Dummy : public osmium::index::map::Map { - - public: - - Dummy() = default; - - ~Dummy() override final = default; - - void set(const TId, const TValue) override final { - // intentionally left blank - } - - const TValue get(const TId id) const override final { - not_found_error(id); - } - - size_t size() const override final { - return 0; - } - - size_t used_memory() const override final { - return 0; - } - - void clear() override final { - } - - }; // class Dummy - - } // namespace map - - } // namespace index - -} // namespace osmium - -#endif // OSMIUM_INDEX_MAP_DUMMY_HPP diff --git a/third_party/osmium/index/map/mmap_vector_anon.hpp b/third_party/osmium/index/map/mmap_vector_anon.hpp deleted file mode 100644 index a62e99aa6..000000000 --- a/third_party/osmium/index/map/mmap_vector_anon.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef OSMIUM_INDEX_MAP_MMAP_VECTOR_ANON_HPP -#define OSMIUM_INDEX_MAP_MMAP_VECTOR_ANON_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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. - -*/ - -#ifdef __linux__ - -#include -#include - -namespace osmium { - - namespace index { - - namespace map { - - template - using DenseMapMmap = VectorBasedDenseMap, TId, TValue>; - - template - using SparseMapMmap = VectorBasedSparseMap; - - } // namespace map - - } // namespace index - -} // namespace osmium - -#endif // __linux__ - -#endif // OSMIUM_INDEX_MAP_MMAP_VECTOR_ANON_HPP diff --git a/third_party/osmium/index/map/mmap_vector_file.hpp b/third_party/osmium/index/map/mmap_vector_file.hpp deleted file mode 100644 index 7ea76fa6b..000000000 --- a/third_party/osmium/index/map/mmap_vector_file.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef OSMIUM_INDEX_MAP_MMAP_VECTOR_FILE_HPP -#define OSMIUM_INDEX_MAP_MMAP_VECTOR_FILE_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -namespace osmium { - - namespace index { - - namespace map { - - template - using DenseMapFile = VectorBasedDenseMap, TId, TValue>; - - template - using SparseMapFile = VectorBasedSparseMap; - - } // namespace map - - } // namespace index - -} // namespace osmium - -#endif // OSMIUM_INDEX_MAP_MMAP_VECTOR_FILE_HPP diff --git a/third_party/osmium/index/map/sparse_table.hpp b/third_party/osmium/index/map/sparse_table.hpp deleted file mode 100644 index 704e33e21..000000000 --- a/third_party/osmium/index/map/sparse_table.hpp +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef OSMIUM_INDEX_MAP_SPARSE_TABLE_HPP -#define OSMIUM_INDEX_MAP_SPARSE_TABLE_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include - -#include - -#include -#include - -namespace osmium { - - namespace index { - - namespace map { - - /** - * The SparseTable index stores elements in a Google sparsetable, - * a data structure that can hold sparsly filled tables in a - * very space efficient way. It will resize automatically. - * - * Use this index if the ID space is only sparsly - * populated, such as when working with smaller OSM files (like - * country extracts). - * - * This will only work on 64 bit machines. - */ - template - class SparseTable : public osmium::index::map::Map { - - TId m_grow_size; - - google::sparsetable m_elements; - - static_assert(sizeof(typename google::sparsetable::size_type) >= 8, "google::sparsetable needs 64bit machine"); - - public: - - /** - * Constructor. - * - * @param grow_size The initial size of the index (ie number of - * elements that fit into the index). - * The storage will grow by at least this size - * every time it runs out of space. - */ - explicit SparseTable(const TId grow_size=10000) : - m_grow_size(grow_size), - m_elements(grow_size) { - } - - ~SparseTable() override final = default; - - void set(const TId id, const TValue value) override final { - if (id >= m_elements.size()) { - m_elements.resize(id + m_grow_size); - } - m_elements[id] = value; - } - - const TValue get(const TId id) const override final { - if (id >= m_elements.size()) { - not_found_error(id); - } - if (m_elements[id] == osmium::index::empty_value()) { - not_found_error(id); - } - return m_elements[id]; - } - - size_t size() const override final { - return m_elements.size(); - } - - size_t used_memory() const override final { - // unused elements use 1 bit, used elements sizeof(TValue) bytes - // http://google-sparsehash.googlecode.com/svn/trunk/doc/sparsetable.html - return (m_elements.size() / 8) + (m_elements.num_nonempty() * sizeof(TValue)); - } - - void clear() override final { - m_elements.clear(); - } - - void dump_as_list(const int fd) const override final { - std::vector> v; - int n=0; - for (const TValue value : m_elements) { - if (value != osmium::index::empty_value()) { - v.emplace_back(n, value); - } - ++n; - } - osmium::io::detail::reliable_write(fd, reinterpret_cast(v.data()), sizeof(std::pair) * v.size()); - } - - }; // class SparseTable - - } // namespace map - - } // namespace index - -} // namespace osmium - -#endif // OSMIUM_INDEX_BYID_SPARSE_TABLE_HPP diff --git a/third_party/osmium/index/map/stl_map.hpp b/third_party/osmium/index/map/stl_map.hpp deleted file mode 100644 index d2781a7e1..000000000 --- a/third_party/osmium/index/map/stl_map.hpp +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef OSMIUM_INDEX_MAP_STL_MAP_HPP -#define OSMIUM_INDEX_MAP_STL_MAP_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include - -#include -#include - -namespace osmium { - - namespace index { - - namespace map { - - /** - * This implementation uses std::map internally. It uses rather a - * lot of memory, but might make sense for small maps. - */ - template - class StlMap : public osmium::index::map::Map { - - // This is a rough estimate for the memory needed for each - // element in the map (id + value + pointers to left, right, - // and parent plus some overhead for color of red-black-tree - // or similar). - static constexpr size_t element_size = sizeof(TId) + sizeof(TValue) + sizeof(void*) * 4; - - std::map m_elements; - - public: - - StlMap() = default; - - ~StlMap() override final = default; - - void set(const TId id, const TValue value) override final { - m_elements[id] = value; - } - - const TValue get(const TId id) const override final { - try { - return m_elements.at(id); - } catch (std::out_of_range&) { - not_found_error(id); - } - } - - size_t size() const override final { - return m_elements.size(); - } - - size_t used_memory() const override final { - return element_size * m_elements.size(); - } - - void clear() override final { - m_elements.clear(); - } - - void dump_as_list(const int fd) const override final { - typedef typename std::map::value_type t; - std::vector v; - std::copy(m_elements.begin(), m_elements.end(), std::back_inserter(v)); - osmium::io::detail::reliable_write(fd, reinterpret_cast(v.data()), sizeof(t) * v.size()); - } - - }; // class StlMap - - } // namespace map - - } // namespace index - -} // namespace osmium - -#endif // OSMIUM_INDEX_MAP_STL_MAP_HPP diff --git a/third_party/osmium/index/map/stl_vector.hpp b/third_party/osmium/index/map/stl_vector.hpp deleted file mode 100644 index 238e9afa9..000000000 --- a/third_party/osmium/index/map/stl_vector.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef OSMIUM_INDEX_MAP_STL_VECTOR_HPP -#define OSMIUM_INDEX_MAP_STL_VECTOR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 - -#include - -namespace osmium { - - namespace index { - - namespace map { - - template - using DenseMapMem = VectorBasedDenseMap, TId, TValue>; - - template - using StdVectorWrap = std::vector; - - template - using SparseMapMem = VectorBasedSparseMap; - - } // namespace map - - } // namespace index - -} // namespace osmium - -#endif // OSMIUM_INDEX_MAP_STL_VECTOR_HPP diff --git a/third_party/osmium/index/map/vector.hpp b/third_party/osmium/index/map/vector.hpp deleted file mode 100644 index 7e47ccfba..000000000 --- a/third_party/osmium/index/map/vector.hpp +++ /dev/null @@ -1,208 +0,0 @@ -#ifndef OSMIUM_INDEX_MAP_VECTOR_HPP -#define OSMIUM_INDEX_MAP_VECTOR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include - -#include -#include - -namespace osmium { - - namespace index { - - namespace map { - - template - class VectorBasedDenseMap : public Map { - - TVector m_vector; - - public: - - VectorBasedDenseMap() : - m_vector() { - } - - explicit VectorBasedDenseMap(int fd) : - m_vector(fd) { - } - - ~VectorBasedDenseMap() {} - - void reserve(const size_t size) override final { - m_vector.reserve(size); - } - - void set(const TId id, const TValue value) override final { - if (size() <= id) { - m_vector.resize(id+1); - } - m_vector[id] = value; - } - - const TValue get(const TId id) const override final { - try { - const TValue& value = m_vector.at(id); - if (value == osmium::index::empty_value()) { - not_found_error(id); - } - return value; - } catch (std::out_of_range&) { - not_found_error(id); - } - } - - size_t size() const override final { - return m_vector.size(); - } - - size_t used_memory() const override final { - return sizeof(TValue) * size(); - } - - void clear() override final { - m_vector.clear(); - m_vector.shrink_to_fit(); - } - - }; // class VectorBasedDenseMap - - - template class TVector> - class VectorBasedSparseMap : public Map { - - public: - - typedef typename std::pair element_type; - typedef TVector vector_type; - typedef typename vector_type::iterator iterator; - typedef typename vector_type::const_iterator const_iterator; - - private: - - vector_type m_vector; - - public: - - VectorBasedSparseMap() : - m_vector() { - } - - VectorBasedSparseMap(int fd) : - m_vector(fd) { - } - - ~VectorBasedSparseMap() override final = default; - - void set(const TId id, const TValue value) override final { - m_vector.push_back(element_type(id, value)); - } - - const TValue get(const TId id) const override final { - const element_type element { - id, - osmium::index::empty_value() - }; - const auto result = std::lower_bound(m_vector.begin(), m_vector.end(), element, [](const element_type& a, const element_type& b) { - return a.first < b.first; - }); - if (result == m_vector.end() || result->first != id) { - not_found_error(id); - } else { - return result->second; - } - } - - size_t size() const override final { - return m_vector.size(); - } - - size_t byte_size() const { - return m_vector.size() * sizeof(element_type); - } - - size_t used_memory() const override final { - return sizeof(element_type) * size(); - } - - void clear() override final { - m_vector.clear(); - m_vector.shrink_to_fit(); - } - - void sort() override final { - std::sort(m_vector.begin(), m_vector.end()); - } - - void dump_as_list(int fd) const override final { - osmium::io::detail::reliable_write(fd, reinterpret_cast(m_vector.data()), byte_size()); - } - - iterator begin() { - return m_vector.begin(); - } - - iterator end() { - return m_vector.end(); - } - - const_iterator cbegin() const { - return m_vector.cbegin(); - } - - const_iterator cend() const { - return m_vector.cend(); - } - - const_iterator begin() const { - return m_vector.cbegin(); - } - - const_iterator end() const { - return m_vector.cend(); - } - - }; // class VectorBasedSparseMap - - } // namespace map - - } // namespace index - -} // namespace osmium - -#endif // OSMIUM_INDEX_MAP_VECTOR_HPP diff --git a/third_party/osmium/index/multimap.hpp b/third_party/osmium/index/multimap.hpp deleted file mode 100644 index f76c65ddb..000000000 --- a/third_party/osmium/index/multimap.hpp +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef OSMIUM_INDEX_MULTIMAP_HPP -#define OSMIUM_INDEX_MULTIMAP_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include - -#include // IWYU pragma: export - -namespace osmium { - - namespace index { - - /** - * @brief Key-value containers with multiple values for an integer key - */ - namespace multimap { - - template - class Multimap { - - static_assert(std::is_integral::value && std::is_unsigned::value, - "TId template parameter for class Multimap must be unsigned integral type"); - - typedef typename std::pair element_type; - - Multimap(const Multimap&) = delete; - Multimap& operator=(const Multimap&) = delete; - - protected: - - Multimap(Multimap&&) = default; - Multimap& operator=(Multimap&&) = default; - - public: - - /// The "key" type, usually osmium::unsigned_object_id_type. - typedef TId key_type; - - /// The "value" type, usually a Location or size_t. - typedef TValue value_type; - - Multimap() = default; - - virtual ~Multimap() noexcept = default; - - /// Set the field with id to value. - virtual void set(const TId id, const TValue value) = 0; - - typedef element_type* iterator; - -// virtual std::pair get_all(const TId id) const = 0; - - /** - * Get the approximate number of items in the storage. The storage - * might allocate memory in blocks, so this size might not be - * accurate. You can not use this to find out how much memory the - * storage uses. Use used_memory() for that. - */ - virtual size_t size() const = 0; - - /** - * Get the memory used for this storage in bytes. Note that this - * is not necessarily entirely accurate but an approximation. - * For storage classes that store the data in memory, this is - * the main memory used, for storage classes storing data on disk - * this is the memory used on disk. - */ - virtual size_t used_memory() const = 0; - - /** - * Clear memory used for this storage. After this you can not - * use the storage container any more. - */ - virtual void clear() = 0; - - /** - * Sort data in map. Call this after writing all data and - * before reading. Not all implementations need this. - */ - virtual void sort() { - // default implementation is empty - } - - virtual void dump_as_list(int /*fd*/) const { - std::runtime_error("can't dump as list"); - } - - }; // class Multimap - - } // namespace map - - } // namespace index - -} // namespace osmium - -#endif // OSMIUM_INDEX_MULTIMAP_HPP diff --git a/third_party/osmium/index/multimap/hybrid.hpp b/third_party/osmium/index/multimap/hybrid.hpp deleted file mode 100644 index abaf31e95..000000000 --- a/third_party/osmium/index/multimap/hybrid.hpp +++ /dev/null @@ -1,199 +0,0 @@ -#ifndef OSMIUM_INDEX_MULTIMAP_HYBRID_HPP -#define OSMIUM_INDEX_MULTIMAP_HYBRID_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -#include -#include -#include - -namespace osmium { - - namespace index { - - namespace multimap { - - template - class HybridIterator { - - typedef SparseMultimapMem main_map_type; - typedef StlMultimap extra_map_type; - - typedef typename std::pair element_type; - - typename main_map_type::iterator m_begin_main; - typename main_map_type::iterator m_end_main; - typename extra_map_type::iterator m_begin_extra; - typename extra_map_type::iterator m_end_extra; - - public: - - explicit HybridIterator(typename main_map_type::iterator begin_main, - typename main_map_type::iterator end_main, - typename extra_map_type::iterator begin_extra, - typename extra_map_type::iterator end_extra) : - m_begin_main(begin_main), - m_end_main(end_main), - m_begin_extra(begin_extra), - m_end_extra(end_extra) { - } - - HybridIterator& operator++() { - if (m_begin_main == m_end_main) { - ++m_begin_extra; - } else { - ++m_begin_main; - while (m_begin_main != m_end_main && m_begin_main->second == osmium::index::empty_value()) { // ignore removed elements - ++m_begin_main; - } - } - return *this; - } - - HybridIterator operator++(int) { - auto tmp(*this); - operator++(); - return tmp; - } - - bool operator==(const HybridIterator& rhs) const { - return m_begin_main == rhs.m_begin_main && - m_end_main == rhs.m_end_main && - m_begin_extra == rhs.m_begin_extra && - m_end_extra == rhs.m_end_extra; - } - - bool operator!=(const HybridIterator& rhs) const { - return ! operator==(rhs); - } - - const element_type& operator*() { - if (m_begin_main == m_end_main) { - return *m_begin_extra; - } else { - return *m_begin_main; - } - } - - const element_type* operator->() { - return &operator*(); - } - - }; // class HybridIterator - - template - class Hybrid : public Multimap { - - typedef SparseMultimapMem main_map_type; - typedef StlMultimap extra_map_type; - - main_map_type m_main; - extra_map_type m_extra; - - public: - - typedef HybridIterator iterator; - typedef const HybridIterator const_iterator; - - Hybrid() : - m_main(), - m_extra() { - } - - size_t size() const override final { - return m_main.size() + m_extra.size(); - } - - size_t used_memory() const override final { - return m_main.used_memory() + m_extra.used_memory(); - } - - void reserve(const size_t size) { - m_main.reserve(size); - } - - void unsorted_set(const TId id, const TValue value) { - m_main.set(id, value); - } - - void set(const TId id, const TValue value) override final { - m_extra.set(id, value); - } - - std::pair get_all(const TId id) { - auto result_main = m_main.get_all(id); - auto result_extra = m_extra.get_all(id); - return std::make_pair(iterator(result_main.first, result_main.second, result_extra.first, result_extra.second), - iterator(result_main.second, result_main.second, result_extra.second, result_extra.second)); - } - - void remove(const TId id, const TValue value) { - m_main.remove(id, value); - m_extra.remove(id, value); - } - - void consolidate() { - m_main.erase_removed(); - for (const auto& element : m_extra) { - m_main.set(element.first, element.second); - } - m_extra.clear(); - m_main.sort(); - } - - void dump_as_list(int fd) override final { - consolidate(); - m_main.dump_as_list(fd); - } - - void clear() override final { - m_main.clear(); - m_extra.clear(); - } - - void sort() override final { - m_main.sort(); - } - - }; // class Hybrid - - } // namespace multimap - - } // namespace index - -} // namespace osmium - -#endif // OSMIUM_INDEX_MULTIMAP_HYBRID_HPP diff --git a/third_party/osmium/index/multimap/mmap_vector_anon.hpp b/third_party/osmium/index/multimap/mmap_vector_anon.hpp deleted file mode 100644 index b9de34a34..000000000 --- a/third_party/osmium/index/multimap/mmap_vector_anon.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_ANON_HPP -#define OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_ANON_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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. - -*/ - -#ifdef __linux__ - -#include -#include - -namespace osmium { - - namespace index { - - namespace multimap { - - template - using SparseMultimapMmap = VectorBasedSparseMultimap; - - } // namespace multimap - - } // namespace index - -} // namespace osmium - -#endif // __linux__ - -#endif // OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_ANON_HPP diff --git a/third_party/osmium/index/multimap/mmap_vector_file.hpp b/third_party/osmium/index/multimap/mmap_vector_file.hpp deleted file mode 100644 index 0a925b4ef..000000000 --- a/third_party/osmium/index/multimap/mmap_vector_file.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_FILE_HPP -#define OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_FILE_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -namespace osmium { - - namespace index { - - namespace multimap { - - template - using SparseMultimapFile = VectorBasedSparseMultimap; - - } // namespace multimap - - } // namespace index - -} // namespace osmium - -#endif // OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_FILE_HPP diff --git a/third_party/osmium/index/multimap/stl_multimap.hpp b/third_party/osmium/index/multimap/stl_multimap.hpp deleted file mode 100644 index 3df07abff..000000000 --- a/third_party/osmium/index/multimap/stl_multimap.hpp +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef OSMIUM_INDEX_MULTIMAP_STL_MULTIMAP_HPP -#define OSMIUM_INDEX_MULTIMAP_STL_MULTIMAP_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include - -#include -#include - -namespace osmium { - - namespace index { - - namespace multimap { - - /** - * This implementation uses std::multimap internally. It uses rather a - * lot of memory, but might make sense for small maps. - */ - template - class StlMultimap : public osmium::index::multimap::Multimap { - - // This is a rough estimate for the memory needed for each - // element in the map (id + value + pointers to left, right, - // and parent plus some overhead for color of red-black-tree - // or similar). - static constexpr size_t element_size = sizeof(TId) + sizeof(TValue) + sizeof(void*) * 4; - - public: - - typedef typename std::multimap collection_type; - typedef typename collection_type::iterator iterator; - typedef typename collection_type::const_iterator const_iterator; - typedef typename collection_type::value_type value_type; - - typedef typename std::pair element_type; - - private: - - collection_type m_elements; - - public: - - StlMultimap() = default; - - ~StlMultimap() noexcept override final = default; - - void unsorted_set(const TId id, const TValue value) { - m_elements.emplace(id, value); - } - - void set(const TId id, const TValue value) override final { - m_elements.emplace(id, value); - } - - std::pair get_all(const TId id) { - return m_elements.equal_range(id); - } - - std::pair get_all(const TId id) const { - return m_elements.equal_range(id); - } - - void remove(const TId id, const TValue value) { - std::pair r = get_all(id); - for (iterator it = r.first; it != r.second; ++it) { - if (it->second == value) { - m_elements.erase(it); - return; - } - } - } - - iterator begin() { - return m_elements.begin(); - } - - iterator end() { - return m_elements.end(); - } - - size_t size() const override final { - return m_elements.size(); - } - - size_t used_memory() const override final { - return element_size * m_elements.size(); - } - - void clear() override final { - m_elements.clear(); - } - - void consolidate() { - // intentionally left blank - } - - void dump_as_list(const int fd) const override final { - std::vector v; - for (const auto& element : m_elements) { - v.emplace_back(element.first, element.second); - } -// std::copy(m_elements.cbegin(), m_elements.cend(), std::back_inserter(v)); - std::sort(v.begin(), v.end()); - osmium::io::detail::reliable_write(fd, reinterpret_cast(v.data()), sizeof(element_type) * v.size()); - } - - }; // class StlMultimap - - } // namespace multimap - - } // namespace index - -} // namespace osmium - -#endif // OSMIUM_INDEX_MULTIMAP_STL_MULTIMAP_HPP diff --git a/third_party/osmium/index/multimap/stl_vector.hpp b/third_party/osmium/index/multimap/stl_vector.hpp deleted file mode 100644 index 2102824d5..000000000 --- a/third_party/osmium/index/multimap/stl_vector.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef OSMIUM_INDEX_MULTIMAP_STL_VECTOR_HPP -#define OSMIUM_INDEX_MULTIMAP_STL_VECTOR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 - -#include - -namespace osmium { - - namespace index { - - namespace multimap { - - template - using StdVectorWrap = std::vector; - - template - using SparseMultimapMem = VectorBasedSparseMultimap; - - } // namespace multimap - - } // namespace index - -} // namespace osmium - -#endif // OSMIUM_INDEX_MULTIMAP_STL_VECTOR_HPP diff --git a/third_party/osmium/index/multimap/vector.hpp b/third_party/osmium/index/multimap/vector.hpp deleted file mode 100644 index b9dae43e5..000000000 --- a/third_party/osmium/index/multimap/vector.hpp +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef OSMIUM_INDEX_MULTIMAP_VECTOR_HPP -#define OSMIUM_INDEX_MULTIMAP_VECTOR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include - -#include -#include - -namespace osmium { - - namespace index { - - namespace multimap { - - template class TVector> - class VectorBasedSparseMultimap : public Multimap { - - public: - - typedef typename std::pair element_type; - typedef TVector vector_type; - typedef typename vector_type::iterator iterator; - typedef typename vector_type::const_iterator const_iterator; - - private: - - vector_type m_vector; - - static bool is_removed(element_type& element) { - return element.second == osmium::index::empty_value(); - } - - public: - - void set(const TId id, const TValue value) override final { - m_vector.push_back(element_type(id, value)); - } - - void unsorted_set(const TId id, const TValue value) { - m_vector.push_back(element_type(id, value)); - } - - std::pair get_all(const TId id) { - const element_type element { - id, - osmium::index::empty_value() - }; - return std::equal_range(m_vector.begin(), m_vector.end(), element, [](const element_type& a, const element_type& b) { - return a.first < b.first; - }); - } - - std::pair get_all(const TId id) const { - const element_type element { - id, - osmium::index::empty_value() - }; - return std::equal_range(m_vector.cbegin(), m_vector.cend(), element, [](const element_type& a, const element_type& b) { - return a.first < b.first; - }); - } - - size_t size() const override final { - return m_vector.size(); - } - - size_t byte_size() const { - return m_vector.size() * sizeof(element_type); - } - - size_t used_memory() const override final { - return sizeof(element_type) * size(); - } - - void clear() override final { - m_vector.clear(); - m_vector.shrink_to_fit(); - } - - void sort() override final { - std::sort(m_vector.begin(), m_vector.end()); - } - - void remove(const TId id, const TValue value) { - auto r = get_all(id); - for (auto it = r.first; it != r.second; ++it) { - if (it->second == value) { - it->second = 0; - return; - } - } - } - - void consolidate() { - std::sort(m_vector.begin(), m_vector.end()); - } - - void erase_removed() { - m_vector.erase( - std::remove_if(m_vector.begin(), m_vector.end(), is_removed), - m_vector.end() - ); - } - - void dump_as_list(int fd) const override final { - osmium::io::detail::reliable_write(fd, reinterpret_cast(m_vector.data()), byte_size()); - } - - }; // class VectorBasedSparseMultimap - - } // namespace multimap - - } // namespace index - -} // namespace osmium - -#endif // OSMIUM_INDEX_MULTIMAP_VECTOR_HPP diff --git a/third_party/osmium/io/any_compression.hpp b/third_party/osmium/io/any_compression.hpp deleted file mode 100644 index 03ad5ce2b..000000000 --- a/third_party/osmium/io/any_compression.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef OSMIUM_IO_ANY_COMPRESSION_HPP -#define OSMIUM_IO_ANY_COMPRESSION_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 // IWYU pragma: export -#include // IWYU pragma: export - -#endif // OSMIUM_IO_ANY_COMPRESSION_HPP diff --git a/third_party/osmium/io/any_input.hpp b/third_party/osmium/io/any_input.hpp deleted file mode 100644 index f60ff1455..000000000 --- a/third_party/osmium/io/any_input.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef OSMIUM_IO_ANY_INPUT_HPP -#define OSMIUM_IO_ANY_INPUT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 // IWYU pragma: export - -#include // IWYU pragma: export -#include // IWYU pragma: export - -#endif // OSMIUM_IO_ANY_INPUT_HPP diff --git a/third_party/osmium/io/any_output.hpp b/third_party/osmium/io/any_output.hpp deleted file mode 100644 index 9d97d7d93..000000000 --- a/third_party/osmium/io/any_output.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef OSMIUM_IO_ANY_OUTPUT_HPP -#define OSMIUM_IO_ANY_OUTPUT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 // IWYU pragma: export - -#include // IWYU pragma: export -#include // IWYU pragma: export -#include // IWYU pragma: export - -#endif // OSMIUM_IO_ANY_OUTPUT_HPP diff --git a/third_party/osmium/io/bzip2_compression.hpp b/third_party/osmium/io/bzip2_compression.hpp deleted file mode 100644 index cbfaf9a5f..000000000 --- a/third_party/osmium/io/bzip2_compression.hpp +++ /dev/null @@ -1,277 +0,0 @@ -#ifndef OSMIUM_IO_BZIP2_COMPRESSION_HPP -#define OSMIUM_IO_BZIP2_COMPRESSION_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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. - -*/ - -#define OSMIUM_LINK_WITH_LIBS_BZ2LIB -lbz2 - -#include -#include -#include - -#include - -#ifndef _MSC_VER -# include -#endif - -#include -#include -#include -#include - -namespace osmium { - - /** - * Exception thrown when there are problems compressing or - * decompressing bzip2 files. - */ - struct bzip2_error : public std::runtime_error { - - int bzip2_error_code; - int system_errno; - - bzip2_error(const std::string& what, int error_code) : - std::runtime_error(what), - bzip2_error_code(error_code), - system_errno(error_code == BZ_IO_ERROR ? errno : 0) { - } - - }; // struct bzip2_error - - namespace io { - - namespace detail { - - OSMIUM_NORETURN inline void throw_bzip2_error(BZFILE* bzfile, const char* msg, int bzlib_error=0) { - std::string error("bzip2 error: "); - error += msg; - error += ": "; - int errnum = bzlib_error; - if (bzlib_error) { - error += std::to_string(bzlib_error); - } else { - error += ::BZ2_bzerror(bzfile, &errnum); - } - throw osmium::bzip2_error(error, errnum); - } - - } // namespace detail - - class Bzip2Compressor : public Compressor { - - FILE* m_file; - int m_bzerror; - BZFILE* m_bzfile; - - public: - - explicit Bzip2Compressor(int fd) : - Compressor(), - m_file(fdopen(dup(fd), "wb")), - m_bzerror(BZ_OK), - m_bzfile(::BZ2_bzWriteOpen(&m_bzerror, m_file, 6, 0, 0)) { - if (!m_bzfile) { - detail::throw_bzip2_error(m_bzfile, "write open failed", m_bzerror); - } - } - - ~Bzip2Compressor() override final { - close(); - } - - void write(const std::string& data) override final { - int error; - ::BZ2_bzWrite(&error, m_bzfile, const_cast(data.data()), static_cast_with_assert(data.size())); - if (error != BZ_OK && error != BZ_STREAM_END) { - detail::throw_bzip2_error(m_bzfile, "write failed", error); - } - } - - void close() override final { - if (m_bzfile) { - int error; - ::BZ2_bzWriteClose(&error, m_bzfile, 0, nullptr, nullptr); - m_bzfile = nullptr; - if (m_file) { - fclose(m_file); - } - if (error != BZ_OK) { - detail::throw_bzip2_error(m_bzfile, "write close failed", error); - } - } - } - - }; // class Bzip2Compressor - - class Bzip2Decompressor : public Decompressor { - - FILE* m_file; - int m_bzerror; - BZFILE* m_bzfile; - bool m_stream_end {false}; - - public: - - Bzip2Decompressor(int fd) : - Decompressor(), - m_file(fdopen(dup(fd), "rb")), - m_bzerror(BZ_OK), - m_bzfile(::BZ2_bzReadOpen(&m_bzerror, m_file, 0, 0, nullptr, 0)) { - if (!m_bzfile) { - detail::throw_bzip2_error(m_bzfile, "read open failed", m_bzerror); - } - } - - ~Bzip2Decompressor() override final { - close(); - } - - std::string read() override final { - if (m_stream_end) { - return std::string(); - } - std::string buffer(osmium::io::Decompressor::input_buffer_size, '\0'); - int error; - int nread = ::BZ2_bzRead(&error, m_bzfile, const_cast(buffer.data()), static_cast_with_assert(buffer.size())); - if (error != BZ_OK && error != BZ_STREAM_END) { - detail::throw_bzip2_error(m_bzfile, "read failed", error); - } - if (error == BZ_STREAM_END) { - void* unused; - int nunused; - if (! feof(m_file)) { - ::BZ2_bzReadGetUnused(&error, m_bzfile, &unused, &nunused); - if (error != BZ_OK) { - detail::throw_bzip2_error(m_bzfile, "get unused failed", error); - } - std::string unused_data(static_cast(unused), static_cast(nunused)); - ::BZ2_bzReadClose(&error, m_bzfile); - if (error != BZ_OK) { - detail::throw_bzip2_error(m_bzfile, "read close failed", error); - } - m_bzfile = ::BZ2_bzReadOpen(&error, m_file, 0, 0, const_cast(static_cast(unused_data.data())), static_cast_with_assert(unused_data.size())); - if (error != BZ_OK) { - detail::throw_bzip2_error(m_bzfile, "read open failed", error); - } - } else { - m_stream_end = true; - } - } - buffer.resize(static_cast(nread)); - return buffer; - } - - void close() override final { - if (m_bzfile) { - int error; - ::BZ2_bzReadClose(&error, m_bzfile); - m_bzfile = nullptr; - if (m_file) { - fclose(m_file); - } - if (error != BZ_OK) { - detail::throw_bzip2_error(m_bzfile, "read close failed", error); - } - } - } - - }; // class Bzip2Decompressor - - class Bzip2BufferDecompressor : public Decompressor { - - const char* m_buffer; - size_t m_buffer_size; - bz_stream m_bzstream; - - public: - - Bzip2BufferDecompressor(const char* buffer, size_t size) : - m_buffer(buffer), - m_buffer_size(size), - m_bzstream() { - m_bzstream.next_in = const_cast(buffer); - m_bzstream.avail_in = static_cast_with_assert(size); - int result = BZ2_bzDecompressInit(&m_bzstream, 0, 0); - if (result != BZ_OK) { - std::string message("bzip2 error: decompression init failed: "); - throw bzip2_error(message, result); - } - } - - ~Bzip2BufferDecompressor() override final { - BZ2_bzDecompressEnd(&m_bzstream); - } - - std::string read() override final { - if (!m_buffer) { - return std::string(); - } - - const size_t buffer_size = 10240; - std::string output(buffer_size, '\0'); - m_bzstream.next_out = const_cast(output.data()); - m_bzstream.avail_out = buffer_size; - int result = BZ2_bzDecompress(&m_bzstream); - - if (result != BZ_OK) { - m_buffer = nullptr; - m_buffer_size = 0; - } - - if (result != BZ_OK && result != BZ_STREAM_END) { - std::string message("bzip2 error: decompress failed: "); - throw bzip2_error(message, result); - } - - output.resize(static_cast(m_bzstream.next_out - output.data())); - return output; - } - - }; // class Bzip2BufferDecompressor - - namespace { - - const bool registered_bzip2_compression = osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::bzip2, - [](int fd) { return new osmium::io::Bzip2Compressor(fd); }, - [](int fd) { return new osmium::io::Bzip2Decompressor(fd); }, - [](const char* buffer, size_t size) { return new osmium::io::Bzip2BufferDecompressor(buffer, size); } - ); - - } // anonymous namespace - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_BZIP2_COMPRESSION_HPP diff --git a/third_party/osmium/io/compression.hpp b/third_party/osmium/io/compression.hpp deleted file mode 100644 index 59776408b..000000000 --- a/third_party/osmium/io/compression.hpp +++ /dev/null @@ -1,279 +0,0 @@ -#ifndef OSMIUM_IO_COMPRESSION_HPP -#define OSMIUM_IO_COMPRESSION_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include -#include -#include - -#ifndef _MSC_VER -# include -#else -# include -#endif - -#include -#include -#include - -namespace osmium { - - namespace io { - - class Compressor { - - public: - - Compressor() = default; - - virtual ~Compressor() { - } - - virtual void write(const std::string& data) = 0; - - virtual void close() = 0; - - }; // class Compressor - - class Decompressor { - - public: - - static constexpr size_t input_buffer_size = 256 * 1024; - - Decompressor() = default; - - Decompressor(const Decompressor&) = delete; - Decompressor& operator=(const Decompressor&) = delete; - - Decompressor(Decompressor&&) = delete; - Decompressor& operator=(Decompressor&&) = delete; - - virtual ~Decompressor() { - } - - virtual std::string read() = 0; - - virtual void close() { - } - - }; // class Decompressor - - /** - * This singleton factory class is used to register compression - * algorithms used for reading and writing OSM files. - * - * For each algorithm we store two functions that construct - * a compressor and decompressor object, respectively. - */ - class CompressionFactory { - - public: - - typedef std::function create_compressor_type; - typedef std::function create_decompressor_type_fd; - typedef std::function create_decompressor_type_buffer; - - private: - - typedef std::map> compression_map_type; - - compression_map_type m_callbacks; - - CompressionFactory() = default; - - CompressionFactory(const CompressionFactory&) = delete; - CompressionFactory& operator=(const CompressionFactory&) = delete; - - CompressionFactory(CompressionFactory&&) = delete; - CompressionFactory& operator=(CompressionFactory&&) = delete; - - OSMIUM_NORETURN void error(osmium::io::file_compression compression) { - std::string error_message {"Support for compression '"}; - error_message += as_string(compression); - error_message += "' not compiled into this binary."; - throw std::runtime_error(error_message); - } - - public: - - static CompressionFactory& instance() { - static CompressionFactory factory; - return factory; - } - - bool register_compression( - osmium::io::file_compression compression, - create_compressor_type create_compressor, - create_decompressor_type_fd create_decompressor_fd, - create_decompressor_type_buffer create_decompressor_buffer) { - - compression_map_type::value_type cc(compression, std::make_tuple(create_compressor, create_decompressor_fd, create_decompressor_buffer)); - return m_callbacks.insert(cc).second; - } - - std::unique_ptr create_compressor(osmium::io::file_compression compression, int fd) { - auto it = m_callbacks.find(compression); - - if (it != m_callbacks.end()) { - return std::unique_ptr(std::get<0>(it->second)(fd)); - } - - error(compression); - } - - std::unique_ptr create_decompressor(osmium::io::file_compression compression, int fd) { - auto it = m_callbacks.find(compression); - - if (it != m_callbacks.end()) { - return std::unique_ptr(std::get<1>(it->second)(fd)); - } - - error(compression); - } - - std::unique_ptr create_decompressor(osmium::io::file_compression compression, const char* buffer, size_t size) { - auto it = m_callbacks.find(compression); - - if (it != m_callbacks.end()) { - return std::unique_ptr(std::get<2>(it->second)(buffer, size)); - } - - error(compression); - } - - }; // class CompressionFactory - - class NoCompressor : public Compressor { - - int m_fd; - - public: - - NoCompressor(int fd) : - Compressor(), - m_fd(fd) { - } - - ~NoCompressor() override final { - close(); - } - - void write(const std::string& data) override final { - osmium::io::detail::reliable_write(m_fd, data.data(), data.size()); - } - - void close() override final { - if (m_fd >= 0) { - ::close(m_fd); - m_fd = -1; - } - } - - }; // class NoCompressor - - class NoDecompressor : public Decompressor { - - int m_fd; - const char *m_buffer; - size_t m_buffer_size; - - public: - - NoDecompressor(int fd) : - Decompressor(), - m_fd(fd), - m_buffer(nullptr), - m_buffer_size(0) { - } - - NoDecompressor(const char* buffer, size_t size) : - Decompressor(), - m_fd(-1), - m_buffer(buffer), - m_buffer_size(size) { - } - - ~NoDecompressor() override final { - close(); - } - - std::string read() override final { - if (m_buffer) { - if (m_buffer_size == 0) { - return std::string(); - } - size_t size = m_buffer_size; - m_buffer_size = 0; - return std::string(m_buffer, size); - } else { - std::string buffer(osmium::io::Decompressor::input_buffer_size, '\0'); - ssize_t nread = ::read(m_fd, const_cast(buffer.data()), buffer.size()); - if (nread < 0) { - throw std::system_error(errno, std::system_category(), "Read failed"); - } - buffer.resize(static_cast(nread)); - return buffer; - } - } - - void close() override final { - if (m_fd >= 0) { - ::close(m_fd); - m_fd = -1; - } - } - - }; // class NoDecompressor - - namespace { - - const bool registered_no_compression = osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::none, - [](int fd) { return new osmium::io::NoCompressor(fd); }, - [](int fd) { return new osmium::io::NoDecompressor(fd); }, - [](const char* buffer, size_t size) { return new osmium::io::NoDecompressor(buffer, size); } - ); - - } // anonymous namespace - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_COMPRESSION_HPP diff --git a/third_party/osmium/io/detail/input_format.hpp b/third_party/osmium/io/detail/input_format.hpp deleted file mode 100644 index f88561b11..000000000 --- a/third_party/osmium/io/detail/input_format.hpp +++ /dev/null @@ -1,160 +0,0 @@ -#ifndef OSMIUM_IO_DETAIL_INPUT_FORMAT_HPP -#define OSMIUM_IO_DETAIL_INPUT_FORMAT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -namespace osmium { - - namespace thread { - template class Queue; - } // namespace thread - - namespace io { - - namespace detail { - - /** - * Virtual base class for all classes reading OSM files in different - * formats. - * - * Do not use this class or derived classes directly. Use the - * osmium::io::Reader class instead. - */ - class InputFormat { - - protected: - - osmium::io::File m_file; - osmium::osm_entity_bits::type m_read_which_entities; - osmium::thread::Queue& m_input_queue; - osmium::io::Header m_header; - - explicit InputFormat(const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue& input_queue) : - m_file(file), - m_read_which_entities(read_which_entities), - m_input_queue(input_queue) { - m_header.set_has_multiple_object_versions(m_file.has_multiple_object_versions()); - } - - InputFormat(const InputFormat&) = delete; - InputFormat(InputFormat&&) = delete; - - InputFormat& operator=(const InputFormat&) = delete; - InputFormat& operator=(InputFormat&&) = delete; - - public: - - virtual ~InputFormat() { - } - - virtual osmium::memory::Buffer read() = 0; - - virtual void close() { - } - - virtual osmium::io::Header header() { - return m_header; - } - - }; // class InputFormat - - /** - * This factory class is used to create objects that read OSM data - * written in a specified format. - * - * Do not use this class directly. Instead use the osmium::io::Reader - * class. - */ - class InputFormatFactory { - - public: - - typedef std::function&)> create_input_type; - - private: - - typedef std::map map_type; - - map_type m_callbacks; - - InputFormatFactory() : - m_callbacks() { - } - - public: - - static InputFormatFactory& instance() { - static InputFormatFactory factory; - return factory; - } - - bool register_input_format(osmium::io::file_format format, create_input_type create_function) { - if (! m_callbacks.insert(map_type::value_type(format, create_function)).second) { - return false; - } - return true; - } - - std::unique_ptr create_input(const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue& input_queue) { - file.check(); - - auto it = m_callbacks.find(file.format()); - if (it != m_callbacks.end()) { - return std::unique_ptr((it->second)(file, read_which_entities, input_queue)); - } - - throw std::runtime_error(std::string("Support for input format '") + as_string(file.format()) + "' not compiled into this binary."); - } - - }; // class InputFormatFactory - - } // namespace detail - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_DETAIL_INPUT_FORMAT_HPP diff --git a/third_party/osmium/io/detail/opl_output_format.hpp b/third_party/osmium/io/detail/opl_output_format.hpp deleted file mode 100644 index b21d118e1..000000000 --- a/third_party/osmium/io/detail/opl_output_format.hpp +++ /dev/null @@ -1,315 +0,0 @@ -#ifndef OSMIUM_IO_DETAIL_OPL_OUTPUT_FORMAT_HPP -#define OSMIUM_IO_DETAIL_OPL_OUTPUT_FORMAT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wmissing-noreturn" -# pragma clang diagnostic ignored "-Wsign-conversion" -#endif - -#if BOOST_VERSION >= 104800 -# include -#else -# include -#endif - -#ifdef __clang__ -# pragma clang diagnostic pop -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace osmium { - - namespace io { - - class File; - - namespace detail { - - /** - * Writes out one buffer with OSM data in OPL format. - */ - class OPLOutputBlock : public osmium::handler::Handler { - - static constexpr size_t tmp_buffer_size = 100; - - osmium::memory::Buffer m_input_buffer; - - std::string m_out; - - char m_tmp_buffer[tmp_buffer_size+1]; - - template - void output_formatted(const char* format, TArgs&&... args) { -#ifndef NDEBUG - int len = -#endif -#ifndef _MSC_VER - snprintf(m_tmp_buffer, tmp_buffer_size, format, std::forward(args)...); -#else - _snprintf(m_tmp_buffer, tmp_buffer_size, format, std::forward(args)...); -#endif - assert(len > 0 && static_cast(len) < tmp_buffer_size); - m_out += m_tmp_buffer; - } - - void append_encoded_string(const std::string& data) { - boost::u8_to_u32_iterator it(data.cbegin(), data.cbegin(), data.cend()); - boost::u8_to_u32_iterator end(data.cend(), data.cend(), data.cend()); - boost::utf8_output_iterator> oit(std::back_inserter(m_out)); - - for (; it != end; ++it) { - uint32_t c = *it; - - // This is a list of Unicode code points that we let - // through instead of escaping them. It is incomplete - // and can be extended later. - // Generally we don't want to let through any character - // that has special meaning in the OPL format such as - // space, comma, @, etc. and any non-printing characters. - if ((0x0021 <= c && c <= 0x0024) || - (0x0026 <= c && c <= 0x002b) || - (0x002d <= c && c <= 0x003c) || - (0x003e <= c && c <= 0x003f) || - (0x0041 <= c && c <= 0x007e) || - (0x00a1 <= c && c <= 0x00ac) || - (0x00ae <= c && c <= 0x05ff)) { - *oit = c; - } else { - m_out += '%'; - output_formatted("%04x", c); - } - } - } - - void write_meta(const osmium::OSMObject& object) { - output_formatted("%" PRId64 " v%d d", object.id(), object.version()); - m_out += (object.visible() ? 'V' : 'D'); - output_formatted(" c%d t", object.changeset()); - m_out += object.timestamp().to_iso(); - output_formatted(" i%d u", object.uid()); - append_encoded_string(object.user()); - m_out += " T"; - bool first = true; - for (const auto& tag : object.tags()) { - if (first) { - first = false; - } else { - m_out += ','; - } - append_encoded_string(tag.key()); - m_out += '='; - append_encoded_string(tag.value()); - } - } - - void write_location(const osmium::Location location, const char x, const char y) { - if (location) { - output_formatted(" %c%.7f %c%.7f", x, location.lon_without_check(), y, location.lat_without_check()); - } else { - m_out += ' '; - m_out += x; - m_out += ' '; - m_out += y; - } - } - - public: - - explicit OPLOutputBlock(osmium::memory::Buffer&& buffer) : - m_input_buffer(std::move(buffer)), - m_out(), - m_tmp_buffer() { - } - - OPLOutputBlock(const OPLOutputBlock&) = delete; - OPLOutputBlock& operator=(const OPLOutputBlock&) = delete; - - OPLOutputBlock(OPLOutputBlock&&) = default; - OPLOutputBlock& operator=(OPLOutputBlock&&) = default; - - std::string operator()() { - osmium::apply(m_input_buffer.cbegin(), m_input_buffer.cend(), *this); - - std::string out; - std::swap(out, m_out); - return out; - } - - void node(const osmium::Node& node) { - m_out += 'n'; - write_meta(node); - write_location(node.location(), 'x', 'y'); - m_out += '\n'; - } - - void way(const osmium::Way& way) { - m_out += 'w'; - write_meta(way); - - m_out += " N"; - bool first = true; - for (const auto& node_ref : way.nodes()) { - if (first) { - first = false; - } else { - m_out += ','; - } - output_formatted("n%" PRId64, node_ref.ref()); - } - m_out += '\n'; - } - - void relation(const osmium::Relation& relation) { - m_out += 'r'; - write_meta(relation); - - m_out += " M"; - bool first = true; - for (const auto& member : relation.members()) { - if (first) { - first = false; - } else { - m_out += ','; - } - m_out += item_type_to_char(member.type()); - output_formatted("%" PRId64 "@", member.ref()); - m_out += member.role(); - } - m_out += '\n'; - } - - void changeset(const osmium::Changeset& changeset) { - output_formatted("c%d k%d s", changeset.id(), changeset.num_changes()); - m_out += changeset.created_at().to_iso(); - m_out += " e"; - m_out += changeset.closed_at().to_iso(); - output_formatted(" i%d u", changeset.uid()); - append_encoded_string(changeset.user()); - write_location(changeset.bounds().bottom_left(), 'x', 'y'); - write_location(changeset.bounds().top_right(), 'X', 'Y'); - m_out += " T"; - bool first = true; - for (const auto& tag : changeset.tags()) { - if (first) { - first = false; - } else { - m_out += ','; - } - append_encoded_string(tag.key()); - m_out += '='; - append_encoded_string(tag.value()); - } - - m_out += '\n'; - } - - }; // OPLOutputBlock - - class OPLOutputFormat : public osmium::io::detail::OutputFormat { - - OPLOutputFormat(const OPLOutputFormat&) = delete; - OPLOutputFormat& operator=(const OPLOutputFormat&) = delete; - - public: - - OPLOutputFormat(const osmium::io::File& file, data_queue_type& output_queue) : - OutputFormat(file, output_queue) { - } - - void write_buffer(osmium::memory::Buffer&& buffer) override final { - m_output_queue.push(osmium::thread::Pool::instance().submit(OPLOutputBlock{std::move(buffer)})); - } - - void close() override final { - std::string out; - std::promise promise; - m_output_queue.push(promise.get_future()); - promise.set_value(out); - } - - }; // class OPLOutputFormat - - namespace { - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-variable" - const bool registered_opl_output = osmium::io::detail::OutputFormatFactory::instance().register_output_format(osmium::io::file_format::opl, - [](const osmium::io::File& file, data_queue_type& output_queue) { - return new osmium::io::detail::OPLOutputFormat(file, output_queue); - }); -#pragma GCC diagnostic pop - - } // anonymous namespace - - } // namespace detail - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_DETAIL_OPL_OUTPUT_FORMAT_HPP diff --git a/third_party/osmium/io/detail/output_format.hpp b/third_party/osmium/io/detail/output_format.hpp deleted file mode 100644 index ad9e70204..000000000 --- a/third_party/osmium/io/detail/output_format.hpp +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef OSMIUM_IO_DETAIL_OUTPUT_FORMAT_HPP -#define OSMIUM_IO_DETAIL_OUTPUT_FORMAT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace osmium { - - namespace memory { - class Buffer; - } - - namespace io { - - namespace detail { - - typedef osmium::thread::Queue> data_queue_type; - - /** - * Virtual base class for all classes writing OSM files in different - * formats. - * - * Do not use this class or derived classes directly. Use the - * osmium::io::Writer class instead. - */ - class OutputFormat { - - protected: - - osmium::io::File m_file; - data_queue_type& m_output_queue; - - public: - - explicit OutputFormat(const osmium::io::File& file, data_queue_type& output_queue) : - m_file(file), - m_output_queue(output_queue) { - } - - OutputFormat(const OutputFormat&) = delete; - OutputFormat(OutputFormat&&) = delete; - - OutputFormat& operator=(const OutputFormat&) = delete; - OutputFormat& operator=(OutputFormat&&) = delete; - - virtual ~OutputFormat() { - } - - virtual void write_header(const osmium::io::Header&) { - } - - virtual void write_buffer(osmium::memory::Buffer&&) = 0; - - virtual void close() = 0; - - }; // class OutputFormat - - /** - * This factory class is used to create objects that write OSM data - * into a specified output format. - * - * Do not use this class directly. Instead use the osmium::io::Writer - * class. - */ - class OutputFormatFactory { - - public: - - typedef std::function create_output_type; - - private: - - typedef std::map map_type; - - map_type m_callbacks; - - OutputFormatFactory() : - m_callbacks() { - } - - public: - - static OutputFormatFactory& instance() { - static OutputFormatFactory factory; - return factory; - } - - bool register_output_format(osmium::io::file_format format, create_output_type create_function) { - if (! m_callbacks.insert(map_type::value_type(format, create_function)).second) { - return false; - } - return true; - } - - std::unique_ptr create_output(const osmium::io::File& file, data_queue_type& output_queue) { - file.check(); - - auto it = m_callbacks.find(file.format()); - if (it != m_callbacks.end()) { - return std::unique_ptr((it->second)(file, output_queue)); - } - - throw std::runtime_error(std::string("Support for output format '") + as_string(file.format()) + "' not compiled into this binary."); - } - - }; // class OutputFormatFactory - - } // namespace detail - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_DETAIL_OUTPUT_FORMAT_HPP diff --git a/third_party/osmium/io/detail/pbf.hpp b/third_party/osmium/io/detail/pbf.hpp deleted file mode 100644 index 9814bd42b..000000000 --- a/third_party/osmium/io/detail/pbf.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef OSMIUM_IO_DETAIL_PBF_HPP -#define OSMIUM_IO_DETAIL_PBF_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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. - -*/ - -#define OSMIUM_LINK_WITH_LIBS_PBF -pthread -lz -lprotobuf-lite -losmpbf - -#include - -#include - -// needed for htonl and ntohl -#ifndef _WIN32 -# include -#else -# include -#endif - -#include -#include - -namespace osmium { - -// avoid g++ false positive -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wreturn-type" - inline item_type osmpbf_membertype_to_item_type(const OSMPBF::Relation::MemberType mt) { - switch (mt) { - case OSMPBF::Relation::NODE: - return item_type::node; - case OSMPBF::Relation::WAY: - return item_type::way; - case OSMPBF::Relation::RELATION: - return item_type::relation; - } - } -#pragma GCC diagnostic pop - - inline OSMPBF::Relation::MemberType item_type_to_osmpbf_membertype(const item_type type) { - switch (type) { - case item_type::node: - return OSMPBF::Relation::NODE; - case item_type::way: - return OSMPBF::Relation::WAY; - case item_type::relation: - return OSMPBF::Relation::RELATION; - default: - throw std::runtime_error("Unknown relation member type"); - } - } - - /** - * Exception thrown when there was a problem with parsing the PBF format of - * a file. - */ - struct pbf_error : public io_error { - - pbf_error(const std::string& what) : - io_error(std::string("PBF error: ") + what) { - } - - pbf_error(const char* what) : - io_error(std::string("PBF error: ") + what) { - } - - }; // struct pbf_error - -} // namespace osmium - -#endif // OSMIUM_IO_DETAIL_PBF_HPP diff --git a/third_party/osmium/io/detail/pbf_input_format.hpp b/third_party/osmium/io/detail/pbf_input_format.hpp deleted file mode 100644 index 3491bed66..000000000 --- a/third_party/osmium/io/detail/pbf_input_format.hpp +++ /dev/null @@ -1,240 +0,0 @@ -#ifndef OSMIUM_IO_DETAIL_PBF_INPUT_FORMAT_HPP -#define OSMIUM_IO_DETAIL_PBF_INPUT_FORMAT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include // IWYU pragma: export -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace osmium { - - namespace io { - - class File; - - namespace detail { - - typedef osmium::thread::Queue> queue_type; - - /** - * Class for parsing PBF files. - */ - class PBFInputFormat : public osmium::io::detail::InputFormat { - - bool m_use_thread_pool; - queue_type m_queue; - std::atomic m_done; - std::thread m_reader; - osmium::thread::Queue& m_input_queue; - std::string m_input_buffer; - - /** - * Read the given number of bytes from the input queue. - * - * @param size Number of bytes to read - * @returns String with the data - * @throws osmium::pbf_error If size bytes can't be read - */ - std::string read_from_input_queue(size_t size) { - while (m_input_buffer.size() < size) { - std::string new_data; - m_input_queue.wait_and_pop(new_data); - if (new_data.empty()) { - throw osmium::pbf_error("truncated data (EOF encountered)"); - } - m_input_buffer += new_data; - } - - std::string output { m_input_buffer.substr(size) }; - m_input_buffer.resize(size); - std::swap(output, m_input_buffer); - return output; - } - - /** - * Read BlobHeader by first reading the size and then the - * BlobHeader. The BlobHeader contains a type field (which is - * checked against the expected type) and a size field. - * - * @param expected_type Expected type of data ("OSMHeader" or - * "OSMData"). - * @returns Size of the data read from BlobHeader (0 on EOF). - */ - size_t read_blob_header(const char* expected_type) { - uint32_t size_in_network_byte_order; - - try { - std::string input_data = read_from_input_queue(sizeof(size_in_network_byte_order)); - size_in_network_byte_order = *reinterpret_cast(input_data.data()); - } catch (osmium::pbf_error&) { - return 0; // EOF - } - - uint32_t size = ntohl(size_in_network_byte_order); - if (size > static_cast(OSMPBF::max_blob_header_size)) { - throw osmium::pbf_error("invalid BlobHeader size (> max_blob_header_size)"); - } - - OSMPBF::BlobHeader blob_header; - if (!blob_header.ParseFromString(read_from_input_queue(size))) { - throw osmium::pbf_error("failed to parse BlobHeader"); - } - - if (blob_header.type() != expected_type) { - throw osmium::pbf_error("blob does not have expected type (OSMHeader in first blob, OSMData in following blobs)"); - } - - return static_cast(blob_header.datasize()); - } - - void parse_osm_data(osmium::osm_entity_bits::type read_types) { - osmium::thread::set_thread_name("_osmium_pbf_in"); - int n=0; - while (auto size = read_blob_header("OSMData")) { - - if (m_use_thread_pool) { - m_queue.push(osmium::thread::Pool::instance().submit(DataBlobParser{read_from_input_queue(size), read_types})); - } else { - std::promise promise; - m_queue.push(promise.get_future()); - DataBlobParser data_blob_parser{read_from_input_queue(size), read_types}; - promise.set_value(data_blob_parser()); - } - ++n; - - if (m_done) { - return; - } - } - m_done = true; - } - - public: - - /** - * Instantiate PBF Parser - * - * @param file osmium::io::File instance describing file to be read from. - * @param read_which_entities Which types of OSM entities (nodes, ways, relations, changesets) should be parsed? - * @param input_queue String queue where data is read from. - */ - PBFInputFormat(const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue& input_queue) : - osmium::io::detail::InputFormat(file, read_which_entities, input_queue), - m_use_thread_pool(osmium::config::use_pool_threads_for_pbf_parsing()), - m_queue(20, "pbf_parser_results"), // XXX - m_done(false), - m_input_queue(input_queue), - m_input_buffer() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - // handle OSMHeader - auto size = read_blob_header("OSMHeader"); - m_header = parse_header_blob(read_from_input_queue(size)); - - if (m_read_which_entities != osmium::osm_entity_bits::nothing) { - m_reader = std::thread(&PBFInputFormat::parse_osm_data, this, m_read_which_entities); - } - } - - ~PBFInputFormat() { - m_done = true; - if (m_reader.joinable()) { - m_reader.join(); - } - } - - /** - * Returns the next buffer with OSM data read from the PBF file. - * Blocks if data is not available yet. - * Returns an empty buffer at end of input. - */ - osmium::memory::Buffer read() override { - if (!m_done || !m_queue.empty()) { - std::future buffer_future; - m_queue.wait_and_pop(buffer_future); - return std::move(buffer_future.get()); - } - - return osmium::memory::Buffer(); - } - - }; // class PBFInputFormat - - namespace { - - const bool registered_pbf_input = osmium::io::detail::InputFormatFactory::instance().register_input_format(osmium::io::file_format::pbf, - [](const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue& input_queue) { - return new osmium::io::detail::PBFInputFormat(file, read_which_entities, input_queue); - }); - - } // anonymous namespace - - } // namespace detail - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_DETAIL_PBF_INPUT_FORMAT_HPP diff --git a/third_party/osmium/io/detail/pbf_output_format.hpp b/third_party/osmium/io/detail/pbf_output_format.hpp deleted file mode 100644 index 44f8ffb5e..000000000 --- a/third_party/osmium/io/detail/pbf_output_format.hpp +++ /dev/null @@ -1,944 +0,0 @@ -#ifndef OSMIUM_IO_DETAIL_PBF_OUTPUT_FORMAT_HPP -#define OSMIUM_IO_DETAIL_PBF_OUTPUT_FORMAT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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. - -*/ - -/* - -About the .osm.pbf file format -This is an excerpt of - -The .osm.pbf format and it's derived formats (.osh.pbf and .osc.pbf) are encoded -using googles protobuf library for the low-level storage. They are constructed -by nesting data on two levels: - -On the lower level the file is constructed using BlobHeaders and Blobs. A .osm.pbf -file contains multiple sequences of - 1. a 4-byte header size, stored in network-byte-order - 2. a BlobHeader of exactly this size - 3. a Blob - -The BlobHeader tells the reader about the type and size of the following Blob. The -Blob can contain data in raw or zlib-compressed form. After uncompressing the blob -it is treated differently depending on the type specified in the BlobHeader. - -The contents of the Blob belongs to the higher level. It contains either an HeaderBlock -(type="OSMHeader") or an PrimitiveBlock (type="OSMData"). The file needs to have -at least one HeaderBlock before the first PrimitiveBlock. - -The HeaderBlock contains meta-information like the writing program or a bbox. It may -also contain multiple "required features" that describe what kinds of input a -reading program needs to handle in order to fully understand the files' contents. - -The PrimitiveBlock can store multiple types of objects (i.e. 5 nodes, 2 ways and -1 relation). It contains one or more PrimitiveGroup which in turn contain multiple -nodes, ways or relations. A PrimitiveGroup should only contain one kind of object. - -There's a special kind of "object type" called dense-nodes. It is used to store nodes -in a very dense format, avoiding message overheads and using delta-encoding for nearly -all ids. - -All Strings are stored as indexes to rows in a StringTable. The StringTable contains -one row for each used string, so strings that are used multiple times need to be -stored only once. The StringTable is sorted by usage-count, so the most often used -string is stored at index 1. - -A simple outline of a .osm.pbf file could look like this: - - 4-bytes header size - BlobHeader - Blob - HeaderBlock - 4-bytes header size - BlobHeader - Blob - PrimitiveBlock - StringTable - PrimitiveGroup - 5 nodes - PrimitiveGroup - 2 ways - PrimitiveGroup - 1 relation - -More complete outlines of real .osm.pbf files can be created using the osmpbf-outline tool: - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include // IWYU pragma: export -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace osmium { - - namespace io { - - namespace detail { - - namespace { - - /** - * Serialize a protobuf message into a Blob, optionally apply compression - * and return it together with a BlobHeader ready to be written to a file. - * - * @param type Type-string used in the BlobHeader. - * @param msg Protobuf-message. - * @param use_compression Should the output be compressed using zlib? - */ - std::string serialize_blob(const std::string& type, const google::protobuf::MessageLite& msg, bool use_compression) { - OSMPBF::Blob pbf_blob; - - { - std::string content; - msg.SerializeToString(&content); - - pbf_blob.set_raw_size(static_cast_with_assert<::google::protobuf::int32>(content.size())); - - if (use_compression) { - pbf_blob.set_zlib_data(osmium::io::detail::zlib_compress(content)); - } else { - pbf_blob.set_raw(content); - } - } - - std::string blob_data; - pbf_blob.SerializeToString(&blob_data); - - OSMPBF::BlobHeader pbf_blob_header; - pbf_blob_header.set_type(type); - pbf_blob_header.set_datasize(static_cast_with_assert<::google::protobuf::int32>(blob_data.size())); - - std::string blob_header_data; - pbf_blob_header.SerializeToString(&blob_header_data); - - uint32_t sz = htonl(static_cast_with_assert(blob_header_data.size())); - - // write to output: the 4-byte BlobHeader-Size followed by the BlobHeader followed by the Blob - std::string output; - output.reserve(sizeof(sz) + blob_header_data.size() + blob_data.size()); - output.append(reinterpret_cast(&sz), sizeof(sz)); - output.append(blob_header_data); - output.append(blob_data); - - return output; - } - - } // anonymous namespace - - class PBFOutputFormat : public osmium::io::detail::OutputFormat, public osmium::handler::Handler { - - /** - * This class models a variable that keeps track of the value - * it was last set to and returns the delta between old and - * new value from the update() call. - */ - template - class Delta { - - T m_value; - - public: - - Delta() : - m_value(0) { - } - - void clear() { - m_value = 0; - } - - T update(T new_value) { - using std::swap; - swap(m_value, new_value); - return m_value - new_value; - } - - }; // class Delta - - /** - * Maximum number of items in a primitive block. - * - * The uncompressed length of a Blob *should* be less - * than 16 megabytes and *must* be less than 32 megabytes. - * - * A block may contain any number of entities, as long as - * the size limits for the surrounding blob are obeyed. - * However, for simplicity, the current Osmosis (0.38) - * as well as Osmium implementation always - * uses at most 8k entities in a block. - */ - static constexpr uint32_t max_block_contents = 8000; - - /** - * The output buffer (block) will be filled to about - * 95% and then written to disk. This leaves more than - * enough space for the string table (which typically - * needs about 0.1 to 0.3% of the block size). - */ - static constexpr int64_t buffer_fill_percent = 95; - - /** - * protobuf-struct of a HeaderBlock - */ - OSMPBF::HeaderBlock pbf_header_block; - - /** - * protobuf-struct of a PrimitiveBlock - */ - OSMPBF::PrimitiveBlock pbf_primitive_block; - - /** - * pointer to PrimitiveGroups inside the current PrimitiveBlock, - * used for writing nodes, ways or relations - */ - OSMPBF::PrimitiveGroup* pbf_nodes; - OSMPBF::PrimitiveGroup* pbf_ways; - OSMPBF::PrimitiveGroup* pbf_relations; - - /** - * To flexibly handle multiple resolutions, the granularity, or - * resolution used for representing locations is adjustable in - * multiples of 1 nanodegree. The default scaling factor is 100 - * nanodegrees, corresponding to about ~1cm at the equator. - * This is the current resolution of the OSM database. - */ - int m_location_granularity; - - /** - * The granularity used for representing timestamps is also adjustable in - * multiples of 1 millisecond. The default scaling factor is 1000 - * milliseconds, which is the current resolution of the OSM database. - */ - int m_date_granularity; - - /** - * should nodes be serialized into the dense format? - * - * nodes can be encoded one of two ways, as a Node - * (m_use_dense_nodes = false) and a special dense format. - * In the dense format, all information is stored 'column wise', - * as an array of ID's, array of latitudes, and array of - * longitudes. Each column is delta-encoded. This reduces - * header overheads and allows delta-coding to work very effectively. - */ - bool m_use_dense_nodes {true}; - - /** - * should the PBF blobs contain zlib compressed data? - * - * the zlib compression is optional, it's possible to store the - * blobs in raw format. Disabling the compression can improve the - * writing speed a little but the output will be 2x to 3x bigger. - */ - bool m_use_compression {true}; - - /** - * While the .osm.pbf-format is able to carry all meta information, it is - * also able to omit this information to reduce size. - */ - bool m_should_add_metadata {true}; - - /** - * Should the visible flag be added on objects? - */ - bool m_add_visible; - - /** - * counter used to quickly check the number of objects stored inside - * the current PrimitiveBlock. When the counter reaches max_block_contents - * the PrimitiveBlock is serialized into a Blob and flushed to the file. - * - * this check is performed in check_block_contents_counter() which is - * called once for each object. - */ - uint16_t primitive_block_contents; - int primitive_block_size; - - // StringTable management - StringTable string_table; - - /** - * These variables are used to calculate the - * delta-encoding while storing dense-nodes. It holds the last seen values - * from which the difference is stored into the protobuf. - */ - Delta m_delta_id; - Delta m_delta_lat; - Delta m_delta_lon; - Delta m_delta_timestamp; - Delta m_delta_changeset; - Delta m_delta_uid; - Delta<::google::protobuf::int32> m_delta_user_sid; - - bool debug; - - bool has_debug_level(int) { - return false; - } - - ///// Blob writing ///// - - /** - * Before a PrimitiveBlock gets serialized, all interim StringTable-ids needs to be - * mapped to the associated real StringTable ids. This is done in this function. - * - * This function needs to know about the concrete structure of all item types to find - * all occurrences of string-ids. - */ - void map_string_ids() { - // test, if the node-block has been allocated - if (pbf_nodes) { - // iterate over all nodes, passing them to the map_common_string_ids function - for (int i=0, l=pbf_nodes->nodes_size(); imutable_nodes(i)); - } - - // test, if the node-block has a densenodes structure - if (pbf_nodes->has_dense()) { - // get a pointer to the densenodes structure - OSMPBF::DenseNodes* dense = pbf_nodes->mutable_dense(); - - // in the densenodes structure keys and vals are encoded in an intermixed - // array, individual nodes are seperated by a value of 0 (0 in the StringTable - // is always unused). String-ids of 0 are thus kept alone. - for (int i=0, l=dense->keys_vals_size(); i 0 to real string ids - auto sid = dense->keys_vals(i); - if (sid > 0) { - dense->set_keys_vals(i, string_table.map_string_id(sid)); - } - } - - // test if the densenodes block has meta infos - if (dense->has_denseinfo()) { - // get a pointer to the denseinfo structure - OSMPBF::DenseInfo* denseinfo = dense->mutable_denseinfo(); - - // iterate over all username string-ids - for (int i=0, l=denseinfo->user_sid_size(); i 0 to real string ids - auto user_sid = string_table.map_string_id(denseinfo->user_sid(i)); - - // delta encode the string-id - denseinfo->set_user_sid(i, m_delta_user_sid.update(user_sid)); - } - } - } - } - - // test, if the ways-block has been allocated - if (pbf_ways) { - // iterate over all ways, passing them to the map_common_string_ids function - for (int i=0, l=pbf_ways->ways_size(); imutable_ways(i)); - } - } - - // test, if the relations-block has been allocated - if (pbf_relations) { - // iterate over all relations - for (int i=0, l=pbf_relations->relations_size(); imutable_relations(i); - - // pass them to the map_common_string_ids function - map_common_string_ids(relation); - - // iterate over all relation members, mapping the interim string-ids - // of the role to real string ids - for (int mi=0; mi < relation->roles_sid_size(); ++mi) { - relation->set_roles_sid(mi, string_table.map_string_id(relation->roles_sid(mi))); - } - } - } - } - - /** - * a helper function used in map_string_ids to map common interim string-ids of the - * user name and all tags to real string ids. - * - * TPBFObject is either OSMPBF::Node, OSMPBF::Way or OSMPBF::Relation. - */ - template - void map_common_string_ids(TPBFObject* in) { - // if the object has meta-info attached - if (in->has_info()) { - // map the interim-id of the user name to a real id - OSMPBF::Info* info = in->mutable_info(); - info->set_user_sid(string_table.map_string_id(info->user_sid())); - } - - // iterate over all tags and map the interim-ids of the key and the value to real ids - for (int i=0, l=in->keys_size(); iset_keys(i, string_table.map_string_id(in->keys(i))); - in->set_vals(i, string_table.map_string_id(in->vals(i))); - } - } - - - ///// MetaData helper ///// - - /** - * convert a double lat or lon value to an int, respecting the current blocks granularity - */ - int64_t lonlat2int(double lonlat) { - return static_cast(std::round(lonlat * OSMPBF::lonlat_resolution / location_granularity())); - } - - /** - * convert a timestamp to an int, respecting the current blocks granularity - */ - int64_t timestamp2int(time_t timestamp) { - return static_cast(std::round(timestamp * (1000.0 / date_granularity()))); - } - - /** - * helper function used in the write()-calls to apply common information from an osmium-object - * onto a pbf-object. - * - * TPBFObject is either OSMPBF::Node, OSMPBF::Way or OSMPBF::Relation. - */ - template - void apply_common_info(const osmium::OSMObject& in, TPBFObject* out) { - // set the object-id - out->set_id(in.id()); - - // iterate over all tags and set the keys and vals, recording the strings in the - // interim StringTable and storing the interim ids - for (const auto& tag : in.tags()) { - out->add_keys(string_table.record_string(tag.key())); - out->add_vals(string_table.record_string(tag.value())); - } - - if (m_should_add_metadata) { - // add an info-section to the pbf object and set the meta-info on it - OSMPBF::Info* out_info = out->mutable_info(); - if (m_add_visible) { - out_info->set_visible(in.visible()); - } - out_info->set_version(static_cast<::google::protobuf::int32>(in.version())); - out_info->set_timestamp(timestamp2int(in.timestamp())); - out_info->set_changeset(in.changeset()); - out_info->set_uid(static_cast<::google::protobuf::int32>(in.uid())); - out_info->set_user_sid(string_table.record_string(in.user())); - } - } - - - ///// High-Level Block writing ///// - - /** - * store the current pbf_header_block into a Blob and clear this struct afterwards. - */ - void store_header_block() { - if (debug && has_debug_level(1)) { - std::cerr << "storing header block" << std::endl; - } - - std::promise promise; - m_output_queue.push(promise.get_future()); - promise.set_value(serialize_blob("OSMHeader", pbf_header_block, m_use_compression)); - - pbf_header_block.Clear(); - } - - /** - * store the interim StringTable to the current pbf_primitive_block, map all interim string ids - * to real StringTable ids and then store the current pbf_primitive_block into a Blob and clear - * this struct and all related pointers and maps afterwards. - */ - void store_primitive_block() { - if (debug && has_debug_level(1)) { - std::cerr << "storing primitive block with " << primitive_block_contents << " items" << std::endl; - } - - // set the granularity - pbf_primitive_block.set_granularity(location_granularity()); - pbf_primitive_block.set_date_granularity(date_granularity()); - - // store the interim StringTable into the protobuf object - string_table.store_stringtable(pbf_primitive_block.mutable_stringtable()); - - // map all interim string ids to real ids - map_string_ids(); - - std::promise promise; - m_output_queue.push(promise.get_future()); - promise.set_value(serialize_blob("OSMData", pbf_primitive_block, m_use_compression)); - - // clear the PrimitiveBlock struct - pbf_primitive_block.Clear(); - - // clear the interim StringTable and its id map - string_table.clear(); - - // reset the delta variables - m_delta_id.clear(); - m_delta_lat.clear(); - m_delta_lon.clear(); - m_delta_timestamp.clear(); - m_delta_changeset.clear(); - m_delta_uid.clear(); - m_delta_user_sid.clear(); - - // reset the contents-counter to zero - primitive_block_contents = 0; - primitive_block_size = 0; - - // reset the node/way/relation pointers to nullptr - pbf_nodes = nullptr; - pbf_ways = nullptr; - pbf_relations = nullptr; - } - - /** - * this little function checks primitive_block_contents counter against its maximum and calls - * store_primitive_block to flush the block to the disk when it's reached. It's also responsible - * for increasing this counter. - * - * this function also checks the estimated size of the current block and calls store_primitive_block - * when the estimated size reaches buffer_fill_percent of the maximum uncompressed blob size. - */ - void check_block_contents_counter() { - if (primitive_block_contents >= max_block_contents) { - store_primitive_block(); - } else if (primitive_block_size > OSMPBF::max_uncompressed_blob_size * buffer_fill_percent / 100) { - if (debug && has_debug_level(1)) { - std::cerr << "storing primitive_block with only " << primitive_block_contents << " items, because its ByteSize (" << primitive_block_size << ") reached " << - (static_cast(primitive_block_size) / static_cast(OSMPBF::max_uncompressed_blob_size) * 100.0) << "% of the maximum blob-size" << std::endl; - } - - store_primitive_block(); - } - - ++primitive_block_contents; - } - - - ///// Block content writing ///// - - /** - * Add a node to the block. - * - * @param node The node to add. - */ - void write_node(const osmium::Node& node) { - // add a way to the group - OSMPBF::Node* pbf_node = pbf_nodes->add_nodes(); - - // copy the common meta-info from the osmium-object to the pbf-object - apply_common_info(node, pbf_node); - - // modify lat & lon to integers, respecting the block's granularity and copy - // the ints to the pbf-object - pbf_node->set_lon(lonlat2int(node.location().lon_without_check())); - pbf_node->set_lat(lonlat2int(node.location().lat_without_check())); - } - - /** - * Add a node to the block using DenseNodes. - * - * @param node The node to add. - */ - void write_dense_node(const osmium::Node& node) { - // add a DenseNodes-Section to the PrimitiveGroup - OSMPBF::DenseNodes* dense = pbf_nodes->mutable_dense(); - - // copy the id, delta encoded - dense->add_id(m_delta_id.update(node.id())); - - // copy the longitude, delta encoded - dense->add_lon(m_delta_lon.update(lonlat2int(node.location().lon_without_check()))); - - // copy the latitude, delta encoded - dense->add_lat(m_delta_lat.update(lonlat2int(node.location().lat_without_check()))); - - // in the densenodes structure keys and vals are encoded in an intermixed - // array, individual nodes are seperated by a value of 0 (0 in the StringTable - // is always unused) - // so for three nodes the keys_vals array may look like this: 3 5 2 1 0 0 8 5 - // the first node has two tags (3=>5 and 2=>1), the second node does not - // have any tags and the third node has a single tag (8=>5) - for (const auto& tag : node.tags()) { - dense->add_keys_vals(string_table.record_string(tag.key())); - dense->add_keys_vals(string_table.record_string(tag.value())); - } - dense->add_keys_vals(0); - - if (m_should_add_metadata) { - // add a DenseInfo-Section to the PrimitiveGroup - OSMPBF::DenseInfo* denseinfo = dense->mutable_denseinfo(); - - denseinfo->add_version(static_cast<::google::protobuf::int32>(node.version())); - - if (m_add_visible) { - denseinfo->add_visible(node.visible()); - } - - // copy the timestamp, delta encoded - denseinfo->add_timestamp(m_delta_timestamp.update(timestamp2int(node.timestamp()))); - - // copy the changeset, delta encoded - denseinfo->add_changeset(m_delta_changeset.update(node.changeset())); - - // copy the user id, delta encoded - denseinfo->add_uid(static_cast<::google::protobuf::int32>(m_delta_uid.update(node.uid()))); - - // record the user-name to the interim stringtable and copy the - // interim string-id to the pbf-object - denseinfo->add_user_sid(string_table.record_string(node.user())); - } - } - - /** - * Add a way to the block. - * - * @param way The way to add. - */ - void write_way(const osmium::Way& way) { - // add a way to the group - OSMPBF::Way* pbf_way = pbf_ways->add_ways(); - - // copy the common meta-info from the osmium-object to the pbf-object - apply_common_info(way, pbf_way); - - // last way-node-id used for delta-encoding - Delta delta_id; - - for (const auto& node_ref : way.nodes()) { - // copy the way-node-id, delta encoded - pbf_way->add_refs(delta_id.update(node_ref.ref())); - } - - // count up blob size by the size of the Way - primitive_block_size += pbf_way->ByteSize(); - } - - /** - * Add a relation to the block. - * - * @param relation The relation to add. - */ - void write_relation(const osmium::Relation& relation) { - // add a relation to the group - OSMPBF::Relation* pbf_relation = pbf_relations->add_relations(); - - // copy the common meta-info from the osmium-object to the pbf-object - apply_common_info(relation, pbf_relation); - - Delta delta_id; - - for (const auto& member : relation.members()) { - // record the relation-member role to the interim stringtable and copy the - // interim string-id to the pbf-object - pbf_relation->add_roles_sid(string_table.record_string(member.role())); - - // copy the relation-member-id, delta encoded - pbf_relation->add_memids(delta_id.update(member.ref())); - - // copy the relation-member-type, mapped to the OSMPBF enum - pbf_relation->add_types(item_type_to_osmpbf_membertype(member.type())); - } - - // count up blob size by the size of the Relation - primitive_block_size += pbf_relation->ByteSize(); - } - - // objects of this class can't be copied - PBFOutputFormat(const PBFOutputFormat&) = delete; - PBFOutputFormat& operator=(const PBFOutputFormat&) = delete; - - public: - - /** - * Create PBFOutputFormat object from File. - */ - explicit PBFOutputFormat(const osmium::io::File& file, data_queue_type& output_queue) : - OutputFormat(file, output_queue), - pbf_header_block(), - pbf_primitive_block(), - pbf_nodes(nullptr), - pbf_ways(nullptr), - pbf_relations(nullptr), - m_location_granularity(pbf_primitive_block.granularity()), - m_date_granularity(pbf_primitive_block.date_granularity()), - m_add_visible(file.has_multiple_object_versions()), - primitive_block_contents(0), - primitive_block_size(0), - string_table(), - m_delta_id(), - m_delta_lat(), - m_delta_lon(), - m_delta_timestamp(), - m_delta_changeset(), - m_delta_uid(), - m_delta_user_sid(), - debug(true) { - GOOGLE_PROTOBUF_VERIFY_VERSION; - if (file.get("pbf_dense_nodes") == "false") { - m_use_dense_nodes = false; - } - if (file.get("pbf_compression") == "none" || file.get("pbf_compression") == "false") { - m_use_compression = false; - } - if (file.get("pbf_add_metadata") == "false") { - m_should_add_metadata = false; - } - } - - void write_buffer(osmium::memory::Buffer&& buffer) override final { - osmium::apply(buffer.cbegin(), buffer.cend(), *this); - } - - - /** - * getter to access the granularity - */ - int location_granularity() const { - return m_location_granularity; - } - - /** - * setter to set the granularity - */ - PBFOutputFormat& location_granularity(int g) { - m_location_granularity = g; - return *this; - } - - - /** - * getter to access the date_granularity - */ - int date_granularity() const { - return m_date_granularity; - } - - /** - * Set date granularity. - */ - PBFOutputFormat& date_granularity(int g) { - m_date_granularity = g; - return *this; - } - - - /** - * Initialize the writing process. - * - * This initializes the header-block, sets the required-features and - * the writing-program and adds the obligatory StringTable-Index 0. - */ - void write_header(const osmium::io::Header& header) override final { - // add the schema version as required feature to the HeaderBlock - pbf_header_block.add_required_features("OsmSchema-V0.6"); - - // when the densenodes-feature is used, add DenseNodes as required feature - if (m_use_dense_nodes) { - pbf_header_block.add_required_features("DenseNodes"); - } - - // when the resulting file will carry history information, add - // HistoricalInformation as required feature - if (m_file.has_multiple_object_versions()) { - pbf_header_block.add_required_features("HistoricalInformation"); - } - - // set the writing program - pbf_header_block.set_writingprogram(header.get("generator")); - - if (!header.boxes().empty()) { - OSMPBF::HeaderBBox* pbf_bbox = pbf_header_block.mutable_bbox(); - osmium::Box box = header.joined_boxes(); - pbf_bbox->set_left(static_cast<::google::protobuf::int64>(box.bottom_left().lon() * OSMPBF::lonlat_resolution)); - pbf_bbox->set_bottom(static_cast<::google::protobuf::int64>(box.bottom_left().lat() * OSMPBF::lonlat_resolution)); - pbf_bbox->set_right(static_cast<::google::protobuf::int64>(box.top_right().lon() * OSMPBF::lonlat_resolution)); - pbf_bbox->set_top(static_cast<::google::protobuf::int64>(box.top_right().lat() * OSMPBF::lonlat_resolution)); - } - - std::string osmosis_replication_timestamp = header.get("osmosis_replication_timestamp"); - if (!osmosis_replication_timestamp.empty()) { - osmium::Timestamp ts(osmosis_replication_timestamp.c_str()); - pbf_header_block.set_osmosis_replication_timestamp(ts); - } - - std::string osmosis_replication_sequence_number = header.get("osmosis_replication_sequence_number"); - if (!osmosis_replication_sequence_number.empty()) { - pbf_header_block.set_osmosis_replication_sequence_number(std::atoll(osmosis_replication_sequence_number.c_str())); - } - - std::string osmosis_replication_base_url = header.get("osmosis_replication_base_url"); - if (!osmosis_replication_base_url.empty()) { - pbf_header_block.set_osmosis_replication_base_url(osmosis_replication_base_url); - } - - store_header_block(); - } - - /** - * Add a node to the pbf. - * - * A call to this method won't write the node to the file directly but - * cache it for later bulk-writing. Calling final() ensures that everything - * gets written and every file pointer is closed. - */ - void node(const osmium::Node& node) { - // first of we check the contents-counter which may flush the cached nodes to - // disk if the limit is reached. This call also increases the contents-counter - check_block_contents_counter(); - - if (debug && has_debug_level(2)) { - std::cerr << "node " << node.id() << " v" << node.version() << std::endl; - } - - // if no PrimitiveGroup for nodes has been added, add one and save the pointer - if (!pbf_nodes) { - pbf_nodes = pbf_primitive_block.add_primitivegroup(); - } - - if (m_use_dense_nodes) { - write_dense_node(node); - } else { - write_node(node); - } - } - - /** - * Add a way to the pbf. - * - * A call to this method won't write the way to the file directly but - * cache it for later bulk-writing. Calling final() ensures that everything - * gets written and every file pointer is closed. - */ - void way(const osmium::Way& way) { - // first of we check the contents-counter which may flush the cached ways to - // disk if the limit is reached. This call also increases the contents-counter - check_block_contents_counter(); - - // if no PrimitiveGroup for nodes has been added, add one and save the pointer - if (!pbf_ways) { - pbf_ways = pbf_primitive_block.add_primitivegroup(); - } - - write_way(way); - } - - /** - * Add a relation to the pbf. - * - * A call to this method won't write the way to the file directly but - * cache it for later bulk-writing. Calling final() ensures that everything - * gets written and every file pointer is closed. - */ - void relation(const osmium::Relation& relation) { - // first of we check the contents-counter which may flush the cached relations to - // disk if the limit is reached. This call also increases the contents-counter - check_block_contents_counter(); - - // if no PrimitiveGroup for relations has been added, add one and save the pointer - if (!pbf_relations) { - pbf_relations = pbf_primitive_block.add_primitivegroup(); - } - - write_relation(relation); - } - - /** - * Finalize the writing process, flush any open primitive blocks to the file and - * close the file. - */ - void close() override final { - if (debug && has_debug_level(1)) { - std::cerr << "finishing" << std::endl; - } - - // if the current block contains any elements, flush it to the protobuf - if (primitive_block_contents > 0) { - store_primitive_block(); - } - - std::promise promise; - m_output_queue.push(promise.get_future()); - promise.set_value(std::string()); - } - - }; // class PBFOutputFormat - - namespace { - - const bool registered_pbf_output = osmium::io::detail::OutputFormatFactory::instance().register_output_format(osmium::io::file_format::pbf, - [](const osmium::io::File& file, data_queue_type& output_queue) { - return new osmium::io::detail::PBFOutputFormat(file, output_queue); - }); - - } // anonymous namespace - - } // namespace detail - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_DETAIL_PBF_OUTPUT_FORMAT_HPP diff --git a/third_party/osmium/io/detail/pbf_parser.hpp b/third_party/osmium/io/detail/pbf_parser.hpp deleted file mode 100644 index 201c57c20..000000000 --- a/third_party/osmium/io/detail/pbf_parser.hpp +++ /dev/null @@ -1,449 +0,0 @@ -#ifndef OSMIUM_IO_DETAIL_PBF_PRIMITIVE_BLOCK_PARSER_HPP -#define OSMIUM_IO_DETAIL_PBF_PRIMITIVE_BLOCK_PARSER_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include - -#include - -#include -#include // IWYU pragma: export -#include -#include -#include -#include -#include -#include -#include -#include - -namespace osmium { - - namespace io { - - namespace detail { - - class PBFPrimitiveBlockParser { - - static constexpr size_t initial_buffer_size = 2 * 1024 * 1024; - - const std::string& m_data; - - const OSMPBF::StringTable* m_stringtable; - int64_t m_lon_offset; - int64_t m_lat_offset; - int64_t m_date_factor; - int32_t m_granularity; - - osmium::osm_entity_bits::type m_read_types; - - osmium::memory::Buffer m_buffer; - - PBFPrimitiveBlockParser(const PBFPrimitiveBlockParser&) = delete; - PBFPrimitiveBlockParser(PBFPrimitiveBlockParser&&) = delete; - - PBFPrimitiveBlockParser& operator=(const PBFPrimitiveBlockParser&) = delete; - PBFPrimitiveBlockParser& operator=(PBFPrimitiveBlockParser&&) = delete; - - public: - - explicit PBFPrimitiveBlockParser(const std::string& data, osmium::osm_entity_bits::type read_types) : - m_data(data), - m_stringtable(nullptr), - m_lon_offset(0), - m_lat_offset(0), - m_date_factor(1000), - m_granularity(100), - m_read_types(read_types), - m_buffer(initial_buffer_size) { - } - - ~PBFPrimitiveBlockParser() = default; - - osmium::memory::Buffer operator()() { - OSMPBF::PrimitiveBlock pbf_primitive_block; - if (!pbf_primitive_block.ParseFromString(m_data)) { - throw osmium::pbf_error("failed to parse PrimitiveBlock"); - } - - m_stringtable = &pbf_primitive_block.stringtable(); - m_lon_offset = pbf_primitive_block.lon_offset(); - m_lat_offset = pbf_primitive_block.lat_offset(); - m_date_factor = pbf_primitive_block.date_granularity() / 1000; - m_granularity = pbf_primitive_block.granularity(); - - for (int i=0; i < pbf_primitive_block.primitivegroup_size(); ++i) { - const OSMPBF::PrimitiveGroup& group = pbf_primitive_block.primitivegroup(i); - - if (group.has_dense()) { - if (m_read_types & osmium::osm_entity_bits::node) parse_dense_node_group(group); - } else if (group.ways_size() != 0) { - if (m_read_types & osmium::osm_entity_bits::way) parse_way_group(group); - } else if (group.relations_size() != 0) { - if (m_read_types & osmium::osm_entity_bits::relation) parse_relation_group(group); - } else if (group.nodes_size() != 0) { - if (m_read_types & osmium::osm_entity_bits::node) parse_node_group(group); - } else { - throw osmium::pbf_error("group of unknown type"); - } - } - - return std::move(m_buffer); - } - - private: - - template - void parse_attributes(TBuilder& builder, const TPBFObject& pbf_object) { - auto& object = builder.object(); - - object.set_id(pbf_object.id()); - - if (pbf_object.has_info()) { - object.set_version(static_cast_with_assert(pbf_object.info().version())) - .set_changeset(static_cast_with_assert(pbf_object.info().changeset())) - .set_timestamp(pbf_object.info().timestamp() * m_date_factor) - .set_uid_from_signed(pbf_object.info().uid()); - if (pbf_object.info().has_visible()) { - object.set_visible(pbf_object.info().visible()); - } - builder.add_user(m_stringtable->s(static_cast_with_assert(pbf_object.info().user_sid()))); - } else { - builder.add_user("", 1); - } - } - - void parse_node_group(const OSMPBF::PrimitiveGroup& group) { - for (int i=0; i < group.nodes_size(); ++i) { - osmium::builder::NodeBuilder builder(m_buffer); - const OSMPBF::Node& pbf_node = group.nodes(i); - parse_attributes(builder, pbf_node); - - if (builder.object().visible()) { - builder.object().set_location(osmium::Location( - (pbf_node.lon() * m_granularity + m_lon_offset) / (OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision), - (pbf_node.lat() * m_granularity + m_lat_offset) / (OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision))); - } - - if (pbf_node.keys_size() > 0) { - osmium::builder::TagListBuilder tl_builder(m_buffer, &builder); - for (int tag=0; tag < pbf_node.keys_size(); ++tag) { - tl_builder.add_tag(m_stringtable->s(static_cast(pbf_node.keys(tag))), - m_stringtable->s(static_cast(pbf_node.vals(tag)))); - } - } - - m_buffer.commit(); - } - } - - void parse_way_group(const OSMPBF::PrimitiveGroup& group) { - for (int i=0; i < group.ways_size(); ++i) { - osmium::builder::WayBuilder builder(m_buffer); - const OSMPBF::Way& pbf_way = group.ways(i); - parse_attributes(builder, pbf_way); - - if (pbf_way.refs_size() > 0) { - osmium::builder::WayNodeListBuilder wnl_builder(m_buffer, &builder); - int64_t ref = 0; - for (int n=0; n < pbf_way.refs_size(); ++n) { - ref += pbf_way.refs(n); - wnl_builder.add_node_ref(ref); - } - } - - if (pbf_way.keys_size() > 0) { - osmium::builder::TagListBuilder tl_builder(m_buffer, &builder); - for (int tag=0; tag < pbf_way.keys_size(); ++tag) { - tl_builder.add_tag(m_stringtable->s(static_cast(pbf_way.keys(tag))), - m_stringtable->s(static_cast(pbf_way.vals(tag)))); - } - } - - m_buffer.commit(); - } - } - - void parse_relation_group(const OSMPBF::PrimitiveGroup& group) { - for (int i=0; i < group.relations_size(); ++i) { - osmium::builder::RelationBuilder builder(m_buffer); - const OSMPBF::Relation& pbf_relation = group.relations(i); - parse_attributes(builder, pbf_relation); - - if (pbf_relation.types_size() > 0) { - osmium::builder::RelationMemberListBuilder rml_builder(m_buffer, &builder); - int64_t ref = 0; - for (int n=0; n < pbf_relation.types_size(); ++n) { - ref += pbf_relation.memids(n); - rml_builder.add_member(osmpbf_membertype_to_item_type(pbf_relation.types(n)), ref, m_stringtable->s(pbf_relation.roles_sid(n))); - } - } - - if (pbf_relation.keys_size() > 0) { - osmium::builder::TagListBuilder tl_builder(m_buffer, &builder); - for (int tag=0; tag < pbf_relation.keys_size(); ++tag) { - tl_builder.add_tag(m_stringtable->s(static_cast(pbf_relation.keys(tag))), - m_stringtable->s(static_cast(pbf_relation.vals(tag)))); - } - } - - m_buffer.commit(); - } - } - - int add_tags(const OSMPBF::DenseNodes& dense, int n, osmium::builder::NodeBuilder* builder) { - if (n >= dense.keys_vals_size()) { - return n; - } - - if (dense.keys_vals(n) == 0) { - return n+1; - } - - osmium::builder::TagListBuilder tl_builder(m_buffer, builder); - - while (n < dense.keys_vals_size()) { - int tag_key_pos = dense.keys_vals(n++); - - if (tag_key_pos == 0) { - break; - } - - tl_builder.add_tag(m_stringtable->s(tag_key_pos), - m_stringtable->s(dense.keys_vals(n))); - - ++n; - } - - return n; - } - - void parse_dense_node_group(const OSMPBF::PrimitiveGroup& group) { - int64_t last_dense_id = 0; - int64_t last_dense_latitude = 0; - int64_t last_dense_longitude = 0; - int64_t last_dense_uid = 0; - int64_t last_dense_user_sid = 0; - int64_t last_dense_changeset = 0; - int64_t last_dense_timestamp = 0; - int last_dense_tag = 0; - - const OSMPBF::DenseNodes& dense = group.dense(); - - for (int i=0; i < dense.id_size(); ++i) { - bool visible = true; - - last_dense_id += dense.id(i); - last_dense_latitude += dense.lat(i); - last_dense_longitude += dense.lon(i); - - if (dense.has_denseinfo()) { - last_dense_changeset += dense.denseinfo().changeset(i); - last_dense_timestamp += dense.denseinfo().timestamp(i); - last_dense_uid += dense.denseinfo().uid(i); - last_dense_user_sid += dense.denseinfo().user_sid(i); - if (dense.denseinfo().visible_size() > 0) { - visible = dense.denseinfo().visible(i); - } - assert(last_dense_changeset >= 0); - assert(last_dense_timestamp >= 0); - assert(last_dense_uid >= -1); - assert(last_dense_user_sid >= 0); - } - - osmium::builder::NodeBuilder builder(m_buffer); - osmium::Node& node = builder.object(); - - node.set_id(last_dense_id); - - if (dense.has_denseinfo()) { - auto v = dense.denseinfo().version(i); - assert(v > 0); - node.set_version(static_cast(v)); - node.set_changeset(static_cast(last_dense_changeset)); - node.set_timestamp(last_dense_timestamp * m_date_factor); - node.set_uid_from_signed(static_cast(last_dense_uid)); - node.set_visible(visible); - builder.add_user(m_stringtable->s(static_cast(last_dense_user_sid))); - } else { - builder.add_user("", 1); - } - - if (visible) { - builder.object().set_location(osmium::Location( - (last_dense_longitude * m_granularity + m_lon_offset) / (OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision), - (last_dense_latitude * m_granularity + m_lat_offset) / (OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision))); - } - - last_dense_tag = add_tags(dense, last_dense_tag, &builder); - m_buffer.commit(); - } - } - - }; // class PBFPrimitiveBlockParser - - /** - * PBF blobs can optionally be packed with the zlib algorithm. - * This function returns the raw data (if it was unpacked) or - * the unpacked data (if it was packed). - * - * @param input_data Reference to input data. - * @returns Unpacked data - * @throws osmium::pbf_error If there was a problem parsing the PBF - */ - inline std::unique_ptr unpack_blob(const std::string& input_data) { - OSMPBF::Blob pbf_blob; - if (!pbf_blob.ParseFromString(input_data)) { - throw osmium::pbf_error("failed to parse blob"); - } - - if (pbf_blob.has_raw()) { - return std::unique_ptr(pbf_blob.release_raw()); - } else if (pbf_blob.has_zlib_data()) { - auto raw_size = pbf_blob.raw_size(); - assert(raw_size >= 0); - assert(raw_size <= OSMPBF::max_uncompressed_blob_size); - return osmium::io::detail::zlib_uncompress(pbf_blob.zlib_data(), static_cast(raw_size)); - } else if (pbf_blob.has_lzma_data()) { - throw osmium::pbf_error("lzma blobs not implemented"); - } else { - throw osmium::pbf_error("blob contains no data"); - } - } - - /** - * Parse blob as a HeaderBlock. - * - * @param input_buffer Blob data - * @returns Header object - * @throws osmium::pbf_error If there was a parsing error - */ - inline osmium::io::Header parse_header_blob(const std::string& input_buffer) { - const std::unique_ptr data = unpack_blob(input_buffer); - - OSMPBF::HeaderBlock pbf_header_block; - if (!pbf_header_block.ParseFromString(*data)) { - throw osmium::pbf_error("failed to parse HeaderBlock"); - } - - osmium::io::Header header; - for (int i=0; i < pbf_header_block.required_features_size(); ++i) { - const std::string& feature = pbf_header_block.required_features(i); - - if (feature == "OsmSchema-V0.6") continue; - if (feature == "DenseNodes") { - header.set("pbf_dense_nodes", true); - continue; - } - if (feature == "HistoricalInformation") { - header.set_has_multiple_object_versions(true); - continue; - } - - throw osmium::pbf_error(std::string("required feature not supported: ") + feature); - } - - for (int i=0; i < pbf_header_block.optional_features_size(); ++i) { - const std::string& feature = pbf_header_block.optional_features(i); - header.set("pbf_optional_feature_" + std::to_string(i), feature); - } - - if (pbf_header_block.has_writingprogram()) { - header.set("generator", pbf_header_block.writingprogram()); - } - - if (pbf_header_block.has_bbox()) { - const OSMPBF::HeaderBBox& pbf_bbox = pbf_header_block.bbox(); - const int64_t resolution_convert = OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision; - osmium::Box box; - box.extend(osmium::Location(pbf_bbox.left() / resolution_convert, pbf_bbox.bottom() / resolution_convert)); - box.extend(osmium::Location(pbf_bbox.right() / resolution_convert, pbf_bbox.top() / resolution_convert)); - header.add_box(box); - } - - if (pbf_header_block.has_osmosis_replication_timestamp()) { - header.set("osmosis_replication_timestamp", osmium::Timestamp(pbf_header_block.osmosis_replication_timestamp()).to_iso()); - } - - if (pbf_header_block.has_osmosis_replication_sequence_number()) { - header.set("osmosis_replication_sequence_number", std::to_string(pbf_header_block.osmosis_replication_sequence_number())); - } - - if (pbf_header_block.has_osmosis_replication_base_url()) { - header.set("osmosis_replication_base_url", pbf_header_block.osmosis_replication_base_url()); - } - - return header; - } - - class DataBlobParser { - - std::string m_input_buffer; - osmium::osm_entity_bits::type m_read_types; - - public: - - DataBlobParser(std::string&& input_buffer, osmium::osm_entity_bits::type read_types) : - m_input_buffer(std::move(input_buffer)), - m_read_types(read_types) { - if (input_buffer.size() > OSMPBF::max_uncompressed_blob_size) { - throw osmium::pbf_error(std::string("invalid blob size: " + std::to_string(input_buffer.size()))); - } - } - - DataBlobParser(const DataBlobParser& other) : - m_input_buffer(std::move(other.m_input_buffer)), - m_read_types(other.m_read_types) { - } - - DataBlobParser& operator=(const DataBlobParser&) = delete; - - osmium::memory::Buffer operator()() { - const std::unique_ptr data = unpack_blob(m_input_buffer); - PBFPrimitiveBlockParser parser(*data, m_read_types); - return std::move(parser()); - } - - }; // class DataBlobParser - - } // namespace detail - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_DETAIL_PBF_PRIMITIVE_BLOCK_PARSER_HPP diff --git a/third_party/osmium/io/detail/pbf_stringtable.hpp b/third_party/osmium/io/detail/pbf_stringtable.hpp deleted file mode 100644 index 6f6c54c89..000000000 --- a/third_party/osmium/io/detail/pbf_stringtable.hpp +++ /dev/null @@ -1,204 +0,0 @@ -#ifndef OSMIUM_IO_DETAIL_PBF_STRINGTABLE_HPP -#define OSMIUM_IO_DETAIL_PBF_STRINGTABLE_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace osmium { - - namespace io { - - namespace detail { - - /** - * StringTable management for PBF writer - * - * All strings are stored as indexes to rows in a StringTable. The StringTable contains - * one row for each used string, so strings that are used multiple times need to be - * stored only once. The StringTable is sorted by usage-count, so the most often used - * string is stored at index 1. - */ - class StringTable { - - public: - - /// type for string IDs (interim and final) - typedef uint16_t string_id_type; - - private: - - /** - * this is the struct used to build the StringTable. It is stored as - * the value-part in the strings-map. - * - * when a new string is added to the map, its count is set to 0 and - * the interim_id is set to the current size of the map. This interim_id - * is then stored into the pbf-objects. - * - * before the PrimitiveBlock is serialized, the map is sorted by count - * and stored into the pbf-StringTable. Afterwards the interim-ids are - * mapped to the "real" id in the StringTable. - * - * this way often used strings get lower ids in the StringTable. As the - * protobuf-serializer stores numbers in variable bit-lengths, lower - * IDs means less used space in the resulting file. - */ - struct string_info { - - /// number of occurrences of this string - uint16_t count; - - /// an intermediate-id - string_id_type interim_id; - - }; // struct string_info - - /** - * Interim StringTable, storing all strings that should be written to - * the StringTable once the block is written to disk. - */ - typedef std::map string2string_info_type; - string2string_info_type m_strings; - - /** - * This vector is used to map the interim IDs to real StringTable IDs after - * writing all strings to the StringTable. - */ - typedef std::vector interim_id2id_type; - interim_id2id_type m_id2id_map; - - size_t m_size = 0; - - public: - - StringTable() { - } - - friend bool operator<(const string_info& lhs, const string_info& rhs) { - return lhs.count > rhs.count; - } - - /** - * record a string in the interim StringTable if it's missing, otherwise just increase its counter, - * return the interim-id assigned to the string. - */ - string_id_type record_string(const std::string& string) { - string_info& info = m_strings[string]; - if (info.interim_id == 0) { - ++m_size; - info.interim_id = static_cast_with_assert(m_size); - } else { - info.count++; - } - return info.interim_id; - } - - /** - * Sort the interim StringTable and store it to the real protobuf StringTable. - * while storing to the real table, this function fills the id2id_map with - * pairs, mapping the interim-ids to final and real StringTable ids. - * - * Note that the m_strings table is a std::map and as such is sorted lexicographically. - * When the transformation into the sortedby multimap is done, it gets sorted by - * the count. The end result (at least with the glibc standard container/algorithm - * implementation) is that the string table is sorted first by reverse count (ie descending) - * and then by reverse lexicographic order. - */ - void store_stringtable(OSMPBF::StringTable* st) { - // add empty StringTable entry at index 0 - // StringTable index 0 is reserved as delimiter in the densenodes key/value list - // this line also ensures that there's always a valid StringTable - st->add_s(""); - - std::multimap sortedbycount; - - m_id2id_map.resize(m_size+1); - - std::transform(m_strings.begin(), m_strings.end(), - std::inserter(sortedbycount, sortedbycount.begin()), - [](const std::pair& p) { - return std::pair(p.second, p.first); - }); - - string_id_type n=0; - - for (const auto& mapping : sortedbycount) { - // add the string of the current item to the pbf StringTable - st->add_s(mapping.second); - - // store the mapping from the interim-id to the real id - m_id2id_map[mapping.first.interim_id] = ++n; - } - } - - /** - * Map from an interim ID to a real string ID. - */ - string_id_type map_string_id(const string_id_type interim_id) const { - return m_id2id_map[interim_id]; - } - - template - string_id_type map_string_id(const T interim_id) const { - return map_string_id(static_cast_with_assert(interim_id)); - } - - /** - * Clear the stringtable, preparing for the next block. - */ - void clear() { - m_strings.clear(); - m_id2id_map.clear(); - m_size = 0; - } - - }; // class StringTable - - } // namespace detail - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_DETAIL_PBF_STRINGTABLE_HPP diff --git a/third_party/osmium/io/detail/read_thread.hpp b/third_party/osmium/io/detail/read_thread.hpp deleted file mode 100644 index 7c371396c..000000000 --- a/third_party/osmium/io/detail/read_thread.hpp +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef OSMIUM_IO_DETAIL_READ_THREAD_HPP -#define OSMIUM_IO_DETAIL_READ_THREAD_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace osmium { - - namespace io { - - namespace detail { - - class ReadThread { - - osmium::thread::Queue& m_queue; - osmium::io::Decompressor* m_decompressor; - - // If this is set in the main thread, we have to wrap up at the - // next possible moment. - std::atomic& m_done; - - public: - - explicit ReadThread(osmium::thread::Queue& queue, osmium::io::Decompressor* decompressor, std::atomic& done) : - m_queue(queue), - m_decompressor(decompressor), - m_done(done) { - } - - bool operator()() { - osmium::thread::set_thread_name("_osmium_input"); - - try { - while (!m_done) { - std::string data {m_decompressor->read()}; - if (data.empty()) { - m_queue.push(std::move(data)); - break; - } - m_queue.push(std::move(data)); - while (m_queue.size() > 10 && !m_done) { - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } - } - - m_decompressor->close(); - } catch (...) { - // If there is an exception in this thread, we make sure - // to push an empty string onto the queue to signal the - // end-of-data to the reading thread so that it will not - // hang. Then we re-throw the exception. - m_queue.push(std::string()); - throw; - } - return true; - } - - }; // class ReadThread - - } // namespace detail - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_DETAIL_READ_THREAD_HPP diff --git a/third_party/osmium/io/detail/read_write.hpp b/third_party/osmium/io/detail/read_write.hpp deleted file mode 100644 index a949296f2..000000000 --- a/third_party/osmium/io/detail/read_write.hpp +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef OSMIUM_IO_DETAIL_READ_WRITE_HPP -#define OSMIUM_IO_DETAIL_READ_WRITE_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include - -#ifndef _MSC_VER -# include -#else -# include -typedef int ssize_t; -#endif - -#include - -namespace osmium { - - namespace io { - - /** - * @brief Namespace for Osmium internal use - */ - namespace detail { - - /** - * Open file for writing. If the file exists, it is truncated, if - * not, it is created. If the file name is empty or "-", no file - * is opened and the stdout file descriptor (1) is returned. - * - * @param filename Name of file to be opened. - * @param allow_overwrite If the file exists, should it be overwritten? - * @returns File descriptor of open file. - * @throws system_error if the file can't be opened. - */ - inline int open_for_writing(const std::string& filename, osmium::io::overwrite allow_overwrite = osmium::io::overwrite::no) { - if (filename == "" || filename == "-") { - return 1; // stdout - } else { - int flags = O_WRONLY | O_CREAT; - if (allow_overwrite == osmium::io::overwrite::allow) { - flags |= O_TRUNC; - } else { - flags |= O_EXCL; - } -#ifdef _WIN32 - flags |= O_BINARY; -#endif - int fd = ::open(filename.c_str(), flags, 0666); - if (fd < 0) { - throw std::system_error(errno, std::system_category(), std::string("Open failed for '") + filename + "'"); - } - return fd; - } - } - - /** - * Open file for reading. If the file name is empty or "-", no file - * is opened and the stdin file descriptor (0) is returned. - * - * @param filename Name of file to be opened. - * @returns File descriptor of open file. - * @throws system_error if the file can't be opened. - */ - inline int open_for_reading(const std::string& filename) { - if (filename == "" || filename == "-") { - return 0; // stdin - } else { - int flags = O_RDONLY; -#ifdef _WIN32 - flags |= O_BINARY; -#endif - int fd = ::open(filename.c_str(), flags); - if (fd < 0) { - throw std::system_error(errno, std::system_category(), std::string("Open failed for '") + filename + "'"); - } - return fd; - } - } - - /** - * Writes the given number of bytes from the output_buffer to the file descriptor. - * This is just a wrapper around write(2), because write(2) can write less than - * the given number of bytes. - * - * @param fd File descriptor. - * @param output_buffer Buffer with data to be written. Must be at least size bytes long. - * @param size Number of bytes to write. - * @throws std::system_error On error. - */ - inline void reliable_write(const int fd, const unsigned char* output_buffer, const size_t size) { - size_t offset = 0; - do { - ssize_t length = ::write(fd, output_buffer + offset, size - offset); - if (length < 0) { - throw std::system_error(errno, std::system_category(), "Write failed"); - } - offset += static_cast(length); - } while (offset < size); - } - - /** - * Writes the given number of bytes from the output_buffer to the file descriptor. - * This is just a wrapper around write(2), because write(2) can write less than - * the given number of bytes. - * - * @param fd File descriptor. - * @param output_buffer Buffer with data to be written. Must be at least size bytes long. - * @param size Number of bytes to write. - * @throws std::system_error On error. - */ - inline void reliable_write(const int fd, const char* output_buffer, const size_t size) { - reliable_write(fd, reinterpret_cast(output_buffer), size); - } - - } // namespace detail - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_DETAIL_READ_WRITE_HPP diff --git a/third_party/osmium/io/detail/write_thread.hpp b/third_party/osmium/io/detail/write_thread.hpp deleted file mode 100644 index 49b7b5dda..000000000 --- a/third_party/osmium/io/detail/write_thread.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef OSMIUM_IO_DETAIL_WRITE_THREAD_HPP -#define OSMIUM_IO_DETAIL_WRITE_THREAD_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -#include -#include -#include - -namespace osmium { - - namespace io { - - namespace detail { - - class WriteThread { - - typedef osmium::io::detail::data_queue_type data_queue_type; - - data_queue_type& m_input_queue; - osmium::io::Compressor* m_compressor; - - public: - - explicit WriteThread(data_queue_type& input_queue, osmium::io::Compressor* compressor) : - m_input_queue(input_queue), - m_compressor(compressor) { - } - - bool operator()() { - osmium::thread::set_thread_name("_osmium_output"); - - std::future data_future; - std::string data; - do { - m_input_queue.wait_and_pop(data_future); - data = data_future.get(); - m_compressor->write(data); - } while (!data.empty()); - - m_compressor->close(); - return true; - } - - }; // class WriteThread - - } // namespace detail - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_DETAIL_WRITE_THREAD_HPP diff --git a/third_party/osmium/io/detail/xml_input_format.hpp b/third_party/osmium/io/detail/xml_input_format.hpp deleted file mode 100644 index 1564b7814..000000000 --- a/third_party/osmium/io/detail/xml_input_format.hpp +++ /dev/null @@ -1,726 +0,0 @@ -#ifndef OSMIUM_IO_DETAIL_XML_INPUT_FORMAT_HPP -#define OSMIUM_IO_DETAIL_XML_INPUT_FORMAT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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. - -*/ - -#define OSMIUM_LINK_WITH_LIBS_EXPAT -lexpat - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace osmium { - - /** - * Exception thrown when the XML parser failed. The exception contains - * information about the place where the error happened and the type of - * error. - */ - struct xml_error : public io_error { - - unsigned long line; - unsigned long column; - XML_Error error_code; - std::string error_string; - - xml_error(XML_Parser parser) : - io_error(std::string("XML parsing error at line ") - + std::to_string(XML_GetCurrentLineNumber(parser)) - + ", column " - + std::to_string(XML_GetCurrentColumnNumber(parser)) - + ": " - + XML_ErrorString(XML_GetErrorCode(parser))), - line(XML_GetCurrentLineNumber(parser)), - column(XML_GetCurrentColumnNumber(parser)), - error_code(XML_GetErrorCode(parser)), - error_string(XML_ErrorString(error_code)) { - } - - }; // struct xml_error - - struct format_version_error : public io_error { - - std::string version; - - explicit format_version_error() : - io_error("Can not read file without version (missing version attribute on osm element)."), - version() { - } - - explicit format_version_error(const char* v) : - io_error(std::string("Can not read file with version ") + v), - version(v) { - } - - }; // struct format_version_error - - namespace io { - - class File; - - namespace detail { - - /** - * Once the header is fully parsed this exception will be thrown if - * the caller is not interested in anything else except the header. - * It will break off the parsing at this point. - * - * This exception is never seen by user code, it is caught internally. - */ - class ParserIsDone : std::exception { - }; - - class XMLParser { - - static constexpr int buffer_size = 10 * 1000 * 1000; - - enum class context { - root, - top, - node, - way, - relation, - changeset, - ignored_node, - ignored_way, - ignored_relation, - ignored_changeset, - in_object - }; // enum class context - - context m_context; - context m_last_context; - - /** - * This is used only for change files which contain create, modify, - * and delete sections. - */ - bool m_in_delete_section; - - osmium::io::Header m_header; - - osmium::memory::Buffer m_buffer; - - std::unique_ptr m_node_builder; - std::unique_ptr m_way_builder; - std::unique_ptr m_relation_builder; - std::unique_ptr m_changeset_builder; - - std::unique_ptr m_tl_builder; - std::unique_ptr m_wnl_builder; - std::unique_ptr m_rml_builder; - - osmium::thread::Queue& m_input_queue; - osmium::thread::Queue& m_queue; - std::promise& m_header_promise; - - osmium::osm_entity_bits::type m_read_types; - - std::atomic& m_done; - - /** - * A C++ wrapper for the Expat parser that makes sure no memory is leaked. - */ - template - class ExpatXMLParser { - - XML_Parser m_parser; - - static void XMLCALL start_element_wrapper(void* data, const XML_Char* element, const XML_Char** attrs) { - static_cast(data)->start_element(element, attrs); - } - - static void XMLCALL end_element_wrapper(void* data, const XML_Char* element) { - static_cast(data)->end_element(element); - } - - public: - - ExpatXMLParser(T* callback_object) : - m_parser(XML_ParserCreate(nullptr)) { - if (!m_parser) { - throw osmium::io_error("Internal error: Can not create parser"); - } - XML_SetUserData(m_parser, callback_object); - XML_SetElementHandler(m_parser, start_element_wrapper, end_element_wrapper); - } - - ExpatXMLParser(const ExpatXMLParser&) = delete; - ExpatXMLParser(ExpatXMLParser&&) = delete; - - ExpatXMLParser& operator=(const ExpatXMLParser&) = delete; - ExpatXMLParser& operator=(ExpatXMLParser&&) = delete; - - ~ExpatXMLParser() { - XML_ParserFree(m_parser); - } - - void operator()(const std::string& data, bool last) { - if (XML_Parse(m_parser, data.data(), static_cast_with_assert(data.size()), last) == XML_STATUS_ERROR) { - throw osmium::xml_error(m_parser); - } - } - - }; // class ExpatXMLParser - - /** - * A helper class that makes sure a promise is kept. It stores - * a reference to some piece of data and to a promise and, on - * destruction, sets the value of the promise from the data. - */ - template - class PromiseKeeper { - - T& m_data; - std::promise& m_promise; - - public: - - PromiseKeeper(T& data, std::promise& promise) : - m_data(data), - m_promise(promise) { - } - - ~PromiseKeeper() { - m_promise.set_value(m_data); - } - - }; // class PromiseKeeper - - public: - - explicit XMLParser(osmium::thread::Queue& input_queue, osmium::thread::Queue& queue, std::promise& header_promise, osmium::osm_entity_bits::type read_types, std::atomic& done) : - m_context(context::root), - m_last_context(context::root), - m_in_delete_section(false), - m_header(), - m_buffer(buffer_size), - m_node_builder(), - m_way_builder(), - m_relation_builder(), - m_changeset_builder(), - m_tl_builder(), - m_wnl_builder(), - m_rml_builder(), - m_input_queue(input_queue), - m_queue(queue), - m_header_promise(header_promise), - m_read_types(read_types), - m_done(done) { - } - - /** - * The copy constructor is needed for storing XMLParser in a std::function. - * The copy will look the same as if it has been initialized with the - * same parameters as the original. Any state changes in the original will - * not be reflected in the copy. - */ - XMLParser(const XMLParser& other) : - m_context(context::root), - m_last_context(context::root), - m_in_delete_section(false), - m_header(), - m_buffer(buffer_size), - m_node_builder(), - m_way_builder(), - m_relation_builder(), - m_changeset_builder(), - m_tl_builder(), - m_wnl_builder(), - m_rml_builder(), - m_input_queue(other.m_input_queue), - m_queue(other.m_queue), - m_header_promise(other.m_header_promise), - m_read_types(other.m_read_types), - m_done(other.m_done) { - } - - XMLParser(XMLParser&&) = default; - - XMLParser& operator=(const XMLParser&) = delete; - - XMLParser& operator=(XMLParser&&) = default; - - ~XMLParser() = default; - - bool operator()() { - ExpatXMLParser parser(this); - PromiseKeeper promise_keeper(m_header, m_header_promise); - bool last; - do { - std::string data; - m_input_queue.wait_and_pop(data); - last = data.empty(); - try { - parser(data, last); - } catch (ParserIsDone&) { - return true; - } catch (...) { - m_queue.push(osmium::memory::Buffer()); // empty buffer to signify eof - throw; - } - } while (!last && !m_done); - if (m_buffer.committed() > 0) { - m_queue.push(std::move(m_buffer)); - } - m_queue.push(osmium::memory::Buffer()); // empty buffer to signify eof - return true; - } - - private: - - const char* init_object(osmium::OSMObject& object, const XML_Char** attrs) { - static const char* empty = ""; - const char* user = empty; - - if (m_in_delete_section) { - object.set_visible(false); - } - - osmium::Location location; - for (int count = 0; attrs[count]; count += 2) { - if (!strcmp(attrs[count], "lon")) { - location.set_lon(std::atof(attrs[count+1])); // XXX doesn't detect garbage after the number - } else if (!strcmp(attrs[count], "lat")) { - location.set_lat(std::atof(attrs[count+1])); // XXX doesn't detect garbage after the number - } else if (!strcmp(attrs[count], "user")) { - user = attrs[count+1]; - } else { - object.set_attribute(attrs[count], attrs[count+1]); - } - } - - if (location && object.type() == osmium::item_type::node) { - static_cast(object).set_location(location); - } - - return user; - } - - void init_changeset(osmium::builder::ChangesetBuilder* builder, const XML_Char** attrs) { - static const char* empty = ""; - const char* user = empty; - osmium::Changeset& new_changeset = builder->object(); - - osmium::Location min; - osmium::Location max; - for (int count = 0; attrs[count]; count += 2) { - if (!strcmp(attrs[count], "min_lon")) { - min.set_lon(atof(attrs[count+1])); - } else if (!strcmp(attrs[count], "min_lat")) { - min.set_lat(atof(attrs[count+1])); - } else if (!strcmp(attrs[count], "max_lon")) { - max.set_lon(atof(attrs[count+1])); - } else if (!strcmp(attrs[count], "max_lat")) { - max.set_lat(atof(attrs[count+1])); - } else if (!strcmp(attrs[count], "user")) { - user = attrs[count+1]; - } else { - new_changeset.set_attribute(attrs[count], attrs[count+1]); - } - } - - new_changeset.bounds().extend(min); - new_changeset.bounds().extend(max); - - builder->add_user(user); - } - - void check_tag(osmium::builder::Builder* builder, const XML_Char* element, const XML_Char** attrs) { - if (!strcmp(element, "tag")) { - m_wnl_builder.reset(); - m_rml_builder.reset(); - - const char* key = ""; - const char* value = ""; - for (int count = 0; attrs[count]; count += 2) { - if (attrs[count][0] == 'k' && attrs[count][1] == 0) { - key = attrs[count+1]; - } else if (attrs[count][0] == 'v' && attrs[count][1] == 0) { - value = attrs[count+1]; - } - } - if (!m_tl_builder) { - m_tl_builder = std::unique_ptr(new osmium::builder::TagListBuilder(m_buffer, builder)); - } - m_tl_builder->add_tag(key, value); - } - } - - void header_is_done() { - if (m_read_types == osmium::osm_entity_bits::nothing) { - throw ParserIsDone(); - } - } - - void start_element(const XML_Char* element, const XML_Char** attrs) { - switch (m_context) { - case context::root: - if (!strcmp(element, "osm") || !strcmp(element, "osmChange")) { - if (!strcmp(element, "osmChange")) { - m_header.set_has_multiple_object_versions(true); - } - for (int count = 0; attrs[count]; count += 2) { - if (!strcmp(attrs[count], "version")) { - m_header.set("version", attrs[count+1]); - if (strcmp(attrs[count+1], "0.6")) { - throw osmium::format_version_error(attrs[count+1]); - } - } else if (!strcmp(attrs[count], "generator")) { - m_header.set("generator", attrs[count+1]); - } - } - if (m_header.get("version") == "") { - throw osmium::format_version_error(); - } - } - m_context = context::top; - break; - case context::top: - assert(!m_tl_builder); - if (!strcmp(element, "node")) { - header_is_done(); - if (m_read_types & osmium::osm_entity_bits::node) { - m_node_builder = std::unique_ptr(new osmium::builder::NodeBuilder(m_buffer)); - m_node_builder->add_user(init_object(m_node_builder->object(), attrs)); - m_context = context::node; - } else { - m_context = context::ignored_node; - } - } else if (!strcmp(element, "way")) { - header_is_done(); - if (m_read_types & osmium::osm_entity_bits::way) { - m_way_builder = std::unique_ptr(new osmium::builder::WayBuilder(m_buffer)); - m_way_builder->add_user(init_object(m_way_builder->object(), attrs)); - m_context = context::way; - } else { - m_context = context::ignored_way; - } - } else if (!strcmp(element, "relation")) { - header_is_done(); - if (m_read_types & osmium::osm_entity_bits::relation) { - m_relation_builder = std::unique_ptr(new osmium::builder::RelationBuilder(m_buffer)); - m_relation_builder->add_user(init_object(m_relation_builder->object(), attrs)); - m_context = context::relation; - } else { - m_context = context::ignored_relation; - } - } else if (!strcmp(element, "changeset")) { - header_is_done(); - if (m_read_types & osmium::osm_entity_bits::changeset) { - m_changeset_builder = std::unique_ptr(new osmium::builder::ChangesetBuilder(m_buffer)); - init_changeset(m_changeset_builder.get(), attrs); - m_context = context::changeset; - } else { - m_context = context::ignored_changeset; - } - } else if (!strcmp(element, "bounds")) { - osmium::Location min; - osmium::Location max; - for (int count = 0; attrs[count]; count += 2) { - if (!strcmp(attrs[count], "minlon")) { - min.set_lon(atof(attrs[count+1])); - } else if (!strcmp(attrs[count], "minlat")) { - min.set_lat(atof(attrs[count+1])); - } else if (!strcmp(attrs[count], "maxlon")) { - max.set_lon(atof(attrs[count+1])); - } else if (!strcmp(attrs[count], "maxlat")) { - max.set_lat(atof(attrs[count+1])); - } - } - osmium::Box box; - box.extend(min).extend(max); - m_header.add_box(box); - } else if (!strcmp(element, "delete")) { - m_in_delete_section = true; - } - break; - case context::node: - m_last_context = context::node; - m_context = context::in_object; - check_tag(m_node_builder.get(), element, attrs); - break; - case context::way: - m_last_context = context::way; - m_context = context::in_object; - if (!strcmp(element, "nd")) { - m_tl_builder.reset(); - - if (!m_wnl_builder) { - m_wnl_builder = std::unique_ptr(new osmium::builder::WayNodeListBuilder(m_buffer, m_way_builder.get())); - } - - for (int count = 0; attrs[count]; count += 2) { - if (!strcmp(attrs[count], "ref")) { - m_wnl_builder->add_node_ref(osmium::string_to_object_id(attrs[count+1])); - } - } - } else { - check_tag(m_way_builder.get(), element, attrs); - } - break; - case context::relation: - m_last_context = context::relation; - m_context = context::in_object; - if (!strcmp(element, "member")) { - m_tl_builder.reset(); - - if (!m_rml_builder) { - m_rml_builder = std::unique_ptr(new osmium::builder::RelationMemberListBuilder(m_buffer, m_relation_builder.get())); - } - - char type = 'x'; - object_id_type ref = 0; - const char* role = ""; - for (int count = 0; attrs[count]; count += 2) { - if (!strcmp(attrs[count], "type")) { - type = static_cast(attrs[count+1][0]); - } else if (!strcmp(attrs[count], "ref")) { - ref = osmium::string_to_object_id(attrs[count+1]); - } else if (!strcmp(attrs[count], "role")) { - role = static_cast(attrs[count+1]); - } - } - // XXX assert type, ref, role are set - m_rml_builder->add_member(char_to_item_type(type), ref, role); - } else { - check_tag(m_relation_builder.get(), element, attrs); - } - break; - case context::changeset: - m_last_context = context::changeset; - m_context = context::in_object; - check_tag(m_changeset_builder.get(), element, attrs); - break; - case context::ignored_node: - break; - case context::ignored_way: - break; - case context::ignored_relation: - break; - case context::ignored_changeset: - break; - case context::in_object: - assert(false); // should never be here - break; - } - } - - void end_element(const XML_Char* element) { - switch (m_context) { - case context::root: - assert(false); // should never be here - break; - case context::top: - if (!strcmp(element, "osm") || !strcmp(element, "osmChange")) { - header_is_done(); - m_context = context::root; - } else if (!strcmp(element, "delete")) { - m_in_delete_section = false; - } - break; - case context::node: - assert(!strcmp(element, "node")); - m_tl_builder.reset(); - m_node_builder.reset(); - m_buffer.commit(); - m_context = context::top; - flush_buffer(); - break; - case context::way: - assert(!strcmp(element, "way")); - m_tl_builder.reset(); - m_wnl_builder.reset(); - m_way_builder.reset(); - m_buffer.commit(); - m_context = context::top; - flush_buffer(); - break; - case context::relation: - assert(!strcmp(element, "relation")); - m_tl_builder.reset(); - m_rml_builder.reset(); - m_relation_builder.reset(); - m_buffer.commit(); - m_context = context::top; - flush_buffer(); - break; - case context::changeset: - assert(!strcmp(element, "changeset")); - m_tl_builder.reset(); - m_changeset_builder.reset(); - m_buffer.commit(); - m_context = context::top; - flush_buffer(); - break; - case context::in_object: - m_context = m_last_context; - break; - case context::ignored_node: - if (!strcmp(element, "node")) { - m_context = context::top; - } - break; - case context::ignored_way: - if (!strcmp(element, "way")) { - m_context = context::top; - } - break; - case context::ignored_relation: - if (!strcmp(element, "relation")) { - m_context = context::top; - } - break; - case context::ignored_changeset: - if (!strcmp(element, "changeset")) { - m_context = context::top; - } - break; - } - } - - void flush_buffer() { - if (m_buffer.capacity() - m_buffer.committed() < 1000 * 1000) { - m_queue.push(std::move(m_buffer)); - osmium::memory::Buffer buffer(buffer_size); - std::swap(m_buffer, buffer); - } - } - - }; // class XMLParser - - class XMLInputFormat : public osmium::io::detail::InputFormat { - - static constexpr size_t max_queue_size = 100; - - osmium::thread::Queue m_queue; - std::atomic m_done; - std::promise m_header_promise; - std::future m_parser_future; - - public: - - /** - * Instantiate XML Parser - * - * @param file osmium::io::File instance describing file to be read from. - * @param read_which_entities Which types of OSM entities (nodes, ways, relations, changesets) should be parsed? - * @param input_queue String queue where data is read from. - */ - explicit XMLInputFormat(const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue& input_queue) : - osmium::io::detail::InputFormat(file, read_which_entities, input_queue), - m_queue(max_queue_size, "xml_parser_results"), - m_done(false), - m_header_promise(), - m_parser_future(std::async(std::launch::async, XMLParser(input_queue, m_queue, m_header_promise, read_which_entities, m_done))) { - } - - ~XMLInputFormat() { - try { - close(); - } catch (...) { - // ignore any exceptions at this point because destructor should not throw - } - } - - virtual osmium::io::Header header() override final { - osmium::thread::check_for_exception(m_parser_future); - return m_header_promise.get_future().get(); - } - - osmium::memory::Buffer read() override { - osmium::memory::Buffer buffer; - if (!m_done || !m_queue.empty()) { - m_queue.wait_and_pop(buffer); - } - - osmium::thread::check_for_exception(m_parser_future); - return buffer; - } - - void close() { - m_done = true; - osmium::thread::wait_until_done(m_parser_future); - } - - }; // class XMLInputFormat - - namespace { - - const bool registered_xml_input = osmium::io::detail::InputFormatFactory::instance().register_input_format(osmium::io::file_format::xml, - [](const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue& input_queue) { - return new osmium::io::detail::XMLInputFormat(file, read_which_entities, input_queue); - }); - - } // anonymous namespace - - } // namespace detail - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_DETAIL_XML_INPUT_FORMAT_HPP diff --git a/third_party/osmium/io/detail/xml_output_format.hpp b/third_party/osmium/io/detail/xml_output_format.hpp deleted file mode 100644 index c8c7a385e..000000000 --- a/third_party/osmium/io/detail/xml_output_format.hpp +++ /dev/null @@ -1,481 +0,0 @@ -#ifndef OSMIUM_IO_DETAIL_XML_OUTPUT_FORMAT_HPP -#define OSMIUM_IO_DETAIL_XML_OUTPUT_FORMAT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace osmium { - - namespace io { - - namespace detail { - - struct XMLWriteError {}; - - namespace { - - void xml_string(std::string& out, const char* in) { - for (; *in != '\0'; ++in) { - switch(*in) { - case '&': out += "&"; break; - case '\"': out += """; break; - case '\'': out += "'"; break; - case '<': out += "<"; break; - case '>': out += ">"; break; - default: out += *in; break; - } - } - } - - const size_t tmp_buffer_size = 100; - - template - void oprintf(std::string& out, const char* format, T value) { - char buffer[tmp_buffer_size+1]; - size_t max_size = sizeof(buffer)/sizeof(char); -#ifndef NDEBUG - int len = -#endif -#ifndef _MSC_VER - snprintf(buffer, max_size, format, value); -#else - _snprintf(buffer, max_size, format, value); -#endif - assert(len > 0 && static_cast(len) < max_size); - out += buffer; - } - - } // anonymous namespace - - class XMLOutputBlock : public osmium::handler::Handler { - - // operation (create, modify, delete) for osc files - enum class operation { - op_none = 0, - op_create = 1, - op_modify = 2, - op_delete = 3 - }; // enum class operation - - osmium::memory::Buffer m_input_buffer; - - std::string m_out; - - operation m_last_op {operation::op_none}; - - const bool m_write_visible_flag; - const bool m_write_change_ops; - - void write_spaces(int num) { - for (; num!=0; --num) { - m_out += ' '; - } - } - - void write_prefix() { - if (m_write_change_ops) { - write_spaces(4); - } else { - write_spaces(2); - } - } - - void write_meta(const osmium::OSMObject& object) { - oprintf(m_out, " id=\"%" PRId64 "\"", object.id()); - - if (object.version()) { - oprintf(m_out, " version=\"%d\"", object.version()); - } - - if (object.timestamp()) { - m_out += " timestamp=\""; - m_out += object.timestamp().to_iso(); - m_out += "\""; - } - - if (!object.user_is_anonymous()) { - oprintf(m_out, " uid=\"%d\" user=\"", object.uid()); - xml_string(m_out, object.user()); - m_out += "\""; - } - - if (object.changeset()) { - oprintf(m_out, " changeset=\"%d\"", object.changeset()); - } - - if (m_write_visible_flag) { - if (object.visible()) { - m_out += " visible=\"true\""; - } else { - m_out += " visible=\"false\""; - } - } - } - - void write_tags(const osmium::TagList& tags) { - for (const auto& tag : tags) { - write_prefix(); - m_out += " \n"; - } - } - - void open_close_op_tag(const operation op = operation::op_none) { - if (op == m_last_op) { - return; - } - - switch (m_last_op) { - case operation::op_none: - break; - case operation::op_create: - m_out += " \n"; - break; - case operation::op_modify: - m_out += " \n"; - break; - case operation::op_delete: - m_out += " \n"; - break; - } - - switch (op) { - case operation::op_none: - break; - case operation::op_create: - m_out += " \n"; - break; - case operation::op_modify: - m_out += " \n"; - break; - case operation::op_delete: - m_out += " \n"; - break; - } - - m_last_op = op; - } - - public: - - explicit XMLOutputBlock(osmium::memory::Buffer&& buffer, bool write_visible_flag, bool write_change_ops) : - m_input_buffer(std::move(buffer)), - m_write_visible_flag(write_visible_flag && !write_change_ops), - m_write_change_ops(write_change_ops) { - } - - XMLOutputBlock(const XMLOutputBlock&) = delete; - XMLOutputBlock& operator=(const XMLOutputBlock&) = delete; - - XMLOutputBlock(XMLOutputBlock&&) = default; - XMLOutputBlock& operator=(XMLOutputBlock&&) = default; - - std::string operator()() { - osmium::apply(m_input_buffer.cbegin(), m_input_buffer.cend(), *this); - - if (m_write_change_ops) { - open_close_op_tag(); - } - - std::string out; - std::swap(out, m_out); - return out; - } - - void node(const osmium::Node& node) { - if (m_write_change_ops) { - open_close_op_tag(node.visible() ? (node.version() == 1 ? operation::op_create : operation::op_modify) : operation::op_delete); - } - - write_prefix(); - m_out += "\n", node_ref.ref()); - } - - write_tags(way.tags()); - - write_prefix(); - m_out += "\n"; - } - - void relation(const osmium::Relation& relation) { - if (m_write_change_ops) { - open_close_op_tag(relation.visible() ? (relation.version() == 1 ? operation::op_create : operation::op_modify) : operation::op_delete); - } - - write_prefix(); - m_out += "\n"; - } - - write_tags(relation.tags()); - - write_prefix(); - m_out += "\n"; - } - - void changeset(const osmium::Changeset& changeset) { - write_prefix(); - m_out += "\n"; - } else { - out += "\n"; - } - - for (const auto& box : header.boxes()) { - out += " \n", box.top_right().lat()); - } - - std::promise promise; - m_output_queue.push(promise.get_future()); - promise.set_value(std::move(out)); - } - - void close() override final { - { - std::string out; - if (m_file.is_true("xml_change_format")) { - out += "\n"; - } else { - out += "\n"; - } - - std::promise promise; - m_output_queue.push(promise.get_future()); - promise.set_value(std::move(out)); - } - - std::promise promise; - m_output_queue.push(promise.get_future()); - promise.set_value(std::string()); - } - - }; // class XMLOutputFormat - - namespace { - - const bool registered_xml_output = osmium::io::detail::OutputFormatFactory::instance().register_output_format(osmium::io::file_format::xml, - [](const osmium::io::File& file, data_queue_type& output_queue) { - return new osmium::io::detail::XMLOutputFormat(file, output_queue); - }); - - } // anonymous namespace - - } // namespace detail - - } // namespace output - -} // namespace osmium - -#endif // OSMIUM_IO_DETAIL_XML_OUTPUT_FORMAT_HPP diff --git a/third_party/osmium/io/detail/zlib.hpp b/third_party/osmium/io/detail/zlib.hpp deleted file mode 100644 index 84ab86c06..000000000 --- a/third_party/osmium/io/detail/zlib.hpp +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef OSMIUM_IO_DETAIL_ZLIB_HPP -#define OSMIUM_IO_DETAIL_ZLIB_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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. - -*/ - -#define OSMIUM_LINK_WITH_LIBS_ZLIB -lz - -#include -#include -#include - -#include - -namespace osmium { - - namespace io { - - namespace detail { - - /** - * Compress data using zlib. - * - * @param input Data to compress. - * @returns Compressed data. - */ - inline std::string zlib_compress(const std::string& input) { - unsigned long output_size = ::compressBound(input.size()); - - std::string output(output_size, '\0'); - - if (::compress(reinterpret_cast(const_cast(output.data())), - &output_size, - reinterpret_cast(input.data()), - input.size()) != Z_OK) { - throw std::runtime_error("failed to compress data"); - } - - output.resize(output_size); - - return output; - } - - /** - * Uncompress data using zlib. - * - * @param input Compressed input data. - * @param raw_size Size of uncompressed data. - * @returns Uncompressed data. - */ - inline std::unique_ptr zlib_uncompress(const std::string& input, unsigned long raw_size) { - auto output = std::unique_ptr(new std::string(raw_size, '\0')); - - if (::uncompress(reinterpret_cast(const_cast(output->data())), - &raw_size, - reinterpret_cast(input.data()), - input.size()) != Z_OK) { - throw std::runtime_error("failed to uncompress data"); - } - - return output; - } - - } // namespace detail - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_DETAIL_ZLIB_HPP diff --git a/third_party/osmium/io/error.hpp b/third_party/osmium/io/error.hpp deleted file mode 100644 index 8fb9f05f6..000000000 --- a/third_party/osmium/io/error.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef OSMIUM_IO_ERROR_HPP -#define OSMIUM_IO_ERROR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 - -namespace osmium { - - /** - * Exception thrown when some kind of input/output operation failed. - */ - struct io_error : public std::runtime_error { - - io_error(const std::string& what) : - std::runtime_error(what) { - } - - io_error(const char* what) : - std::runtime_error(what) { - } - - }; // struct io_error - -} // namespace osmium - -#endif // OSMIUM_IO_ERROR_HPP diff --git a/third_party/osmium/io/file.hpp b/third_party/osmium/io/file.hpp deleted file mode 100644 index 21469b865..000000000 --- a/third_party/osmium/io/file.hpp +++ /dev/null @@ -1,343 +0,0 @@ -#ifndef OSMIUM_IO_FILE_HPP -#define OSMIUM_IO_FILE_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include - -#include -#include -#include - -namespace osmium { - - /** - * @brief Everything related to input and output of OSM data. - */ - namespace io { - - namespace detail { - - inline std::vector split(const std::string& in, const char delim) { - std::vector result; - std::stringstream ss(in); - std::string item; - while (std::getline(ss, item, delim)) { - result.push_back(item); - } - return result; - } - - } // namespace detail - - /** - * This class describes an OSM file in one of several different formats. - * - * If the filename is empty or "-", this means stdin or stdout is used. - */ - class File : public osmium::util::Options { - - private: - - std::string m_filename; - - const char* m_buffer; - size_t m_buffer_size; - - std::string m_format_string; - - file_format m_file_format {file_format::unknown}; - - file_compression m_file_compression {file_compression::none}; - - bool m_has_multiple_object_versions {false}; - - public: - - /** - * Create File using type and encoding from filename or given - * format specification. - * - * @param filename Filename including suffix. The type and encoding - * of the file will be taken from the suffix. - * An empty filename or "-" means stdin or stdout. - * @param format File format as string. See the description of the - * parse_format() function for details. - */ - explicit File(const std::string& filename = "", const std::string& format = "") : - Options(), - m_filename(filename), - m_buffer(nullptr), - m_buffer_size(0), - m_format_string(format) { - - // stdin/stdout - if (filename == "" || filename == "-") { - m_filename = ""; - default_settings_for_stdinout(); - } - - // filename is actually a URL - std::string protocol = m_filename.substr(0, m_filename.find_first_of(':')); - if (protocol == "http" || protocol == "https") { - default_settings_for_url(); - } - - detect_format_from_suffix(m_filename); - - if (format != "") { - parse_format(format); - } - } - - /** - * Create File using buffer pointer and size and type and encoding - * from given format specification. - * - * @param buffer Pointer to buffer with data. - * @param size Size of buffer. - * @param format File format as string. See the description of the - * parse_format() function for details. - */ - explicit File(const char* buffer, size_t size, const std::string& format = "") : - Options(), - m_filename(), - m_buffer(buffer), - m_buffer_size(size), - m_format_string(format) { - - default_settings_for_stdinout(); - - if (format != "") { - parse_format(format); - } - } - - File(const File&) = default; - File& operator=(const File&) = default; - - File(File&&) = default; - File& operator=(File&&) = default; - - ~File() = default; - - const char* buffer() const noexcept { - return m_buffer; - } - - size_t buffer_size() const noexcept { - return m_buffer_size; - } - - void parse_format(const std::string& format) { - std::vector options = detail::split(format, ','); - - // if the first item in the format list doesn't contain - // an equals sign, it is a format - if (!options.empty() && options[0].find_first_of('=') == std::string::npos) { - detect_format_from_suffix(options[0]); - options.erase(options.begin()); - } - - for (auto& option : options) { - size_t pos = option.find_first_of('='); - if (pos == std::string::npos) { - set(option, true); - } else { - std::string value = option.substr(pos+1); - option.erase(pos); - set(option, value); - } - } - - if (get("history") == "true") { - m_has_multiple_object_versions = true; - } else if (get("history") == "false") { - m_has_multiple_object_versions = false; - } - } - - void detect_format_from_suffix(const std::string& name) { - std::vector suffixes = detail::split(name, '.'); - - if (suffixes.empty()) return; - - // if the last suffix is one of a known set of compressions, - // set that compression - if (suffixes.back() == "gz") { - m_file_compression = file_compression::gzip; - suffixes.pop_back(); - } else if (suffixes.back() == "bz2") { - m_file_compression = file_compression::bzip2; - suffixes.pop_back(); - } - - if (suffixes.empty()) return; - - // if the last suffix is one of a known set of formats, - // set that format - if (suffixes.back() == "pbf") { - m_file_format = file_format::pbf; - suffixes.pop_back(); - } else if (suffixes.back() == "xml") { - m_file_format = file_format::xml; - suffixes.pop_back(); - } else if (suffixes.back() == "opl") { - m_file_format = file_format::opl; - suffixes.pop_back(); - } - - if (suffixes.empty()) return; - - if (suffixes.back() == "osm") { - if (m_file_format == file_format::unknown) m_file_format = file_format::xml; - suffixes.pop_back(); - } else if (suffixes.back() == "osh") { - if (m_file_format == file_format::unknown) m_file_format = file_format::xml; - m_has_multiple_object_versions = true; - suffixes.pop_back(); - } else if (suffixes.back() == "osc") { - if (m_file_format == file_format::unknown) m_file_format = file_format::xml; - m_has_multiple_object_versions = true; - set("xml_change_format", true); - suffixes.pop_back(); - } - } - - /** - * Check file format etc. for consistency and throw exception if there - * is a problem. - * - * @throws std::runtime_error - */ - void check() const { - if (m_file_format == file_format::unknown) { - std::string msg = "Could not detect file format"; - if (!m_format_string.empty()) { - msg += " from format string '"; - msg += m_format_string; - msg += "'"; - } - if (m_filename.empty()) { - msg += " for stdin/stdout"; - } else { - msg += " for filename '"; - msg += m_filename; - msg += "'"; - } - msg += "."; - throw std::runtime_error(msg); - } - } - - /** - * Set default settings for type and encoding when the filename is - * empty or "-". If you want to have a different default setting - * override this in a subclass. - */ - void default_settings_for_stdinout() { - m_file_format = file_format::unknown; - m_file_compression = file_compression::none; - } - - /** - * Set default settings for type and encoding when the filename is - * a normal file. If you want to have a different default setting - * override this in a subclass. - */ - void default_settings_for_file() { - m_file_format = file_format::unknown; - m_file_compression = file_compression::none; - } - - /** - * Set default settings for type and encoding when the filename is a URL. - * If you want to have a different default setting override this in a - * subclass. - */ - void default_settings_for_url() { - m_file_format = file_format::xml; - m_file_compression = file_compression::none; - } - - file_format format() const noexcept { - return m_file_format; - } - - File& set_format(file_format format) noexcept { - m_file_format = format; - return *this; - } - - file_compression compression() const noexcept { - return m_file_compression; - } - - File& set_compression(file_compression compression) noexcept { - m_file_compression = compression; - return *this; - } - - bool has_multiple_object_versions() const noexcept { - return m_has_multiple_object_versions; - } - - File& set_has_multiple_object_versions(bool value) noexcept { - m_has_multiple_object_versions = value; - return *this; - } - - File& filename(const std::string& filename) { - if (filename == "-") { - m_filename = ""; - } else { - m_filename = filename; - } - return *this; - } - - const std::string& filename() const noexcept { - return m_filename; - } - - }; // class File - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_FILE_HPP diff --git a/third_party/osmium/io/file_compression.hpp b/third_party/osmium/io/file_compression.hpp deleted file mode 100644 index c71871553..000000000 --- a/third_party/osmium/io/file_compression.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef OSMIUM_IO_FILE_COMPRESSION_HPP -#define OSMIUM_IO_FILE_COMPRESSION_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 - -namespace osmium { - - namespace io { - - enum class file_compression { - none = 0, - gzip = 1, - bzip2 = 2 - }; - -// avoid g++ false positive -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wreturn-type" - inline const char* as_string(file_compression compression) { - switch (compression) { - case file_compression::none: - return "none"; - case file_compression::gzip: - return "gzip"; - case file_compression::bzip2: - return "bzip2"; - } - } -#pragma GCC diagnostic pop - - template - inline std::basic_ostream& operator<<(std::basic_ostream& out, const file_compression compression) { - return out << as_string(compression); - } - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_FILE_COMPRESSION_HPP diff --git a/third_party/osmium/io/file_format.hpp b/third_party/osmium/io/file_format.hpp deleted file mode 100644 index 5a4aa5c01..000000000 --- a/third_party/osmium/io/file_format.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef OSMIUM_IO_FILE_FORMAT_HPP -#define OSMIUM_IO_FILE_FORMAT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 - -namespace osmium { - - namespace io { - - enum class file_format { - unknown = 0, - xml = 1, - pbf = 2, - opl = 3, - json = 4 - }; - -// avoid g++ false positive -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wreturn-type" - inline const char* as_string(file_format format) { - switch (format) { - case file_format::unknown: - return "unknown"; - case file_format::xml: - return "XML"; - case file_format::pbf: - return "PBF"; - case file_format::opl: - return "OPL"; - case file_format::json: - return "JSON"; - } - } -#pragma GCC diagnostic pop - - template - inline std::basic_ostream& operator<<(std::basic_ostream& out, const file_format format) { - return out << as_string(format); - } - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_FILE_FORMAT_HPP diff --git a/third_party/osmium/io/gzip_compression.hpp b/third_party/osmium/io/gzip_compression.hpp deleted file mode 100644 index db99acb9a..000000000 --- a/third_party/osmium/io/gzip_compression.hpp +++ /dev/null @@ -1,238 +0,0 @@ -#ifndef OSMIUM_IO_GZIP_COMPRESSION_HPP -#define OSMIUM_IO_GZIP_COMPRESSION_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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. - -*/ - -#define OSMIUM_LINK_WITH_LIBS_ZLIB -lz - -#include -#include - -#include -#include - -#include -#include -#include -#include - -namespace osmium { - - /** - * Exception thrown when there are problems compressing or - * decompressing gzip files. - */ - struct gzip_error : public std::runtime_error { - - int gzip_error_code; - int system_errno; - - gzip_error(const std::string& what, int error_code) : - std::runtime_error(what), - gzip_error_code(error_code), - system_errno(error_code == Z_ERRNO ? errno : 0) { - } - - }; // struct gzip_error - - namespace io { - - namespace detail { - - OSMIUM_NORETURN inline void throw_gzip_error(gzFile gzfile, const char* msg, int zlib_error=0) { - std::string error("gzip error: "); - error += msg; - error += ": "; - int errnum = zlib_error; - if (zlib_error) { - error += std::to_string(zlib_error); - } else { - error += ::gzerror(gzfile, &errnum); - } - throw osmium::gzip_error(error, errnum); - } - - } // namespace detail - - class GzipCompressor : public Compressor { - - gzFile m_gzfile; - - public: - - explicit GzipCompressor(int fd) : - Compressor(), - m_gzfile(::gzdopen(fd, "w")) { - if (!m_gzfile) { - detail::throw_gzip_error(m_gzfile, "write initialization failed"); - } - } - - ~GzipCompressor() override final { - close(); - } - - void write(const std::string& data) override final { - if (!data.empty()) { - int nwrite = ::gzwrite(m_gzfile, data.data(), static_cast_with_assert(data.size())); - if (nwrite == 0) { - detail::throw_gzip_error(m_gzfile, "write failed"); - } - } - } - - void close() override final { - if (m_gzfile) { - int result = ::gzclose(m_gzfile); - m_gzfile = nullptr; - if (result != Z_OK) { - detail::throw_gzip_error(m_gzfile, "write close failed", result); - } - } - } - - }; // class GzipCompressor - - class GzipDecompressor : public Decompressor { - - gzFile m_gzfile; - - public: - - explicit GzipDecompressor(int fd) : - Decompressor(), - m_gzfile(::gzdopen(fd, "r")) { - if (!m_gzfile) { - detail::throw_gzip_error(m_gzfile, "read initialization failed"); - } - } - - ~GzipDecompressor() override final { - close(); - } - - std::string read() override final { - std::string buffer(osmium::io::Decompressor::input_buffer_size, '\0'); - int nread = ::gzread(m_gzfile, const_cast(buffer.data()), static_cast_with_assert(buffer.size())); - if (nread < 0) { - detail::throw_gzip_error(m_gzfile, "read failed"); - } - buffer.resize(static_cast(nread)); - return buffer; - } - - void close() override final { - if (m_gzfile) { - int result = ::gzclose(m_gzfile); - m_gzfile = nullptr; - if (result != Z_OK) { - detail::throw_gzip_error(m_gzfile, "read close failed", result); - } - } - } - - }; // class GzipDecompressor - - class GzipBufferDecompressor : public Decompressor { - - const char* m_buffer; - size_t m_buffer_size; - z_stream m_zstream; - - public: - - GzipBufferDecompressor(const char* buffer, size_t size) : - m_buffer(buffer), - m_buffer_size(size), - m_zstream() { - m_zstream.next_in = reinterpret_cast(const_cast(buffer)); - m_zstream.avail_in = static_cast_with_assert(size); - int result = inflateInit2(&m_zstream, MAX_WBITS | 32); - if (result != Z_OK) { - std::string message("gzip error: decompression init failed: "); - if (m_zstream.msg) { - message.append(m_zstream.msg); - } - throw osmium::gzip_error(message, result); - } - } - - ~GzipBufferDecompressor() override final { - inflateEnd(&m_zstream); - } - - std::string read() override final { - if (!m_buffer) { - return std::string(); - } - - const size_t buffer_size = 10240; - std::string output(buffer_size, '\0'); - m_zstream.next_out = reinterpret_cast(const_cast(output.data())); - m_zstream.avail_out = buffer_size; - int result = inflate(&m_zstream, Z_SYNC_FLUSH); - - if (result != Z_OK) { - m_buffer = nullptr; - m_buffer_size = 0; - } - - if (result != Z_OK && result != Z_STREAM_END) { - std::string message("gzip error: inflate failed: "); - if (m_zstream.msg) { - message.append(m_zstream.msg); - } - throw osmium::gzip_error(message, result); - } - - output.resize(static_cast(m_zstream.next_out - reinterpret_cast(output.data()))); - return output; - } - - }; // class GzipBufferDecompressor - - namespace { - - const bool registered_gzip_compression = osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::gzip, - [](int fd) { return new osmium::io::GzipCompressor(fd); }, - [](int fd) { return new osmium::io::GzipDecompressor(fd); }, - [](const char* buffer, size_t size) { return new osmium::io::GzipBufferDecompressor(buffer, size); } - ); - - } // anonymous namespace - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_GZIP_COMPRESSION_HPP diff --git a/third_party/osmium/io/header.hpp b/third_party/osmium/io/header.hpp deleted file mode 100644 index 0fdbf77fc..000000000 --- a/third_party/osmium/io/header.hpp +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef OSMIUM_IO_HEADER_HPP -#define OSMIUM_IO_HEADER_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -#include -#include - -namespace osmium { - - namespace io { - - /** - * Meta information from the header of an OSM file. - */ - class Header : public osmium::util::Options { - - /// Bounding boxes - std::vector m_boxes; - - /** - * Are there possibly multiple versions of the same object in this stream of objects? - * This is true for history files and for change files, but not for normal OSM files. - */ - bool m_has_multiple_object_versions = false; - - public: - - Header() = default; - - explicit Header(const std::initializer_list& values) : - Options(values) { - } - - Header(const Header&) = default; - Header& operator=(const Header&) = default; - - Header(Header&&) = default; - Header& operator=(Header&&) = default; - - ~Header() = default; - - std::vector& boxes() noexcept { - return m_boxes; - } - - const std::vector& boxes() const noexcept { - return m_boxes; - } - - Header& boxes(const std::vector& boxes) noexcept { - m_boxes = boxes; - return *this; - } - - osmium::Box box() const { - return m_boxes.empty() ? osmium::Box() : m_boxes.front(); - } - - osmium::Box joined_boxes() const { - osmium::Box box; - for (const auto& b : m_boxes) { - box.extend(b.bottom_left()); - box.extend(b.top_right()); - } - return box; - } - - Header& add_box(const osmium::Box& box) { - m_boxes.push_back(box); - return *this; - } - - bool has_multiple_object_versions() const noexcept { - return m_has_multiple_object_versions; - } - - Header& set_has_multiple_object_versions(bool value) noexcept { - m_has_multiple_object_versions = value; - return *this; - } - - }; // class Header - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_HEADER_HPP diff --git a/third_party/osmium/io/input_iterator.hpp b/third_party/osmium/io/input_iterator.hpp deleted file mode 100644 index a2e3b83b3..000000000 --- a/third_party/osmium/io/input_iterator.hpp +++ /dev/null @@ -1,139 +0,0 @@ -#ifndef OSMIUM_IO_INPUT_ITERATOR_HPP -#define OSMIUM_IO_INPUT_ITERATOR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include - -#include -#include - -namespace osmium { - - namespace io { - - /** - * This iterator class allows you to iterate over all items from a - * source. It hides all the buffer handling and makes the contents of a - * source accessible as a normal STL input iterator. - */ - template - class InputIterator { - - static_assert(std::is_base_of::value, "TItem must derive from osmium::buffer::Item"); - - typedef typename osmium::memory::Buffer::t_iterator item_iterator; - - TSource* m_source; - std::shared_ptr m_buffer; - item_iterator m_iter {}; - - void update_buffer() { - do { - m_buffer = std::make_shared(std::move(m_source->read())); - if (!m_buffer || !*m_buffer) { // end of input - m_source = nullptr; - m_buffer.reset(); - m_iter = item_iterator(); - return; - } - m_iter = m_buffer->begin(); - } while (m_iter == m_buffer->end()); - } - - public: - - typedef std::input_iterator_tag iterator_category; - typedef TItem value_type; - typedef ptrdiff_t difference_type; - typedef TItem* pointer; - typedef TItem& reference; - - explicit InputIterator(TSource& source) : - m_source(&source) { - update_buffer(); - } - - // end iterator - InputIterator() noexcept : - m_source(nullptr) { - } - - InputIterator& operator++() { - assert(m_source); - assert(m_buffer); - assert(m_iter); - ++m_iter; - if (m_iter == m_buffer->end()) { - update_buffer(); - } - return *this; - } - - InputIterator operator++(int) { - InputIterator tmp(*this); - operator++(); - return tmp; - } - - bool operator==(const InputIterator& rhs) const noexcept { - return m_source == rhs.m_source && - m_buffer == rhs.m_buffer && - m_iter == rhs.m_iter; - } - - bool operator!=(const InputIterator& rhs) const noexcept { - return !(*this == rhs); - } - - reference operator*() const { - assert(m_iter); - return static_cast(*m_iter); - } - - pointer operator->() const { - assert(m_iter); - return &static_cast(*m_iter); - } - - }; // class InputIterator - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_INPUT_ITERATOR_HPP diff --git a/third_party/osmium/io/opl_output.hpp b/third_party/osmium/io/opl_output.hpp deleted file mode 100644 index 46a12240b..000000000 --- a/third_party/osmium/io/opl_output.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef OSMIUM_IO_OPL_OUTPUT_HPP -#define OSMIUM_IO_OPL_OUTPUT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 // IWYU pragma: export -#include // IWYU pragma: export - -#endif // OSMIUM_IO_OPL_OUTPUT_HPP diff --git a/third_party/osmium/io/output_iterator.hpp b/third_party/osmium/io/output_iterator.hpp deleted file mode 100644 index e6a9cc096..000000000 --- a/third_party/osmium/io/output_iterator.hpp +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef OSMIUM_IO_OUTPUT_ITERATOR_HPP -#define OSMIUM_IO_OUTPUT_ITERATOR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include - -#include -#include - -namespace osmium { - - namespace memory { - class Item; - } // namespace memory - - namespace io { - - template - class OutputIterator : public std::iterator { - - struct buffer_wrapper { - - osmium::memory::Buffer buffer; - - buffer_wrapper(size_t buffer_size) : - buffer(buffer_size, osmium::memory::Buffer::auto_grow::no) { - } - - }; // struct buffer_wrapper - - static constexpr size_t default_buffer_size = 10 * 1024 * 1024; - - TDest* m_destination; - - std::shared_ptr m_buffer_wrapper; - - public: - - explicit OutputIterator(TDest& destination, const size_t buffer_size = default_buffer_size) : - m_destination(&destination), - m_buffer_wrapper(std::make_shared(buffer_size)) { - } - - void flush() { - osmium::memory::Buffer buffer(m_buffer_wrapper->buffer.capacity(), osmium::memory::Buffer::auto_grow::no); - std::swap(m_buffer_wrapper->buffer, buffer); - (*m_destination)(std::move(buffer)); - } - - OutputIterator& operator=(const osmium::memory::Item& item) { - try { - m_buffer_wrapper->buffer.push_back(item); - } catch (osmium::buffer_is_full&) { - flush(); - m_buffer_wrapper->buffer.push_back(item); - } - return *this; - } - - OutputIterator& operator=(const osmium::DiffObject& diff) { - return this->operator=(diff.curr()); - } - - OutputIterator& operator*() { - return *this; - } - - OutputIterator& operator++() { - return *this; - } - - OutputIterator& operator++(int) { - return *this; - } - - }; // class OutputIterator - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_OUTPUT_ITERATOR_HPP diff --git a/third_party/osmium/io/overwrite.hpp b/third_party/osmium/io/overwrite.hpp deleted file mode 100644 index f29a93228..000000000 --- a/third_party/osmium/io/overwrite.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef OSMIUM_IO_OVERWRITE_HPP -#define OSMIUM_IO_OVERWRITE_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2014 Jochen Topf 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. - -*/ - -namespace osmium { - - namespace io { - - /** - * Allow overwriting of existing file. - */ - enum class overwrite : bool { - no = false, - allow = true - }; - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_OVERWRITE_HPP diff --git a/third_party/osmium/io/pbf_input.hpp b/third_party/osmium/io/pbf_input.hpp deleted file mode 100644 index 8426f6cf6..000000000 --- a/third_party/osmium/io/pbf_input.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef OSMIUM_IO_PBF_INPUT_HPP -#define OSMIUM_IO_PBF_INPUT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 // IWYU pragma: export -#include // IWYU pragma: export - -#endif // OSMIUM_IO_PBF_INPUT_HPP diff --git a/third_party/osmium/io/pbf_output.hpp b/third_party/osmium/io/pbf_output.hpp deleted file mode 100644 index 9fd039654..000000000 --- a/third_party/osmium/io/pbf_output.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef OSMIUM_IO_PBF_OUTPUT_HPP -#define OSMIUM_IO_PBF_OUTPUT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 // IWYU pragma: export -#include // IWYU pragma: export - -#endif // OSMIUM_IO_PBF_OUTPUT_HPP diff --git a/third_party/osmium/io/reader.hpp b/third_party/osmium/io/reader.hpp deleted file mode 100644 index a9b8b954d..000000000 --- a/third_party/osmium/io/reader.hpp +++ /dev/null @@ -1,303 +0,0 @@ -#ifndef OSMIUM_IO_READER_HPP -#define OSMIUM_IO_READER_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef _WIN32 -# include -#endif - -#ifndef _MSC_VER -# include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace osmium { - - namespace io { - - /** - * This is the user-facing interface for reading OSM files. Instantiate - * an object of this class with a file name or osmium::io::File object - * and then call read() on it in a loop until it returns an invalid - * Buffer. - */ - class Reader { - - osmium::io::File m_file; - osmium::osm_entity_bits::type m_read_which_entities; - std::atomic m_input_done; - int m_childpid; - - osmium::thread::Queue m_input_queue; - - std::unique_ptr m_decompressor; - std::future m_read_future; - - std::unique_ptr m_input; - -#ifndef _WIN32 - /** - * Fork and execute the given command in the child. - * A pipe is created between the child and the parent. - * The child writes to the pipe, the parent reads from it. - * This function never returns in the child. - * - * @param command Command to execute in the child. - * @param filename Filename to give to command as argument. - * @returns File descriptor of pipe in the parent. - * @throws std::system_error if a system call fails. - */ - static int execute(const std::string& command, const std::string& filename, int* childpid) { - int pipefd[2]; - if (pipe(pipefd) < 0) { - throw std::system_error(errno, std::system_category(), "opening pipe failed"); - } - pid_t pid = fork(); - if (pid < 0) { - throw std::system_error(errno, std::system_category(), "fork failed"); - } - if (pid == 0) { // child - // close all file descriptors except one end of the pipe - for (int i=0; i < 32; ++i) { - if (i != pipefd[1]) { - ::close(i); - } - } - if (dup2(pipefd[1], 1) < 0) { // put end of pipe as stdout/stdin - exit(1); - } - - ::open("/dev/null", O_RDONLY); // stdin - ::open("/dev/null", O_WRONLY); // stderr - // hack: -g switches off globbing in curl which allows [] to be used in file names - // this is important for XAPI URLs - // in theory this execute() function could be used for other commands, but it is - // only used for curl at the moment, so this is okay. - if (::execlp(command.c_str(), command.c_str(), "-g", filename.c_str(), nullptr) < 0) { - exit(1); - } - } - // parent - *childpid = pid; - ::close(pipefd[1]); - return pipefd[0]; - } -#endif - - /** - * Open File for reading. Handles URLs or normal files. URLs - * are opened by executing the "curl" program (which must be installed) - * and reading from its output. - * - * @returns File descriptor of open file or pipe. - * @throws std::system_error if a system call fails. - */ - static int open_input_file_or_url(const std::string& filename, int* childpid) { - std::string protocol = filename.substr(0, filename.find_first_of(':')); - if (protocol == "http" || protocol == "https" || protocol == "ftp" || protocol == "file") { -#ifndef _WIN32 - return execute("curl", filename, childpid); -#else - throw std::runtime_error("Reading OSM files from the network currently not supported on Windows."); -#endif - } else { - return osmium::io::detail::open_for_reading(filename); - } - } - - public: - - /** - * Create new Reader object. - * - * @param file The file we want to open. - * @param read_which_entities 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. - */ - explicit Reader(const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities = osmium::osm_entity_bits::all) : - m_file(file), - m_read_which_entities(read_which_entities), - m_input_done(false), - m_childpid(0), - m_input_queue(20, "raw_input"), // XXX - m_decompressor(m_file.buffer() ? - osmium::io::CompressionFactory::instance().create_decompressor(file.compression(), m_file.buffer(), m_file.buffer_size()) : - osmium::io::CompressionFactory::instance().create_decompressor(file.compression(), open_input_file_or_url(m_file.filename(), &m_childpid))), - m_read_future(std::async(std::launch::async, detail::ReadThread(m_input_queue, m_decompressor.get(), m_input_done))), - m_input(osmium::io::detail::InputFormatFactory::instance().create_input(m_file, m_read_which_entities, m_input_queue)) { - } - - explicit Reader(const std::string& filename, osmium::osm_entity_bits::type read_types = osmium::osm_entity_bits::all) : - Reader(osmium::io::File(filename), read_types) { - } - - explicit Reader(const char* filename, osmium::osm_entity_bits::type read_types = osmium::osm_entity_bits::all) : - Reader(osmium::io::File(filename), read_types) { - } - - Reader(const Reader&) = delete; - Reader& operator=(const Reader&) = delete; - - ~Reader() { - try { - close(); - } - catch (...) { - } - } - - /** - * Close down the Reader. A call to this is optional, because the - * destructor of Reader will also call this. But if you don't call - * this function first, the destructor might throw an exception - * which is not good. - * - * @throws Some form of std::runtime_error when there is a problem. - */ - void close() { - // Signal to input child process that it should wrap up. - m_input_done = true; - - m_input->close(); - -#ifndef _WIN32 - if (m_childpid) { - int status; - pid_t pid = ::waitpid(m_childpid, &status, 0); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" - if (pid < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) { - throw std::system_error(errno, std::system_category(), "subprocess returned error"); - } -#pragma GCC diagnostic pop - m_childpid = 0; - } -#endif - - osmium::thread::wait_until_done(m_read_future); - } - - /** - * Get the header data from the file. - */ - osmium::io::Header header() const { - return m_input->header(); - } - - /** - * Reads the next buffer from the input. An invalid buffer signals - * end-of-file. After end-of-file all read() calls will return an - * invalid buffer. An invalid buffer is also always returned if - * osmium::osm_entity_bits::nothing was set when the Reader was - * constructed. - * - * @returns Buffer. - * @throws Some form of std::runtime_error if there is an error. - */ - osmium::memory::Buffer read() { - // If an exception happened in the input thread, re-throw - // it in this (the main) thread. - osmium::thread::check_for_exception(m_read_future); - - if (m_read_which_entities == osmium::osm_entity_bits::nothing || m_input_done) { - // If the caller didn't want anything but the header, it will - // always get an empty buffer here. - return osmium::memory::Buffer(); - } - - osmium::memory::Buffer buffer = m_input->read(); - if (!buffer) { - m_input_done = true; - } - return buffer; - } - - /** - * Has the end of file been reached? This is set after the last - * data has been read. It is also set by calling close(). - */ - bool eof() const { - return m_input_done; - } - - }; // class Reader - - /** - * Read contents of the given file into a buffer in one go. Takes - * the same arguments as any of the Reader constructors. - * - * The buffer can take up quite a lot of memory, so don't do this - * unless you are working with small OSM files and/or have lots of - * RAM. - */ - template - osmium::memory::Buffer read_file(TArgs&&... args) { - osmium::memory::Buffer buffer(1024*1024, osmium::memory::Buffer::auto_grow::yes); - - Reader reader(std::forward(args)...); - while (osmium::memory::Buffer read_buffer = reader.read()) { - buffer.add_buffer(read_buffer); - buffer.commit(); - } - - return buffer; - } - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_READER_HPP diff --git a/third_party/osmium/io/reader_iterator.hpp b/third_party/osmium/io/reader_iterator.hpp deleted file mode 100644 index 8d71418e0..000000000 --- a/third_party/osmium/io/reader_iterator.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef OSMIUM_IO_READER_ITERATOR_HPP -#define OSMIUM_IO_READER_ITERATOR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2014 Jochen Topf 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 -#include - -namespace std { - - inline osmium::io::InputIterator begin(osmium::io::Reader& reader) { - return osmium::io::InputIterator(reader); - } - - inline osmium::io::InputIterator end(osmium::io::Reader&) { - return osmium::io::InputIterator(); - } - -} // namespace std - -#endif // OSMIUM_IO_READER_ITERATOR_HPP diff --git a/third_party/osmium/io/writer.hpp b/third_party/osmium/io/writer.hpp deleted file mode 100644 index 7e9bd1383..000000000 --- a/third_party/osmium/io/writer.hpp +++ /dev/null @@ -1,145 +0,0 @@ -#ifndef OSMIUM_IO_WRITER_HPP -#define OSMIUM_IO_WRITER_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace osmium { - - namespace io { - - /** - * This is the user-facing interface for writing OSM files. Instantiate - * an object of this class with a file name or osmium::io::File object - * and optionally the data for the header and then call operator() on it - * to write Buffers. Call close() to finish up. - */ - class Writer { - - osmium::io::File m_file; - - osmium::io::detail::data_queue_type m_output_queue; - - std::unique_ptr m_output; - - std::unique_ptr m_compressor; - - std::future m_write_future; - - public: - - /** - * The constructor of the Writer object opens a file and writes the - * header to it. - * - * @param file File (contains name and format info) to open. - * @param header Optional header data. If this is not given sensible - * defaults will be used. See the default constructor - * of osmium::io::Header for details. - * @param allow_overwrite Allow overwriting of existing file? Can be - * osmium::io::overwrite::allow or osmium::io::overwrite::no+ - * (default). - * - * @throws std::runtime_error If the file could not be opened. - * @throws std::system_error If the file could not be opened. - */ - explicit Writer(const osmium::io::File& file, const osmium::io::Header& header = osmium::io::Header(), overwrite allow_overwrite = overwrite::no) : - m_file(file), - m_output_queue(20, "raw_output"), // XXX - m_output(osmium::io::detail::OutputFormatFactory::instance().create_output(m_file, m_output_queue)), - m_compressor(osmium::io::CompressionFactory::instance().create_compressor(file.compression(), osmium::io::detail::open_for_writing(m_file.filename(), allow_overwrite))), - m_write_future(std::async(std::launch::async, detail::WriteThread(m_output_queue, m_compressor.get()))) { - assert(!m_file.buffer()); - m_output->write_header(header); - } - - explicit Writer(const std::string& filename, const osmium::io::Header& header = osmium::io::Header(), overwrite allow_overwrite = overwrite::no) : - Writer(osmium::io::File(filename), header, allow_overwrite) { - } - - explicit Writer(const char* filename, const osmium::io::Header& header = osmium::io::Header(), overwrite allow_overwrite = overwrite::no) : - Writer(osmium::io::File(filename), header, allow_overwrite) { - } - - Writer(const Writer&) = delete; - Writer& operator=(const Writer&) = delete; - - ~Writer() { - close(); - } - - /** - * Write contents of a buffer to the output file. - * - * @throws Some form of std::runtime_error when there is a problem. - */ - void operator()(osmium::memory::Buffer&& buffer) { - osmium::thread::check_for_exception(m_write_future); - if (buffer.committed() > 0) { - m_output->write_buffer(std::move(buffer)); - } - } - - /** - * Flush writes to output file and closes it. If you do not - * call this, the destructor of Writer will also do the same - * thing. But because this call might thrown an exception, - * it is better to call close() explicitly. - * - * @throws Some form of std::runtime_error when there is a problem. - */ - void close() { - m_output->close(); - osmium::thread::wait_until_done(m_write_future); - } - - }; // class Writer - - } // namespace io - -} // namespace osmium - -#endif // OSMIUM_IO_WRITER_HPP diff --git a/third_party/osmium/io/xml_input.hpp b/third_party/osmium/io/xml_input.hpp deleted file mode 100644 index f33d37ee2..000000000 --- a/third_party/osmium/io/xml_input.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef OSMIUM_IO_XML_INPUT_HPP -#define OSMIUM_IO_XML_INPUT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 // IWYU pragma: export -#include // IWYU pragma: export - -#endif // OSMIUM_IO_XML_INPUT_HPP diff --git a/third_party/osmium/io/xml_output.hpp b/third_party/osmium/io/xml_output.hpp deleted file mode 100644 index d5b839f60..000000000 --- a/third_party/osmium/io/xml_output.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef OSMIUM_IO_XML_OUTPUT_HPP -#define OSMIUM_IO_XML_OUTPUT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 // IWYU pragma: export -#include // IWYU pragma: export - -#endif // OSMIUM_IO_XML_OUTPUT_HPP diff --git a/third_party/osmium/memory/buffer.hpp b/third_party/osmium/memory/buffer.hpp deleted file mode 100644 index fe040caf1..000000000 --- a/third_party/osmium/memory/buffer.hpp +++ /dev/null @@ -1,534 +0,0 @@ -#ifndef OSMIUM_MEMORY_BUFFER_HPP -#define OSMIUM_MEMORY_BUFFER_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace osmium { - - /** - * Exception thrown by the osmium::memory::Buffer class when somebody tries - * to write data into a buffer and it doesn't fit. Buffers with internal - * memory management will not throw this exception, but increase their size. - */ - struct buffer_is_full : public std::runtime_error { - - buffer_is_full() : - std::runtime_error("Osmium buffer is full") { - } - - }; // struct buffer_is_full - - /** - * @brief Memory management of items in buffers and iterators over this data. - */ - namespace memory { - - /** - * A memory area for storing OSM objects and other items. Each item stored - * has a type and a length. See the Item class for details. - * - * Data can be added to a buffer piece by piece using reserve_space() and - * add_item(). After all data that together forms an item is added, it must - * be committed using the commit() call. Usually this is done through the - * Builder class and its derived classes. - * - * You can iterate over all items in a buffer using the iterators returned - * by begin(), end(), cbegin(), and cend(). - * - * Buffers exist in two flavours, those with external memory management and - * those with internal memory management. If you already have some memory - * with data in it (for instance read from disk), you create a Buffer with - * external memory managment. It is your job then to free the memory once - * the buffer isn't used any more. If you don't have memory already, you can - * create a Buffer object and have it manage the memory internally. It will - * dynamically allocate memory and free it again after use. - * - * By default, if a buffer gets full it will throw a buffer_is_full exception. - * You can use the set_full_callback() method to set a callback functor - * which will be called instead of throwing an exception. - */ - class Buffer { - - public: - - enum class auto_grow : bool { - yes = true, - no = false - }; // enum class auto_grow - - private: - - std::vector m_memory; - unsigned char* m_data; - size_t m_capacity; - size_t m_written; - size_t m_committed; - auto_grow m_auto_grow {auto_grow::no}; - std::function m_full; - - public: - - typedef Item value_type; - - /** - * The constructor without any parameters creates a non-initialized - * buffer, ie an empty hull of a buffer that has no actual memory - * associated with it. It can be used to signify end-of-input. - */ - Buffer() noexcept : - m_memory(), - m_data(nullptr), - m_capacity(0), - m_written(0), - m_committed(0) { - } - - /** - * Constructs an externally memory-managed buffer using the given - * memory and size. - * - * @param data A pointer to some already initialized data. - * @param size The size of the initialized data. - * @throws std::invalid_argument When the size isn't a multiple of the alignment. - */ - explicit Buffer(unsigned char* data, size_t size) : - m_memory(), - m_data(data), - m_capacity(size), - m_written(size), - m_committed(size) { - if (size % align_bytes != 0) { - throw std::invalid_argument("buffer size needs to be multiple of alignment"); - } - } - - /** - * Constructs an externally memory-managed buffer with the given - * capacity that already contains 'committed' bytes of data. - * - * @param data A pointer to some (possibly initialized) data. - * @param capacity The size of the memory for this buffer. - * @param committed The size of the initialized data. If this is 0, the buffer startes out empty. - * @throws std::invalid_argument When the capacity or committed isn't a multiple of the alignment. - */ - explicit Buffer(unsigned char* data, size_t capacity, size_t committed) : - m_memory(), - m_data(data), - m_capacity(capacity), - m_written(committed), - m_committed(committed) { - if (capacity % align_bytes != 0) { - throw std::invalid_argument("buffer capacity needs to be multiple of alignment"); - } - if (committed % align_bytes != 0) { - throw std::invalid_argument("buffer parameter 'committed' needs to be multiple of alignment"); - } - } - - /** - * Create an internally memory-managed buffer with the given capacity. - * different in that it internally gets dynamic memory of the - * required size. The dynamic memory will be automatically - * freed when the Buffer is destroyed. - */ - explicit Buffer(size_t capacity, auto_grow auto_grow = auto_grow::yes) : - m_memory(capacity), - m_data(m_memory.data()), - m_capacity(capacity), - m_written(0), - m_committed(0), - m_auto_grow(auto_grow) { - if (capacity % align_bytes != 0) { - throw std::invalid_argument("buffer capacity needs to be multiple of alignment"); - } - } - - // buffers can not be copied - Buffer(const Buffer&) = delete; - Buffer& operator=(const Buffer&) = delete; - - // buffers can be moved - Buffer(Buffer&&) = default; - Buffer& operator=(Buffer&&) = default; - - ~Buffer() = default; - - /** - * Return a pointer to data inside the buffer. - */ - unsigned char* data() const noexcept { - return m_data; - } - - /** - * Returns the capacity of the buffer, ie how many bytes it can contain. - */ - size_t capacity() const noexcept { - return m_capacity; - } - - /** - * Returns the number of bytes already filled in this buffer. - */ - size_t committed() const noexcept { - return m_committed; - } - - /** - * Returns the number of bytes currently filled in this buffer that - * are not yet committed. - */ - size_t written() const noexcept { - return m_written; - } - - /** - * This tests if the current state of the buffer is aligned - * properly. Can be used for asserts. - */ - bool is_aligned() const noexcept { - return (m_written % align_bytes == 0) && (m_committed % align_bytes == 0); - } - - /** - * Set functor to be called whenever the buffer is full - * instead of throwing buffer_is_full. - */ - void set_full_callback(std::function full) { - m_full = full; - } - - /** - * Grow capacity of this buffer to the given size. - * This works only with internally memory-managed buffers. - * If the given size is not larger than the current capacity, nothing is done. - * Already written but not committed data is discarded. - * - * @param size New capacity. - */ - void grow(size_t size) { - if (m_memory.empty()) { - throw std::logic_error("Can't grow Buffer if it doesn't use internal memory management."); - } - if (m_capacity < size) { - if (size % align_bytes != 0) { - throw std::invalid_argument("buffer capacity needs to be multiple of alignment"); - } - m_memory.resize(size); - m_data = m_memory.data(); - m_capacity = size; - } - } - - /** - * Mark currently written bytes in the buffer as committed. - * - * @returns Last number of committed bytes before this commit. - */ - size_t commit() { - assert(is_aligned()); - - const size_t offset = m_committed; - m_committed = m_written; - return offset; - } - - /** - * Roll back changes in buffer to last committed state. - */ - void rollback() { - m_written = m_committed; - } - - /** - * Clear the buffer. - * - * @returns Number of bytes in the buffer before it was cleared. - */ - size_t clear() { - const size_t committed = m_committed; - m_written = 0; - m_committed = 0; - return committed; - } - - /** - * Get the data in the buffer at the given offset. - * - * @tparam T Type we want to the data to be interpreted as. - * @returns Reference of given type pointing to the data in the buffer. - */ - template - T& get(const size_t offset) const { - return *reinterpret_cast(&m_data[offset]); - } - - /** - * Reserve space of given size in buffer and return pointer to it. - * This is the only way of adding data to the buffer. You reserve - * the space and then fill it. - * - * Note that you have to eventually call commit() to actually - * commit this data. - * - * If there isn't enough space in the buffer, one of three things - * can happen: - * - * * If you have set a callback with set_full_callback(), it is - * called. After the call returns, you must have either grown - * the buffer or cleared it by calling buffer.clear(). - * * If no callback is defined and this buffer uses internal - * memory management, the buffers capacity is grown, so that - * the new data will fit. - * * Else the buffer_is_full exception is thrown. - * - * @param size Number of bytes to reserve. - * @returns Pointer to reserved space. Note that this pointer is - * only guaranteed to be valid until the next call to - * reserve_space(). - * @throws osmium::buffer_is_full Might be thrown if the buffer is full. - */ - unsigned char* reserve_space(const size_t size) { - if (m_written + size > m_capacity) { - if (m_full) { - m_full(*this); - } else if (!m_memory.empty() && (m_auto_grow == auto_grow::yes)) { - // double buffer size until there is enough space - size_t new_capacity = m_capacity * 2; - while (m_written + size > new_capacity) { - new_capacity *= 2; - } - grow(new_capacity); - } else { - throw osmium::buffer_is_full(); - } - } - unsigned char* data = &m_data[m_written]; - m_written += size; - return data; - } - - /** - * Add an item to the buffer. The size of the item is stored inside - * the item, so we know how much memory to copy. - * - * Note that you have to eventually call commit() to actually - * commit this data. - * - * @tparam T Class of the item to be copied. - * @param item Reference to the item to be copied. - * @returns Reference to newly copied data in the buffer. - */ - template - T& add_item(const T& item) { - unsigned char* ptr = reserve_space(item.padded_size()); - std::memcpy(ptr, &item, item.padded_size()); - return *reinterpret_cast(ptr); - } - - /** - * Add committed contents of the given buffer to this buffer. - * - * Note that you have to eventually call commit() to actually - * commit this data. - */ - void add_buffer(const Buffer& buffer) { - unsigned char* ptr = reserve_space(buffer.committed()); - std::memcpy(ptr, buffer.data(), buffer.committed()); - } - - /** - * Add an item to the buffer. This function is provided so that - * you can use std::back_inserter. - */ - void push_back(const osmium::memory::Item& item) { - add_item(item); - commit(); - } - - /** - * These iterators can be used to iterate over all items in - * a buffer. - */ - template - using t_iterator = osmium::memory::ItemIterator; - - template - using t_const_iterator = osmium::memory::ItemIterator; - - typedef t_iterator iterator; - typedef t_const_iterator const_iterator; - - template - t_iterator begin() { - return t_iterator(m_data, m_data + m_committed); - } - - iterator begin() { - return iterator(m_data, m_data + m_committed); - } - - template - t_iterator end() { - return t_iterator(m_data + m_committed, m_data + m_committed); - } - - iterator end() { - return iterator(m_data + m_committed, m_data + m_committed); - } - - template - t_const_iterator cbegin() const { - return t_const_iterator(m_data, m_data + m_committed); - } - - const_iterator cbegin() const { - return const_iterator(m_data, m_data + m_committed); - } - - template - t_const_iterator cend() const { - return t_const_iterator(m_data + m_committed, m_data + m_committed); - } - - const_iterator cend() const { - return const_iterator(m_data + m_committed, m_data + m_committed); - } - - template - t_const_iterator begin() const { - return cbegin(); - } - - const_iterator begin() const { - return cbegin(); - } - - template - t_const_iterator end() const { - return cend(); - } - - const_iterator end() const { - return cend(); - } - - /** - * In a bool context any initialized buffer is true. - */ - explicit operator bool() const { - return m_data != nullptr; - } - - friend void swap(Buffer& lhs, Buffer& rhs) { - using std::swap; - - swap(lhs.m_memory, rhs.m_memory); - swap(lhs.m_data, rhs.m_data); - swap(lhs.m_capacity, rhs.m_capacity); - swap(lhs.m_written, rhs.m_written); - swap(lhs.m_committed, rhs.m_committed); - } - - /** - * Purge removed items from the buffer. This is done by moving all - * non-removed items forward in the buffer overwriting removed - * items and then correcting the m_written and m_committed numbers. - * - * Note that calling this function invalidates all iterators on this - * buffer and all offsets in this buffer. - * - * For every non-removed item that moves its position, the function - * 'moving_in_buffer' is called on the given callback object with - * the old and new offsets in the buffer where the object used to - * be and is now, respectively. This call can be used to update any - * indexes. - */ - template - void purge_removed(TCallbackClass* callback) { - if (begin() == end()) { - return; - } - - iterator it_write = begin(); - - iterator next; - for (iterator it_read = begin(); it_read != end(); it_read = next) { - next = std::next(it_read); - if (!it_read->removed()) { - if (it_read != it_write) { - assert(it_read.data() >= data()); - assert(it_write.data() >= data()); - size_t old_offset = static_cast(it_read.data() - data()); - size_t new_offset = static_cast(it_write.data() - data()); - callback->moving_in_buffer(old_offset, new_offset); - std::memmove(it_write.data(), it_read.data(), it_read->padded_size()); - } - it_write.advance_once(); - } - } - - assert(it_write.data() >= data()); - m_written = static_cast(it_write.data() - data()); - m_committed = m_written; - } - - }; // class Buffer - - inline bool operator==(const Buffer& lhs, const Buffer& rhs) noexcept { - return lhs.data() == rhs.data() && lhs.capacity() == rhs.capacity() && lhs.committed() == rhs.committed(); - } - - inline bool operator!=(const Buffer& lhs, const Buffer& rhs) noexcept { - return ! (lhs == rhs); - } - - } // namespace memory - -} // namespace osmium - -#endif // OSMIUM_MEMORY_BUFFER_HPP diff --git a/third_party/osmium/memory/collection.hpp b/third_party/osmium/memory/collection.hpp deleted file mode 100644 index b25dd64ec..000000000 --- a/third_party/osmium/memory/collection.hpp +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef OSMIUM_MEMORY_COLLECTION_HPP -#define OSMIUM_MEMORY_COLLECTION_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include - -#include - -namespace osmium { - - namespace memory { - - template - class CollectionIterator : public std::iterator { - - // This data_type is either 'unsigned char*' or 'const unsigned char*' depending - // on whether TMember is const. This allows this class to be used as an iterator and - // as a const_iterator. - typedef typename std::conditional::value, const unsigned char*, unsigned char*>::type data_type; - - data_type m_data; - - public: - - CollectionIterator() noexcept : - m_data(nullptr) { - } - - CollectionIterator(data_type data) noexcept : - m_data(data) { - } - - CollectionIterator& operator++() { - m_data = reinterpret_cast(m_data)->next(); - return *static_cast*>(this); - } - - CollectionIterator operator++(int) { - CollectionIterator tmp(*this); - operator++(); - return tmp; - } - - bool operator==(const CollectionIterator& rhs) const noexcept { - return m_data == rhs.m_data; - } - - bool operator!=(const CollectionIterator& rhs) const noexcept { - return m_data != rhs.m_data; - } - - unsigned char* data() const noexcept { - return m_data; - } - - TMember& operator*() const { - return *reinterpret_cast(m_data); - } - - TMember* operator->() const { - return reinterpret_cast(m_data); - } - - template - friend std::basic_ostream& operator<<(std::basic_ostream& out, const CollectionIterator& iter) { - return out << static_cast(iter.m_data); - } - - }; // class CollectionIterator - - template - class Collection : public Item { - - public: - - typedef CollectionIterator iterator; - typedef CollectionIterator const_iterator; - typedef TMember value_type; - - static constexpr osmium::item_type itemtype = TCollectionItemType; - - Collection() : - Item(sizeof(Collection), TCollectionItemType) { - } - - bool empty() const { - return sizeof(Collection) == byte_size(); - } - - iterator begin() { - return iterator(data() + sizeof(Collection)); - } - - iterator end() { - return iterator(data() + byte_size()); - } - - const_iterator cbegin() const { - return const_iterator(data() + sizeof(Collection)); - } - - const_iterator cend() const { - return const_iterator(data() + byte_size()); - } - - const_iterator begin() const { - return cbegin(); - } - - const_iterator end() const { - return cend(); - } - - }; // class Collection - - } // namespace memory - -} // namespace osmium - -#endif // OSMIUM_MEMORY_COLLECTION_HPP diff --git a/third_party/osmium/memory/item.hpp b/third_party/osmium/memory/item.hpp deleted file mode 100644 index 2d22f948e..000000000 --- a/third_party/osmium/memory/item.hpp +++ /dev/null @@ -1,179 +0,0 @@ -#ifndef OSMIUM_MEMORY_ITEM_HPP -#define OSMIUM_MEMORY_ITEM_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include - -namespace osmium { - - // forward declaration, see osmium/osm/item_type.hpp for declaration - enum class item_type : uint16_t; - - namespace builder { - class Builder; - } - - namespace memory { - - typedef uint32_t item_size_type; - - // align datastructures to this many bytes - constexpr item_size_type align_bytes = 8; - - template - inline T padded_length(T length) noexcept { - static_assert(std::is_integral::value && std::is_unsigned::value, - "Template parameter must be unsigned integral type"); - return (length + align_bytes - 1) & ~(align_bytes - 1); - } - - /** - * @brief Namespace for Osmium internal use - */ - namespace detail { - - /** - * This class contains only a helper method used in several - * other classes. - */ - class ItemHelper { - - protected: - - ItemHelper() = default; - - ~ItemHelper() = default; - - ItemHelper(const ItemHelper&) = default; - ItemHelper(ItemHelper&&) = default; - - ItemHelper& operator=(const ItemHelper&) = default; - ItemHelper& operator=(ItemHelper&&) = default; - - public: - - unsigned char* data() noexcept { - return reinterpret_cast(this); - } - - const unsigned char* data() const noexcept { - return reinterpret_cast(this); - } - - }; // class ItemHelper - - } // namespace detail - - class Item : public osmium::memory::detail::ItemHelper { - - item_size_type m_size; - item_type m_type; - uint16_t m_removed : 1; - uint16_t m_padding : 15; - - template - friend class CollectionIterator; - - template - friend class ItemIterator; - - friend class osmium::builder::Builder; - - Item& add_size(const item_size_type size) noexcept { - m_size += size; - return *this; - } - - protected: - - explicit Item(item_size_type size=0, item_type type=item_type()) noexcept : - m_size(size), - m_type(type), - m_removed(false), - m_padding(0) { - } - - Item(const Item&) = delete; - Item(Item&&) = delete; - - Item& operator=(const Item&) = delete; - Item& operator=(Item&&) = delete; - - Item& set_type(const item_type item_type) noexcept { - m_type = item_type; - return *this; - } - - public: - - unsigned char* next() noexcept { - return data() + padded_size(); - } - - const unsigned char* next() const noexcept { - return data() + padded_size(); - } - - item_size_type byte_size() const noexcept { - return m_size; - } - - item_size_type padded_size() const { - return padded_length(m_size); - } - - item_type type() const noexcept { - return m_type; - } - - bool removed() const noexcept { - return m_removed; - } - - void set_removed(bool removed) noexcept { - m_removed = removed; - } - - }; // class Item - - static_assert(sizeof(Item) == 8, "Class osmium::Item has wrong size!"); - static_assert(sizeof(Item) % align_bytes == 0, "Class osmium::Item has wrong size to be aligned properly!"); - - } // namespace memory - -} // namespace osmium - -#endif // OSMIUM_MEMORY_ITEM_HPP diff --git a/third_party/osmium/memory/item_iterator.hpp b/third_party/osmium/memory/item_iterator.hpp deleted file mode 100644 index 34ed60083..000000000 --- a/third_party/osmium/memory/item_iterator.hpp +++ /dev/null @@ -1,234 +0,0 @@ -#ifndef OSMIUM_ITEM_ITERATOR_HPP -#define OSMIUM_ITEM_ITERATOR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2014 Jochen Topf 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 -#include -#include -#include - -#include -#include - -namespace osmium { - - class Node; - class Way; - class Relation; - class Area; - class Changeset; - class OSMObject; - class OSMEntity; - class TagList; - class WayNodeList; - class RelationMemberList; - class InnerRing; - class OuterRing; - - namespace memory { - - namespace detail { - - template - inline bool type_is_compatible(osmium::item_type) noexcept { - return true; - } - - template <> - inline bool type_is_compatible(osmium::item_type t) noexcept { - return t == osmium::item_type::node; - } - - template <> - inline bool type_is_compatible(osmium::item_type t) noexcept { - return t == osmium::item_type::way; - } - - template <> - inline bool type_is_compatible(osmium::item_type t) noexcept { - return t == osmium::item_type::relation; - } - - template <> - inline bool type_is_compatible(osmium::item_type t) noexcept { - return t == osmium::item_type::area; - } - - template <> - inline bool type_is_compatible(osmium::item_type t) noexcept { - return t == osmium::item_type::changeset; - } - - template <> - inline bool type_is_compatible(osmium::item_type t) noexcept { - return t == osmium::item_type::node || t == osmium::item_type::way || t == osmium::item_type::relation || t == osmium::item_type::area; - } - - template <> - inline bool type_is_compatible(osmium::item_type t) noexcept { - return t == osmium::item_type::node || t == osmium::item_type::way || t == osmium::item_type::relation || t == osmium::item_type::area || t == osmium::item_type::changeset; - } - - template <> - inline bool type_is_compatible(osmium::item_type t) noexcept { - return t == osmium::item_type::tag_list; - } - - template <> - inline bool type_is_compatible(osmium::item_type t) noexcept { - return t == osmium::item_type::way_node_list; - } - - template <> - inline bool type_is_compatible(osmium::item_type t) noexcept { - return t == osmium::item_type::relation_member_list || t == osmium::item_type::relation_member_list_with_full_members; - } - - template <> - inline bool type_is_compatible(osmium::item_type t) noexcept { - return t == osmium::item_type::outer_ring; - } - - template <> - inline bool type_is_compatible(osmium::item_type t) noexcept { - return t == osmium::item_type::inner_ring; - } - - } // namespace detail - - template - class ItemIterator : public std::iterator { - - static_assert(std::is_base_of::value, "TMember must derive from osmium::memory::Item"); - - // This data_type is either 'unsigned char*' or 'const unsigned char*' depending - // on whether TMember is const. This allows this class to be used as an iterator and - // as a const_iterator. - typedef typename std::conditional::value, const unsigned char*, unsigned char*>::type data_type; - - data_type m_data; - data_type m_end; - - void advance_to_next_item_of_right_type() { - while (m_data != m_end && - !detail::type_is_compatible::type>(reinterpret_cast(m_data)->type())) { - m_data = reinterpret_cast(m_data)->next(); - } - } - - public: - - ItemIterator() noexcept : - m_data(nullptr), - m_end(nullptr) { - } - - ItemIterator(data_type data, data_type end) : - m_data(data), - m_end(end) { - advance_to_next_item_of_right_type(); - } - - template - ItemIterator cast() const { - return ItemIterator(m_data, m_end); - } - - ItemIterator& operator++() { - assert(m_data); - assert(m_data != m_end); - m_data = reinterpret_cast(m_data)->next(); - advance_to_next_item_of_right_type(); - return *static_cast*>(this); - } - - /** - * Like operator++() but will NOT skip items of unwanted - * types. Do not use this unless you know what you are - * doing. - */ - ItemIterator& advance_once() { - assert(m_data); - assert(m_data != m_end); - m_data = reinterpret_cast(m_data)->next(); - return *static_cast*>(this); - } - - ItemIterator operator++(int) { - ItemIterator tmp(*this); - operator++(); - return tmp; - } - - bool operator==(const ItemIterator& rhs) const { - return m_data == rhs.m_data && m_end == rhs.m_end; - } - - bool operator!=(const ItemIterator& rhs) const { - return !(*this == rhs); - } - - unsigned char* data() const { - assert(m_data); - return m_data; - } - - TMember& operator*() const { - assert(m_data); - assert(m_data != m_end); - return *reinterpret_cast(m_data); - } - - TMember* operator->() const { - assert(m_data); - assert(m_data != m_end); - return reinterpret_cast(m_data); - } - - explicit operator bool() const { - return m_data != nullptr; - } - - template - friend std::basic_ostream& operator<<(std::basic_ostream& out, const ItemIterator& iter) { - return out << static_cast(iter.m_data); - } - - }; // class ItemIterator - - } // namespace memory - -} // namespace osmium - -#endif // OSMIUM_ITEM_ITERATOR_HPP diff --git a/third_party/osmium/object_pointer_collection.hpp b/third_party/osmium/object_pointer_collection.hpp deleted file mode 100644 index 22029a149..000000000 --- a/third_party/osmium/object_pointer_collection.hpp +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef OSMIUM_OBJECT_POINTER_COLLECTION_HPP -#define OSMIUM_OBJECT_POINTER_COLLECTION_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include - -#include - -#include -#include -#include - -// IWYU pragma: no_forward_declare osmium::OSMObject -// IWYU pragma: no_forward_declare osmium::memory::Item - -namespace osmium { - - /** - * A collection of pointers to OSM objects. The pointers can be easily - * and quickly sorted or otherwise manipulated, while the objects - * themselves or the buffers they are in, do not have to be changed. - * - * An iterator is provided that can iterate over the pointers but looks - * like it is iterating over the underlying OSM objects. - * - * This class implements the visitor pattern which makes it easy to - * populate the collection from a buffer of OSM objects: - * - * osmium::ObjectPointerCollection objects; - * osmium::memory::Buffer buffer = reader.read(); - * osmium::apply(buffer, objects); - * - */ - class ObjectPointerCollection : public osmium::handler::Handler { - - std::vector m_objects; - - public: - - typedef boost::indirect_iterator::iterator, osmium::OSMObject> iterator; - typedef boost::indirect_iterator::const_iterator, const osmium::OSMObject> const_iterator; - - ObjectPointerCollection() noexcept : - m_objects() { - } - - void osm_object(osmium::OSMObject& object) { - m_objects.push_back(&object); - } - - /** - * Sort objects according to the given order functor. - */ - template - void sort(TCompare&& compare) { - std::sort(m_objects.begin(), m_objects.end(), std::forward(compare)); - } - - iterator begin() { - return iterator { m_objects.begin() }; - } - - iterator end() { - return iterator { m_objects.end() }; - } - - const_iterator cbegin() const { - return const_iterator { m_objects.cbegin() }; - } - - const_iterator cend() const { - return const_iterator { m_objects.cend() }; - } - - }; // class ObjectPointerCollection - -} // namespace osmium - -#endif // OSMIUM_OBJECT_POINTER_COLLECTION_HPP diff --git a/third_party/osmium/osm.hpp b/third_party/osmium/osm.hpp deleted file mode 100644 index bf21c19dc..000000000 --- a/third_party/osmium/osm.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef OSMIUM_OSM_HPP -#define OSMIUM_OSM_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 // IWYU pragma: export -#include // IWYU pragma: export -#include // IWYU pragma: export -#include // IWYU pragma: export -#include // IWYU pragma: export - -/** - * @brief Namespace for everything in the Osmium library. - */ -namespace osmium { -} // namespace osmium - -#endif // OSMIUM_OSM_HPP diff --git a/third_party/osmium/osm/area.hpp b/third_party/osmium/osm/area.hpp deleted file mode 100644 index a388de2e9..000000000 --- a/third_party/osmium/osm/area.hpp +++ /dev/null @@ -1,193 +0,0 @@ -#ifndef OSMIUM_OSM_AREA_HPP -#define OSMIUM_OSM_AREA_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace osmium { - - namespace builder { - template class ObjectBuilder; - } - - /** - * An outer ring of an Area. - */ - class OuterRing : public NodeRefList { - - public: - - OuterRing(): - NodeRefList() { - } - - }; // class OuterRing - - static_assert(sizeof(OuterRing) % osmium::memory::align_bytes == 0, "Class osmium::OuterRing has wrong size to be aligned properly!"); - - /** - * An inner ring of an Area. - */ - class InnerRing : public NodeRefList { - - public: - - InnerRing(): - NodeRefList() { - } - - }; // class InnerRing - - static_assert(sizeof(InnerRing) % osmium::memory::align_bytes == 0, "Class osmium::InnerRing has wrong size to be aligned properly!"); - - /** - * Convert way or (multipolygon) relation id into unique area id. - * - * @param id Id of a way or relation - * @param type Type of object (way or relation) - * @returns Area id - */ - inline osmium::object_id_type object_id_to_area_id(osmium::object_id_type id, osmium::item_type type) { - osmium::object_id_type area_id = std::abs(id) * 2; - if (type == osmium::item_type::relation) { - ++area_id; - } - return id < 0 ? -area_id : area_id; - } - - /** - * Convert area id into id of the way or relation it was created from. - * - * @param id Area id - * @returns Way or Relation id. - */ - inline osmium::object_id_type area_id_to_object_id(osmium::object_id_type id) { - return id / 2; - } - - /** - * An OSM area created out of a closed way or a multipolygon relation. - */ - class Area : public OSMObject { - - friend class osmium::builder::ObjectBuilder; - - Area() : - OSMObject(sizeof(Area), osmium::item_type::area) { - } - - public: - - static constexpr osmium::item_type itemtype = osmium::item_type::area; - - /** - * Was this area created from a way? (In contrast to areas - * created from a relation and their members.) - */ - bool from_way() const noexcept { - return (positive_id() & 0x1) == 0; - } - - /** - * Return the Id of the way or relation this area was created from. - */ - osmium::object_id_type orig_id() const { - return osmium::area_id_to_object_id(id()); - } - - /** - * Count the number of outer and inner rings of this area. - */ - std::pair num_rings() const { - std::pair counter; - - for (auto it = cbegin(); it != cend(); ++it) { - switch (it->type()) { - case osmium::item_type::outer_ring: - ++counter.first; - break; - case osmium::item_type::inner_ring: - ++counter.second; - break; - case osmium::item_type::tag_list: - // ignore tags - break; - case osmium::item_type::undefined: - case osmium::item_type::node: - case osmium::item_type::way: - case osmium::item_type::relation: - case osmium::item_type::area: - case osmium::item_type::changeset: - case osmium::item_type::way_node_list: - case osmium::item_type::relation_member_list: - case osmium::item_type::relation_member_list_with_full_members: - assert(false && "Children of Area can only be outer/inner_ring and tag_list."); - break; - } - } - - return counter; - } - - /** - * Is this area a multipolygon, ie. has it more than one outer ring? - */ - bool is_multipolygon() const { - return num_rings().first > 1; - } - - osmium::memory::ItemIterator inner_ring_cbegin(const osmium::memory::ItemIterator& it) const { - return it.cast(); - } - - osmium::memory::ItemIterator inner_ring_cend(const osmium::memory::ItemIterator& it) const { - return std::next(it).cast(); - } - - }; // class Area - - static_assert(sizeof(Area) % osmium::memory::align_bytes == 0, "Class osmium::Area has wrong size to be aligned properly!"); - -} // namespace osmium - -#endif // OSMIUM_OSM_AREA_HPP diff --git a/third_party/osmium/osm/box.hpp b/third_party/osmium/osm/box.hpp deleted file mode 100644 index 2b761fefc..000000000 --- a/third_party/osmium/osm/box.hpp +++ /dev/null @@ -1,207 +0,0 @@ -#ifndef OSMIUM_OSM_BOX_HPP -#define OSMIUM_OSM_BOX_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 - -#include -#include - -namespace osmium { - - /** - * Bounding box. - */ - class Box { - - osmium::Location m_bottom_left; - osmium::Location m_top_right; - - public: - - /** - * Create undefined Box. Use the extend() function - * to add actual bounds. - */ - constexpr Box() noexcept : - m_bottom_left(), - m_top_right() { - } - - Box(double minx, double miny, double maxx, double maxy) : - m_bottom_left(minx, miny), - m_top_right(maxx, maxy) { - } - - Box(const osmium::Location& bottom_left, const osmium::Location& top_right) : - m_bottom_left(bottom_left), - m_top_right(top_right) { - } - - Box(const Box&) = default; - Box(Box&&) = default; - Box& operator=(const Box&) = default; - Box& operator=(Box&&) = default; - ~Box() = default; - - /** - * Extend this bounding box by the given location. If the - * location is undefined, the bounding box is unchanged. - */ - Box& extend(const Location& location) noexcept { - if (location) { - if (m_bottom_left) { - if (location.x() < m_bottom_left.x()) { - m_bottom_left.set_x(location.x()); - } - if (location.x() > m_top_right.x()) { - m_top_right.set_x(location.x()); - } - if (location.y() < m_bottom_left.y()) { - m_bottom_left.set_y(location.y()); - } - if (location.y() > m_top_right.y()) { - m_top_right.set_y(location.y()); - } - } else { - m_bottom_left = location; - m_top_right = location; - } - } - return *this; - } - - /** - * Extend this bounding box by the given box. If the - * box is undefined, the bounding box is unchanged. - */ - Box& extend(const Box& box) noexcept { - extend(box.bottom_left()); - extend(box.top_right()); - return *this; - } - - /** - * Box are defined, ie. contains defined coordinates. - */ - explicit constexpr operator bool() const noexcept { - return static_cast(m_bottom_left); - } - - /** - * Box are valid, ie. defined and inside usual bounds - * (-180<=lon<=180, -90<=lat<=90). - */ - constexpr bool valid() const noexcept { - return bottom_left().valid() && top_right().valid(); - } - - /** - * Bottom-left location. - */ - OSMIUM_CONSTEXPR Location bottom_left() const noexcept { - return m_bottom_left; - } - - /** - * Bottom-left location. - */ - Location& bottom_left() noexcept { - return m_bottom_left; - } - - /** - * Top-right location. - */ - OSMIUM_CONSTEXPR Location top_right() const noexcept { - return m_top_right; - } - - /** - * Top-right location. - */ - Location& top_right() noexcept { - return m_top_right; - } - - /** - * Is the location inside the box? - */ - bool contains(const osmium::Location& location) const { - return location.x() >= bottom_left().x() && location.y() >= bottom_left().y() && - location.x() <= top_right().x() && location.y() <= top_right().y(); - } - - /** - * Calculate size of the box in square degrees. - * - * @throws osmium::invalid_location unless all coordinates are valid - */ - double size() const { - return (m_top_right.lon() - m_bottom_left.lon()) * - (m_top_right.lat() - m_bottom_left.lat()); - } - - }; // class Box - - /** - * Boxes are equal if both locations are equal. - */ - inline OSMIUM_CONSTEXPR bool operator==(const Box& lhs, const Box& rhs) noexcept { - return lhs.bottom_left() == rhs.bottom_left() && lhs.top_right() == rhs.top_right(); - } - - /** - * Output a box to a stream. - */ - template - inline std::basic_ostream& operator<<(std::basic_ostream& out, const osmium::Box& box) { - if (box) { - out << '(' - << box.bottom_left().lon() - << ',' - << box.bottom_left().lat() - << ',' - << box.top_right().lon() - << ',' - << box.top_right().lat() - << ')'; - } else { - out << "(undefined)"; - } - return out; - } -} // namespace osmium - -#endif // OSMIUM_OSM_BOX_HPP diff --git a/third_party/osmium/osm/changeset.hpp b/third_party/osmium/osm/changeset.hpp deleted file mode 100644 index 2b79fb5cf..000000000 --- a/third_party/osmium/osm/changeset.hpp +++ /dev/null @@ -1,336 +0,0 @@ -#ifndef OSMIUM_OSM_CHANGESET_HPP -#define OSMIUM_OSM_CHANGESET_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace osmium { - - namespace builder { - template class ObjectBuilder; - } - - /** - * \brief An OSM Changeset, a group of changes made by a single user over - * a short period of time. - * - * You can not create Changeset objects directly. Use the ChangesetBuilder - * class to create Changesets in a Buffer. - */ - class Changeset : public osmium::OSMEntity { - - friend class osmium::builder::ObjectBuilder; - - osmium::Timestamp m_created_at; - osmium::Timestamp m_closed_at; - osmium::Box m_bounds; - changeset_id_type m_id {0}; - num_changes_type m_num_changes {0}; - user_id_type m_uid {0}; - string_size_type m_user_size; - - Changeset() : - OSMEntity(sizeof(Changeset), osmium::item_type::changeset) { - } - - void set_user_size(string_size_type size) { - m_user_size = size; - } - - unsigned char* subitems_position() { - return data() + osmium::memory::padded_length(sizeof(Changeset) + m_user_size); - } - - const unsigned char* subitems_position() const { - return data() + osmium::memory::padded_length(sizeof(Changeset) + m_user_size); - } - - public: - - /// Get ID of this changeset - changeset_id_type id() const noexcept { - return m_id; - } - - /** - * Set ID of this changeset - * - * @param id The id. - * @returns Reference to changeset to make calls chainable. - */ - Changeset& set_id(changeset_id_type id) noexcept { - m_id = id; - return *this; - } - - /** - * Set ID of this changeset. - * - * @param id The id. - * @returns Reference to object to make calls chainable. - */ - Changeset& set_id(const char* id) { - return set_id(osmium::string_to_changeset_id(id)); - } - - /// Get user id. - user_id_type uid() const noexcept { - return m_uid; - } - - /** - * Set user id. - * - * @param uid The user id. - * @returns Reference to changeset to make calls chainable. - */ - Changeset& set_uid(user_id_type uid) noexcept { - m_uid = uid; - return *this; - } - - /** - * Set user id to given uid or to 0 (anonymous user) if the given - * uid is smaller than 0. - * - * @param uid The user id. - * @returns Reference to changeset to make calls chainable. - */ - Changeset& set_uid_from_signed(signed_user_id_type uid) noexcept { - m_uid = uid < 0 ? 0 : static_cast(uid); - return *this; - } - - /** - * Set user id to given uid or to 0 (anonymous user) if the given - * uid is smaller than 0. - * - * @returns Reference to changeset to make calls chainable. - */ - Changeset& set_uid(const char* uid) { - return set_uid_from_signed(string_to_user_id(uid)); - } - - /// Is this user anonymous? - bool user_is_anonymous() const noexcept { - return m_uid == 0; - } - - /// Get timestamp when this changeset was created. - osmium::Timestamp created_at() const noexcept { - return m_created_at; - } - - /** - * Get timestamp when this changeset was closed. - * - * @returns Timestamp. Will return the empty Timestamp when the - * changeset is not yet closed. - */ - osmium::Timestamp closed_at() const noexcept { - return m_closed_at; - } - - /// Is this changeset open? - bool open() const noexcept { - return m_closed_at == osmium::Timestamp(); - } - - /// Is this changeset closed? - bool closed() const noexcept { - return !open(); - } - - /** - * Set the timestamp when this changeset was created. - * - * @param timestamp Timestamp - * @returns Reference to changeset to make calls chainable. - */ - Changeset& set_created_at(const osmium::Timestamp timestamp) { - m_created_at = timestamp; - return *this; - } - - /** - * Set the timestamp when this changeset was closed. - * - * @param timestamp Timestamp - * @returns Reference to changeset to make calls chainable. - */ - Changeset& set_closed_at(const osmium::Timestamp timestamp) { - m_closed_at = timestamp; - return *this; - } - - /// Get the number of changes in this changeset - num_changes_type num_changes() const noexcept { - return m_num_changes; - } - - /// Set the number of changes in this changeset - Changeset& set_num_changes(num_changes_type num_changes) noexcept { - m_num_changes = num_changes; - return *this; - } - - /// Set the number of changes in this changeset - Changeset& set_num_changes(const char* num_changes) noexcept { - return set_num_changes(osmium::string_to_num_changes(num_changes)); - } - - /** - * Get the bounding box of this changeset. - * - * @returns Bounding box. Can be empty. - */ - osmium::Box& bounds() noexcept { - return m_bounds; - } - - /** - * Get the bounding box of this changeset. - * - * @returns Bounding box. Can be empty. - */ - const osmium::Box& bounds() const noexcept { - return m_bounds; - } - - /// Get user name. - const char* user() const { - return reinterpret_cast(data() + sizeof(Changeset)); - } - - /// Get the list of tags. - const TagList& tags() const { - return osmium::detail::subitem_of_type(cbegin(), cend()); - } - - /** - * Set named attribute. - * - * @param attr Name of the attribute (must be one of "id", "version", - * "changeset", "timestamp", "uid", "visible") - * @param value Value of the attribute - */ - void set_attribute(const char* attr, const char* value) { - if (!strcmp(attr, "id")) { - set_id(value); - } else if (!strcmp(attr, "num_changes")) { - set_num_changes(value); - } else if (!strcmp(attr, "created_at")) { - set_created_at(osmium::Timestamp(value)); - } else if (!strcmp(attr, "closed_at")) { - set_closed_at(osmium::Timestamp(value)); - } else if (!strcmp(attr, "uid")) { - set_uid(value); - } - } - - typedef osmium::memory::CollectionIterator iterator; - typedef osmium::memory::CollectionIterator const_iterator; - - iterator begin() { - return iterator(subitems_position()); - } - - iterator end() { - return iterator(data() + padded_size()); - } - - const_iterator cbegin() const { - return const_iterator(subitems_position()); - } - - const_iterator cend() const { - return const_iterator(data() + padded_size()); - } - - const_iterator begin() const { - return cbegin(); - } - - const_iterator end() const { - return cend(); - } - - }; // class Changeset - - static_assert(sizeof(Changeset) % osmium::memory::align_bytes == 0, - "Class osmium::Changeset has wrong size to be aligned properly!"); - - /** - * Changesets are equal if their IDs are equal. - */ - inline bool operator==(const Changeset& lhs, const Changeset& rhs) { - return lhs.id() == rhs.id(); - } - - inline bool operator!=(const Changeset& lhs, const Changeset& rhs) { - return ! (lhs == rhs); - } - - /** - * Changesets can be ordered by id. - */ - inline bool operator<(const Changeset& lhs, const Changeset& rhs) { - return lhs.id() < rhs.id(); - } - - inline bool operator>(const Changeset& lhs, const Changeset& rhs) { - return rhs < lhs; - } - - inline bool operator<=(const Changeset& lhs, const Changeset& rhs) { - return ! (rhs < lhs); - } - - inline bool operator>=(const Changeset& lhs, const Changeset& rhs) { - return ! (lhs < rhs); - } - -} // namespace osmium - -#endif // OSMIUM_OSM_CHANGESET_HPP diff --git a/third_party/osmium/osm/diff_object.hpp b/third_party/osmium/osm/diff_object.hpp deleted file mode 100644 index a8f91ecd5..000000000 --- a/third_party/osmium/osm/diff_object.hpp +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef OSMIUM_OSM_DIFF_OBJECT_HPP -#define OSMIUM_OSM_DIFF_OBJECT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include - -namespace osmium { - - class Node; - class Way; - class Relation; - - class DiffObject { - - protected: - - osmium::OSMObject* m_prev; - osmium::OSMObject* m_curr; - osmium::OSMObject* m_next; - - public: - - DiffObject() noexcept : - m_prev(nullptr), - m_curr(nullptr), - m_next(nullptr) { - } - - explicit DiffObject(osmium::OSMObject& prev, osmium::OSMObject& curr, osmium::OSMObject& next) noexcept : - m_prev(&prev), - m_curr(&curr), - m_next(&next) { - } - - DiffObject(const DiffObject&) = default; - DiffObject& operator=(const DiffObject&) = default; - - DiffObject(DiffObject&&) = default; - DiffObject& operator=(DiffObject&&) = default; - - const osmium::OSMObject& prev() const noexcept { - return *m_prev; - } - - const osmium::OSMObject& curr() const noexcept { - return *m_curr; - } - - const osmium::OSMObject& next() const noexcept { - return *m_next; - } - - bool first() const noexcept { - return m_prev == m_curr; - } - - bool last() const noexcept { - return m_curr == m_next; - } - - osmium::item_type type() const noexcept { - return m_curr->type(); - } - - osmium::object_id_type id() const noexcept { - return m_curr->id(); - } - - osmium::object_version_type version() const noexcept { - return m_curr->version(); - } - - osmium::changeset_id_type changeset() const noexcept { - return m_curr->changeset(); - } - - const osmium::Timestamp start_time() const noexcept { - return m_curr->timestamp(); - } - - const osmium::Timestamp end_time() const noexcept { - return last() ? osmium::Timestamp() : m_next->timestamp(); - } - - }; // class DiffObject - - template - class DiffObjectDerived : public DiffObject { - - public: - - DiffObjectDerived(T& prev, T& curr, T& next) noexcept : - DiffObject(prev, curr, next) { - } - - DiffObjectDerived(const DiffObjectDerived&) = default; - DiffObjectDerived& operator=(const DiffObjectDerived&) = default; - - DiffObjectDerived(DiffObjectDerived&&) = default; - DiffObjectDerived& operator=(DiffObjectDerived&&) = default; - - const T& prev() const noexcept { - return *static_cast(m_prev); - } - - const T& curr() const noexcept { - return *static_cast(m_curr); - } - - const T& next() const noexcept { - return *static_cast(m_next); - } - - }; // class DiffObjectDerived - - typedef DiffObjectDerived DiffNode; - typedef DiffObjectDerived DiffWay; - typedef DiffObjectDerived DiffRelation; - -} // namespace osmium - -#endif // OSMIUM_OSM_DIFF_OBJECT_HPP diff --git a/third_party/osmium/osm/entity.hpp b/third_party/osmium/osm/entity.hpp deleted file mode 100644 index e37ed4c94..000000000 --- a/third_party/osmium/osm/entity.hpp +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef OSMIUM_OSM_ENTITY_HPP -#define OSMIUM_OSM_ENTITY_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 - -namespace osmium { - - namespace detail { - - template - inline TSubitem& subitem_of_type(TIter it, TIter end) { - for (; it != end; ++it) { - if (it->type() == TSubitem::itemtype) { - return reinterpret_cast(*it); - } - } - - // If no subitem of the TSubitem type was found, - // return a default constructed one. - static TSubitem subitem; - return subitem; - } - - } // namespace detail - - /** - * \brief OSMEntity is the abstract base class for the OSMObject and - * Changeset classes. - */ - class OSMEntity : public osmium::memory::Item { - - public: - - explicit OSMEntity(osmium::memory::item_size_type size, osmium::item_type type) : - Item(size, type) { - } - - }; // class OSMEntity - -} // namespace osmium - -#endif // OSMIUM_OSM_ENTITY_HPP diff --git a/third_party/osmium/osm/entity_bits.hpp b/third_party/osmium/osm/entity_bits.hpp deleted file mode 100644 index 2a4d96416..000000000 --- a/third_party/osmium/osm/entity_bits.hpp +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef OSMIUM_OSM_ENTITY_BITS_HPP -#define OSMIUM_OSM_ENTITY_BITS_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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. - -*/ - -namespace osmium { - - /** - * @brief Bitfield for OSM entity types. - */ - namespace osm_entity_bits { - - /** - * Describes zero or more OSM entities. - * - * Usage: - * - * @code{.cpp} - * osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::node | osmium::osm_entity_bits::way; - * - * entities |= osmium::osm_entity_bits::relation; - * - * assert(entities & osmium::osm_entity_bits::object); - * - * assert(! (entities & osmium::osm_entity_bits::changeset)); - * @endcode - */ - enum type : unsigned char { - - nothing = 0x00, - node = 0x01, - way = 0x02, - relation = 0x04, - nwr = 0x07, ///< node, way, or relation object - area = 0x08, - nwra = 0x0f, ///< node, way, relation, or area object - object = 0x0f, ///< node, way, relation, or area object - changeset = 0x10, - all = 0x1f ///< object or changeset - - }; // enum type - - inline type operator|(const type lhs, const type rhs) noexcept { - return static_cast(static_cast(lhs) | static_cast (rhs)); - } - - inline type& operator|=(type& lhs, const type rhs) noexcept { - lhs = lhs | rhs; - return lhs; - } - - inline type operator&(const type lhs, const type rhs) noexcept { - return static_cast(static_cast(lhs) & static_cast (rhs)); - } - - inline type operator~(const type value) noexcept { - return static_cast(~static_cast(value)); - } - - inline type operator&=(type& lhs, const type rhs) noexcept { - lhs = lhs & rhs; - return lhs; - } - - } // namespace osm_entity_bits - -} // namespace osmium - -#endif // OSMIUM_OSM_ENTITY_BITS_HPP diff --git a/third_party/osmium/osm/item_type.hpp b/third_party/osmium/osm/item_type.hpp deleted file mode 100644 index d277e06c8..000000000 --- a/third_party/osmium/osm/item_type.hpp +++ /dev/null @@ -1,173 +0,0 @@ -#ifndef OSMIUM_OSM_ITEM_TYPE_HPP -#define OSMIUM_OSM_ITEM_TYPE_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 // IWYU pragma: keep -#include -#include - -namespace osmium { - - enum class item_type : uint16_t { - - undefined = 0x00, - node = 0x01, - way = 0x02, - relation = 0x03, - area = 0x04, - changeset = 0x05, - tag_list = 0x11, - way_node_list = 0x12, - relation_member_list = 0x13, - relation_member_list_with_full_members = 0x23, - outer_ring = 0x40, - inner_ring = 0x41 - - }; // enum class item_type - - inline item_type char_to_item_type(const char c) noexcept { - switch (c) { - case 'X': - return item_type::undefined; - case 'n': - return item_type::node; - case 'w': - return item_type::way; - case 'r': - return item_type::relation; - case 'a': - return item_type::area; - case 'c': - return item_type::changeset; - case 'T': - return item_type::tag_list; - case 'N': - return item_type::way_node_list; - case 'M': - return item_type::relation_member_list; - case 'F': - return item_type::relation_member_list_with_full_members; - case 'O': - return item_type::outer_ring; - case 'I': - return item_type::inner_ring; - default: - return item_type::undefined; - } - } - -// avoid g++ false positive -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wreturn-type" - inline char item_type_to_char(const item_type type) noexcept { - switch (type) { - case item_type::undefined: - return 'X'; - case item_type::node: - return 'n'; - case item_type::way: - return 'w'; - case item_type::relation: - return 'r'; - case item_type::area: - return 'a'; - case item_type::changeset: - return 'c'; - case item_type::tag_list: - return 'T'; - case item_type::way_node_list: - return 'N'; - case item_type::relation_member_list: - return 'M'; - case item_type::relation_member_list_with_full_members: - return 'F'; - case item_type::outer_ring: - return 'O'; - case item_type::inner_ring: - return 'I'; - } - } - - inline const char* item_type_to_name(const item_type type) noexcept { - switch (type) { - case item_type::undefined: - return "undefined"; - case item_type::node: - return "node"; - case item_type::way: - return "way"; - case item_type::relation: - return "relation"; - case item_type::area: - return "area"; - case item_type::changeset: - return "changeset"; - case item_type::tag_list: - return "tag_list"; - case item_type::way_node_list: - return "way_node_list"; - case item_type::relation_member_list: - return "relation_member_list"; - case item_type::relation_member_list_with_full_members: - return "relation_member_list_with_full_members"; - case item_type::outer_ring: - return "outer_ring"; - case item_type::inner_ring: - return "inner_ring"; - } - } -#pragma GCC diagnostic pop - - template - inline std::basic_ostream& operator<<(std::basic_ostream& out, const item_type item_type) { - return out << item_type_to_char(item_type); - } - - /** - * This exception is thrown when a visitor encounters an unknown item type. - * Under usual circumstance this should not happen. If it does happen, it - * probably means the buffer contains different kinds of objects than were - * expected or that there is some kind of data corruption. - */ - struct unknown_type : public std::runtime_error { - - unknown_type() : - std::runtime_error("unknown item type") { - } - - }; // struct unknown_type - -} // namespace osmium - -#endif // OSMIUM_OSM_ITEM_TYPE_HPP diff --git a/third_party/osmium/osm/location.hpp b/third_party/osmium/osm/location.hpp deleted file mode 100644 index cabecd50f..000000000 --- a/third_party/osmium/osm/location.hpp +++ /dev/null @@ -1,285 +0,0 @@ -#ifndef OSMIUM_OSM_LOCATION_HPP -#define OSMIUM_OSM_LOCATION_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include - -#include - -#include -#include - -namespace osmium { - - /** - * Exception signaling an invalid location, ie a location - * outside the -180 to 180 and -90 to 90 degree range. - */ - struct invalid_location : public std::range_error { - - invalid_location(const std::string& what) : - std::range_error(what) { - } - - invalid_location(const char* what) : - std::range_error(what) { - } - - }; // struct invalid_location - - /** - * Locations define a place on earth. - * - * Locations are stored in 32 bit integers for the x and y - * coordinates, respectively. This gives you an accuracy of a few - * centimeters, good enough for OSM use. (The main OSM database - * uses the same scheme.) - * - * An undefined Location can be created by calling the constructor - * without parameters. - * - * Coordinates are never checked on whether they are inside bounds. - * Call valid() to check this. - */ - class Location { - - int32_t m_x; - int32_t m_y; - - public: - - // this value is used for a coordinate to mark it as undefined - // MSVC doesn't declare std::numeric_limits::max() as - // constexpr, so we hard code this for the time being. - // static constexpr int32_t undefined_coordinate = std::numeric_limits::max(); - static constexpr int32_t undefined_coordinate = 2147483647; - - static constexpr int coordinate_precision = 10000000; - - static int32_t double_to_fix(const double c) noexcept { - return static_cast(std::round(c * coordinate_precision)); - } - - static OSMIUM_CONSTEXPR double fix_to_double(const int32_t c) noexcept { - return static_cast(c) / coordinate_precision; - } - - /** - * Create undefined Location. - */ - explicit constexpr Location() noexcept : - m_x(undefined_coordinate), - m_y(undefined_coordinate) { - } - - /** - * Create Location with given x and y coordinates. - * Note that these coordinates are coordinate_precision - * times larger than the real coordinates. - */ - constexpr Location(const int32_t x, const int32_t y) noexcept : - m_x(x), - m_y(y) { - } - - /** - * Create Location with given x and y coordinates. - * Note that these coordinates are coordinate_precision - * times larger than the real coordinates. - */ - constexpr Location(const int64_t x, const int64_t y) noexcept : - m_x(static_cast(x)), - m_y(static_cast(y)) { - } - - /** - * Create Location with given longitude and latitude. - */ - Location(const double lon, const double lat) : - m_x(double_to_fix(lon)), - m_y(double_to_fix(lat)) { - } - - Location(const Location&) = default; - Location(Location&&) = default; - Location& operator=(const Location&) = default; - Location& operator=(Location&&) = default; - ~Location() = default; - - /** - * Check whether the coordinates of this location - * are defined. - */ - explicit constexpr operator bool() const noexcept { - return m_x != undefined_coordinate && m_y != undefined_coordinate; - } - - /** - * Check whether the coordinates are inside the - * usual bounds (-180<=lon<=180, -90<=lat<=90). - */ - constexpr bool valid() const noexcept { - return m_x >= -180 * coordinate_precision - && m_x <= 180 * coordinate_precision - && m_y >= -90 * coordinate_precision - && m_y <= 90 * coordinate_precision; - } - - constexpr int32_t x() const noexcept { - return m_x; - } - - constexpr int32_t y() const noexcept { - return m_y; - } - - Location& set_x(const int32_t x) noexcept { - m_x = x; - return *this; - } - - Location& set_y(const int32_t y) noexcept { - m_y = y; - return *this; - } - - /** - * Get longitude. - * - * @throws invalid_location if the location is invalid - */ - double lon() const { - if (!valid()) { - throw osmium::invalid_location("invalid location"); - } - return fix_to_double(m_x); - } - - /** - * Get longitude without checking the validity. - */ - double lon_without_check() const { - return fix_to_double(m_x); - } - - /** - * Get latitude. - * - * @throws invalid_location if the location is invalid - */ - double lat() const { - if (!valid()) { - throw osmium::invalid_location("invalid location"); - } - return fix_to_double(m_y); - } - - /** - * Get latitude without checking the validity. - */ - double lat_without_check() const { - return fix_to_double(m_y); - } - - Location& set_lon(double lon) noexcept { - m_x = double_to_fix(lon); - return *this; - } - - Location& set_lat(double lat) noexcept { - m_y = double_to_fix(lat); - return *this; - } - - template - T as_string(T iterator, const char separator) const { - iterator = osmium::util::double2string(iterator, lon(), 7); - *iterator++ = separator; - return osmium::util::double2string(iterator, lat(), 7); - } - - }; // class Location - - /** - * Locations are equal if both coordinates are equal. - */ - inline OSMIUM_CONSTEXPR bool operator==(const Location& lhs, const Location& rhs) noexcept { - return lhs.x() == rhs.x() && lhs.y() == rhs.y(); - } - - inline OSMIUM_CONSTEXPR bool operator!=(const Location& lhs, const Location& rhs) noexcept { - return ! (lhs == rhs); - } - - /** - * Compare two locations by comparing first the x and then - * the y coordinate. If either of the locations is - * undefined the result is undefined. - */ - inline OSMIUM_CONSTEXPR bool operator<(const Location& lhs, const Location& rhs) noexcept { - return (lhs.x() == rhs.x() && lhs.y() < rhs.y()) || lhs.x() < rhs.x(); - } - - inline OSMIUM_CONSTEXPR bool operator>(const Location& lhs, const Location& rhs) noexcept { - return rhs < lhs; - } - - inline OSMIUM_CONSTEXPR bool operator<=(const Location& lhs, const Location& rhs) noexcept { - return ! (rhs < lhs); - } - - inline OSMIUM_CONSTEXPR bool operator>=(const Location& lhs, const Location& rhs) noexcept { - return ! (lhs < rhs); - } - - /** - * Output a location to a stream. - */ - template - inline std::basic_ostream& operator<<(std::basic_ostream& out, const osmium::Location& location) { - if (location) { - out << '(' << location.lon() << ',' << location.lat() << ')'; - } else { - out << "(undefined,undefined)"; - } - return out; - } - -} // namespace osmium - -#endif // OSMIUM_OSM_LOCATION_HPP diff --git a/third_party/osmium/osm/node.hpp b/third_party/osmium/osm/node.hpp deleted file mode 100644 index 50146c568..000000000 --- a/third_party/osmium/osm/node.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef OSMIUM_OSM_NODE_HPP -#define OSMIUM_OSM_NODE_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include - -namespace osmium { - - namespace builder { - template class ObjectBuilder; - } - - class Node : public OSMObject { - - friend class osmium::builder::ObjectBuilder; - - osmium::Location m_location; - - Node() : - OSMObject(sizeof(Node), osmium::item_type::node) { - } - - public: - - static constexpr osmium::item_type itemtype = osmium::item_type::node; - - osmium::Location location() const noexcept { - return m_location; - } - - Node& set_location(const osmium::Location& location) { - m_location = location; - return *this; - } - - }; // class Node - - static_assert(sizeof(Node) % osmium::memory::align_bytes == 0, "Class osmium::Node has wrong size to be aligned properly!"); - -} // namespace osmium - -#endif // OSMIUM_OSM_NODE_HPP diff --git a/third_party/osmium/osm/node_ref.hpp b/third_party/osmium/osm/node_ref.hpp deleted file mode 100644 index ed50b9e66..000000000 --- a/third_party/osmium/osm/node_ref.hpp +++ /dev/null @@ -1,173 +0,0 @@ -#ifndef OSMIUM_OSM_NODE_REF_HPP -#define OSMIUM_OSM_NODE_REF_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -#include -#include -#include -#include - -namespace osmium { - - /** - * This reference to a node contains a node ID and a (possibly empty) - * location. - */ - class NodeRef : public osmium::memory::detail::ItemHelper { - - osmium::object_id_type m_ref; - osmium::Location m_location; - - public: - - NodeRef(const osmium::object_id_type ref=0, const osmium::Location& location=Location()) noexcept : - m_ref(ref), - m_location(location) { - } - - osmium::object_id_type ref() const noexcept { - return m_ref; - } - - osmium::unsigned_object_id_type positive_ref() const noexcept { - return static_cast(std::abs(m_ref)); - } - - /** - * Get reference to location in this NodeRef. Can be used to update it. - */ - osmium::Location& location() noexcept { - return m_location; - } - - osmium::Location location() const noexcept { - return m_location; - } - - double lon() const { - return m_location.lon(); - } - - double lat() const { - return m_location.lat(); - } - - int32_t x() const noexcept { - return m_location.x(); - } - - int32_t y() const noexcept { - return m_location.y(); - } - - NodeRef& set_ref(const osmium::object_id_type ref) noexcept { - m_ref = ref; - return *this; - } - - NodeRef& set_location(const osmium::Location& location) noexcept { - m_location = location; - return *this; - } - - }; // class NodeRef - - inline bool operator==(const NodeRef& lhs, const NodeRef& rhs) noexcept { - return lhs.ref() == rhs.ref(); - } - - inline bool operator!=(const NodeRef& lhs, const NodeRef& rhs) noexcept { - return ! (lhs == rhs); - } - - inline bool operator<(const NodeRef& lhs, const NodeRef& rhs) noexcept { - return lhs.ref() < rhs.ref(); - } - - inline bool operator>(const NodeRef& lhs, const NodeRef& rhs) noexcept { - return rhs < lhs; - } - - inline bool operator<=(const NodeRef& lhs, const NodeRef& rhs) noexcept { - return ! (rhs < lhs); - } - - inline bool operator>=(const NodeRef& lhs, const NodeRef& rhs) noexcept { - return ! (lhs < rhs); - } - - /** - * Output a NodeRef to a stream. - */ - template - inline std::basic_ostream& operator<<(std::basic_ostream& out, const osmium::NodeRef& nr) { - return out << "<" << nr.ref() << " " << nr.location() << ">"; - } - - /** - * Functor to compare NodeRefs by Location instead of id. - */ - struct location_equal { - - bool operator()(const NodeRef& lhs, const NodeRef& rhs) const noexcept { - return lhs.location() == rhs.location(); - } - - typedef NodeRef first_argument_type; - typedef NodeRef second_argument_type; - typedef bool result_type; - - }; // struct location_equal - - /** - * Functor to compare NodeRefs by Location instead of id. - */ - struct location_less { - - bool operator()(const NodeRef& lhs, const NodeRef& rhs) const noexcept { - return lhs.location() < rhs.location(); - } - - typedef NodeRef first_argument_type; - typedef NodeRef second_argument_type; - typedef bool result_type; - - }; // struct location_less - -} // namespace osmium - -#endif // OSMIUM_OSM_NODE_REF_HPP diff --git a/third_party/osmium/osm/node_ref_list.hpp b/third_party/osmium/osm/node_ref_list.hpp deleted file mode 100644 index 321c952f4..000000000 --- a/third_party/osmium/osm/node_ref_list.hpp +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef OSMIUM_OSM_NODE_REF_LIST_HPP -#define OSMIUM_OSM_NODE_REF_LIST_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include - -#include -#include -#include - -namespace osmium { - - /** - * A vector of NodeRef objects. Usually this is not instatiated directly, - * but one of its subclasses are used. - */ - template - class NodeRefList : public osmium::memory::Item { - - public: - - static constexpr osmium::item_type itemtype = TItemType; - - NodeRefList() noexcept : - osmium::memory::Item(sizeof(NodeRefList), TItemType) { - } - - bool empty() const noexcept { - return sizeof(NodeRefList) == byte_size(); - } - - size_t size() const noexcept { - assert((osmium::memory::Item::byte_size() - sizeof(NodeRefList)) % sizeof(NodeRef) == 0); - return (osmium::memory::Item::byte_size() - sizeof(NodeRefList)) / sizeof(NodeRef); - } - - const NodeRef& operator[](size_t n) const { - const NodeRef* node_ref = &*(cbegin()); - return node_ref[n]; - } - - const NodeRef& front() const { - return operator[](0); - } - - const NodeRef& back() const { - return operator[](size()-1); - } - - bool is_closed() const { - return front().ref() == back().ref(); - } - - bool ends_have_same_id() const { - return front().ref() == back().ref(); - } - - bool ends_have_same_location() const { - return front().location() == back().location(); - } - - typedef NodeRef* iterator; - typedef const NodeRef* const_iterator; - typedef std::reverse_iterator const_reverse_iterator; - - iterator begin() { - return iterator(data() + sizeof(NodeRefList)); - } - - iterator end() { - return iterator(data() + byte_size()); - } - - const_iterator cbegin() const { - return const_iterator(data() + sizeof(NodeRefList)); - } - - const_iterator cend() const { - return const_iterator(data() + byte_size()); - } - - const_iterator begin() const { - return cbegin(); - } - - const_iterator end() const { - return cend(); - } - - const_reverse_iterator crbegin() const { - return const_reverse_iterator(cend()); - } - - const_reverse_iterator crend() const { - return const_reverse_iterator(cbegin()); - } - - }; // class NodeRefList - -} // namespace osmium - -#endif // OSMIUM_OSM_NODE_REF_LIST_HPP diff --git a/third_party/osmium/osm/object.hpp b/third_party/osmium/osm/object.hpp deleted file mode 100644 index 9c4d60341..000000000 --- a/third_party/osmium/osm/object.hpp +++ /dev/null @@ -1,437 +0,0 @@ -#ifndef OSMIUM_OSM_OBJECT_HPP -#define OSMIUM_OSM_OBJECT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace osmium { - - /** - * OSMObject (Node, Way, Relation, or Area). - */ - class OSMObject : public osmium::OSMEntity { - - object_id_type m_id; - bool m_deleted : 1; - object_version_type m_version : 31; - osmium::Timestamp m_timestamp; - user_id_type m_uid; - changeset_id_type m_changeset; - - size_t sizeof_object() const noexcept { - return sizeof(OSMObject) + (type() == item_type::node ? sizeof(osmium::Location) : 0) + sizeof(string_size_type); - } - - unsigned char* user_position() noexcept { - return data() + sizeof_object() - sizeof(string_size_type); - } - - const unsigned char* user_position() const noexcept { - return data() + sizeof_object() - sizeof(string_size_type); - } - - string_size_type user_size() const noexcept { - return *reinterpret_cast(user_position()); - } - - unsigned char* subitems_position() { - return data() + osmium::memory::padded_length(sizeof_object() + user_size()); - } - - const unsigned char* subitems_position() const { - return data() + osmium::memory::padded_length(sizeof_object() + user_size()); - } - - protected: - - OSMObject(osmium::memory::item_size_type size, osmium::item_type type) : - OSMEntity(size, type), - m_id(0), - m_deleted(false), - m_version(0), - m_timestamp(), - m_uid(0), - m_changeset(0) { - } - - void set_user_size(string_size_type size) { - *reinterpret_cast(user_position()) = size; - } - - public: - - /// Get ID of this object. - object_id_type id() const noexcept { - return m_id; - } - - /// Get absolute value of the ID of this object. - unsigned_object_id_type positive_id() const noexcept { - return static_cast(std::abs(m_id)); - } - - /** - * Set ID of this object. - * - * @returns Reference to object to make calls chainable. - */ - OSMObject& set_id(object_id_type id) noexcept { - m_id = id; - return *this; - } - - /** - * Set ID of this object. - * - * @returns Reference to object to make calls chainable. - */ - OSMObject& set_id(const char* id) { - return set_id(osmium::string_to_object_id(id)); - } - - /// Is this object marked as deleted? - bool deleted() const noexcept { - return m_deleted; - } - - /// Is this object marked visible (ie not deleted)? - bool visible() const noexcept { - return !deleted(); - } - - /** - * Mark this object as deleted (or not). - * - * @returns Reference to object to make calls chainable. - */ - OSMObject& set_deleted(bool deleted) noexcept { - m_deleted = deleted; - return *this; - } - - /** - * Mark this object as visible (ie not deleted) (or not). - * - * @returns Reference to object to make calls chainable. - */ - OSMObject& set_visible(bool visible) noexcept { - m_deleted = !visible; - return *this; - } - - /** - * Mark this object as visible (ie not deleted) or deleted. - * - * @param visible Either "true" or "false" - * @returns Reference to object to make calls chainable. - */ - OSMObject& set_visible(const char* visible) { - if (!strcmp("true", visible)) { - set_visible(true); - } else if (!strcmp("false", visible)) { - set_visible(false); - } else { - throw std::invalid_argument("Unknown value for visible attribute (allowed is 'true' or 'false')"); - } - return *this; - } - - /// Get version of this object. - object_version_type version() const noexcept { - return m_version; - } - - /** - * Set object version. - * - * @returns Reference to object to make calls chainable. - */ - OSMObject& set_version(object_version_type version) noexcept { - m_version = version; - return *this; - } - - /** - * Set object version. - * - * @returns Reference to object to make calls chainable. - */ - OSMObject& set_version(const char* version) { - return set_version(string_to_object_version(version)); - } - - /// Get changeset id of this object. - changeset_id_type changeset() const noexcept { - return m_changeset; - } - - /** - * Set changeset id of this object. - * - * @returns Reference to object to make calls chainable. - */ - OSMObject& set_changeset(changeset_id_type changeset) noexcept { - m_changeset = changeset; - return *this; - } - - /** - * Set changeset id of this object. - * - * @returns Reference to object to make calls chainable. - */ - OSMObject& set_changeset(const char* changeset) { - return set_changeset(string_to_changeset_id(changeset)); - } - - /// Get user id of this object. - user_id_type uid() const noexcept { - return m_uid; - } - - /** - * Set user id of this object. - * - * @returns Reference to object to make calls chainable. - */ - OSMObject& set_uid(user_id_type uid) noexcept { - m_uid = uid; - return *this; - } - - /** - * Set user id of this object. - * Sets uid to 0 (anonymous) if the given uid is smaller than 0. - * - * @returns Reference to object to make calls chainable. - */ - OSMObject& set_uid_from_signed(signed_user_id_type uid) noexcept { - m_uid = uid < 0 ? 0 : static_cast(uid); - return *this; - } - - /** - * Set user id of this object. - * - * @returns Reference to object to make calls chainable. - */ - OSMObject& set_uid(const char* uid) { - return set_uid_from_signed(string_to_user_id(uid)); - } - - /// Is this user anonymous? - bool user_is_anonymous() const noexcept { - return m_uid == 0; - } - - /// Get timestamp when this object last changed. - osmium::Timestamp timestamp() const noexcept { - return m_timestamp; - } - - /** - * Set the timestamp when this object last changed. - * - * @param timestamp Timestamp - * @returns Reference to object to make calls chainable. - */ - OSMObject& set_timestamp(const osmium::Timestamp timestamp) noexcept { - m_timestamp = timestamp; - return *this; - } - - /// Get user name for this object. - const char* user() const noexcept { - return reinterpret_cast(data() + sizeof_object()); - } - - /// Get the list of tags for this object. - const TagList& tags() const { - return osmium::detail::subitem_of_type(cbegin(), cend()); - } - - /** - * Get tag value by key. - * - * Convenience function that will forward to same function on TagList - * object. - */ - const char* get_value_by_key(const char* key, const char* default_value = nullptr) const noexcept { - return tags().get_value_by_key(key, default_value); - } - - /** - * Set named attribute. - * - * @param attr Name of the attribute (must be one of "id", "version", "changeset", "timestamp", "uid", "visible") - * @param value Value of the attribute - */ - void set_attribute(const char* attr, const char* value) { - if (!strcmp(attr, "id")) { - set_id(value); - } else if (!strcmp(attr, "version")) { - set_version(value); - } else if (!strcmp(attr, "changeset")) { - set_changeset(value); - } else if (!strcmp(attr, "timestamp")) { - set_timestamp(osmium::Timestamp(value)); - } else if (!strcmp(attr, "uid")) { - set_uid(value); - } else if (!strcmp(attr, "visible")) { - set_visible(value); - } - } - - typedef osmium::memory::CollectionIterator iterator; - typedef osmium::memory::CollectionIterator const_iterator; - - iterator begin() { - return iterator(subitems_position()); - } - - iterator end() { - return iterator(next()); - } - - const_iterator cbegin() const { - return const_iterator(subitems_position()); - } - - const_iterator cend() const { - return const_iterator(next()); - } - - const_iterator begin() const { - return cbegin(); - } - - const_iterator end() const { - return cend(); - } - - template - using t_iterator = osmium::memory::ItemIterator; - - template - using t_const_iterator = osmium::memory::ItemIterator; - - template - t_iterator begin() { - return t_iterator(subitems_position(), next()); - } - - template - t_iterator end() { - return t_iterator(next(), next()); - } - - template - t_const_iterator cbegin() const { - return t_const_iterator(subitems_position(), next()); - } - - template - t_const_iterator cend() const { - return t_const_iterator(next(), next()); - } - - template - t_const_iterator begin() const { - return cbegin(); - } - - template - t_const_iterator end() const { - return cend(); - } - - }; // class OSMObject - - static_assert(sizeof(OSMObject) % osmium::memory::align_bytes == 0, "Class osmium::OSMObject has wrong size to be aligned properly!"); - - /** - * OSMObjects are equal if their type, id, and version are equal. - */ - inline bool operator==(const OSMObject& lhs, const OSMObject& rhs) noexcept { - return lhs.type() == rhs.type() && - lhs.id() == rhs.id() && - lhs.version() == rhs.version(); - } - - inline bool operator!=(const OSMObject& lhs, const OSMObject& rhs) noexcept { - return ! (lhs == rhs); - } - - /** - * OSMObjects can be ordered by type, id and version. - * Note that we use the absolute value of the id for a - * better ordering of objects with negative id. - */ - inline bool operator<(const OSMObject& lhs, const OSMObject& rhs) noexcept { - if (lhs.type() != rhs.type()) { - return lhs.type() < rhs.type(); - } - return (lhs.id() == rhs.id() && lhs.version() < rhs.version()) || - lhs.positive_id() < rhs.positive_id(); - } - - inline bool operator>(const OSMObject& lhs, const OSMObject& rhs) noexcept { - return rhs < lhs; - } - - inline bool operator<=(const OSMObject& lhs, const OSMObject& rhs) noexcept { - return ! (rhs < lhs); - } - - inline bool operator>=(const OSMObject& lhs, const OSMObject& rhs) noexcept { - return ! (lhs < rhs); - } - -} // namespace osmium - -#endif // OSMIUM_OSM_OBJECT_HPP diff --git a/third_party/osmium/osm/object_comparisons.hpp b/third_party/osmium/osm/object_comparisons.hpp deleted file mode 100644 index db11b0d4c..000000000 --- a/third_party/osmium/osm/object_comparisons.hpp +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef OSMIUM_OSM_OBJECT_COMPARISONS_HPP -#define OSMIUM_OSM_OBJECT_COMPARISONS_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 - -namespace osmium { - - /** - * Function object class for comparing OSM objects for equality by type, id, and version. - */ - struct object_equal_type_id_version { - - bool operator()(const osmium::OSMObject& lhs, const osmium::OSMObject& rhs) const noexcept { - return lhs == rhs; - } - - bool operator()(const osmium::OSMObject* lhs, const osmium::OSMObject* rhs) const noexcept { - return *lhs == *rhs; - } - - }; // struct object_equal_type_id_version - - /** - * Function object class for comparing OSM objects for equality by type and id, - * ignoring the version. - */ - struct object_equal_type_id { - - bool operator()(const osmium::OSMObject& lhs, const osmium::OSMObject& rhs) const noexcept { - return lhs.type() == rhs.type() && - lhs.id() == rhs.id(); - } - - bool operator()(const osmium::OSMObject* lhs, const osmium::OSMObject* rhs) const noexcept { - return operator()(*lhs, *rhs); - } - - }; // struct object_equal_type_id - - /** - * Function object class for ordering OSM objects by type, id, and version. - */ - struct object_order_type_id_version { - - bool operator()(const osmium::OSMObject& lhs, const osmium::OSMObject& rhs) const noexcept { - return lhs < rhs; - } - - bool operator()(const osmium::OSMObject* lhs, const osmium::OSMObject* rhs) const noexcept { - return *lhs < *rhs; - } - - }; // struct object_order_type_id_version - - /** - * Function object class for ordering OSM objects by type, id, and reverse version, - * ie objects are ordered by type and id, but later versions of an object are - * ordered before earlier versions of the same object. - */ - struct object_order_type_id_reverse_version { - - bool operator()(const osmium::OSMObject& lhs, const osmium::OSMObject& rhs) const noexcept { - if (lhs.type() != rhs.type()) { - return lhs.type() < rhs.type(); - } - return (lhs.id() == rhs.id() && lhs.version() > rhs.version()) || - lhs.positive_id() < rhs.positive_id(); - } - - bool operator()(const osmium::OSMObject* lhs, const osmium::OSMObject* rhs) const noexcept { - return operator()(*lhs, *rhs); - } - - }; // struct object_order_type_id_reverse_version - -} // namespace osmium - -#endif // OSMIUM_OSM_OBJECT_COMPARISONS_HPP diff --git a/third_party/osmium/osm/relation.hpp b/third_party/osmium/osm/relation.hpp deleted file mode 100644 index f5d040100..000000000 --- a/third_party/osmium/osm/relation.hpp +++ /dev/null @@ -1,189 +0,0 @@ -#ifndef OSMIUM_OSM_RELATION_HPP -#define OSMIUM_OSM_RELATION_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include - -#include // IWYU pragma: keep -#include -#include -#include -#include - -namespace osmium { - - namespace builder { - template class ObjectBuilder; - class RelationMemberListBuilder; - } - - class RelationMember : public osmium::memory::detail::ItemHelper { - - friend class osmium::builder::RelationMemberListBuilder; - - object_id_type m_ref; - item_type m_type; - uint16_t m_flags; - string_size_type m_role_size {0}; - - RelationMember(const RelationMember&) = delete; - RelationMember(RelationMember&&) = delete; - - RelationMember& operator=(const RelationMember&) = delete; - RelationMember& operator=(RelationMember&&) = delete; - - unsigned char* endpos() { - return data() + osmium::memory::padded_length(sizeof(RelationMember) + m_role_size); - } - - const unsigned char* endpos() const { - return data() + osmium::memory::padded_length(sizeof(RelationMember) + m_role_size); - } - - template - friend class osmium::memory::CollectionIterator; - - unsigned char* next() { - if (full_member()) { - return endpos() + reinterpret_cast(endpos())->byte_size(); - } else { - return endpos(); - } - } - - unsigned const char* next() const { - if (full_member()) { - return endpos() + reinterpret_cast(endpos())->byte_size(); - } else { - return endpos(); - } - } - - void set_role_size(string_size_type size) noexcept { - m_role_size = size; - } - - public: - - static constexpr item_type collection_type = item_type::relation_member_list; - - RelationMember(const object_id_type ref=0, const item_type type=item_type(), const bool full=false) noexcept : - m_ref(ref), - m_type(type), - m_flags(full ? 1 : 0) { - } - - object_id_type ref() const noexcept { - return m_ref; - } - - RelationMember& ref(object_id_type ref) noexcept { - m_ref = ref; - return *this; - } - - unsigned_object_id_type positive_ref() const noexcept { - return static_cast(std::abs(m_ref)); - } - - item_type type() const noexcept { - return m_type; - } - - bool full_member() const noexcept { - return m_flags == 1; - } - - const char* role() const noexcept { - return reinterpret_cast(data() + sizeof(RelationMember)); - } - - OSMObject& get_object() { - return *reinterpret_cast(endpos()); - } - - const OSMObject& get_object() const { - return *reinterpret_cast(endpos()); - } - - }; // class RelationMember - - class RelationMemberList : public osmium::memory::Collection { - - public: - - typedef size_t size_type; - - RelationMemberList() : - osmium::memory::Collection() { - } - - size_type size() const noexcept { - return static_cast(std::distance(begin(), end())); - } - - }; // class RelationMemberList - - static_assert(sizeof(RelationMemberList) % osmium::memory::align_bytes == 0, "Class osmium::RelationMemberList has wrong size to be aligned properly!"); - - class Relation : public OSMObject { - - friend class osmium::builder::ObjectBuilder; - - Relation() noexcept : - OSMObject(sizeof(Relation), osmium::item_type::relation) { - } - - public: - - static constexpr osmium::item_type itemtype = osmium::item_type::relation; - - RelationMemberList& members() { - return osmium::detail::subitem_of_type(begin(), end()); - } - - const RelationMemberList& members() const { - return osmium::detail::subitem_of_type(cbegin(), cend()); - } - - }; // class Relation - - static_assert(sizeof(Relation) % osmium::memory::align_bytes == 0, "Class osmium::Relation has wrong size to be aligned properly!"); - -} // namespace osmium - -#endif // OSMIUM_OSM_RELATION_HPP diff --git a/third_party/osmium/osm/segment.hpp b/third_party/osmium/osm/segment.hpp deleted file mode 100644 index 205036ec6..000000000 --- a/third_party/osmium/osm/segment.hpp +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef OSMIUM_OSM_SEGMENT_HPP -#define OSMIUM_OSM_SEGMENT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -#include -#include - -namespace osmium { - - /** - * A Segment is the directed connection between two Locations. - */ - class Segment { - - osmium::Location m_first; - osmium::Location m_second; - - public: - - explicit constexpr Segment(const osmium::Location& location1, const osmium::Location& location2) noexcept : - m_first(location1), - m_second(location2) { - } - - constexpr Segment(const Segment&) = default; - constexpr Segment(Segment&&) = default; - - Segment& operator=(const Segment&) = default; - Segment& operator=(Segment&&) = default; - - ~Segment() = default; - - /// Return first Location of Segment. - OSMIUM_CONSTEXPR osmium::Location first() const noexcept { - return m_first; - } - - /// Return second Location of Segment. - OSMIUM_CONSTEXPR osmium::Location second() const noexcept { - return m_second; - } - - protected: - - void swap_locations() { - using std::swap; - swap(m_first, m_second); - } - - }; // class Segment - - /// Segments are equal if both their locations are equal - inline OSMIUM_CONSTEXPR bool operator==(const Segment& lhs, const Segment& rhs) noexcept { - return lhs.first() == rhs.first() && lhs.second() == rhs.second(); - } - - inline OSMIUM_CONSTEXPR bool operator!=(const Segment& lhs, const Segment& rhs) noexcept { - return ! (lhs == rhs); - } - - /** - * Output Segment to a stream. - */ - template - inline std::basic_ostream& operator<<(std::basic_ostream& out, const osmium::Segment& segment) { - return out << segment.first() << "->" << segment.second(); - } - -} // namespace osmium - -#endif // OSMIUM_OSM_SEGMENT_HPP diff --git a/third_party/osmium/osm/tag.hpp b/third_party/osmium/osm/tag.hpp deleted file mode 100644 index fe80de34f..000000000 --- a/third_party/osmium/osm/tag.hpp +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef OSMIUM_OSM_TAG_HPP -#define OSMIUM_OSM_TAG_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include - -#include -#include -#include - -namespace osmium { - - class Tag : public osmium::memory::detail::ItemHelper { - - Tag(const Tag&) = delete; - Tag(Tag&&) = delete; - - Tag& operator=(const Tag&) = delete; - Tag& operator=(Tag&&) = delete; - - template - friend class osmium::memory::CollectionIterator; - - static unsigned char* after_null(unsigned char* ptr) { - return reinterpret_cast(std::strchr(reinterpret_cast(ptr), 0) + 1); - } - - static const unsigned char* after_null(const unsigned char* ptr) { - return reinterpret_cast(std::strchr(reinterpret_cast(ptr), 0) + 1); - } - - unsigned char* next() { - return after_null(after_null(data())); - } - - const unsigned char* next() const { - return after_null(after_null(data())); - } - - public: - - static constexpr item_type collection_type = item_type::tag_list; - - const char* key() const noexcept { - return reinterpret_cast(data()); - } - - const char* value() const { - return reinterpret_cast(after_null(data())); - } - - }; // class Tag - - inline bool operator==(const Tag& a, const Tag& b) { - return !std::strcmp(a.key(), b.key()) && !strcmp(a.value(), b.value()); - } - - inline bool operator<(const Tag& a, const Tag& b) { - return (!std::strcmp(a.key(), b.key()) && (std::strcmp(a.value(), b.value()) < 0)) || (std::strcmp(a.key(), b.key()) < 0); - } - - /** - * Output a Tag to a stream. - */ - template - inline std::basic_ostream& operator<<(std::basic_ostream& out, const Tag& tag) { - return out << tag.key() << '=' << tag.value(); - } - - class TagList : public osmium::memory::Collection { - - public: - - typedef size_t size_type; - - TagList() : - osmium::memory::Collection() { - } - - size_type size() const noexcept { - return static_cast(std::distance(begin(), end())); - } - - const char* get_value_by_key(const char* key, const char* default_value = nullptr) const noexcept { - auto result = std::find_if(cbegin(), cend(), [key](const Tag& tag) { - return !strcmp(tag.key(), key); - }); - if (result == cend()) { - return default_value; - } else { - return result->value(); - } - } - - const char* operator[](const char* key) const noexcept { - return get_value_by_key(key); - } - - }; // class TagList - - static_assert(sizeof(TagList) % osmium::memory::align_bytes == 0, "Class osmium::TagList has wrong size to be aligned properly!"); - -} // namespace osmium - -#endif // OSMIUM_OSM_TAG_HPP diff --git a/third_party/osmium/osm/timestamp.hpp b/third_party/osmium/osm/timestamp.hpp deleted file mode 100644 index 662b61f5b..000000000 --- a/third_party/osmium/osm/timestamp.hpp +++ /dev/null @@ -1,169 +0,0 @@ -#ifndef OSMIUM_OSM_TIMESTAMP_HPP -#define OSMIUM_OSM_TIMESTAMP_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include -#include - -#include - -namespace osmium { - - /** - * A timestamp. Internal representation is an unsigned 32bit integer - * holding seconds since epoch, so this will overflow in 2038. - */ - class Timestamp { - - // length of ISO timestamp string yyyy-mm-ddThh:mm:ssZ\0 - static constexpr int timestamp_length = 20 + 1; - - /** - * The timestamp format for OSM timestamps in strftime(3) format. - * This is the ISO-Format yyyy-mm-ddThh:mm:ssZ - */ - static const char* timestamp_format() { - static const char f[timestamp_length] = "%Y-%m-%dT%H:%M:%SZ"; - return f; - } - - uint32_t m_timestamp; - - public: - - constexpr Timestamp() noexcept : - m_timestamp(0) { - } - - // Not "explicit" so that conversions from time_t work - // like in node.timestamp(123); - constexpr Timestamp(time_t timestamp) noexcept : - m_timestamp(static_cast(timestamp)) { - } - - /** - * Construct timestamp from ISO date/time string. - * Throws std::invalid_argument, if the timestamp can not be parsed. - */ - explicit Timestamp(const char* timestamp) { -#ifndef _WIN32 - struct tm tm { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - if (strptime(timestamp, timestamp_format(), &tm) == nullptr) { - throw std::invalid_argument("can't parse timestamp"); - } - m_timestamp = static_cast(timegm(&tm)); -#else - struct tm tm; - int n = sscanf(timestamp, "%4d-%2d-%2dT%2d:%2d:%2dZ", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec); - if (n != 6) { - throw std::invalid_argument("can't parse timestamp"); - } - tm.tm_year -= 1900; - tm.tm_mon--; - tm.tm_wday = 0; - tm.tm_yday = 0; - tm.tm_isdst = 0; - m_timestamp = _mkgmtime(&tm); -#endif - } - - constexpr time_t seconds_since_epoch() const noexcept { - return static_cast(m_timestamp); - } - - constexpr operator time_t() const noexcept { - return static_cast(m_timestamp); - } - - template - void operator+=(T time_difference) noexcept { - m_timestamp += time_difference; - } - - template - void operator-=(T time_difference) noexcept { - m_timestamp -= time_difference; - } - - /** - * Return UTC Unix time as string in ISO date/time format. - */ - std::string to_iso() const { - if (m_timestamp == 0) { - return std::string(""); - } - struct tm tm; - time_t sse = seconds_since_epoch(); -#ifndef _MSC_VER - gmtime_r(&sse, &tm); -#else - gmtime_s(&tm, &sse); -#endif - - std::string s(timestamp_length, '\0'); - /* This const_cast is ok, because we know we have enough space - in the string for the format we are using (well at least until - the year will have 5 digits). And by setting the size - afterwards from the result of strftime we make sure thats set - right, too. */ - s.resize(strftime(const_cast(s.c_str()), timestamp_length, timestamp_format(), &tm)); - return s; - } - - }; // class Timestamp - - inline OSMIUM_CONSTEXPR Timestamp start_of_time() noexcept { - return Timestamp(1); - } - - inline OSMIUM_CONSTEXPR Timestamp end_of_time() noexcept { - return Timestamp(std::numeric_limits::max()); - } - - template - inline std::basic_ostream& operator<<(std::basic_ostream& out, Timestamp timestamp) { - out << timestamp.to_iso(); - return out; - } - -} // namespace osmium - -#endif // OSMIUM_OSM_TIMESTAMP_HPP diff --git a/third_party/osmium/osm/types.hpp b/third_party/osmium/osm/types.hpp deleted file mode 100644 index 532b5497c..000000000 --- a/third_party/osmium/osm/types.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef OSMIUM_OSM_TYPES_HPP -#define OSMIUM_OSM_TYPES_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -namespace osmium { - - /* - * The following typedefs are chosen so that they can represent all needed - * numbers and still be reasonably space efficient. As the OSM database - * needs 64 bit IDs for nodes, this size is used for all object IDs. - */ - typedef int64_t object_id_type; ///< Type for OSM object (node, way, or relation) IDs. - typedef uint64_t unsigned_object_id_type; ///< Type for OSM object (node, way, or relation) IDs where we only allow positive IDs. - typedef uint32_t object_version_type; ///< Type for OSM object version number. - typedef uint32_t changeset_id_type; ///< Type for OSM changeset IDs. - typedef uint32_t user_id_type; ///< Type for OSM user IDs. - typedef int32_t signed_user_id_type; ///< Type for signed OSM user IDs. - typedef uint32_t num_changes_type; ///< Type for changeset num_changes. - - /** - * Size for strings in OSM data such as user names, tag keys, roles, etc. - * In Osmium they can be up to 2^16 bytes long, but OSM usually has lower - * defined limits. - */ - typedef uint16_t string_size_type; - - inline object_id_type string_to_object_id(const char* string) { - return std::atoll(string); - } - - inline object_version_type string_to_object_version(const char* string) { - return static_cast(std::atol(string)); - } - - inline changeset_id_type string_to_changeset_id(const char* string) { - return static_cast(std::atol(string)); - } - - inline signed_user_id_type string_to_user_id(const char* string) { - return static_cast(std::atol(string)); - } - - inline num_changes_type string_to_num_changes(const char* string) { - return static_cast(std::atol(string)); - } - -} // namespace osmium - -#endif // OSMIUM_OSM_TYPES_HPP diff --git a/third_party/osmium/osm/undirected_segment.hpp b/third_party/osmium/osm/undirected_segment.hpp deleted file mode 100644 index 487e7bf32..000000000 --- a/third_party/osmium/osm/undirected_segment.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef OSMIUM_OSM_UNDIRECTED_SEGMENT_HPP -#define OSMIUM_OSM_UNDIRECTED_SEGMENT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 - -#include -#include - -namespace osmium { - - /** - * Undirected connection between two Locations. The first Location is - * always equal or "smaller" than the second Location, ie to the left - * and down. - */ - class UndirectedSegment : public Segment { - - public: - - explicit UndirectedSegment(const osmium::Location& location1, const osmium::Location& location2) : - Segment(location1, location2) { - if (location2 < location1) { - swap_locations(); - } - } - - UndirectedSegment(const UndirectedSegment&) = default; - UndirectedSegment(UndirectedSegment&&) = default; - - UndirectedSegment& operator=(const UndirectedSegment&) = default; - UndirectedSegment& operator=(UndirectedSegment&&) = default; - - ~UndirectedSegment() = default; - - }; // class UndirectedSegment - - /** - * UndirectedSegments are "smaller" if they are to the left and down of another - * segment. The first() location is checked first() and only if they have the - * same first() location the second() location is taken into account. - */ - inline bool operator<(const UndirectedSegment& lhs, const UndirectedSegment& rhs) noexcept { - return (lhs.first() == rhs.first() && lhs.second() < rhs.second()) || lhs.first() < rhs.first(); - } - - inline bool operator>(const UndirectedSegment& lhs, const UndirectedSegment& rhs) noexcept { - return rhs < lhs; - } - - inline bool operator<=(const UndirectedSegment& lhs, const UndirectedSegment& rhs) noexcept { - return ! (rhs < lhs); - } - - inline bool operator>=(const UndirectedSegment& lhs, const UndirectedSegment& rhs) noexcept { - return ! (lhs < rhs); - } - - /** - * Output UndirectedSegment to a stream. - */ - template - inline std::basic_ostream& operator<<(std::basic_ostream& out, const osmium::UndirectedSegment& segment) { - return out << segment.first() << "--" << segment.second(); - } - -} // namespace osmium - -#endif // OSMIUM_OSM_UNDIRECTED_SEGMENT_HPP diff --git a/third_party/osmium/osm/way.hpp b/third_party/osmium/osm/way.hpp deleted file mode 100644 index a30cf911f..000000000 --- a/third_party/osmium/osm/way.hpp +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef OSMIUM_OSM_WAY_HPP -#define OSMIUM_OSM_WAY_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include - -namespace osmium { - - namespace builder { - template class ObjectBuilder; - } - - /** - * List of node references (id and location) in a way. - */ - class WayNodeList : public NodeRefList { - - public: - - WayNodeList(): - NodeRefList() { - } - - }; // class WayNodeList - - static_assert(sizeof(WayNodeList) % osmium::memory::align_bytes == 0, "Class osmium::WayNodeList has wrong size to be aligned properly!"); - - class Way : public OSMObject { - - friend class osmium::builder::ObjectBuilder; - - Way() noexcept : - OSMObject(sizeof(Way), osmium::item_type::way) { - } - - public: - - WayNodeList& nodes() { - return osmium::detail::subitem_of_type(begin(), end()); - } - - const WayNodeList& nodes() const { - return osmium::detail::subitem_of_type(cbegin(), cend()); - } - - /** - * Update all nodes in a way with the ID of the given NodeRef with the - * location of the given NodeRef. - */ - void update_node_location(const NodeRef& new_node_ref) { - for (auto& node_ref : nodes()) { - if (node_ref.ref() == new_node_ref.ref()) { - node_ref.set_location(new_node_ref.location()); - } - } - } - - /** - * Do the nodes in this way form a closed ring? - */ - bool is_closed() const { - return nodes().is_closed(); - } - - bool ends_have_same_id() const { - return nodes().ends_have_same_id(); - } - - bool ends_have_same_location() const { - return nodes().ends_have_same_location(); - } - - }; // class Way - - static_assert(sizeof(Way) % osmium::memory::align_bytes == 0, "Class osmium::Way has wrong size to be aligned properly!"); - -} // namespace osmium - -#endif // OSMIUM_OSM_WAY_HPP diff --git a/third_party/osmium/relations/collector.hpp b/third_party/osmium/relations/collector.hpp deleted file mode 100644 index 60864d308..000000000 --- a/third_party/osmium/relations/collector.hpp +++ /dev/null @@ -1,544 +0,0 @@ -#ifndef OSMIUM_RELATIONS_COLLECTOR_HPP -#define OSMIUM_RELATIONS_COLLECTOR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include // IWYU pragma: keep -#include -#include -#include -#include - -#include -#include - -namespace osmium { - - class Node; - class Way; - - /** - * @brief Code related to the assembly of OSM relations - */ - namespace relations { - - /** - * The Collector class collects members of a relation. This is a generic - * base class that can be used to assemble all kinds of relations. It has numerous - * hooks you can implement in derived classes to customize its behaviour. - * - * The collector provides two handlers (HandlerPass1 and HandlerPass2) for a first - * and second pass through an input file, respectively. In the first pass all - * relations we are interested in are stored in RelationMeta objects in the - * m_relations vector. All members we are interested in are stored in MemberMeta - * objects in the m_member_meta vectors. - * The MemberMeta objects also store the information where the relations containing - * those members are to be found. - * - * Later the m_member_meta vectors are sorted according to the - * member ids so that a binary search (with std::equal_range) can be used in the second - * pass to find the parent relations for each node, way, or relation coming along. - * The member objects are stored together with their relation and once a relation - * is complete the complete_relation() method is called which you must overwrite in - * a derived class of Collector. - * - * @tparam TCollector Derived class of this class. - * - * @tparam TNodes Are we interested in member nodes? - * - * @tparam TWays Are we interested in member ways? - * - * @tparam TRelations Are we interested in member relations? - */ - template - class Collector { - - /** - * This is the handler class for the first pass of the Collector. - */ - class HandlerPass1 : public osmium::handler::Handler { - - TCollector& m_collector; - - public: - - HandlerPass1(TCollector& collector) noexcept : - m_collector(collector) { - } - - void relation(const osmium::Relation& relation) { - if (m_collector.keep_relation(relation)) { - m_collector.add_relation(relation); - } - } - - }; // class HandlerPass1 - - public: - - /** - * This is the handler class for the second pass of the Collector. - */ - class HandlerPass2 : public osmium::handler::Handler { - - TCollector& m_collector; - - /** - * This variable is initialized with the number of different - * kinds of OSM objects we are interested in. If we only need - * way members (for instance for the multipolygon collector) - * it is intialized with 1 for instance. If node and way - * members are needed, it is initialized with 2. - * - * In the after_* methods of this handler, it is decremented - * and once it reaches 0, we know we have all members available - * that we are ever going to get. - */ - int m_want_types; - - /** - * Find this object in the member vectors and add it to all - * relations that need it. - * - * @returns true if the member was added to at least one - * relation and false otherwise - */ - bool find_and_add_object(const osmium::OSMObject& object) { - auto& mmv = m_collector.member_meta(object.type()); - auto range = std::equal_range(mmv.begin(), mmv.end(), MemberMeta(object.id())); - - if (osmium::relations::count_not_removed(range.first, range.second) == 0) { - // nothing found - return false; - } - - { - m_collector.members_buffer().add_item(object); - const size_t member_offset = m_collector.members_buffer().commit(); - - for (auto it = range.first; it != range.second; ++it) { - it->set_buffer_offset(member_offset); - } - } - - for (auto it = range.first; it != range.second; ++it) { - MemberMeta& member_meta = *it; - if (member_meta.removed()) { - break; - } - assert(member_meta.member_id() == object.id()); - assert(member_meta.relation_pos() < m_collector.m_relations.size()); - RelationMeta& relation_meta = m_collector.m_relations[member_meta.relation_pos()]; -// std::cerr << " => " << member_meta.member_pos() << " < " << m_collector.get_relation(relation_meta).members().size() << " (id=" << m_collector.get_relation(relation_meta).id() << ")\n"; - assert(member_meta.member_pos() < m_collector.get_relation(relation_meta).members().size()); -// std::cerr << " add way " << member_meta.member_id() << " to rel " << m_collector.get_relation(relation_meta).id() << " at pos " << member_meta.member_pos() << "\n"; - relation_meta.got_one_member(); - if (relation_meta.has_all_members()) { - const size_t relation_offset = member_meta.relation_pos(); - m_collector.complete_relation(relation_meta); - m_collector.m_relations[relation_offset] = RelationMeta(); - m_collector.possibly_purge_removed_members(); - } - } - - // Remove MemberMetas that were marked as removed. - mmv.erase(std::remove_if(mmv.begin(), mmv.end(), [](MemberMeta& mm) { - return mm.removed(); - }), mmv.end()); - - return true; - } - - public: - - HandlerPass2(TCollector& collector) noexcept : - m_collector(collector), - m_want_types((TNodes?1:0) + (TWays?1:0) + (TRelations?1:0)) { - } - - void node(const osmium::Node& node) { - if (TNodes) { - if (! find_and_add_object(node)) { - m_collector.node_not_in_any_relation(node); - } - } - } - - void way(const osmium::Way& way) { - if (TWays) { - if (! find_and_add_object(way)) { - m_collector.way_not_in_any_relation(way); - } - } - } - - void relation(const osmium::Relation& relation) { - if (TRelations) { - if (! find_and_add_object(relation)) { - m_collector.relation_not_in_any_relation(relation); - } - } - } - - void flush() { - m_collector.flush(); - } - - }; // class HandlerPass2 - - HandlerPass2 m_handler_pass2; - - // All relations we are interested in will be kept in this buffer - osmium::memory::Buffer m_relations_buffer; - - // All members we are interested in will be kept in this buffer - osmium::memory::Buffer m_members_buffer; - - /// Vector with all relations we are interested in - std::vector m_relations; - - /** - * One vector each for nodes, ways, and relations containing all - * mappings from member ids to their relations. - */ - std::vector m_member_meta[3]; - - int m_count_complete = 0; - - typedef std::function callback_func_type; - callback_func_type m_callback; - - static constexpr size_t initial_buffer_size = 1024 * 1024; - - public: - - /** - * Create an Collector. - */ - Collector() : - m_handler_pass2(*static_cast(this)), - m_relations_buffer(initial_buffer_size, osmium::memory::Buffer::auto_grow::yes), - m_members_buffer(initial_buffer_size, osmium::memory::Buffer::auto_grow::yes), - m_relations(), - m_member_meta() { - } - - protected: - - std::vector& member_meta(const item_type type) { - return m_member_meta[static_cast(type) - 1]; - } - - callback_func_type callback() { - return m_callback; - } - - const std::vector& relations() const { - return m_relations; - } - - /** - * This method is called from the first pass handler for every - * relation in the input, to check whether it should be kept. - * - * Overwrite this method in a child class to only add relations - * you are interested in, for instance depending on the type tag. - * Storing relations takes a lot of memory, so it makes sense to - * filter this as much as possible. - */ - bool keep_relation(const osmium::Relation& /*relation*/) const { - return true; - } - - /** - * This method is called for every member of every relation that - * should be kept. It should decide if the member is interesting or - * not and return true or false to signal that. Only interesting - * members are later added to the relation. - * - * Overwrite this method in a child class. In the MultiPolygonCollector - * this is for instance used to only keep members of type way and - * ignore all others. - */ - bool keep_member(const osmium::relations::RelationMeta& /*relation_meta*/, const osmium::RelationMember& /*member*/) const { - return true; - } - - /** - * This method is called for all nodes that are not a member of - * any relation. - * - * Overwrite this method in a child class if you are interested - * in this. - */ - void node_not_in_any_relation(const osmium::Node& /*node*/) { - } - - /** - * This method is called for all ways that are not a member of - * any relation. - * - * Overwrite this method in a child class if you are interested - * in this. - */ - void way_not_in_any_relation(const osmium::Way& /*way*/) { - } - - /** - * This method is called for all relations that are not a member of - * any relation. - * - * Overwrite this method in a child class if you are interested - * in this. - */ - void relation_not_in_any_relation(const osmium::Relation& /*relation*/) { - } - - /** - * This method is called from the 2nd pass handler when all objects - * of types we are interested in have been seen. - * - * Overwrite this method in a child class if you are interested - * in this. - * - * Note that even after this call members might be missing if they - * were not in the input file! The derived class has to handle this - * case. - */ - void flush() { - } - - /** - * This removes all relations that have already been assembled - * from the m_relations vector. - */ - void clean_assembled_relations() { - m_relations.erase( - std::remove_if(m_relations.begin(), m_relations.end(), has_all_members()), - m_relations.end() - ); - } - - const osmium::Relation& get_relation(size_t offset) const { - return m_relations_buffer.get(offset); - } - - /** - * Get the relation from a relation_meta. - */ - const osmium::Relation& get_relation(const RelationMeta& relation_meta) const { - return get_relation(relation_meta.relation_offset()); - } - - osmium::OSMObject& get_member(size_t offset) const { - return m_members_buffer.get(offset); - } - - /** - * Tell the Collector that you are interested in this relation - * and want it kept until all members have been assembled and - * it is handed back to you. - * - * The relation is copied and stored in a buffer inside the - * collector. - */ - void add_relation(const osmium::Relation& relation) { - const size_t offset = m_relations_buffer.committed(); - m_relations_buffer.add_item(relation); - - RelationMeta relation_meta(offset); - - int n=0; - for (auto& member : m_relations_buffer.get(offset).members()) { - if (static_cast(this)->keep_member(relation_meta, member)) { - member_meta(member.type()).emplace_back(member.ref(), m_relations.size(), n); - relation_meta.increment_need_members(); - } else { - member.ref(0); // set member id to zero to indicate we are not interested - } - ++n; - } - - assert(offset == m_relations_buffer.committed()); - if (relation_meta.has_all_members()) { - m_relations_buffer.rollback(); - } else { - m_relations_buffer.commit(); - m_relations.push_back(std::move(relation_meta)); -// std::cerr << "added relation id=" << relation.id() << "\n"; - } - } - - /** - * Sort the vectors with the member infos so that we can do binary - * search on them. - */ - void sort_member_meta() { -/* std::cerr << "relations: " << m_relations.size() << "\n"; - std::cerr << "node members: " << m_member_meta[0].size() << "\n"; - std::cerr << "way members: " << m_member_meta[1].size() << "\n"; - std::cerr << "relation members: " << m_member_meta[2].size() << "\n";*/ - std::sort(m_member_meta[0].begin(), m_member_meta[0].end()); - std::sort(m_member_meta[1].begin(), m_member_meta[1].end()); - std::sort(m_member_meta[2].begin(), m_member_meta[2].end()); - } - - public: - - uint64_t used_memory() const { - const uint64_t nmembers = m_member_meta[0].capacity() + m_member_meta[1].capacity() + m_member_meta[2].capacity(); - const uint64_t members = nmembers * sizeof(MemberMeta); - const uint64_t relations = m_relations.capacity() * sizeof(RelationMeta); - const uint64_t relations_buffer_capacity = m_relations_buffer.capacity(); - const uint64_t members_buffer_capacity = m_members_buffer.capacity(); - - std::cout << " nR = m_relations.capacity() ........... = " << std::setw(12) << m_relations.capacity() << "\n"; - std::cout << " nMN = m_member_meta[NODE].capacity() ... = " << std::setw(12) << m_member_meta[0].capacity() << "\n"; - std::cout << " nMW = m_member_meta[WAY].capacity() .... = " << std::setw(12) << m_member_meta[1].capacity() << "\n"; - std::cout << " nMR = m_member_meta[RELATION].capacity() = " << std::setw(12) << m_member_meta[2].capacity() << "\n"; - std::cout << " nM = m_member_meta[*].capacity() ...... = " << std::setw(12) << nmembers << "\n"; - - std::cout << " sRM = sizeof(RelationMeta) ............. = " << std::setw(12) << sizeof(RelationMeta) << "\n"; - std::cout << " sMM = sizeof(MemberMeta) ............... = " << std::setw(12) << sizeof(MemberMeta) << "\n\n"; - - std::cout << " nR * sRM ............................... = " << std::setw(12) << relations << "\n"; - std::cout << " nM * sMM ............................... = " << std::setw(12) << members << "\n"; - std::cout << " relations_buffer_capacity .............. = " << std::setw(12) << relations_buffer_capacity << "\n"; - std::cout << " members_buffer_capacity ................ = " << std::setw(12) << members_buffer_capacity << "\n"; - - const uint64_t total = relations + members + relations_buffer_capacity + members_buffer_capacity; - - std::cout << " total .................................. = " << std::setw(12) << total << "\n"; - std::cout << " =======================================================\n"; - - return relations_buffer_capacity + members_buffer_capacity + relations + members; - } - - /** - * Return reference to second pass handler. - */ - HandlerPass2& handler(const callback_func_type& callback = nullptr) { - m_callback = callback; - return m_handler_pass2; - } - - osmium::memory::Buffer& members_buffer() { - return m_members_buffer; - } - - size_t get_offset(osmium::item_type type, osmium::object_id_type id) { - const auto& mmv = member_meta(type); - const auto range = std::equal_range(mmv.cbegin(), mmv.cend(), MemberMeta(id)); - assert(range.first != range.second); - return range.first->buffer_offset(); - } - - template - void read_relations(TIter begin, TIter end) { - HandlerPass1 handler(*static_cast(this)); - osmium::apply(begin, end, handler); - sort_member_meta(); - } - - template - void read_relations(TSource& source) { - read_relations(std::begin(source), std::end(source)); - source.close(); - } - - void moving_in_buffer(size_t old_offset, size_t new_offset) { - const osmium::OSMObject& object = m_members_buffer.get(old_offset); - auto& mmv = member_meta(object.type()); - auto range = std::equal_range(mmv.begin(), mmv.end(), osmium::relations::MemberMeta(object.id())); - for (auto it = range.first; it != range.second; ++it) { - assert(it->buffer_offset() == old_offset); - it->set_buffer_offset(new_offset); - } - } - - /** - * Decide whether to purge removed members and then do it. - * - * Currently the purging is done every thousand calls. - * This could probably be improved upon. - */ - void possibly_purge_removed_members() { - ++m_count_complete; - if (m_count_complete > 10000) { // XXX - const size_t size_before = m_members_buffer.committed(); - m_members_buffer.purge_removed(this); - const size_t size_after = m_members_buffer.committed(); - double percent = size_before - size_after; - percent /= size_before; - percent *= 100; - std::cerr << "PURGE (size before=" << size_before << " after=" << size_after << " purged=" << (size_before - size_after) << " / " << static_cast(percent) << "%)\n"; - m_count_complete = 0; - } - } - - /** - * Get a vector with pointers to all Relations that could not - * be completed, because members were missing in the input - * data. - * - * Note that these pointers point into memory allocated and - * owned by the Collector object. - */ - std::vector get_incomplete_relations() const { - std::vector relations; - for (const auto& relation_meta : m_relations) { - if (!relation_meta.has_all_members()) { - relations.push_back(&get_relation(relation_meta)); - } - } - return relations; - } - - }; // class Collector - - } // namespace relations - -} // namespace osmium - -#endif // OSMIUM_RELATIONS_COLLECTOR_HPP diff --git a/third_party/osmium/relations/detail/member_meta.hpp b/third_party/osmium/relations/detail/member_meta.hpp deleted file mode 100644 index 5463a1cb8..000000000 --- a/third_party/osmium/relations/detail/member_meta.hpp +++ /dev/null @@ -1,158 +0,0 @@ -#ifndef OSMIUM_RELATIONS_DETAIL_MEMBER_META_HPP -#define OSMIUM_RELATIONS_DETAIL_MEMBER_META_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include - -#include - -namespace osmium { - - namespace relations { - - /** - * Helper class for the Collector class. - * - * Stores an object ID and information where the object should be - * stored. - */ - class MemberMeta { - - /** - * Object ID of this relation member. Can be a node, way, or relation ID. - * It depends on the vector in which this object is stored which kind of - * object is referenced here. - */ - osmium::object_id_type m_member_id; - - /** - * Position of the relation this member is a part of in the - * m_relations vector. - */ - size_t m_relation_pos; - - /** - * Position of this member in the list of members of the - * relation this member is a part of. - */ - size_t m_member_pos; - - /** - * Offset in the buffer where the object is stored. - */ - size_t m_buffer_offset { 0 }; - - bool m_removed = false; - - public: - - /** - * Create new MemberMeta. The variant with zeros for relation_pos and - * 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 : - m_member_id(member_id), - m_relation_pos(relation_pos), - m_member_pos(member_pos) { - } - - osmium::object_id_type member_id() const noexcept { - return m_member_id; - } - - size_t relation_pos() const noexcept { - return m_relation_pos; - } - - size_t member_pos() const noexcept { - return m_member_pos; - } - - size_t buffer_offset() const noexcept { - return m_buffer_offset; - } - - void set_buffer_offset(size_t offset) noexcept { - m_buffer_offset = offset; - } - - bool removed() const noexcept { - return m_removed; - } - - void remove() noexcept { - m_removed = true; - } - - }; // class MemberMeta - - /** - * Compares two MemberMeta objects by only looking at the member id. - * Used to sort a vector of MemberMeta objects and to later find - * them using binary search. - */ - inline bool operator<(const MemberMeta& a, const MemberMeta& b) noexcept { - return a.member_id() < b.member_id(); - } - - template - inline std::basic_ostream& operator<<(std::basic_ostream& out, const MemberMeta& mm) { - out << "MemberMeta(member_id=" << mm.member_id() << " relation_pos=" << mm.relation_pos() << " member_pos=" << mm.member_pos() << " buffer_offset=" << mm.buffer_offset() << ")"; - return out; - } - - /** - * Count the number of MemberMeta objects in the iterator range - * that are not marked as removed. - * - * @tparam TIter Iterator that dereferences to a MemberMeta - * @param begin Begin of iterator range - * @param end End of iterator range - */ - template - inline typename std::iterator_traits::difference_type count_not_removed(TIter begin, TIter end) { - return std::count_if(begin, end, [](MemberMeta& mm) { - return !mm.removed(); - }); - } - - } // namespace relations - -} // namespace osmium - -#endif // OSMIUM_RELATIONS_DETAIL_MEMBER_META_HPP diff --git a/third_party/osmium/relations/detail/relation_meta.hpp b/third_party/osmium/relations/detail/relation_meta.hpp deleted file mode 100644 index 77ca0c130..000000000 --- a/third_party/osmium/relations/detail/relation_meta.hpp +++ /dev/null @@ -1,136 +0,0 @@ -#ifndef OSMIUM_RELATIONS_DETAIL_RELATION_META_HPP -#define OSMIUM_RELATIONS_DETAIL_RELATION_META_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include - -namespace osmium { - - namespace relations { - - /** - * Helper class for the Collector class. - * - * Stores information needed to collect all members of a relation. This - * includes the offset of the relation in a buffer plus the information - * needed to add members to this relation. - */ - class RelationMeta { - - /// The relation we are assembling. - size_t m_relation_offset; - - /** - * The number of members still needed before the relation is - * complete. This will be set to the number of members we are - * interested in and then count down for every member we find. - * When it is 0, the relation is complete. - */ - int m_need_members = 0; - - public: - - /** - * Initialize an empty RelationMeta. This is needed to zero out - * relations that have been completed. - */ - RelationMeta() noexcept : - m_relation_offset(0) { - } - - explicit RelationMeta(size_t relation_offset) noexcept : - m_relation_offset(relation_offset) { - } - - /** - * Get offset of relation in buffer. - */ - size_t relation_offset() const noexcept { - return m_relation_offset; - } - - /** - * Increment the m_need_members counter. - */ - void increment_need_members() noexcept { - ++m_need_members; - } - - /** - * This decrements the "members needed" counter. - */ - void got_one_member() { - assert(m_need_members > 0); - --m_need_members; - } - - /** - * Returns true if all members for this relation are available. - */ - bool has_all_members() const noexcept { - return m_need_members == 0; - } - - }; // class RelationMeta - - template - inline std::basic_ostream& operator<<(std::basic_ostream& out, const RelationMeta& rm) { - out << "RelationMeta(relation_offset=" << rm.relation_offset() << " has_all_members=" << rm.has_all_members() << ")"; - return out; - } - - /** - * Function object to check if a relation is complete. - */ - struct has_all_members { - - typedef RelationMeta& argument_type; - typedef bool result_type; - - /** - * @returns true if this relation is complete, false otherwise. - */ - bool operator()(RelationMeta& relation_info) const { - return relation_info.has_all_members(); - } - - }; // struct has_all_members - - } // namespace relations - -} // namespace osmium - -#endif // OSMIUM_RELATIONS_DETAIL_RELATION_META_HPP diff --git a/third_party/osmium/tags/filter.hpp b/third_party/osmium/tags/filter.hpp deleted file mode 100644 index 0a0fd3b56..000000000 --- a/third_party/osmium/tags/filter.hpp +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef OSMIUM_TAGS_FILTER_HPP -#define OSMIUM_TAGS_FILTER_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include - -#include - -#include -#include - -namespace osmium { - - namespace tags { - - template - struct match_key { - bool operator()(const TKey& rule_key, const char* tag_key) { - return rule_key == tag_key; - } - }; // struct match_key - - struct match_key_prefix { - bool operator()(const std::string& rule_key, const char* tag_key) { - return rule_key.compare(0, std::string::npos, tag_key, 0, rule_key.size()) == 0; - } - }; // struct match_key_prefix - - template - struct match_value { - bool operator()(const TValue& rule_value, const char* tag_value) { - return rule_value == tag_value; - } - }; // struct match_value - - template <> - struct match_value { - bool operator()(const bool, const char*) { - return true; - } - }; // struct match_value - - template , class TValueComp=match_value> - class Filter { - - typedef TKey key_type; - typedef typename std::conditional::value, bool, TValue>::type value_type; - - struct Rule { - key_type key; - value_type value; - bool ignore_value; - bool result; - - explicit Rule(bool r, bool ignore, const key_type& k, const value_type& v) : - key(k), - value(v), - ignore_value(ignore), - result(r) { - } - - explicit Rule(bool r, bool ignore, const key_type& k) : - key(k), - value(), - ignore_value(ignore), - result(r) { - } - - }; // struct Rule - - std::vector m_rules; - bool m_default_result; - - public: - - typedef Filter filter_type; - typedef const osmium::Tag& argument_type; - typedef bool result_type; - typedef boost::filter_iterator iterator; - - explicit Filter(bool default_result = false) : - m_default_result(default_result) { - } - - template ::value, int>::type = 0> - Filter& add(bool result, const key_type& key, const value_type& value) { - m_rules.emplace_back(result, false, key, value); - return *this; - } - - Filter& add(bool result, const key_type& key) { - m_rules.emplace_back(result, true, key); - return *this; - } - - bool operator()(const osmium::Tag& tag) const { - for (const Rule& rule : m_rules) { - if (TKeyComp()(rule.key, tag.key()) && (rule.ignore_value || TValueComp()(rule.value, tag.value()))) { - return rule.result; - } - } - return m_default_result; - } - - }; // class Filter - - typedef Filter KeyValueFilter; - typedef Filter KeyFilter; - typedef Filter KeyPrefixFilter; - - } // namespace tags - -} // namespace osmium - -#endif // OSMIUM_TAGS_FILTER_HPP diff --git a/third_party/osmium/tags/regex_filter.hpp b/third_party/osmium/tags/regex_filter.hpp deleted file mode 100644 index ae2703a30..000000000 --- a/third_party/osmium/tags/regex_filter.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef OSMIUM_TAGS_REGEX_FILTER_HPP -#define OSMIUM_TAGS_REGEX_FILTER_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2014 Jochen Topf 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 -#include - -#include - -namespace osmium { - - namespace tags { - - template <> - struct match_value { - bool operator()(const std::regex& rule_value, const char* tag_value) { - return std::regex_match(tag_value, rule_value); - } - }; // struct match_value - - typedef Filter RegexFilter; - - } // namespace tags - -} // namespace osmium - -#endif // OSMIUM_TAGS_REGEX_FILTER_HPP diff --git a/third_party/osmium/tags/taglist.hpp b/third_party/osmium/tags/taglist.hpp deleted file mode 100644 index 41ef993a0..000000000 --- a/third_party/osmium/tags/taglist.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef OSMIUM_TAGS_TAGLIST_HPP -#define OSMIUM_TAGS_TAGLIST_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2014 Jochen Topf 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 -#include - -#include - -namespace osmium { - - /** - * @brief Code related to working with OSM tags - */ - namespace tags { - - template - inline bool match_any_of(const osmium::TagList& tag_list, TFilter&& filter) { - return std::any_of(tag_list.begin(), tag_list.end(), std::forward(filter)); - } - - template - inline bool match_all_of(const osmium::TagList& tag_list, TFilter&& filter) { - return std::all_of(tag_list.begin(), tag_list.end(), std::forward(filter)); - } - - template - inline bool match_none_of(const osmium::TagList& tag_list, TFilter&& filter) { - return std::none_of(tag_list.begin(), tag_list.end(), std::forward(filter)); - } - - } // namespace tags - -} // namespace osmium - -#endif // OSMIUM_TAGS_TAGLIST_HPP diff --git a/third_party/osmium/thread/checked_task.hpp b/third_party/osmium/thread/checked_task.hpp deleted file mode 100644 index 75c664c99..000000000 --- a/third_party/osmium/thread/checked_task.hpp +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef OSMIUM_THREAD_CHECKED_TASK_HPP -#define OSMIUM_THREAD_CHECKED_TASK_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include - -namespace osmium { - - namespace thread { - - template - class CheckedTask { - - std::thread m_thread; - std::future m_future; - - public: - - template - explicit CheckedTask(TArgs&&... args) { - std::packaged_task pack_task(T(std::forward(args)...)); - m_future = pack_task.get_future(); - m_thread = std::thread(std::move(pack_task)); - } - - ~CheckedTask() { - // Make sure task is done. - if (m_thread.joinable()) { - m_thread.join(); - } - } - - CheckedTask(const CheckedTask&) = delete; - CheckedTask& operator=(const CheckedTask&) = delete; - - /** - * Check task for exceptions. - * - * If an exception happened in the task, re-throw it in this - * thread. This will not do anything if there was no exception. - */ - void check_for_exception() { - if (m_future.valid() && m_future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) { - m_future.get(); - } - } - - /** - * Close the task. This will raise in this thread any exception the - * task generated in the other thread. - */ - void close() { - // If an exception happened in the task, re-throw - // it in this thread. This will block if the task - // isn't finished. - if (m_future.valid()) { - m_future.get(); - } - - // Make sure task is done. - if (m_thread.joinable()) { - m_thread.join(); - } - } - - }; // class CheckedTask - - } // namespace thread - -} // namespace osmium - -#endif // OSMIUM_THREAD_CHECKED_TASK_HPP diff --git a/third_party/osmium/thread/function_wrapper.hpp b/third_party/osmium/thread/function_wrapper.hpp deleted file mode 100644 index dbb47ff87..000000000 --- a/third_party/osmium/thread/function_wrapper.hpp +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef OSMIUM_THREAD_FUNCTION_WRAPPER_HPP -#define OSMIUM_THREAD_FUNCTION_WRAPPER_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -namespace osmium { - - namespace thread { - - /** - * This function wrapper can collect move-only functions unlike - * std::function which needs copyable functions. - * Taken from the book "C++ Concurrency in Action". - */ - class function_wrapper { - - struct impl_base { - - virtual ~impl_base() = default; - virtual void call() = 0; - - }; // struct impl_base - - std::unique_ptr impl; - - template - struct impl_type : impl_base { - F m_functor; - - impl_type(F&& functor) : - m_functor(std::move(functor)) { - } - - void call() override { - m_functor(); - } - }; // struct impl_type - - public: - - // Constructor must not be "explicit" for wrapper - // to work seemlessly. - template - function_wrapper(F&& f) : - impl(new impl_type(std::move(f))) { - } - - void operator()() { - impl->call(); - } - - function_wrapper() = default; - - function_wrapper(function_wrapper&& other) : - impl(std::move(other.impl)) { - } - - function_wrapper& operator=(function_wrapper&& other) { - impl = std::move(other.impl); - return *this; - } - - function_wrapper(const function_wrapper&) = delete; - function_wrapper(function_wrapper&) = delete; - function_wrapper& operator=(const function_wrapper&) = delete; - - explicit operator bool() const { - return static_cast(impl); - } - - }; // class function_wrapper - - } // namespace thread - -} // namespace osmium - -#endif // OSMIUM_THREAD_FUNCTION_WRAPPER_HPP diff --git a/third_party/osmium/thread/name.hpp b/third_party/osmium/thread/name.hpp deleted file mode 100644 index 20ec5c4b9..000000000 --- a/third_party/osmium/thread/name.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef OSMIUM_THREAD_NAME_HPP -#define OSMIUM_THREAD_NAME_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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. - -*/ - -#ifdef __linux__ -# include -#endif - -namespace osmium { - - namespace thread { - - /** - * Set name of current thread for debugging. This only works on Linux. - */ -#ifdef __linux__ - inline void set_thread_name(const char* name) { - prctl(PR_SET_NAME, name, 0, 0, 0); - } -#else - inline void set_thread_name(const char*) { - // intentionally left blank - } -#endif - - } // namespace thread - -} // namespace osmium - -#endif // OSMIUM_THREAD_NAME_HPP diff --git a/third_party/osmium/thread/pool.hpp b/third_party/osmium/thread/pool.hpp deleted file mode 100644 index 702be66e0..000000000 --- a/third_party/osmium/thread/pool.hpp +++ /dev/null @@ -1,180 +0,0 @@ -#ifndef OSMIUM_THREAD_POOL_HPP -#define OSMIUM_THREAD_POOL_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace osmium { - - /** - * @brief Threading-related low-level code - */ - namespace thread { - - /** - * Thread pool. - */ - class Pool { - - /** - * This class makes sure all pool threads will be joined when - * the pool is destructed. - */ - class thread_joiner { - - std::vector& m_threads; - - public: - - explicit thread_joiner(std::vector& threads) : - m_threads(threads) { - } - - ~thread_joiner() { - for (auto& thread : m_threads) { - if (thread.joinable()) { - thread.join(); - } - } - } - - }; // class thread_joiner - - std::atomic m_done; - osmium::thread::Queue m_work_queue; - std::vector m_threads; - thread_joiner m_joiner; - int m_num_threads; - - void worker_thread() { - osmium::thread::set_thread_name("_osmium_worker"); - while (!m_done) { - function_wrapper task; - m_work_queue.wait_and_pop_with_timeout(task); - if (task) { - task(); - } - } - } - - /** - * Create thread pool with the given number of threads. If - * num_threads is 0, the number of threads is read from - * the environment variable OSMIUM_POOL_THREADS. The default - * value in that case is -2. - * - * If the number of threads is a negative number, it will be - * set to the actual number of cores on the system plus the - * given number, ie it will leave a number of cores unused. - * - * In all cases the minimum number of threads in the pool is 1. - */ - explicit Pool(int num_threads, size_t max_queue_size) : - m_done(false), - m_work_queue(max_queue_size, "work"), - m_threads(), - m_joiner(m_threads), - m_num_threads(num_threads) { - - if (m_num_threads == 0) { - m_num_threads = osmium::config::get_pool_threads(); - } - - if (m_num_threads <= 0) { - m_num_threads = std::max(1, static_cast(std::thread::hardware_concurrency()) + m_num_threads); - } - - try { - for (int i=0; i < m_num_threads; ++i) { - m_threads.push_back(std::thread(&Pool::worker_thread, this)); - } - } catch (...) { - m_done = true; - throw; - } - } - - public: - - static constexpr int default_num_threads = 0; - static constexpr size_t max_work_queue_size = 10; - - static Pool& instance() { - static Pool pool(default_num_threads, max_work_queue_size); - return pool; - } - - ~Pool() { - m_done = true; - } - - size_t queue_size() const { - return m_work_queue.size(); - } - - bool queue_empty() const { - return m_work_queue.empty(); - } - - template - std::future::type> submit(TFunction f) { - - typedef typename std::result_of::type result_type; - - std::packaged_task task(std::move(f)); - std::future future_result(task.get_future()); - m_work_queue.push(std::move(task)); - - return future_result; - } - - }; // class Pool - - } // namespace thread - -} // namespace osmium - -#endif // OSMIUM_THREAD_POOL_HPP diff --git a/third_party/osmium/thread/queue.hpp b/third_party/osmium/thread/queue.hpp deleted file mode 100644 index b01dd39bf..000000000 --- a/third_party/osmium/thread/queue.hpp +++ /dev/null @@ -1,178 +0,0 @@ -#ifndef OSMIUM_THREAD_QUEUE_HPP -#define OSMIUM_THREAD_QUEUE_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include -#include -#include -#include -#include - -namespace osmium { - - namespace thread { - - constexpr std::chrono::milliseconds full_queue_sleep_duration { 10 }; // XXX - - /** - * A thread-safe queue. - */ - template - class Queue { - - /// Maximum size of this queue. If the queue is full pushing to - /// the queue will block. - const size_t m_max_size; - - /// Name of this queue (for debugging only). - const std::string m_name; - - mutable std::mutex m_mutex; - - std::queue m_queue; - - /// Used to signal readers when data is available in the queue. - std::condition_variable m_data_available; - -#ifdef OSMIUM_DEBUG_QUEUE_SIZE - /// The largest size the queue has been so far. - size_t m_largest_size; - - /// The number of times the queue was full and a thread pushing - /// to the queue was blocked. - std::atomic m_full_counter; -#endif - - public: - - /** - * Construct a multithreaded queue. - * - * @param max_size Maximum number of elements in the queue. Set to - * 0 for an unlimited size. - * @param name Optional name for this queue. (Used for debugging.) - */ - Queue(size_t max_size = 0, const std::string& name = "") : - m_max_size(max_size), - m_name(name), - m_mutex(), - m_queue(), - m_data_available() -#ifdef OSMIUM_DEBUG_QUEUE_SIZE - , - m_largest_size(0), - m_full_counter(0) -#endif - { - } - - ~Queue() { -#ifdef OSMIUM_DEBUG_QUEUE_SIZE - std::cerr << "queue '" << m_name << "' with max_size=" << m_max_size << " had largest size " << m_largest_size << " and was full " << m_full_counter << " times\n"; -#endif - } - - /** - * Push an element onto the queue. If the queue has a max size, this - * call will block if the queue is full. - */ - void push(T value) { - if (m_max_size) { - while (size() >= m_max_size) { - std::this_thread::sleep_for(full_queue_sleep_duration); -#ifdef OSMIUM_DEBUG_QUEUE_SIZE - ++m_full_counter; -#endif - } - } - std::lock_guard lock(m_mutex); - m_queue.push(std::move(value)); -#ifdef OSMIUM_DEBUG_QUEUE_SIZE - if (m_largest_size < m_queue.size()) { - m_largest_size = m_queue.size(); - } -#endif - m_data_available.notify_one(); - } - - void wait_and_pop(T& value) { - std::unique_lock lock(m_mutex); - m_data_available.wait(lock, [this] { - return !m_queue.empty(); - }); - value=std::move(m_queue.front()); - m_queue.pop(); - } - - void wait_and_pop_with_timeout(T& value) { - std::unique_lock lock(m_mutex); - if (!m_data_available.wait_for(lock, std::chrono::seconds(1), [this] { - return !m_queue.empty(); - })) { - return; - } - value=std::move(m_queue.front()); - m_queue.pop(); - } - - bool try_pop(T& value) { - std::lock_guard lock(m_mutex); - if (m_queue.empty()) { - return false; - } - value=std::move(m_queue.front()); - m_queue.pop(); - return true; - } - - bool empty() const { - std::lock_guard lock(m_mutex); - return m_queue.empty(); - } - - size_t size() const { - std::lock_guard lock(m_mutex); - return m_queue.size(); - } - - }; // class Queue - - } // namespace thread - -} // namespace osmium - -#endif // OSMIUM_THREAD_QUEUE_HPP diff --git a/third_party/osmium/thread/sorted_queue.hpp b/third_party/osmium/thread/sorted_queue.hpp deleted file mode 100644 index e33dfe696..000000000 --- a/third_party/osmium/thread/sorted_queue.hpp +++ /dev/null @@ -1,159 +0,0 @@ -#ifndef OSMIUM_THREAD_SORTED_QUEUE_HPP -#define OSMIUM_THREAD_SORTED_QUEUE_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include - -namespace osmium { - - namespace thread { - - /** - * This implements a sorted queue. It is a bit like a priority - * queue. We have n worker threads pushing items into the queue - * and one thread pulling them out again "in order". The order - * is defined by the monotonically increasing "num" parameter - * to the push() method. The wait_and_pop() and try_pop() methods - * will only give out the next numbered item. This way several - * workers can work in their own time on different pieces of - * some incoming data, but it all gets serialized properly again - * after the workers have done their work. - */ - template - class SortedQueue { - - typedef typename std::deque::size_type size_type; - - mutable std::mutex m_mutex; - std::deque m_queue; - std::condition_variable m_data_available; - - size_type m_offset; - - // this method expects that we already have the lock - bool empty_intern() const { - return m_queue.front() == T(); - } - - public: - - SortedQueue() : - m_mutex(), - m_queue(1), - m_data_available(), - m_offset(0) { - } - - /** - * Push an item into the queue. - * - * @param value The item to push into the queue. - * @param num Number to describe ordering for the items. - * It must increase monotonically. - */ - void push(T value, size_type num) { - std::lock_guard lock(m_mutex); - - num -= m_offset; - if (m_queue.size() <= num + 1) { - m_queue.resize(num + 2); - } - m_queue[num] = std::move(value); - - m_data_available.notify_one(); - } - - /** - * Wait until the next item becomes available and make it - * available through value. - */ - void wait_and_pop(T& value) { - std::unique_lock lock(m_mutex); - - m_data_available.wait(lock, [this] { - return !empty_intern(); - }); - value=std::move(m_queue.front()); - m_queue.pop_front(); - ++m_offset; - } - - /** - * Get next item if it is available and return true. Or - * return false otherwise. - */ - bool try_pop(T& value) { - std::lock_guard lock(m_mutex); - - if (empty_intern()) { - return false; - } - value=std::move(m_queue.front()); - m_queue.pop_front(); - ++m_offset; - return true; - } - - /** - * The queue is empty. This means try_pop() would fail if called. - * It does not mean that there is nothing on the queue. Because - * the queue is sorted, it could mean that the next item in the - * queue is not available, but other items are. - */ - bool empty() const { - std::lock_guard lock(m_mutex); - - return empty_intern(); - } - - /** - * Returns the number of items in the queue, regardless of whether - * they can be accessed. If this is =0 it - * implies empty()==true, but not the other way around. - */ - size_t size() const { - std::lock_guard lock(m_mutex); - return m_queue.size(); - } - - }; // class SortedQueue - - } // namespace thread - -} // namespace osmium - -#endif // OSMIUM_THREAD_SORTED_QUEUE_HPP diff --git a/third_party/osmium/thread/util.hpp b/third_party/osmium/thread/util.hpp deleted file mode 100644 index 286ea5e06..000000000 --- a/third_party/osmium/thread/util.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef OSMIUM_THREAD_UTIL_HPP -#define OSMIUM_THREAD_UTIL_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -#ifdef __linux__ -# include -#endif - -namespace osmium { - - namespace thread { - - /** - * Check if the future resulted in an exception. This will re-throw - * the exception stored in the future if there was one. Otherwise it - * will just return. - */ - template - inline void check_for_exception(std::future& future) { - if (future.valid() && future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) { - future.get(); - } - } - - /** - * Wait until the given future becomes ready. Will block if the future - * is not ready. Can be called more than once unless future.get(). - */ - template - inline void wait_until_done(std::future& future) { - if (future.valid()) { - future.get(); - } - } - - /** - * Set name of current thread for debugging. This only works on Linux. - */ -#ifdef __linux__ - inline void set_thread_name(const char* name) { - prctl(PR_SET_NAME, name, 0, 0, 0); - } -#else - inline void set_thread_name(const char*) { - // intentionally left blank - } -#endif - - } // namespace thread - -} // namespace osmium - -#endif // OSMIUM_THREAD_UTIL_HPP diff --git a/third_party/osmium/util/cast.hpp b/third_party/osmium/util/cast.hpp deleted file mode 100644 index 750326706..000000000 --- a/third_party/osmium/util/cast.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef OSMIUM_UTIL_CAST_HPP -#define OSMIUM_UTIL_CAST_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include - -namespace osmium { - - template ::value && std::is_integral::value && std::is_signed::value && std::is_signed::value, int>::type = 0> - inline T static_cast_with_assert(const F value) { - static_assert(sizeof(T) < sizeof(F), "unnecessary static_cast_with_assert when casting into type of equal or larger size"); - assert(value >= std::numeric_limits::min() && value <= std::numeric_limits::max()); - return static_cast(value); - } - - template ::value && std::is_integral::value && std::is_unsigned::value && std::is_signed::value, int>::type = 0> - inline T static_cast_with_assert(const F value) { - static_assert(sizeof(T) <= sizeof(F), "unnecessary static_cast_with_assert when casting into type of larger size"); - assert(value >= 0 && static_cast::type>(value) <= std::numeric_limits::max()); - return static_cast(value); - } - - template ::value && std::is_integral::value && std::is_unsigned::value && std::is_unsigned::value, int>::type = 0> - inline T static_cast_with_assert(const F value) { - static_assert(sizeof(T) < sizeof(F), "unnecessary static_cast_with_assert when casting into type of equal or larger size"); - assert(value <= std::numeric_limits::max()); - return static_cast(value); - } - - template ::value && std::is_integral::value && std::is_signed::value && std::is_unsigned::value, int>::type = 0> - inline T static_cast_with_assert(const F value) { - static_assert(sizeof(T) <= sizeof(F), "unnecessary static_cast_with_assert when casting into type of larger size"); - assert(value <= std::numeric_limits::max()); - return static_cast(value); - } - -} // namespace osmium - -#endif // OSMIUM_UTIL_CAST_HPP diff --git a/third_party/osmium/util/compatibility.hpp b/third_party/osmium/util/compatibility.hpp deleted file mode 100644 index 48a6db017..000000000 --- a/third_party/osmium/util/compatibility.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef OSMIUM_UTIL_COMPATIBILITY_HPP -#define OSMIUM_UTIL_COMPATIBILITY_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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. - -*/ - -// Workarounds for MSVC which doesn't support -// * constexpr in all cases yet -// * [[noreturn]] -#ifdef _MSC_VER -# define OSMIUM_CONSTEXPR -# define OSMIUM_NORETURN __declspec(noreturn) -#else -# define OSMIUM_CONSTEXPR constexpr -# define OSMIUM_NORETURN [[noreturn]] -#endif - -#endif // OSMIUM_UTIL_COMPATIBILITY_HPP diff --git a/third_party/osmium/util/config.hpp b/third_party/osmium/util/config.hpp deleted file mode 100644 index 6c86d686f..000000000 --- a/third_party/osmium/util/config.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef OSMIUM_UTIL_CONFIG_HPP -#define OSMIUM_UTIL_CONFIG_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include - -#ifdef _MSC_VER -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#endif - -namespace osmium { - - namespace config { - - inline int get_pool_threads() { - const char* env = getenv("OSMIUM_POOL_THREADS"); - if (env) { - return std::atoi(env); - } - return -2; - } - - inline bool use_pool_threads_for_pbf_parsing() { - const char* env = getenv("OSMIUM_USE_POOL_THREADS_FOR_PBF_PARSING"); - if (env) { - if (!strcasecmp(env, "off") || - !strcasecmp(env, "false") || - !strcasecmp(env, "no") || - !strcasecmp(env, "0")) { - return false; - } - } - return true; - } - - } // namespace config - -} // namespace osmium - -#endif // OSMIUM_UTIL_CONFIG_HPP diff --git a/third_party/osmium/util/double.hpp b/third_party/osmium/util/double.hpp deleted file mode 100644 index 91f4ac7f1..000000000 --- a/third_party/osmium/util/double.hpp +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef OSMIUM_UTIL_DOUBLE_HPP -#define OSMIUM_UTIL_DOUBLE_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include - -namespace osmium { - - namespace util { - - constexpr int max_double_length = 20; // should fit any double - - /** - * Write double to iterator, removing superfluous '0' characters at - * the end. The decimal dot will also be removed if necessary. - * - * @tparam T iterator type - * @param iterator output iterator - * @param value the value that should be written - * @param precision max number of digits after the decimal point (must be <= 17) - */ - template - inline T double2string(T iterator, double value, int precision) { - assert(precision <= 17); - - char buffer[max_double_length]; - -#ifndef _MSC_VER - int len = snprintf(buffer, max_double_length, "%.*f", precision, value); -#else - int len = _snprintf(buffer, max_double_length, "%.*f", precision, value); -#endif - assert(len > 0 && len < max_double_length); - - while (buffer[len-1] == '0') --len; - if (buffer[len-1] == '.') --len; - - return std::copy_n(buffer, len, iterator); - } - - /** - * Write double to string, removing superfluous '0' characters at - * the end. The decimal dot will also be removed if necessary. - * - * @param out string - * @param value the value that should be written - * @param precision max number of digits after the decimal point - */ - inline void double2string(std::string& out, double value, int precision) { - double2string(std::back_inserter(out), value, precision); - } - - } // namespace util - -} // namespace osmium - -#endif // OSMIUM_UTIL_DOUBLE_HPP diff --git a/third_party/osmium/util/options.hpp b/third_party/osmium/util/options.hpp deleted file mode 100644 index fc74980d1..000000000 --- a/third_party/osmium/util/options.hpp +++ /dev/null @@ -1,155 +0,0 @@ -#ifndef OSMIUM_UTIL_OPTIONS_HPP -#define OSMIUM_UTIL_OPTIONS_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 -#include -#include -#include - -namespace osmium { - - namespace util { - - /** - * Stores key=value type options. This class can be used stand-alone or - * as a base class. Options are stored and retrieved by key using the - * different set() and get() methods. - * - * You can iterate over all set options. Dereferencing an iterator - * yields a std::pair of the key and value strings. - */ - class Options { - - typedef std::map option_map; - option_map m_options; - - public: - - typedef option_map::iterator iterator; - typedef option_map::const_iterator const_iterator; - typedef option_map::value_type value_type; - - Options() = default; - - explicit Options(const std::initializer_list& values) : - m_options(values) { - } - - Options(const Options&) = default; - Options& operator=(const Options&) = default; - - Options(Options&&) = default; - Options& operator=(Options&&) = default; - - ~Options() = default; - - void set(const std::string& key, const std::string& value) { - m_options[key] = value; - } - - void set(const std::string& key, const char* value) { - m_options[key] = value; - } - - void set(const std::string& key, bool value) { - m_options[key] = value ? "true" : "false"; - } - - void set(std::string data) { - size_t pos = data.find_first_of('='); - if (pos == std::string::npos) { - m_options[data] = "true"; - } else { - std::string value = data.substr(pos+1); - data.erase(pos); - set(data, value); - } - } - - /** - * Get value of "key" option. If not set the default_value (or - * empty string) is returned. - */ - std::string get(const std::string& key, const std::string& default_value="") const noexcept { - auto it = m_options.find(key); - if (it == m_options.end()) { - return default_value; - } - return it->second; - } - - /** - * Is this option set to a true value ("true" or "yes")? - */ - bool is_true(const std::string& key) const noexcept { - std::string value = get(key); - return (value == "true" || value == "yes"); - } - - size_t size() const noexcept { - return m_options.size(); - } - - iterator begin() noexcept { - return m_options.begin(); - } - - iterator end() noexcept { - return m_options.end(); - } - - const_iterator begin() const noexcept { - return m_options.cbegin(); - } - - const_iterator end() const noexcept { - return m_options.cend(); - } - - const_iterator cbegin() const noexcept { - return m_options.cbegin(); - } - - const_iterator cend() const noexcept { - return m_options.cend(); - } - - }; // class Options - - } // namespace util - -} // namespace osmium - -#endif // OSMIUM_UTIL_OPTIONS_HPP diff --git a/third_party/osmium/util/verbose_output.hpp b/third_party/osmium/util/verbose_output.hpp deleted file mode 100644 index 8709441af..000000000 --- a/third_party/osmium/util/verbose_output.hpp +++ /dev/null @@ -1,139 +0,0 @@ -#ifndef OSMIUM_UTIL_VERBOSE_OUTPUT_HPP -#define OSMIUM_UTIL_VERBOSE_OUTPUT_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 - -#include -#include -#include - -namespace osmium { - - /** - * @brief Helpful utility classes and functions not strictly OSM related - */ - namespace util { - - /** - * Osmium programs often run for a long time because of the amount of - * OSM data processed. This class helps with keeping the user up to - * date by offering an easy way for programs to optionally output - * verbose information about what's going on. - * - * Use an object of this class instead of std::cerr as an output - * stream. Nothing is actually written if the object is not set to - * verbose mode. If it is set to verbose mode, each line is prepended - * with the running time, ie the time since the VerboseOutput object - * was created. - */ - class VerboseOutput { - - /// all time output will be relative to this start time - time_t m_start; - - /// is verbose mode enabled? - bool m_verbose; - - /// a newline was written, start next output with runtime - bool m_newline; - - /** - * If we remember that a newline was written as the last thing - * write out the time elapsed and reset the newline flag. - */ - void start_line() { - if (m_newline) { - time_t elapsed = runtime(); - - char old_fill = std::cerr.fill(); - std::cerr << '[' << std::setw(2) << (elapsed / 60) << ':' << std::setw(2) << std::setfill('0') << (elapsed % 60) << "] "; - std::cerr.fill(old_fill); - - m_newline = false; - } - } - - public: - - explicit VerboseOutput(bool verbose=false) noexcept : - m_start(time(NULL)), - m_verbose(verbose), - m_newline(true) { - } - - ~VerboseOutput() = default; - - VerboseOutput(const VerboseOutput&) = default; - VerboseOutput& operator=(const VerboseOutput&) = default; - VerboseOutput(VerboseOutput&&) = default; - VerboseOutput& operator=(VerboseOutput&&) = default; - - time_t runtime() const noexcept { - return time(NULL) - m_start; - } - - /// Get "verbose" setting. - bool verbose() const noexcept { - return m_verbose; - } - - /// Set "verbose" setting. - void verbose(bool verbose) noexcept { - m_verbose = verbose; - } - - template - friend VerboseOutput& operator<<(VerboseOutput& verbose_output, const T& value) { - if (verbose_output.m_verbose) { - verbose_output.start_line(); - std::cerr << value; - - // check if there was a newline a the end and remember that - std::ostringstream output_buffer; - output_buffer << value; - if (!output_buffer.str().empty() && output_buffer.str().back() == '\n') { - verbose_output.m_newline = true; - } - } - return verbose_output; - } - - }; // class VerboseOutput - - } // namespace util - -} // namespace osmium - -#endif // OSMIUM_UTIL_VERBOSE_OUTPUT_HPP diff --git a/third_party/osmium/visitor.hpp b/third_party/osmium/visitor.hpp deleted file mode 100644 index d71a2e01c..000000000 --- a/third_party/osmium/visitor.hpp +++ /dev/null @@ -1,255 +0,0 @@ -#ifndef OSMIUM_VISITOR_HPP -#define OSMIUM_VISITOR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf 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 - -#include // IWYU pragma: keep -#include -#include -#include -#include - -namespace osmium { - - class TagList; - class WayNodeList; - class RelationMemberList; - class OuterRing; - class InnerRing; - - namespace memory { - class Item; - } - - namespace detail { - - template - using ConstIfConst = typename std::conditional::value, typename std::add_const::type, U>::type; - - template - inline void apply_item_recurse(TItem& item, THandler& handler) { - switch (item.type()) { - case osmium::item_type::undefined: - break; - case osmium::item_type::node: - handler.osm_object(static_cast&>(item)); - handler.node(static_cast&>(item)); - break; - case osmium::item_type::way: - handler.osm_object(static_cast&>(item)); - handler.way(static_cast&>(item)); - break; - case osmium::item_type::relation: - handler.osm_object(static_cast&>(item)); - handler.relation(static_cast&>(item)); - break; - case osmium::item_type::area: - handler.osm_object(static_cast&>(item)); - handler.area(static_cast&>(item)); - break; - case osmium::item_type::changeset: - handler.changeset(static_cast&>(item)); - break; - case osmium::item_type::tag_list: - handler.tag_list(static_cast&>(item)); - break; - case osmium::item_type::way_node_list: - handler.way_node_list(static_cast&>(item)); - break; - case osmium::item_type::relation_member_list: - case osmium::item_type::relation_member_list_with_full_members: - handler.relation_member_list(static_cast&>(item)); - break; - case osmium::item_type::outer_ring: - handler.outer_ring(static_cast&>(item)); - break; - case osmium::item_type::inner_ring: - handler.inner_ring(static_cast&>(item)); - break; - } - } - - template - inline void apply_item_recurse(const osmium::OSMEntity& item, THandler& handler) { - switch (item.type()) { - case osmium::item_type::node: - handler.osm_object(static_cast(item)); - handler.node(static_cast(item)); - break; - case osmium::item_type::way: - handler.osm_object(static_cast(item)); - handler.way(static_cast(item)); - break; - case osmium::item_type::relation: - handler.osm_object(static_cast(item)); - handler.relation(static_cast(item)); - break; - case osmium::item_type::area: - handler.osm_object(static_cast(item)); - handler.area(static_cast(item)); - break; - case osmium::item_type::changeset: - handler.changeset(static_cast(item)); - break; - default: - throw osmium::unknown_type(); - } - } - - template - inline void apply_item_recurse(osmium::OSMEntity& item, THandler& handler) { - switch (item.type()) { - case osmium::item_type::node: - handler.osm_object(static_cast(item)); - handler.node(static_cast(item)); - break; - case osmium::item_type::way: - handler.osm_object(static_cast(item)); - handler.way(static_cast(item)); - break; - case osmium::item_type::relation: - handler.osm_object(static_cast(item)); - handler.relation(static_cast(item)); - break; - case osmium::item_type::area: - handler.osm_object(static_cast(item)); - handler.area(static_cast(item)); - break; - case osmium::item_type::changeset: - handler.changeset(static_cast(item)); - break; - default: - throw osmium::unknown_type(); - } - } - - template - inline void apply_item_recurse(const osmium::OSMObject& item, THandler& handler) { - switch (item.type()) { - case osmium::item_type::node: - handler.osm_object(item); - handler.node(static_cast(item)); - break; - case osmium::item_type::way: - handler.osm_object(item); - handler.way(static_cast(item)); - break; - case osmium::item_type::relation: - handler.osm_object(item); - handler.relation(static_cast(item)); - break; - case osmium::item_type::area: - handler.osm_object(item); - handler.area(static_cast(item)); - break; - default: - throw osmium::unknown_type(); - } - } - - template - inline void apply_item_recurse(osmium::OSMObject& item, THandler& handler) { - switch (item.type()) { - case osmium::item_type::node: - handler.osm_object(item); - handler.node(static_cast(item)); - break; - case osmium::item_type::way: - handler.osm_object(item); - handler.way(static_cast(item)); - break; - case osmium::item_type::relation: - handler.osm_object(item); - handler.relation(static_cast(item)); - break; - case osmium::item_type::area: - handler.osm_object(item); - handler.area(static_cast(item)); - break; - default: - throw osmium::unknown_type(); - } - } - - template - inline void apply_item_recurse(TItem& item, THandler& handler, TRest&... more) { - apply_item_recurse(item, handler); - apply_item_recurse(item, more...); - } - - template - inline void flush_recurse(THandler& handler) { - handler.flush(); - } - - template - inline void flush_recurse(THandler& handler, TRest&... more) { - flush_recurse(handler); - flush_recurse(more...); - } - - } // namespace detail - - template - inline void apply_item(const osmium::memory::Item& item, THandlers&... handlers) { - detail::apply_item_recurse(item, handlers...); - } - - template - inline void apply_item(osmium::memory::Item& item, THandlers&... handlers) { - detail::apply_item_recurse(item, handlers...); - } - - template - inline void apply(TIterator it, TIterator end, THandlers&... handlers) { - for (; it != end; ++it) { - detail::apply_item_recurse(*it, handlers...); - } - detail::flush_recurse(handlers...); - } - - template - inline void apply(TContainer& c, THandlers&... handlers) { - apply(std::begin(c), std::end(c), handlers...); - } - - template - inline void apply(const osmium::memory::Buffer& buffer, THandlers&... handlers) { - apply(buffer.cbegin(), buffer.cend(), handlers...); - } - -} // namespace osmium - -#endif // OSMIUM_VISITOR_HPP From 73efcc6b0ccedf8c1b6d95abdba8340cc9adf100 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 13 Jan 2015 16:54:25 +0100 Subject: [PATCH 043/360] Squashed 'third_party/libosmium/' content from commit 910f8f1 git-subtree-dir: third_party/libosmium git-subtree-split: 910f8f1e992402e0f1acd0132eaffa7539ca83d2 --- .gitignore | 3 + .travis.yml | 43 + CMakeLists.txt | 259 + CONTRIBUTING.md | 132 + LICENSE.txt | 23 + Makefile | 25 + README-changes-from-old-osmium | 43 + README.md | 217 + appveyor.yml | 55 + cmake/FindOSMPBF.cmake | 50 + cmake/FindOsmium.cmake | 285 + cmake/build.bat | 15 + cmake/iwyu.sh | 43 + doc/Doxyfile.in | 2313 +++++ doc/doc.txt | 26 + doc/osmium.css | 22 + examples/CMakeLists.txt | 64 + examples/osmium_area_test.cpp | 138 + examples/osmium_convert.cpp | 112 + examples/osmium_count.cpp | 57 + examples/osmium_create_node_cache.cpp | 58 + examples/osmium_debug.cpp | 52 + examples/osmium_index.cpp | 236 + examples/osmium_read.cpp | 32 + examples/osmium_serdump.cpp | 210 + examples/osmium_toogr.cpp | 251 + examples/osmium_toogr2.cpp | 350 + examples/osmium_toogr2_exp.cpp | 330 + examples/osmium_use_node_cache.cpp | 71 + include/boost_unicode_iterator.hpp | 776 ++ include/mmap_for_windows.hpp | 106 + include/osmium/area/assembler.hpp | 783 ++ .../osmium/area/detail/node_ref_segment.hpp | 262 + include/osmium/area/detail/proto_ring.hpp | 274 + include/osmium/area/detail/segment_list.hpp | 216 + .../osmium/area/multipolygon_collector.hpp | 212 + include/osmium/area/problem_reporter.hpp | 149 + .../area/problem_reporter_exception.hpp | 96 + include/osmium/area/problem_reporter_ogr.hpp | 203 + .../osmium/area/problem_reporter_stream.hpp | 96 + include/osmium/builder/builder.hpp | 222 + include/osmium/builder/builder_helper.hpp | 103 + include/osmium/builder/osm_object_builder.hpp | 283 + include/osmium/diff_handler.hpp | 67 + include/osmium/diff_iterator.hpp | 129 + include/osmium/diff_visitor.hpp | 104 + include/osmium/dynamic_handler.hpp | 195 + include/osmium/experimental/flex_reader.hpp | 134 + include/osmium/geom/coordinates.hpp | 97 + include/osmium/geom/factory.hpp | 328 + include/osmium/geom/geojson.hpp | 154 + include/osmium/geom/geos.hpp | 221 + include/osmium/geom/haversine.hpp | 94 + include/osmium/geom/mercator_projection.hpp | 109 + include/osmium/geom/ogr.hpp | 176 + include/osmium/geom/projection.hpp | 158 + include/osmium/geom/relations.hpp | 57 + include/osmium/geom/util.hpp | 75 + include/osmium/geom/wkb.hpp | 277 + include/osmium/geom/wkt.hpp | 150 + include/osmium/handler.hpp | 101 + include/osmium/handler/chain.hpp | 128 + include/osmium/handler/disk_store.hpp | 111 + include/osmium/handler/dump.hpp | 294 + .../handler/node_locations_for_ways.hpp | 177 + include/osmium/handler/object_relations.hpp | 106 + .../osmium/index/detail/mmap_vector_anon.hpp | 78 + .../osmium/index/detail/mmap_vector_base.hpp | 183 + .../osmium/index/detail/mmap_vector_file.hpp | 85 + include/osmium/index/detail/tmpfile.hpp | 62 + include/osmium/index/detail/typed_mmap.hpp | 229 + include/osmium/index/index.hpp | 100 + include/osmium/index/map.hpp | 155 + include/osmium/index/map/dummy.hpp | 87 + include/osmium/index/map/mmap_vector_anon.hpp | 61 + include/osmium/index/map/mmap_vector_file.hpp | 57 + include/osmium/index/map/sparse_table.hpp | 140 + include/osmium/index/map/stl_map.hpp | 112 + include/osmium/index/map/stl_vector.hpp | 61 + include/osmium/index/map/vector.hpp | 237 + include/osmium/index/multimap.hpp | 129 + include/osmium/index/multimap/hybrid.hpp | 199 + .../index/multimap/mmap_vector_anon.hpp | 58 + .../index/multimap/mmap_vector_file.hpp | 54 + .../osmium/index/multimap/stl_multimap.hpp | 151 + include/osmium/index/multimap/stl_vector.hpp | 58 + include/osmium/index/multimap/vector.hpp | 151 + include/osmium/io/any_compression.hpp | 39 + include/osmium/io/any_input.hpp | 41 + include/osmium/io/any_output.hpp | 42 + include/osmium/io/bzip2_compression.hpp | 278 + include/osmium/io/compression.hpp | 281 + include/osmium/io/detail/input_format.hpp | 158 + .../osmium/io/detail/opl_output_format.hpp | 323 + include/osmium/io/detail/output_format.hpp | 156 + include/osmium/io/detail/pbf.hpp | 98 + include/osmium/io/detail/pbf_input_format.hpp | 240 + .../osmium/io/detail/pbf_output_format.hpp | 944 ++ include/osmium/io/detail/pbf_parser.hpp | 449 + include/osmium/io/detail/pbf_stringtable.hpp | 204 + include/osmium/io/detail/read_thread.hpp | 106 + include/osmium/io/detail/read_write.hpp | 156 + include/osmium/io/detail/write_thread.hpp | 86 + include/osmium/io/detail/xml_input_format.hpp | 724 ++ .../osmium/io/detail/xml_output_format.hpp | 481 + include/osmium/io/detail/zlib.hpp | 97 + include/osmium/io/error.hpp | 57 + include/osmium/io/file.hpp | 343 + include/osmium/io/file_compression.hpp | 72 + include/osmium/io/file_format.hpp | 78 + include/osmium/io/gzip_compression.hpp | 237 + include/osmium/io/header.hpp | 122 + include/osmium/io/input_iterator.hpp | 139 + include/osmium/io/opl_output.hpp | 39 + include/osmium/io/output_iterator.hpp | 116 + include/osmium/io/overwrite.hpp | 52 + include/osmium/io/pbf_input.hpp | 39 + include/osmium/io/pbf_output.hpp | 39 + include/osmium/io/reader.hpp | 303 + include/osmium/io/reader_iterator.hpp | 51 + include/osmium/io/writer.hpp | 145 + include/osmium/io/xml_input.hpp | 39 + include/osmium/io/xml_output.hpp | 39 + include/osmium/memory/buffer.hpp | 535 + include/osmium/memory/collection.hpp | 153 + include/osmium/memory/item.hpp | 179 + include/osmium/memory/item_iterator.hpp | 234 + include/osmium/object_pointer_collection.hpp | 112 + include/osmium/osm.hpp | 48 + include/osmium/osm/area.hpp | 193 + include/osmium/osm/box.hpp | 207 + include/osmium/osm/changeset.hpp | 336 + include/osmium/osm/diff_object.hpp | 156 + include/osmium/osm/entity.hpp | 74 + include/osmium/osm/entity_bits.hpp | 99 + include/osmium/osm/item_type.hpp | 173 + include/osmium/osm/location.hpp | 285 + include/osmium/osm/node.hpp | 76 + include/osmium/osm/node_ref.hpp | 173 + include/osmium/osm/node_ref_list.hpp | 135 + include/osmium/osm/object.hpp | 437 + include/osmium/osm/object_comparisons.hpp | 110 + include/osmium/osm/relation.hpp | 189 + include/osmium/osm/segment.hpp | 105 + include/osmium/osm/tag.hpp | 140 + include/osmium/osm/timestamp.hpp | 171 + include/osmium/osm/types.hpp | 83 + include/osmium/osm/undirected_segment.hpp | 100 + include/osmium/osm/way.hpp | 115 + include/osmium/relations/collector.hpp | 544 + .../osmium/relations/detail/member_meta.hpp | 158 + .../osmium/relations/detail/relation_meta.hpp | 136 + include/osmium/tags/filter.hpp | 148 + include/osmium/tags/regex_filter.hpp | 58 + include/osmium/tags/taglist.hpp | 67 + include/osmium/thread/function_wrapper.hpp | 110 + include/osmium/thread/pool.hpp | 180 + include/osmium/thread/queue.hpp | 178 + include/osmium/thread/sorted_queue.hpp | 159 + include/osmium/thread/util.hpp | 87 + include/osmium/util/cast.hpp | 72 + include/osmium/util/compatibility.hpp | 47 + include/osmium/util/config.hpp | 72 + include/osmium/util/double.hpp | 93 + include/osmium/util/options.hpp | 155 + include/osmium/util/string.hpp | 68 + include/osmium/util/verbose_output.hpp | 139 + include/osmium/visitor.hpp | 255 + make_osmium_project.sh | 96 + osmium.imp | 4 + test/CMakeLists.txt | 123 + test/README | 12 + test/include/catch.hpp | 8987 +++++++++++++++++ test/include/catch_orig.hpp | 8974 ++++++++++++++++ test/include/win_mkstemp.hpp | 42 + test/osm-testdata/.gitignore | 1 + test/osm-testdata/CMakeLists.txt | 87 + test/osm-testdata/README.md | 23 + .../include/check_basics_handler.hpp | 92 + .../include/check_wkt_handler.hpp | 86 + test/osm-testdata/include/common.hpp | 21 + .../include/testdata-testcases.hpp | 10 + test/osm-testdata/multipolygon.qgs | 880 ++ .../run-testdata-multipolygon.bat | 7 + .../osm-testdata/run-testdata-multipolygon.sh | 10 + test/osm-testdata/testcases/test-100.cpp | 41 + test/osm-testdata/testcases/test-101.cpp | 43 + test/osm-testdata/testcases/test-110.cpp | 58 + test/osm-testdata/testdata-multipolygon.cpp | 305 + test/osm-testdata/testdata-overview.cpp | 212 + test/osm-testdata/testdata-testcases.cpp | 27 + test/osm-testdata/testdata-xml.cpp | 372 + test/t/area/test_area_id.cpp | 25 + test/t/area/test_node_ref_segment.cpp | 115 + test/t/basic/helper.hpp | 97 + test/t/basic/test_box.cpp | 81 + test/t/basic/test_changeset.cpp | 57 + test/t/basic/test_entity_bits.cpp | 25 + test/t/basic/test_location.cpp | 154 + test/t/basic/test_node.cpp | 114 + test/t/basic/test_node_ref.cpp | 57 + test/t/basic/test_object_comparisons.cpp | 147 + test/t/basic/test_relation.cpp | 60 + test/t/basic/test_timestamp.cpp | 45 + test/t/basic/test_way.cpp | 79 + test/t/buffer/test_buffer_node.cpp | 135 + test/t/buffer/test_buffer_purge.cpp | 186 + test/t/geom/helper.hpp | 15 + test/t/geom/test_factory_with_projection.cpp | 41 + test/t/geom/test_geojson.cpp | 236 + test/t/geom/test_geos.cpp | 198 + test/t/geom/test_geos_wkb.cpp | 156 + test/t/geom/test_mercator.cpp | 37 + test/t/geom/test_ogr.cpp | 185 + test/t/geom/test_projection.cpp | 131 + test/t/geom/test_wkb.cpp | 133 + test/t/geom/test_wkt.cpp | 198 + test/t/index/test_id_to_location.cpp | 143 + test/t/index/test_typed_mmap.cpp | 95 + test/t/io/data.osm | 4 + test/t/io/data.osm.bz2 | Bin 0 -> 200 bytes test/t/io/data.osm.gz | Bin 0 -> 187 bytes test/t/io/data_bzip2.txt | 1 + test/t/io/data_bzip2.txt.bz2 | Bin 0 -> 45 bytes test/t/io/test_bzip2.cpp | 30 + test/t/io/test_file_formats.cpp | 251 + test/t/io/test_reader.cpp | 116 + test/t/tags/test_filter.cpp | 216 + test/t/tags/test_operators.cpp | 61 + test/t/tags/test_tag_list.cpp | 76 + test/t/util/test_double.cpp | 33 + test/t/util/test_options.cpp | 48 + test/t/util/test_string.cpp | 57 + test/test_main.cpp | 2 + test/valgrind.supp | 38 + 235 files changed, 53733 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 CMakeLists.txt create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE.txt create mode 100644 Makefile create mode 100644 README-changes-from-old-osmium create mode 100644 README.md create mode 100644 appveyor.yml create mode 100644 cmake/FindOSMPBF.cmake create mode 100644 cmake/FindOsmium.cmake create mode 100644 cmake/build.bat create mode 100755 cmake/iwyu.sh create mode 100644 doc/Doxyfile.in create mode 100644 doc/doc.txt create mode 100644 doc/osmium.css create mode 100644 examples/CMakeLists.txt create mode 100644 examples/osmium_area_test.cpp create mode 100644 examples/osmium_convert.cpp create mode 100644 examples/osmium_count.cpp create mode 100644 examples/osmium_create_node_cache.cpp create mode 100644 examples/osmium_debug.cpp create mode 100644 examples/osmium_index.cpp create mode 100644 examples/osmium_read.cpp create mode 100644 examples/osmium_serdump.cpp create mode 100644 examples/osmium_toogr.cpp create mode 100644 examples/osmium_toogr2.cpp create mode 100644 examples/osmium_toogr2_exp.cpp create mode 100644 examples/osmium_use_node_cache.cpp create mode 100644 include/boost_unicode_iterator.hpp create mode 100644 include/mmap_for_windows.hpp create mode 100644 include/osmium/area/assembler.hpp create mode 100644 include/osmium/area/detail/node_ref_segment.hpp create mode 100644 include/osmium/area/detail/proto_ring.hpp create mode 100644 include/osmium/area/detail/segment_list.hpp create mode 100644 include/osmium/area/multipolygon_collector.hpp create mode 100644 include/osmium/area/problem_reporter.hpp create mode 100644 include/osmium/area/problem_reporter_exception.hpp create mode 100644 include/osmium/area/problem_reporter_ogr.hpp create mode 100644 include/osmium/area/problem_reporter_stream.hpp create mode 100644 include/osmium/builder/builder.hpp create mode 100644 include/osmium/builder/builder_helper.hpp create mode 100644 include/osmium/builder/osm_object_builder.hpp create mode 100644 include/osmium/diff_handler.hpp create mode 100644 include/osmium/diff_iterator.hpp create mode 100644 include/osmium/diff_visitor.hpp create mode 100644 include/osmium/dynamic_handler.hpp create mode 100644 include/osmium/experimental/flex_reader.hpp create mode 100644 include/osmium/geom/coordinates.hpp create mode 100644 include/osmium/geom/factory.hpp create mode 100644 include/osmium/geom/geojson.hpp create mode 100644 include/osmium/geom/geos.hpp create mode 100644 include/osmium/geom/haversine.hpp create mode 100644 include/osmium/geom/mercator_projection.hpp create mode 100644 include/osmium/geom/ogr.hpp create mode 100644 include/osmium/geom/projection.hpp create mode 100644 include/osmium/geom/relations.hpp create mode 100644 include/osmium/geom/util.hpp create mode 100644 include/osmium/geom/wkb.hpp create mode 100644 include/osmium/geom/wkt.hpp create mode 100644 include/osmium/handler.hpp create mode 100644 include/osmium/handler/chain.hpp create mode 100644 include/osmium/handler/disk_store.hpp create mode 100644 include/osmium/handler/dump.hpp create mode 100644 include/osmium/handler/node_locations_for_ways.hpp create mode 100644 include/osmium/handler/object_relations.hpp create mode 100644 include/osmium/index/detail/mmap_vector_anon.hpp create mode 100644 include/osmium/index/detail/mmap_vector_base.hpp create mode 100644 include/osmium/index/detail/mmap_vector_file.hpp create mode 100644 include/osmium/index/detail/tmpfile.hpp create mode 100644 include/osmium/index/detail/typed_mmap.hpp create mode 100644 include/osmium/index/index.hpp create mode 100644 include/osmium/index/map.hpp create mode 100644 include/osmium/index/map/dummy.hpp create mode 100644 include/osmium/index/map/mmap_vector_anon.hpp create mode 100644 include/osmium/index/map/mmap_vector_file.hpp create mode 100644 include/osmium/index/map/sparse_table.hpp create mode 100644 include/osmium/index/map/stl_map.hpp create mode 100644 include/osmium/index/map/stl_vector.hpp create mode 100644 include/osmium/index/map/vector.hpp create mode 100644 include/osmium/index/multimap.hpp create mode 100644 include/osmium/index/multimap/hybrid.hpp create mode 100644 include/osmium/index/multimap/mmap_vector_anon.hpp create mode 100644 include/osmium/index/multimap/mmap_vector_file.hpp create mode 100644 include/osmium/index/multimap/stl_multimap.hpp create mode 100644 include/osmium/index/multimap/stl_vector.hpp create mode 100644 include/osmium/index/multimap/vector.hpp create mode 100644 include/osmium/io/any_compression.hpp create mode 100644 include/osmium/io/any_input.hpp create mode 100644 include/osmium/io/any_output.hpp create mode 100644 include/osmium/io/bzip2_compression.hpp create mode 100644 include/osmium/io/compression.hpp create mode 100644 include/osmium/io/detail/input_format.hpp create mode 100644 include/osmium/io/detail/opl_output_format.hpp create mode 100644 include/osmium/io/detail/output_format.hpp create mode 100644 include/osmium/io/detail/pbf.hpp create mode 100644 include/osmium/io/detail/pbf_input_format.hpp create mode 100644 include/osmium/io/detail/pbf_output_format.hpp create mode 100644 include/osmium/io/detail/pbf_parser.hpp create mode 100644 include/osmium/io/detail/pbf_stringtable.hpp create mode 100644 include/osmium/io/detail/read_thread.hpp create mode 100644 include/osmium/io/detail/read_write.hpp create mode 100644 include/osmium/io/detail/write_thread.hpp create mode 100644 include/osmium/io/detail/xml_input_format.hpp create mode 100644 include/osmium/io/detail/xml_output_format.hpp create mode 100644 include/osmium/io/detail/zlib.hpp create mode 100644 include/osmium/io/error.hpp create mode 100644 include/osmium/io/file.hpp create mode 100644 include/osmium/io/file_compression.hpp create mode 100644 include/osmium/io/file_format.hpp create mode 100644 include/osmium/io/gzip_compression.hpp create mode 100644 include/osmium/io/header.hpp create mode 100644 include/osmium/io/input_iterator.hpp create mode 100644 include/osmium/io/opl_output.hpp create mode 100644 include/osmium/io/output_iterator.hpp create mode 100644 include/osmium/io/overwrite.hpp create mode 100644 include/osmium/io/pbf_input.hpp create mode 100644 include/osmium/io/pbf_output.hpp create mode 100644 include/osmium/io/reader.hpp create mode 100644 include/osmium/io/reader_iterator.hpp create mode 100644 include/osmium/io/writer.hpp create mode 100644 include/osmium/io/xml_input.hpp create mode 100644 include/osmium/io/xml_output.hpp create mode 100644 include/osmium/memory/buffer.hpp create mode 100644 include/osmium/memory/collection.hpp create mode 100644 include/osmium/memory/item.hpp create mode 100644 include/osmium/memory/item_iterator.hpp create mode 100644 include/osmium/object_pointer_collection.hpp create mode 100644 include/osmium/osm.hpp create mode 100644 include/osmium/osm/area.hpp create mode 100644 include/osmium/osm/box.hpp create mode 100644 include/osmium/osm/changeset.hpp create mode 100644 include/osmium/osm/diff_object.hpp create mode 100644 include/osmium/osm/entity.hpp create mode 100644 include/osmium/osm/entity_bits.hpp create mode 100644 include/osmium/osm/item_type.hpp create mode 100644 include/osmium/osm/location.hpp create mode 100644 include/osmium/osm/node.hpp create mode 100644 include/osmium/osm/node_ref.hpp create mode 100644 include/osmium/osm/node_ref_list.hpp create mode 100644 include/osmium/osm/object.hpp create mode 100644 include/osmium/osm/object_comparisons.hpp create mode 100644 include/osmium/osm/relation.hpp create mode 100644 include/osmium/osm/segment.hpp create mode 100644 include/osmium/osm/tag.hpp create mode 100644 include/osmium/osm/timestamp.hpp create mode 100644 include/osmium/osm/types.hpp create mode 100644 include/osmium/osm/undirected_segment.hpp create mode 100644 include/osmium/osm/way.hpp create mode 100644 include/osmium/relations/collector.hpp create mode 100644 include/osmium/relations/detail/member_meta.hpp create mode 100644 include/osmium/relations/detail/relation_meta.hpp create mode 100644 include/osmium/tags/filter.hpp create mode 100644 include/osmium/tags/regex_filter.hpp create mode 100644 include/osmium/tags/taglist.hpp create mode 100644 include/osmium/thread/function_wrapper.hpp create mode 100644 include/osmium/thread/pool.hpp create mode 100644 include/osmium/thread/queue.hpp create mode 100644 include/osmium/thread/sorted_queue.hpp create mode 100644 include/osmium/thread/util.hpp create mode 100644 include/osmium/util/cast.hpp create mode 100644 include/osmium/util/compatibility.hpp create mode 100644 include/osmium/util/config.hpp create mode 100644 include/osmium/util/double.hpp create mode 100644 include/osmium/util/options.hpp create mode 100644 include/osmium/util/string.hpp create mode 100644 include/osmium/util/verbose_output.hpp create mode 100644 include/osmium/visitor.hpp create mode 100755 make_osmium_project.sh create mode 100644 osmium.imp create mode 100644 test/CMakeLists.txt create mode 100644 test/README create mode 100644 test/include/catch.hpp create mode 100644 test/include/catch_orig.hpp create mode 100644 test/include/win_mkstemp.hpp create mode 100644 test/osm-testdata/.gitignore create mode 100644 test/osm-testdata/CMakeLists.txt create mode 100644 test/osm-testdata/README.md create mode 100644 test/osm-testdata/include/check_basics_handler.hpp create mode 100644 test/osm-testdata/include/check_wkt_handler.hpp create mode 100644 test/osm-testdata/include/common.hpp create mode 100644 test/osm-testdata/include/testdata-testcases.hpp create mode 100644 test/osm-testdata/multipolygon.qgs create mode 100644 test/osm-testdata/run-testdata-multipolygon.bat create mode 100755 test/osm-testdata/run-testdata-multipolygon.sh create mode 100644 test/osm-testdata/testcases/test-100.cpp create mode 100644 test/osm-testdata/testcases/test-101.cpp create mode 100644 test/osm-testdata/testcases/test-110.cpp create mode 100644 test/osm-testdata/testdata-multipolygon.cpp create mode 100644 test/osm-testdata/testdata-overview.cpp create mode 100644 test/osm-testdata/testdata-testcases.cpp create mode 100644 test/osm-testdata/testdata-xml.cpp create mode 100644 test/t/area/test_area_id.cpp create mode 100644 test/t/area/test_node_ref_segment.cpp create mode 100644 test/t/basic/helper.hpp create mode 100644 test/t/basic/test_box.cpp create mode 100644 test/t/basic/test_changeset.cpp create mode 100644 test/t/basic/test_entity_bits.cpp create mode 100644 test/t/basic/test_location.cpp create mode 100644 test/t/basic/test_node.cpp create mode 100644 test/t/basic/test_node_ref.cpp create mode 100644 test/t/basic/test_object_comparisons.cpp create mode 100644 test/t/basic/test_relation.cpp create mode 100644 test/t/basic/test_timestamp.cpp create mode 100644 test/t/basic/test_way.cpp create mode 100644 test/t/buffer/test_buffer_node.cpp create mode 100644 test/t/buffer/test_buffer_purge.cpp create mode 100644 test/t/geom/helper.hpp create mode 100644 test/t/geom/test_factory_with_projection.cpp create mode 100644 test/t/geom/test_geojson.cpp create mode 100644 test/t/geom/test_geos.cpp create mode 100644 test/t/geom/test_geos_wkb.cpp create mode 100644 test/t/geom/test_mercator.cpp create mode 100644 test/t/geom/test_ogr.cpp create mode 100644 test/t/geom/test_projection.cpp create mode 100644 test/t/geom/test_wkb.cpp create mode 100644 test/t/geom/test_wkt.cpp create mode 100644 test/t/index/test_id_to_location.cpp create mode 100644 test/t/index/test_typed_mmap.cpp create mode 100644 test/t/io/data.osm create mode 100644 test/t/io/data.osm.bz2 create mode 100644 test/t/io/data.osm.gz create mode 100644 test/t/io/data_bzip2.txt create mode 100644 test/t/io/data_bzip2.txt.bz2 create mode 100644 test/t/io/test_bzip2.cpp create mode 100644 test/t/io/test_file_formats.cpp create mode 100644 test/t/io/test_reader.cpp create mode 100644 test/t/tags/test_filter.cpp create mode 100644 test/t/tags/test_operators.cpp create mode 100644 test/t/tags/test_tag_list.cpp create mode 100644 test/t/util/test_double.cpp create mode 100644 test/t/util/test_options.cpp create mode 100644 test/t/util/test_string.cpp create mode 100644 test/test_main.cpp create mode 100644 test/valgrind.supp diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..608d46daf --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +core +*.swp +build* diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..2c420728e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,43 @@ +language: cpp + +compiler: + - gcc + - clang + +before_install: + # we need at least g++-4.8 for c++11 features + - sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test + - sudo apt-get update --yes --quiet + +install: + # upgrade compilers + - sudo apt-get install --yes gcc-4.8 g++-4.8 + # make sure 'cpp' is the just installed current one + - sudo rm /usr/bin/cpp + - sudo ln -s /usr/bin/cpp-4.8 /usr/bin/cpp + # upgrade libosmium dependencies + - sudo apt-get install --yes make libboost-dev libboost-program-options-dev libsparsehash-dev libprotobuf-dev protobuf-compiler libgeos++-dev libproj-dev + - sudo apt-get install --yes make libgdal1h libgdal-dev + # OSMPBF is too old, install from git + #- sudo apt-get install --yes libosmpbf-dev + - git clone https://github.com/scrosby/OSM-binary.git + - cd OSM-binary/src + - make + - sudo make install + - cd ../.. + +#env: + +before_script: + - true + +script: + - if [ "${CXX}" = 'g++' ]; then export CXX=g++-4.8; fi; + - mkdir build + - cd build + - cmake -L -DCMAKE_BUILD_TYPE=Dev .. + - make VERBOSE=1 + # Disable multipolygon test because it needs ruby and the 'json' gem, but the + # travis ruby installation doesn't find the gem it did install itself. + - ctest -V -E testdata-multipolygon + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..19b88cfc2 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,259 @@ +#---------------------------------------------------------------------- +# +# Libosmium CMakeLists.txt +# +#---------------------------------------------------------------------- + +cmake_minimum_required(VERSION 2.8 FATAL_ERROR) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") + + +#---------------------------------------------------------------------- +# +# Project version +# +#---------------------------------------------------------------------- + +project(libosmium) + +set(LIBOSMIUM_VERSION_MAJOR 0) +set(LIBOSMIUM_VERSION_MINOR 0) +set(LIBOSMIUM_VERSION_PATCH 1) + +set(LIBOSMIUM_VERSION ${LIBOSMIUM_VERSION_MAJOR}.${LIBOSMIUM_VERSION_MINOR}.${LIBOSMIUM_VERSION_PATCH}) + + +#---------------------------------------------------------------------- +# +# Build options +# +# (Change with -DOPTION=VALUE on cmake command line.) +# +#---------------------------------------------------------------------- + +option(BUILD_EXAMPLES "compile example programs" ON) +option(BUILD_UNIT_TESTS "compile unit tests, please run them with ctest" ON) +option(BUILD_DATA_TESTS "compile data tests, please run them with ctest" ON) + +if(CMAKE_BUILD_TYPE STREQUAL "Dev") + option(BUILD_HEADERS "compile every header file on its own" ON) +else() + option(BUILD_HEADERS "compile every header file on its own" OFF) +endif() + + +#---------------------------------------------------------------------- +# +# Find external dependencies +# +#---------------------------------------------------------------------- + +# check that the essential libraries were found +if(BUILD_EXAMPLES OR BUILD_TESTING OR BUILD_UNIT_TESTS OR BUILD_DATA_TESTS OR BUILD_HEADERS) + + find_package(Boost 1.38) + mark_as_advanced(CLEAR BOOST_ROOT) + + if(Boost_FOUND) + include_directories(${Boost_INCLUDE_DIRS}) + else() + set(BOOST_ROOT "NOT FOUND: please choose" CACHE PATH "") + message(FATAL_ERROR "PLEASE, specify the directory where the Boost library is installed in BOOST_ROOT") + endif() + + set(OSMIUM_INCLUDE_DIR include) + find_package(Osmium COMPONENTS io gdal geos proj sparsehash) + include_directories(${OSMIUM_INCLUDE_DIRS}) + + if(MSVC) + find_path(GETOPT_INCLUDE_DIR getopt.h) + find_library(GETOPT_LIBRARY NAMES wingetopt) + if(GETOPT_INCLUDE_DIR AND GETOPT_LIBRARY) + include_directories(${GETOPT_INCLUDE_DIR}) + list(APPEND OSMIUM_LIBRARIES ${GETOPT_LIBRARY}) + else() + set(GETOPT_MISSING 1) + endif() + endif() + + include_directories(include) +endif() + +#---------------------------------------------------------------------- +# +# Decide which C++ version to use (Minimum/default: C++11). +# +#---------------------------------------------------------------------- + +if(NOT USE_CPP_VERSION) + set(USE_CPP_VERSION c++11) +endif() +message(STATUS "Use C++ version: ${USE_CPP_VERSION}") +# following only available from cmake 2.8.12: +# add_compile_options(-std=${USE_CPP_VERSION}) +# so using this instead: +add_definitions(-std=${USE_CPP_VERSION}) + +#---------------------------------------------------------------------- + +set(CMAKE_CXX_FLAGS_DEV "-O3 -g" + CACHE STRING "Flags used by the compiler during developer builds." + FORCE) +set(CMAKE_EXE_LINKER_FLAGS_DEV "" + CACHE STRING "Flags used by the linker during developer builds." + FORCE) +mark_as_advanced( + CMAKE_CXX_FLAGS_DEV + CMAKE_EXE_LINKER_FLAGS_DEV +) + +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g" + CACHE STRING "Flags used by the compiler during RELWITHDEBINFO builds." + FORCE) + +set(CMAKE_CONFIGURATION_TYPES "Debug Release RelWithDebInfo MinSizeRel Dev") + +# Force RelWithDebInfo build type if none was given +if (CMAKE_BUILD_TYPE STREQUAL "") + set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build, options are: ${CMAKE_CONFIGURATION_TYPES}." FORCE) +else() + set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING "Choose the type of build, options are: ${CMAKE_CONFIGURATION_TYPES}." FORCE) +endif() + + +#---------------------------------------------------------------------- + +if(WIN32) + add_definitions(-DWIN32 -D_WIN32 -DMSWIN32 -DBGDWIN32 -DWINVER=0x0500 -D_WIN32_WINNT=0x0500 -D_WIN32_IE=0x0600) + set(CPACK_GENERATOR ZIP) +else() + set(CPACK_GENERATOR TGZ) +endif() + + +#---------------------------------------------------------------------- +# +# Set up testing +# +#---------------------------------------------------------------------- +enable_testing() + +find_program(MEMORYCHECK_COMMAND valgrind) +set(MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full --show-reachable=yes --error-exitcode=1") +set(MEMORYCHECK_SUPPRESSIONS_FILE "${PROJECT_SOURCE_DIR}/test/valgrind.supp") + +if(BUILD_UNIT_TESTS OR BUILD_TESTING) + add_subdirectory(test) +endif() + +if(BUILD_DATA_TESTS OR BUILD_TESTING) + add_subdirectory(test/osm-testdata) +endif() + + +#---------------------------------------------------------------------- +# +# Optional "cppcheck" target that checks C++ code +# +#---------------------------------------------------------------------- +message(STATUS "Looking for cppcheck") +find_program(CPPCHECK cppcheck) + +if(CPPCHECK) + message(STATUS "Looking for cppcheck - found") + set(CPPCHECK_OPTIONS --enable=warning,style,performance,portability,information,missingInclude) + + # cpp doesn't find system includes for some reason, suppress that report + set(CPPCHECK_OPTIONS ${CPPCHECK_OPTIONS} --suppress=missingIncludeSystem) + + file(GLOB_RECURSE ALL_INCLUDES include/osmium/*.hpp) + file(GLOB ALL_EXAMPLES examples/*.cpp) + file(GLOB ALL_UNIT_TESTS test/t/*/test_*.cpp) + file(GLOB ALL_DATA_TESTS test/osm-testdata/*.cpp) + + if(Osmium_DEBUG) + message(STATUS "Checking includes : ${ALL_INCLUDES}") + message(STATUS "Checking example code : ${ALL_EXAMPLES}") + message(STATUS "Checking unit test code: ${ALL_UNIT_TESTS}") + message(STATUS "Checking data test code: ${ALL_DATA_TESTS}") + endif() + + set(CPPCHECK_FILES ${ALL_INCLUDES} ${ALL_EXAMPLES} ${ALL_UNIT_TESTS} ${ALL_DATA_TESTS}) + + add_custom_target(cppcheck + ${CPPCHECK} + --std=c++11 ${CPPCHECK_OPTIONS} + -I ${CMAKE_SOURCE_DIR}/include + ${CPPCHECK_FILES} + ) +else() + message(STATUS "Looking for cppcheck - not found") + message(STATUS " Make target cppcheck not available") +endif(CPPCHECK) + + +#---------------------------------------------------------------------- +# +# Doxygen-based documentation +# +#---------------------------------------------------------------------- +find_package(Doxygen) +if(DOXYGEN_FOUND) + configure_file(doc/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) + add_custom_target(doc + ${DOXYGEN_EXECUTABLE} + ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" VERBATIM + ) + install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/doc/html" DESTINATION "share/doc/libosmium-dev") +else() + message(STATUS "Doxygen not found, so 'doc' target will not be available.") +endif() + + +#---------------------------------------------------------------------- + +if(BUILD_EXAMPLES) + add_subdirectory(examples) +endif() + +#---------------------------------------------------------------------- +# This will try to compile include files on their own to detect missing +# include directives and other dependency-related problems. Note that if this +# work, it is not enough to be sure it will compile in production code. +# But if it reports an error we know we are missing something. +if(BUILD_HEADERS) + file(GLOB_RECURSE ALL_HPPS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/include" include/osmium/*.hpp) + + # In 'Dev' mode: compile with very strict warnings and turn them into errors. + if(CMAKE_BUILD_TYPE STREQUAL "Dev") + add_definitions(-Werror ${OSMIUM_WARNING_OPTIONS}) + endif() + + file(MAKE_DIRECTORY header_check) + + foreach(hpp ${ALL_HPPS}) + string(REPLACE ".hpp" "" tmp ${hpp}) + string(REPLACE "/" "__" libname ${tmp}) + + # Create a dummy .cpp file that includes the header file we want to + # check. + set(DUMMYCPP ${CMAKE_BINARY_DIR}/header_check/${libname}.cpp) + file(WRITE ${DUMMYCPP} "#include <${hpp}>\n") + + # There is no way in CMake to just compile but not link a C++ file, + # so we pretend to build a library here. + add_library(${libname} OBJECT ${DUMMYCPP} include/${hpp}) + endforeach() +endif() + +install(DIRECTORY include/osmium DESTINATION include) + +# We only have a copy of this file so we can use older boost versions which +# don't have it. We probably don't want to install it. +#install(FILES include/boost_unicode_iterator.hpp DESTINATION include) + +#---------------------------------------------------------------------- +include(CPack) + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..323c84744 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,132 @@ + +# Notes for Developers + +Read this if you want to contribute to Libosmium. + + +## Versioning + +Osmium is currently considered in beta and doesn't use versioning yet. Proper +versions will be introduced as soon as it is somewhat stable. + + +## Namespace + +All Osmium code MUST be in the `osmium` namespace or one of its sub-namespaces. + + +## Include-Only + +Osmium is a include-only library. You can't compile the library itself. There +is no libosmium.so. + +One drawback ist that you can't have static data in classes, because there +is no place to put this data. + +All free functions must be declared `inline`. + + +## Coding Conventions + +These coding conventions have been changing over time and some code is still +different. + +* All include files have `#ifdef` guards around them, macros are the path name + in all uppercase where the slashes (`/`) have been changed to underscore (`_`). +* Class names begin with uppercase chars and use CamelCase. Smaller helper + classes are usually defined as struct and have lowercase names. +* Macros (and only macros) are all uppercase. Use macros sparingly, usually + a constexpr is better. +* Variables, attributes, and function names are lowercase with + `underscores_between_words`. +* Class attribute names start with `m_` (member). +* Template parameters are single uppercase letters or start with uppercase `T` + and use CamelCase. +* Typedefs have `names_like_this_type` which end in `_type`. +* Macros should only be used for controlling which parts of the code should be + included when compiling. +* Use `descriptive_variable_names`, exceptions are well-established conventions + like `i` for a loop variable. Iterators are usually called `it`. +* Declare variables where they are first used (C++ style), not at the beginning + of a function (old C style). +* Names from external namespaces (even `std`) are always mentioned explicitly. + Do not use `using` (except for `std::swap`). This way we can't even by + accident pollute the namespace of the code including Osmium. +* `#include` directives appear in three "blocks" after the copyright notice. + The blocks are separated by blank lines. First block contains `#include`s for + standard C/C++ includes, second block for any external libs used, third + block for osmium internal includes. Within each block `#include`s are usually + sorted by path name. All `#include`s use `<>` syntax not `""`. +* Names not to be used from outside the library should be in a namespace + called `detail` under the namespace where they would otherwise appear. If + whole include files are never meant to be included from outside they should + be in a subdirectory called `detail`. +* All files have suffix `.hpp`. +* Closing } of all classes and namespaces should have a trailing comment + with the name of the class/namespace. +* All constructors with one or more arguments should be declared "explicit" + unless there is a reason for them not to be. Document that reason. + +Keep to the indentation and other styles used in the code. Use `make indent` +in the toplevel directory to fix indentation and styling. It calls `astyle` +with the right parameters. This program is in the `astyle` Debian package. + + +## C++11 + +Osmium uses C++11 and you can use its features such as auto, lambdas, +threading, etc. There are a few features we do not use, because even modern +compilers don't support them yet. This list might change as we get more data +about which compilers support which feature and what operating system versions +or distributions have which versions of these compilers installed. + +GCC 4.6 - too old, not supported (Ubuntu 12.04 LTS) +GCC 4.7.2 - can probably not be supported (Debian wheezy/stable) +GCC 4.7.3 - works +GCC 4.8 - works +clang 3.0 - too old, not supported (Debian wheezy/stable, Ubuntu 12.04 LTS) +clang 3.2 - works + +C++11 features you should not use: +* Inherited Constructors (works only in GCC 4.8+ and clang 3.3+, not in Visual + Studio) + + +## Checking your code + +The Osmium makefiles use pretty draconian warning options for the compiler. +This is good. Code MUST never produce any warnings, even with those settings. +If absolutely necessary pragmas can be used to disable certain warnings in +specific areas of the code. + +If the static code checker `cppcheck` is installed, the CMake configuration +will add a new build target `cppcheck` that will check all `.cpp` and `.hpp` +files. Cppcheck finds some bugs that gcc/clang doesn't. But take the result +with a grain of salt, it also sometimes produces wrong warnings. + +Set `BUILD_HEADERS=ON` in the CMake config to enable compiling all include +files on their own to check whether dependencies are all okay. All include +files MUST include all other include files they depend on. + +Call `cmake/iwyu.sh` to check for proper includes and forward declarations. +This uses the clang-based `include-what-you-use` program. Note that it does +produce some false reports and crashes often. The `osmium.imp` file can be +used to define mappings for iwyu. See the IWYU tool at +. + + +## Testing + +There are a unit tests using the Catch Unit Test Framework in the `test` +directory and some data tests in `test/osm-testdata`. They are built by the +default cmake config. Run `ctest` to run them. Many more tests are needed. + + +## Documenting the code + +All namespaces, classes, functions, attributes, etc. should be documented. + +Osmium uses the Doxygen (www.doxygen.org) source code documentation system. +If it is installed, the CMake configuration will add a new build target, so +you can build it with `make doc`. + diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 000000000..36b7cd93c --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,23 @@ +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. diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..b445e8e82 --- /dev/null +++ b/Makefile @@ -0,0 +1,25 @@ + +all: + mkdir -p build && cd build && cmake .. && $(MAKE) + +doc: + mkdir -p build && cd build && cmake .. && $(MAKE) doc + +clean: + if test -d build; then cd build && $(MAKE) clean; fi + +distclean: + rm -fr build + +deb: + debuild -I -us -uc + +deb-clean: + debuild clean + +indent: + astyle --style=java --indent-namespaces --indent-switches --pad-header --lineend=linux --suffix=none --recursive include/\*.hpp examples/\*.cpp test/\*.cpp +# astyle --style=java --indent-namespaces --indent-switches --pad-header --unpad-paren --align-pointer=type --lineend=linux --suffix=none --recursive include/\*.hpp examples/\*.cpp test/\*.cpp + +.PHONY: clean distclean deb deb-clean doc indent + diff --git a/README-changes-from-old-osmium b/README-changes-from-old-osmium new file mode 100644 index 000000000..3e94500ea --- /dev/null +++ b/README-changes-from-old-osmium @@ -0,0 +1,43 @@ + +Changes from old versions of Osmium +=================================== + +This version has some substantial changes and users of Osmium will have to +rewrite their code. Use the examples provided in the "example" directory +or in the osmium-contrib repository to get an idea what needs changing. +These examples are often similar to the examples provided with the old +Osmium so they should give you an idea how your code has to change. + +Here are some of the more important changes: + +* Osmium now needs C++11. It will not work with older compilers. You need + at least GCC 4.7.3 or clang (LLVM) 3.2. + +* Namespaces are now all lower case. Everything is in the "osmium" namespace + or sub-namespaces of it. Many classes and functions have been moved to + different, more logical or shorter namespaces. + +* You can't just instantiate OSM objects such as Nodes, Ways, or Relations. + You need a Buffer first to hold them and use the Builder classes to + create them. This is a bit more cumbersome, but greatly reduces the need + for memory management and makes Osmium faster and easier to parallelize. + +* Usually you don't act on single OSM objects any more, but on groups of + them in a Buffer. + +* Reading and writing of OSM data is much simpler. Use the Reader and Writer + classes as they hide much of the detail and have much nicer interfaces + than the old Input/Output classes. + +* The class Osmium::OSM::Position was renamed to osmium::Location. This + better reflects that it is a location on the planet we are talking about. + The word "position" has many meanings and is, for instance, often used + to denote a position in a file or buffer or so. + +* The dependency on boost has been greatly reduced. C++11 offers many + features that used to be only available with boost, such as shared_ptr. + Osmium now uses the C++11 versions of these. + +* Osmium now makes use of the new C++11 threading support when reading and + writing OSM files. + diff --git a/README.md b/README.md new file mode 100644 index 000000000..8c7957f3b --- /dev/null +++ b/README.md @@ -0,0 +1,217 @@ +# Osmium Library + +http://osmcode.org/libosmium + +A fast and flexible C++ library for working with OpenStreetMap data. + +NOTE: This is a beta version of the next-generation Osmium. For production +use, see the Osmium version at https://github.com/joto/osmium . + +There are a few applications that use the Osmium library in the examples +directory. See the [osmium-contrib](http://github.com/osmcode/osmium-contrib) +repository for more example code. + +[![Build Status](https://secure.travis-ci.org/osmcode/libosmium.png)](http://travis-ci.org/osmcode/libosmium) +[![Build status](https://ci.appveyor.com/api/projects/status/mkbg6e6stdgq7c1b?svg=true)](https://ci.appveyor.com/project/Mapbox/libosmium) + +Libosmium is developed on Linux, but also works on OSX and Windows (with some +limitations). + +## Prerequisites + +Because Osmium uses many C++11 features you need a modern compiler and standard +C++ library. Osmium needs at least GCC 4.8 or clang (LLVM) 3.2. (Some parts may +work with older versions.) + +Different parts of Osmium (and the applications built on top of it) need +different libraries. You DO NOT NEED to install all of them, just install those +you need for the programs you need. + + boost-iterator, boost-regex + http://www.boost.org/ + Debian/Ubuntu: libboost-dev + openSUSE: boost-devel + Homebrew: boost + + boost-program-options (for parsing command line options in some examples) + http://www.boost.org/doc/libs/1_54_0/doc/html/program_options.html + Debian/Ubuntu: libboost-program-options-dev + + Google protocol buffers (for PBF support) + http://code.google.com/p/protobuf/ (at least version 2.3.0 needed) + Debian/Ubuntu: libprotobuf-dev protobuf-compiler + openSUSE: protobuf-devel + Homebrew: protobuf + Also see http://wiki.openstreetmap.org/wiki/PBF_Format + + OSMPBF (for PBF support) + https://github.com/scrosby/OSM-binary + Debian/Ubuntu: libosmpbf-dev + (The package in Ubuntu 14.04 and older is too old, install from source + in these cases.) + Homebrew: osm-pbf + + Expat (for parsing XML files) + http://expat.sourceforge.net/ + Debian/Ubuntu: libexpat1-dev + openSUSE: libexpat-devel + Homebrew: expat + + zlib (for PBF and for gzip support when reading/writing XML) + http://www.zlib.net/ + Debian/Ubuntu: zlib1g-dev + openSUSE: zlib-devel + + bz2lib (for bzip2 support when reading/writing XML) + http://www.bzip.org/ + Debian/Ubuntu: libbz2-dev + + Google sparsehash + http://code.google.com/p/google-sparsehash/ + Debian/Ubuntu: libsparsehash-dev + openSUSE: sparsehash + Homebrew: google-sparsehash + + GDAL (for OGR support) + http://gdal.org/ + Debian/Ubuntu: libgdal1-dev + openSUSE: libgdal-devel + Homebrew: gdal + + GEOS (for GEOS support) + http://trac.osgeo.org/geos/ + Debian/Ubuntu: libgeos++-dev + openSUSE: libgeos-devel + Homebrew: geos + + libproj (for projection support) + http://trac.osgeo.org/proj/ + Debian/Ubuntu: libproj-dev + + Doxygen (to build API documentation) and tools + http://www.stack.nl/~dimitri/doxygen/ + Debian/Ubuntu: doxygen graphviz xmlstarlet + Homebrew: doxygen + +You need to either install the packages for your distribution or install those +libraries from source. Most libraries should be available in all distributions. + + +## Directories + +* include: C/C++ include files. All of Osmium is in those header files which + are needed for building Osmium applications. + +* examples: Osmium example applications. + +* test: Tests (see below). + +* doc: Config for documentation. + + +## Building + +Osmium is a header-only library, so there is nothing to build for the +library itself. + +But there are some tests and examples that can be build. Libosmium uses +cmake: + + mkdir build + cd build + cmake .. + make + +This will build the examples and tests. Call `ctest` to run the tests. + +To build the documentation you need Doxygen. If cmake can find it it will +enable the `doc` target so you can build the documentation like this: + + make doc + +If the 'cppcheck' binary is found, cmake will add another target to the +Makfile which allows you to call cppheck on all `*.cpp` and `*.hpp` files: + + make cppcheck + +For Mac users: If you have clang 3.2 or newer, use the system compiler. +If not you have to build the compiler yourself. See the instructions +on http://clang.llvm.org/ . + +Preliminary support for cmake is provided. You can use this instead of "make": + + +## Testing + +### Unit Tests + +There are a few unit tests using the Catch unit test framework in the "test" +directory. Many more tests are needed, any help appreciated. + +For [Catch](https://github.com/philsquared/Catch/) only one header file is +needed which is included (`test/include/catch.hpp`). + +To compile these unit tests make sure `BUILD_UNIT_TESTS` is set in the cmake +config, then build the project and call + + ctest + +You can run tests matching a pattern by calling + + ctest -R test_name + +for instance: + + ctest basic_test_node + +will run the `basic_test_node` and `basic_test_node_ref` tests. + +### Data Tests + +In addition there are some test based on the OSM Test Data Repository at +http://osmcode.org/osm-testdata/ . Make sure `BUILD_DATA_TESTS` is set in the +cmake config, then build the project and call `ctest`. + +Some of these tests need Ruby and then 'json' gem installed. + +### Valgrind + +Running tests with valgrind: + + ctest -D ExperimentalMemCheck + + +## Osmium on 32bit Machines + +Osmium works well on 64 bit machines, but on 32 bit machines there are some +problems. Be aware that not everything will work on 32 bit architectures. +This is mostly due to the 64 bit needed for node IDs. Also Osmium hasn't been +tested well on 32 bit systems. Here are some issues you might run into: + +* Google Sparsehash does not work on 32 bit machines in our use case. +* The `mmap` system call is called with a `size_t` argument, so it can't + give you more than 4GByte of memory on 32 bit systems. This might be a + problem. + +Please report any issues you have and we might be able to solve them. + + +## Switching from the old Osmium + +See `README-changes-from-old-osmium`. + + +## License + +The Osmium Library is available under the Boost Software License. See +LICENSE.txt. + + +## Authors + +The Osmium Library was mainly written and is maintained by Jochen Topf +(jochen@topf.org). + +Other authors: +* Peter Körner (github@mazdermind.de) (PBF writer, ...) + diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..d084b7dad --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,55 @@ +# +# Configuration for appveyor.com +# + +environment: + matrix: + - configuration: Dev +# - configuration: Release + +# branches to build +branches: + # whitelist + only: + - master + +# Operating system (build VM template) +os: Windows Server 2012 R2 + +# scripts that are called at very beginning, before repo cloning +init: + +# clone directory +clone_folder: c:\projects\libosmium + +platform: x64 + +install: + # by default, all script lines are interpreted as batch + - cd c:\projects + - nuget install boost + - nuget install bzip2 + - nuget install zlib + - nuget install GDAL + - nuget install expat + - nuget install protobuf + - dir /S c:\projects + - git clone https://github.com/scrosby/OSM-binary + - cd OSM-binary + - mkdir build + - cd build + - call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64 + - cmake .. -G "Visual Studio 12 Win64" -DSEARCH_PREFIX=c:\projects -T CTP_Nov2013 + - msbuild /clp:Verbosity=minimal /nologo OSM-binary.sln + +build_script: + - cd c:\projects\libosmium + - mkdir build + - cd build + - call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64 + - SET PATH=C:\Program Files (x86)\MSBuild\12.0\bin\;%PATH% + - SET P=c:/projects/libosmium + - cmake .. -G "Visual Studio 12 Win64" -DCMAKE_BUILD_TYPE=%Configuration% -DCMAKE_PREFIX_PATH=c:\projects -DBoost_USE_STATIC_LIBS=ON -T CTP_Nov2013 + - msbuild /clp:Verbosity=minimal /nologo libosmium.sln + - msbuild /clp:Verbosity=minimal /nologo tests.vcxproj + diff --git a/cmake/FindOSMPBF.cmake b/cmake/FindOSMPBF.cmake new file mode 100644 index 000000000..deeebd8b6 --- /dev/null +++ b/cmake/FindOSMPBF.cmake @@ -0,0 +1,50 @@ +# +# Locate OSMPBF library +# +# This module defines +# OSMPBF_FOUND - if false, do not try to link to OSMPBF +# OSMPBF_LIBRARIES - full library path name +# OSMPBF_INCLUDE_DIRS - where to find OSMPBF.hpp +# +# Note that the expected include convention is +# #include +# and not +# #include +# + +find_path(OSMPBF_INCLUDE_DIR osmpbf/osmpbf.h + HINTS $ENV{OSMPBF_DIR} + PATH_SUFFIXES include + PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /opt/local # DarwinPorts + /opt +) + +find_library(OSMPBF_LIBRARY + NAMES osmpbf + HINTS $ENV{OSMPBF_DIR} + PATH_SUFFIXES lib64 lib + PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /opt/local + /opt +) + +# Handle the QUIETLY and REQUIRED arguments and set OSMPBF_FOUND to TRUE if +# all listed variables are TRUE. +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(OSMPBF DEFAULT_MSG OSMPBF_LIBRARY OSMPBF_INCLUDE_DIR) + +# Copy the results to the output variables. +if(OSMPBF_FOUND) + set(OSMPBF_INCLUDE_DIRS ${OSMPBF_INCLUDE_DIR}) + set(OSMPBF_LIBRARIES ${OSMPBF_LIBRARY}) +endif() + diff --git a/cmake/FindOsmium.cmake b/cmake/FindOsmium.cmake new file mode 100644 index 000000000..085983149 --- /dev/null +++ b/cmake/FindOsmium.cmake @@ -0,0 +1,285 @@ +#---------------------------------------------------------------------- +# +# FindOsmium.cmake +# +# Find the Libosmium headers and, optionally, several components needed for +# different Libosmium functions. +# +#---------------------------------------------------------------------- +# +# Usage: +# +# Copy this file (and OsmiumOptions.cmake) somewhere into your project +# directory, where cmake can find it. Usually this will be a directory +# called "cmake" which you can add to your module search path with the +# following line in your CMakeLists.txt: +# +# list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") +# +# Then add the following in your CMakeLists.txt: +# +# include(OsmiumOptions) +# find_package(Osmium REQUIRED COMPONENTS ) +# include_directories(${OSMIUM_INCLUDE_DIRS}) +# +# For the substitute a space separated list of one or more of the +# following components: +# +# pbf - include libraries needed for PBF input and output +# xml - include libraries needed for XML input and output +# io - include libraries needed for any type of input/output +# geos - include if you want to use any of the GEOS functions +# gdal - include if you want to use any of the OGR functions +# proj - include if you want to use any of the Proj.4 functions +# sparsehash - include if you use the sparsehash index +# +# You can check for success with something like this: +# +# if(NOT OSMIUM_FOUND) +# message(WARNING "Libosmium not found!\n") +# endif() +# +#---------------------------------------------------------------------- +# +# Variables: +# +# OSMIUM_FOUND - True if Osmium found. +# OSMIUM_INCLUDE_DIRS - Where to find include files. +# OSMIUM_XML_LIBRARIES - Libraries needed for XML I/O. +# OSMIUM_PBF_LIBRARIES - Libraries needed for PBF I/O. +# OSMIUM_IO_LIBRARIES - Libraries needed for XML or PBF I/O. +# OSMIUM_LIBRARIES - All libraries Osmium uses somewhere. +# +#---------------------------------------------------------------------- + +# Look for the header file. +find_path(OSMIUM_INCLUDE_DIR osmium/osm.hpp + PATH_SUFFIXES include + PATHS + ../libosmium + ../../libosmium + libosmium + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr/ + /opt/local # DarwinPorts + /opt +) + +# Handle the QUIETLY and REQUIRED arguments and set OSMIUM_FOUND to TRUE if +# all listed variables are TRUE. +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(OSMIUM REQUIRED_VARS OSMIUM_INCLUDE_DIR) + +# Copy the results to the output variables. +if(OSMIUM_FOUND) + set(OSMIUM_INCLUDE_DIRS ${OSMIUM_INCLUDE_DIR}) +endif() + +if(Osmium_FIND_REQUIRED AND NOT OSMIUM_FOUND) + message(FATAL_ERROR "Can not find libosmium headers, please install them or configure the paths") +endif() + +#---------------------------------------------------------------------- +# +# Check for optional components +# +#---------------------------------------------------------------------- +if(Osmium_FIND_COMPONENTS) + foreach(_component ${Osmium_FIND_COMPONENTS}) + string(TOUPPER ${_component} _component_uppercase) + set(Osmium_USE_${_component_uppercase} TRUE) + endforeach() +endif() + +#---------------------------------------------------------------------- +# Component 'io' is an alias for 'pbf' and 'xml' +if(Osmium_USE_IO) + set(Osmium_USE_PBF TRUE) + set(Osmium_USE_XML TRUE) +endif() + +#---------------------------------------------------------------------- +# Component 'ogr' is an alias for 'gdal' +if(Osmium_USE_OGR) + set(Osmium_USE_GDAL TRUE) +endif() + +#---------------------------------------------------------------------- +# Component 'pbf' +if(Osmium_USE_PBF) + find_package(OSMPBF) + find_package(Protobuf) + find_package(ZLIB) + find_package(Threads) + + if(OSMPBF_FOUND AND PROTOBUF_FOUND AND ZLIB_FOUND AND Threads_FOUND) + list(APPEND OSMIUM_PBF_LIBRARIES + ${OSMPBF_LIBRARIES} + ${PROTOBUF_LITE_LIBRARY} + ${ZLIB_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ) + if(WIN32) + list(APPEND OSMIUM_PBF_LIBRARIES ws2_32) + endif() + list(APPEND OSMIUM_INCLUDE_DIRS + ${OSMPBF_INCLUDE_DIRS} + ${PROTOBUF_INCLUDE_DIR} + ${ZLIB_INCLUDE_DIR} + ) + else() + set(_missing_libraries 1) + message(WARNING "Osmium: Can not find some libraries for PBF input/output, please install them or configure the paths.") + endif() +endif() + +#---------------------------------------------------------------------- +# Component 'xml' +if(Osmium_USE_XML) + find_package(EXPAT) + find_package(BZip2) + find_package(ZLIB) + find_package(Threads) + + if(EXPAT_FOUND AND BZIP2_FOUND AND ZLIB_FOUND AND Threads_FOUND) + list(APPEND OSMIUM_XML_LIBRARIES + ${EXPAT_LIBRARIES} + ${BZIP2_LIBRARIES} + ${ZLIB_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ) + list(APPEND OSMIUM_INCLUDE_DIRS + ${EXPAT_INCLUDE_DIR} + ${BZIP2_INCLUDE_DIR} + ${ZLIB_INCLUDE_DIR} + ) + else() + set(_missing_libraries 1) + message(WARNING "Osmium: Can not find some libraries for XML input/output, please install them or configure the paths.") + endif() +endif() + +#---------------------------------------------------------------------- +list(APPEND OSMIUM_IO_LIBRARIES + ${OSMIUM_PBF_LIBRARIES} + ${OSMIUM_XML_LIBRARIES} +) + +list(APPEND OSMIUM_LIBRARIES + ${OSMIUM_IO_LIBRARIES} +) + +#---------------------------------------------------------------------- +# Component 'geos' +if(Osmium_USE_GEOS) + find_path(GEOS_INCLUDE_DIR geos/geom.h) + find_library(GEOS_LIBRARY NAMES geos) + + if(GEOS_INCLUDE_DIR AND GEOS_LIBRARY) + SET(GEOS_FOUND 1) + list(APPEND OSMIUM_LIBRARIES ${GEOS_LIBRARY}) + list(APPEND OSMIUM_INCLUDE_DIRS ${GEOS_INCLUDE_DIR}) + else() + set(_missing_libraries 1) + message(WARNING "Osmium: GEOS library is required but not found, please install it or configure the paths.") + endif() +endif() + +#---------------------------------------------------------------------- +# Component 'gdal' (alias 'ogr') +if(Osmium_USE_GDAL) + find_package(GDAL) + + if(GDAL_FOUND) + list(APPEND OSMIUM_LIBRARIES ${GDAL_LIBRARIES}) + list(APPEND OSMIUM_INCLUDE_DIRS ${GDAL_INCLUDE_DIRS}) + else() + set(_missing_libraries 1) + message(WARNING "Osmium: GDAL library is required but not found, please install it or configure the paths.") + endif() +endif() + +#---------------------------------------------------------------------- +# Component 'proj' +if(Osmium_USE_PROJ) + find_path(PROJ_INCLUDE_DIR proj_api.h) + find_library(PROJ_LIBRARY NAMES proj) + + if(PROJ_INCLUDE_DIR AND PROJ_LIBRARY) + set(PROJ_FOUND 1) + list(APPEND OSMIUM_LIBRARIES ${PROJ_LIBRARY}) + list(APPEND OSMIUM_INCLUDE_DIRS ${PROJ_INCLUDE_DIR}) + else() + set(_missing_libraries 1) + message(WARNING "Osmium: PROJ.4 library is required but not found, please install it or configure the paths.") + endif() +endif() + +#---------------------------------------------------------------------- +# Component 'sparsehash' +if(Osmium_USE_SPARSEHASH) + find_path(SPARSEHASH_INCLUDE_DIR google/sparsetable) + + if(SPARSEHASH_INCLUDE_DIR) + set(SPARSEHASH_FOUND 1) + list(APPEND OSMIUM_INCLUDE_DIRS ${SPARSEHASH_INCLUDE_DIR}) + else() + set(_missing_libraries 1) + message(WARNING "Osmium: Google SparseHash library is required but not found, please install it or configure the paths.") + endif() +endif() + +#---------------------------------------------------------------------- + +list(REMOVE_DUPLICATES OSMIUM_INCLUDE_DIRS) +list(REMOVE_DUPLICATES OSMIUM_XML_LIBRARIES) +list(REMOVE_DUPLICATES OSMIUM_PBF_LIBRARIES) +list(REMOVE_DUPLICATES OSMIUM_IO_LIBRARIES) +list(REMOVE_DUPLICATES OSMIUM_LIBRARIES) + +#---------------------------------------------------------------------- +# +# Check that all required libraries are available +# +#---------------------------------------------------------------------- +if(Osmium_FIND_REQUIRED AND _missing_libraries) + message(FATAL_ERROR "Required library or libraries missing. Aborting.") +endif() + +#---------------------------------------------------------------------- +# +# Add compiler flags +# +#---------------------------------------------------------------------- +add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64) + +if(MSVC) + add_definitions(-wd4996 -DNOMINMAX -DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_WARNINGS) +endif() + +if(APPLE) +# following only available from cmake 2.8.12: +# add_compile_options(-stdlib=libc++) +# so using this instead: + add_definitions(-stdlib=libc++) + set(LDFLAGS ${LDFLAGS} -stdlib=libc++) +endif() + +#---------------------------------------------------------------------- + +# This is a set of recommended warning options that can be added when compiling +# libosmium code. +set(OSMIUM_WARNING_OPTIONS "-Wall -Wextra -pedantic -Wredundant-decls -Wdisabled-optimization -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wsign-promo -Wold-style-cast -Wno-return-type" CACHE STRING "Recommended warning options for libosmium") + +set(OSMIUM_DRACONIC_CLANG_OPTIONS "-Wdocumentation -Wunused-exception-parameter -Wmissing-declarations -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-unused-macros -Wno-exit-time-destructors -Wno-global-constructors -Wno-padded -Wno-switch-enum -Wno-missing-prototypes -Wno-weak-vtables -Wno-cast-align -Wno-float-equal") + +if(Osmium_DEBUG) + message(STATUS "OSMIUM_XML_LIBRARIES=" ${OSMIUM_XML_LIBRARIES}) + message(STATUS "OSMIUM_PBF_LIBRARIES=" ${OSMIUM_PBF_LIBRARIES}) + message(STATUS "OSMIUM_IO_LIBRARIES=" ${OSMIUM_IO_LIBRARIES}) + message(STATUS "OSMIUM_LIBRARIES=" ${OSMIUM_LIBRARIES}) + message(STATUS "OSMIUM_INCLUDE_DIRS=" ${OSMIUM_INCLUDE_DIRS}) +endif() + diff --git a/cmake/build.bat b/cmake/build.bat new file mode 100644 index 000000000..5ffab124e --- /dev/null +++ b/cmake/build.bat @@ -0,0 +1,15 @@ +call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64 +set CMAKE_PREFIX_PATH=C:\PROJ +set VERSION=Debug +set TESTS=ON +set ALLHPPS=ON +set PREFIX=d:\libs18d +set BOOST_ROOT=d:\boost + +cmake .. -G "Visual Studio 12 Win64" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=%PREFIX% -DBOOST_ROOT=%BOOST_ROOT% -DBoost_USE_STATIC_LIBS=ON -DBUILD_TESTING=%TESTS% -DBUILD_TRY_HPPS=%ALLHPPS$ -T CTP_Nov2013 +msbuild /clp:Verbosity=minimal /nologo libosmium.sln /flp1:logfile=build_errors.txt;errorsonly /flp2:logfile=build_warnings.txt;warningsonly +set PATH=%PATH%;%PREFIX%/bin + +del test\osm-testdata\*.db +del test\osm-testdata\*.json +if "%TESTS%"=="ON" ctest -VV >build_tests.log diff --git a/cmake/iwyu.sh b/cmake/iwyu.sh new file mode 100755 index 000000000..d20384491 --- /dev/null +++ b/cmake/iwyu.sh @@ -0,0 +1,43 @@ +#!/bin/sh +# +# This will run IWYU (Include What You Use) on includes files. The iwyu +# program isn't very reliable and crashes often, but is still useful. +# +# TODO: This script should be integrated with cmake in some way... +# + +cmdline="iwyu -Xiwyu --mapping_file=osmium.imp -std=c++11 -I include" + +log=build/iwyu.log + +echo "INCLUDE WHAT YOU USE REPORT:" >$log + +allok=yes + +mkdir -p build/check_reports + +for file in `find include/osmium -name \*.hpp`; do + mkdir -p `dirname build/check_reports/$file` + ifile="build/check_reports/${file%.hpp}.iwyu" + $cmdline $file >$ifile 2>&1 + if grep -q 'has correct #includes/fwd-decls' ${ifile}; then + echo "\n\033[1m\033[32m========\033[0m \033[1m${file}\033[0m" >>$log + echo "[OK] ${file}" + elif grep -q 'Assertion failed' ${ifile}; then + echo "\n\033[1m======== ${file}\033[0m" >>$log + echo "[--] ${file}" + allok=no + else + echo "\n\033[1m\033[31m========\033[0m \033[1m${file}\033[0m" >>$log + echo "[ ] ${file}" + allok=no + fi + cat $ifile >>$log +done + +if [ "$allok" = "yes" ]; then + echo "All files OK" +else + echo "There were errors" +fi + diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in new file mode 100644 index 000000000..e48d2da7e --- /dev/null +++ b/doc/Doxyfile.in @@ -0,0 +1,2313 @@ +# Doxyfile 1.8.7 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "Osmium" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = @LIBOSMIUM_VERSION@ + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "Fast and flexible C++ library for working with OpenStreetMap data" + +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = "@PROJECT_BINARY_DIR@/doc" + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. Do not use file names with spaces, bibtex cannot handle them. See +# also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = @PROJECT_SOURCE_DIR@/include/osmium \ + @PROJECT_SOURCE_DIR@/doc/doc.txt + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = *.hpp + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = detail + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = *::detail + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = NO + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- +# defined cascading style sheet that is included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet file to the output directory. For an example +# see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = doc/osmium.css + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NONE + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /\n"; + break; + case operation::op_modify: + m_out += " \n"; + break; + case operation::op_delete: + m_out += " \n"; + break; + } + + switch (op) { + case operation::op_none: + break; + case operation::op_create: + m_out += " \n"; + break; + case operation::op_modify: + m_out += " \n"; + break; + case operation::op_delete: + m_out += " \n"; + break; + } + + m_last_op = op; + } + + public: + + explicit XMLOutputBlock(osmium::memory::Buffer&& buffer, bool write_visible_flag, bool write_change_ops) : + m_input_buffer(std::move(buffer)), + m_write_visible_flag(write_visible_flag && !write_change_ops), + m_write_change_ops(write_change_ops) { + } + + XMLOutputBlock(const XMLOutputBlock&) = delete; + XMLOutputBlock& operator=(const XMLOutputBlock&) = delete; + + XMLOutputBlock(XMLOutputBlock&&) = default; + XMLOutputBlock& operator=(XMLOutputBlock&&) = default; + + std::string operator()() { + osmium::apply(m_input_buffer.cbegin(), m_input_buffer.cend(), *this); + + if (m_write_change_ops) { + open_close_op_tag(); + } + + std::string out; + std::swap(out, m_out); + return out; + } + + void node(const osmium::Node& node) { + if (m_write_change_ops) { + open_close_op_tag(node.visible() ? (node.version() == 1 ? operation::op_create : operation::op_modify) : operation::op_delete); + } + + write_prefix(); + m_out += "\n", node_ref.ref()); + } + + write_tags(way.tags()); + + write_prefix(); + m_out += "\n"; + } + + void relation(const osmium::Relation& relation) { + if (m_write_change_ops) { + open_close_op_tag(relation.visible() ? (relation.version() == 1 ? operation::op_create : operation::op_modify) : operation::op_delete); + } + + write_prefix(); + m_out += "\n"; + } + + write_tags(relation.tags()); + + write_prefix(); + m_out += "\n"; + } + + void changeset(const osmium::Changeset& changeset) { + write_prefix(); + m_out += "\n"; + } else { + out += "\n"; + } + + for (const auto& box : header.boxes()) { + out += " \n", box.top_right().lat()); + } + + std::promise promise; + m_output_queue.push(promise.get_future()); + promise.set_value(std::move(out)); + } + + void close() override final { + { + std::string out; + if (m_file.is_true("xml_change_format")) { + out += "\n"; + } else { + out += "\n"; + } + + std::promise promise; + m_output_queue.push(promise.get_future()); + promise.set_value(std::move(out)); + } + + std::promise promise; + m_output_queue.push(promise.get_future()); + promise.set_value(std::string()); + } + + }; // class XMLOutputFormat + + namespace { + + const bool registered_xml_output = osmium::io::detail::OutputFormatFactory::instance().register_output_format(osmium::io::file_format::xml, + [](const osmium::io::File& file, data_queue_type& output_queue) { + return new osmium::io::detail::XMLOutputFormat(file, output_queue); + }); + + } // anonymous namespace + + } // namespace detail + + } // namespace output + +} // namespace osmium + +#endif // OSMIUM_IO_DETAIL_XML_OUTPUT_FORMAT_HPP diff --git a/include/osmium/io/detail/zlib.hpp b/include/osmium/io/detail/zlib.hpp new file mode 100644 index 000000000..b16ff6a99 --- /dev/null +++ b/include/osmium/io/detail/zlib.hpp @@ -0,0 +1,97 @@ +#ifndef OSMIUM_IO_DETAIL_ZLIB_HPP +#define OSMIUM_IO_DETAIL_ZLIB_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include + +#include + +namespace osmium { + + namespace io { + + namespace detail { + + /** + * Compress data using zlib. + * + * @param input Data to compress. + * @returns Compressed data. + */ + inline std::string zlib_compress(const std::string& input) { + unsigned long output_size = ::compressBound(input.size()); + + std::string output(output_size, '\0'); + + if (::compress(reinterpret_cast(const_cast(output.data())), + &output_size, + reinterpret_cast(input.data()), + input.size()) != Z_OK) { + throw std::runtime_error("failed to compress data"); + } + + output.resize(output_size); + + return output; + } + + /** + * Uncompress data using zlib. + * + * @param input Compressed input data. + * @param raw_size Size of uncompressed data. + * @returns Uncompressed data. + */ + inline std::unique_ptr zlib_uncompress(const std::string& input, unsigned long raw_size) { + auto output = std::unique_ptr(new std::string(raw_size, '\0')); + + if (::uncompress(reinterpret_cast(const_cast(output->data())), + &raw_size, + reinterpret_cast(input.data()), + input.size()) != Z_OK) { + throw std::runtime_error("failed to uncompress data"); + } + + return output; + } + + } // namespace detail + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_DETAIL_ZLIB_HPP diff --git a/include/osmium/io/error.hpp b/include/osmium/io/error.hpp new file mode 100644 index 000000000..8fb9f05f6 --- /dev/null +++ b/include/osmium/io/error.hpp @@ -0,0 +1,57 @@ +#ifndef OSMIUM_IO_ERROR_HPP +#define OSMIUM_IO_ERROR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 + +namespace osmium { + + /** + * Exception thrown when some kind of input/output operation failed. + */ + struct io_error : public std::runtime_error { + + io_error(const std::string& what) : + std::runtime_error(what) { + } + + io_error(const char* what) : + std::runtime_error(what) { + } + + }; // struct io_error + +} // namespace osmium + +#endif // OSMIUM_IO_ERROR_HPP diff --git a/include/osmium/io/file.hpp b/include/osmium/io/file.hpp new file mode 100644 index 000000000..21469b865 --- /dev/null +++ b/include/osmium/io/file.hpp @@ -0,0 +1,343 @@ +#ifndef OSMIUM_IO_FILE_HPP +#define OSMIUM_IO_FILE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include +#include + +#include +#include +#include + +namespace osmium { + + /** + * @brief Everything related to input and output of OSM data. + */ + namespace io { + + namespace detail { + + inline std::vector split(const std::string& in, const char delim) { + std::vector result; + std::stringstream ss(in); + std::string item; + while (std::getline(ss, item, delim)) { + result.push_back(item); + } + return result; + } + + } // namespace detail + + /** + * This class describes an OSM file in one of several different formats. + * + * If the filename is empty or "-", this means stdin or stdout is used. + */ + class File : public osmium::util::Options { + + private: + + std::string m_filename; + + const char* m_buffer; + size_t m_buffer_size; + + std::string m_format_string; + + file_format m_file_format {file_format::unknown}; + + file_compression m_file_compression {file_compression::none}; + + bool m_has_multiple_object_versions {false}; + + public: + + /** + * Create File using type and encoding from filename or given + * format specification. + * + * @param filename Filename including suffix. The type and encoding + * of the file will be taken from the suffix. + * An empty filename or "-" means stdin or stdout. + * @param format File format as string. See the description of the + * parse_format() function for details. + */ + explicit File(const std::string& filename = "", const std::string& format = "") : + Options(), + m_filename(filename), + m_buffer(nullptr), + m_buffer_size(0), + m_format_string(format) { + + // stdin/stdout + if (filename == "" || filename == "-") { + m_filename = ""; + default_settings_for_stdinout(); + } + + // filename is actually a URL + std::string protocol = m_filename.substr(0, m_filename.find_first_of(':')); + if (protocol == "http" || protocol == "https") { + default_settings_for_url(); + } + + detect_format_from_suffix(m_filename); + + if (format != "") { + parse_format(format); + } + } + + /** + * Create File using buffer pointer and size and type and encoding + * from given format specification. + * + * @param buffer Pointer to buffer with data. + * @param size Size of buffer. + * @param format File format as string. See the description of the + * parse_format() function for details. + */ + explicit File(const char* buffer, size_t size, const std::string& format = "") : + Options(), + m_filename(), + m_buffer(buffer), + m_buffer_size(size), + m_format_string(format) { + + default_settings_for_stdinout(); + + if (format != "") { + parse_format(format); + } + } + + File(const File&) = default; + File& operator=(const File&) = default; + + File(File&&) = default; + File& operator=(File&&) = default; + + ~File() = default; + + const char* buffer() const noexcept { + return m_buffer; + } + + size_t buffer_size() const noexcept { + return m_buffer_size; + } + + void parse_format(const std::string& format) { + std::vector options = detail::split(format, ','); + + // if the first item in the format list doesn't contain + // an equals sign, it is a format + if (!options.empty() && options[0].find_first_of('=') == std::string::npos) { + detect_format_from_suffix(options[0]); + options.erase(options.begin()); + } + + for (auto& option : options) { + size_t pos = option.find_first_of('='); + if (pos == std::string::npos) { + set(option, true); + } else { + std::string value = option.substr(pos+1); + option.erase(pos); + set(option, value); + } + } + + if (get("history") == "true") { + m_has_multiple_object_versions = true; + } else if (get("history") == "false") { + m_has_multiple_object_versions = false; + } + } + + void detect_format_from_suffix(const std::string& name) { + std::vector suffixes = detail::split(name, '.'); + + if (suffixes.empty()) return; + + // if the last suffix is one of a known set of compressions, + // set that compression + if (suffixes.back() == "gz") { + m_file_compression = file_compression::gzip; + suffixes.pop_back(); + } else if (suffixes.back() == "bz2") { + m_file_compression = file_compression::bzip2; + suffixes.pop_back(); + } + + if (suffixes.empty()) return; + + // if the last suffix is one of a known set of formats, + // set that format + if (suffixes.back() == "pbf") { + m_file_format = file_format::pbf; + suffixes.pop_back(); + } else if (suffixes.back() == "xml") { + m_file_format = file_format::xml; + suffixes.pop_back(); + } else if (suffixes.back() == "opl") { + m_file_format = file_format::opl; + suffixes.pop_back(); + } + + if (suffixes.empty()) return; + + if (suffixes.back() == "osm") { + if (m_file_format == file_format::unknown) m_file_format = file_format::xml; + suffixes.pop_back(); + } else if (suffixes.back() == "osh") { + if (m_file_format == file_format::unknown) m_file_format = file_format::xml; + m_has_multiple_object_versions = true; + suffixes.pop_back(); + } else if (suffixes.back() == "osc") { + if (m_file_format == file_format::unknown) m_file_format = file_format::xml; + m_has_multiple_object_versions = true; + set("xml_change_format", true); + suffixes.pop_back(); + } + } + + /** + * Check file format etc. for consistency and throw exception if there + * is a problem. + * + * @throws std::runtime_error + */ + void check() const { + if (m_file_format == file_format::unknown) { + std::string msg = "Could not detect file format"; + if (!m_format_string.empty()) { + msg += " from format string '"; + msg += m_format_string; + msg += "'"; + } + if (m_filename.empty()) { + msg += " for stdin/stdout"; + } else { + msg += " for filename '"; + msg += m_filename; + msg += "'"; + } + msg += "."; + throw std::runtime_error(msg); + } + } + + /** + * Set default settings for type and encoding when the filename is + * empty or "-". If you want to have a different default setting + * override this in a subclass. + */ + void default_settings_for_stdinout() { + m_file_format = file_format::unknown; + m_file_compression = file_compression::none; + } + + /** + * Set default settings for type and encoding when the filename is + * a normal file. If you want to have a different default setting + * override this in a subclass. + */ + void default_settings_for_file() { + m_file_format = file_format::unknown; + m_file_compression = file_compression::none; + } + + /** + * Set default settings for type and encoding when the filename is a URL. + * If you want to have a different default setting override this in a + * subclass. + */ + void default_settings_for_url() { + m_file_format = file_format::xml; + m_file_compression = file_compression::none; + } + + file_format format() const noexcept { + return m_file_format; + } + + File& set_format(file_format format) noexcept { + m_file_format = format; + return *this; + } + + file_compression compression() const noexcept { + return m_file_compression; + } + + File& set_compression(file_compression compression) noexcept { + m_file_compression = compression; + return *this; + } + + bool has_multiple_object_versions() const noexcept { + return m_has_multiple_object_versions; + } + + File& set_has_multiple_object_versions(bool value) noexcept { + m_has_multiple_object_versions = value; + return *this; + } + + File& filename(const std::string& filename) { + if (filename == "-") { + m_filename = ""; + } else { + m_filename = filename; + } + return *this; + } + + const std::string& filename() const noexcept { + return m_filename; + } + + }; // class File + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_FILE_HPP diff --git a/include/osmium/io/file_compression.hpp b/include/osmium/io/file_compression.hpp new file mode 100644 index 000000000..c71871553 --- /dev/null +++ b/include/osmium/io/file_compression.hpp @@ -0,0 +1,72 @@ +#ifndef OSMIUM_IO_FILE_COMPRESSION_HPP +#define OSMIUM_IO_FILE_COMPRESSION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 + +namespace osmium { + + namespace io { + + enum class file_compression { + none = 0, + gzip = 1, + bzip2 = 2 + }; + +// avoid g++ false positive +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wreturn-type" + inline const char* as_string(file_compression compression) { + switch (compression) { + case file_compression::none: + return "none"; + case file_compression::gzip: + return "gzip"; + case file_compression::bzip2: + return "bzip2"; + } + } +#pragma GCC diagnostic pop + + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const file_compression compression) { + return out << as_string(compression); + } + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_FILE_COMPRESSION_HPP diff --git a/include/osmium/io/file_format.hpp b/include/osmium/io/file_format.hpp new file mode 100644 index 000000000..5a4aa5c01 --- /dev/null +++ b/include/osmium/io/file_format.hpp @@ -0,0 +1,78 @@ +#ifndef OSMIUM_IO_FILE_FORMAT_HPP +#define OSMIUM_IO_FILE_FORMAT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 + +namespace osmium { + + namespace io { + + enum class file_format { + unknown = 0, + xml = 1, + pbf = 2, + opl = 3, + json = 4 + }; + +// avoid g++ false positive +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wreturn-type" + inline const char* as_string(file_format format) { + switch (format) { + case file_format::unknown: + return "unknown"; + case file_format::xml: + return "XML"; + case file_format::pbf: + return "PBF"; + case file_format::opl: + return "OPL"; + case file_format::json: + return "JSON"; + } + } +#pragma GCC diagnostic pop + + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const file_format format) { + return out << as_string(format); + } + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_FILE_FORMAT_HPP diff --git a/include/osmium/io/gzip_compression.hpp b/include/osmium/io/gzip_compression.hpp new file mode 100644 index 000000000..c1f8888ba --- /dev/null +++ b/include/osmium/io/gzip_compression.hpp @@ -0,0 +1,237 @@ +#ifndef OSMIUM_IO_GZIP_COMPRESSION_HPP +#define OSMIUM_IO_GZIP_COMPRESSION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include + +#include +#include + +#include +#include +#include +#include + +namespace osmium { + + /** + * Exception thrown when there are problems compressing or + * decompressing gzip files. + */ + struct gzip_error : public std::runtime_error { + + int gzip_error_code; + int system_errno; + + gzip_error(const std::string& what, int error_code) : + std::runtime_error(what), + gzip_error_code(error_code), + system_errno(error_code == Z_ERRNO ? errno : 0) { + } + + }; // struct gzip_error + + namespace io { + + namespace detail { + + OSMIUM_NORETURN inline void throw_gzip_error(gzFile gzfile, const char* msg, int zlib_error=0) { + std::string error("gzip error: "); + error += msg; + error += ": "; + int errnum = zlib_error; + if (zlib_error) { + error += std::to_string(zlib_error); + } else { + error += ::gzerror(gzfile, &errnum); + } + throw osmium::gzip_error(error, errnum); + } + + } // namespace detail + + class GzipCompressor : public Compressor { + + gzFile m_gzfile; + + public: + + explicit GzipCompressor(int fd) : + Compressor(), + m_gzfile(::gzdopen(fd, "w")) { + if (!m_gzfile) { + detail::throw_gzip_error(m_gzfile, "write initialization failed"); + } + } + + ~GzipCompressor() override final { + close(); + } + + void write(const std::string& data) override final { + if (!data.empty()) { + int nwrite = ::gzwrite(m_gzfile, data.data(), static_cast_with_assert(data.size())); + if (nwrite == 0) { + detail::throw_gzip_error(m_gzfile, "write failed"); + } + } + } + + void close() override final { + if (m_gzfile) { + int result = ::gzclose(m_gzfile); + m_gzfile = nullptr; + if (result != Z_OK) { + detail::throw_gzip_error(m_gzfile, "write close failed", result); + } + } + } + + }; // class GzipCompressor + + class GzipDecompressor : public Decompressor { + + gzFile m_gzfile; + + public: + + explicit GzipDecompressor(int fd) : + Decompressor(), + m_gzfile(::gzdopen(fd, "r")) { + if (!m_gzfile) { + detail::throw_gzip_error(m_gzfile, "read initialization failed"); + } + } + + ~GzipDecompressor() override final { + close(); + } + + std::string read() override final { + std::string buffer(osmium::io::Decompressor::input_buffer_size, '\0'); + int nread = ::gzread(m_gzfile, const_cast(buffer.data()), static_cast_with_assert(buffer.size())); + if (nread < 0) { + detail::throw_gzip_error(m_gzfile, "read failed"); + } + buffer.resize(static_cast(nread)); + return buffer; + } + + void close() override final { + if (m_gzfile) { + int result = ::gzclose(m_gzfile); + m_gzfile = nullptr; + if (result != Z_OK) { + detail::throw_gzip_error(m_gzfile, "read close failed", result); + } + } + } + + }; // class GzipDecompressor + + class GzipBufferDecompressor : public Decompressor { + + const char* m_buffer; + size_t m_buffer_size; + z_stream m_zstream; + + public: + + GzipBufferDecompressor(const char* buffer, size_t size) : + m_buffer(buffer), + m_buffer_size(size), + m_zstream() { + m_zstream.next_in = reinterpret_cast(const_cast(buffer)); + m_zstream.avail_in = static_cast_with_assert(size); + int result = inflateInit2(&m_zstream, MAX_WBITS | 32); + if (result != Z_OK) { + std::string message("gzip error: decompression init failed: "); + if (m_zstream.msg) { + message.append(m_zstream.msg); + } + throw osmium::gzip_error(message, result); + } + } + + ~GzipBufferDecompressor() override final { + inflateEnd(&m_zstream); + } + + std::string read() override final { + std::string output; + + if (m_buffer) { + const size_t buffer_size = 10240; + output.append(buffer_size, '\0'); + m_zstream.next_out = reinterpret_cast(const_cast(output.data())); + m_zstream.avail_out = buffer_size; + int result = inflate(&m_zstream, Z_SYNC_FLUSH); + + if (result != Z_OK) { + m_buffer = nullptr; + m_buffer_size = 0; + } + + if (result != Z_OK && result != Z_STREAM_END) { + std::string message("gzip error: inflate failed: "); + if (m_zstream.msg) { + message.append(m_zstream.msg); + } + throw osmium::gzip_error(message, result); + } + + output.resize(static_cast(m_zstream.next_out - reinterpret_cast(output.data()))); + } + + return output; + } + + }; // class GzipBufferDecompressor + + namespace { + + const bool registered_gzip_compression = osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::gzip, + [](int fd) { return new osmium::io::GzipCompressor(fd); }, + [](int fd) { return new osmium::io::GzipDecompressor(fd); }, + [](const char* buffer, size_t size) { return new osmium::io::GzipBufferDecompressor(buffer, size); } + ); + + } // anonymous namespace + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_GZIP_COMPRESSION_HPP diff --git a/include/osmium/io/header.hpp b/include/osmium/io/header.hpp new file mode 100644 index 000000000..0fdbf77fc --- /dev/null +++ b/include/osmium/io/header.hpp @@ -0,0 +1,122 @@ +#ifndef OSMIUM_IO_HEADER_HPP +#define OSMIUM_IO_HEADER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include + +#include +#include + +namespace osmium { + + namespace io { + + /** + * Meta information from the header of an OSM file. + */ + class Header : public osmium::util::Options { + + /// Bounding boxes + std::vector m_boxes; + + /** + * Are there possibly multiple versions of the same object in this stream of objects? + * This is true for history files and for change files, but not for normal OSM files. + */ + bool m_has_multiple_object_versions = false; + + public: + + Header() = default; + + explicit Header(const std::initializer_list& values) : + Options(values) { + } + + Header(const Header&) = default; + Header& operator=(const Header&) = default; + + Header(Header&&) = default; + Header& operator=(Header&&) = default; + + ~Header() = default; + + std::vector& boxes() noexcept { + return m_boxes; + } + + const std::vector& boxes() const noexcept { + return m_boxes; + } + + Header& boxes(const std::vector& boxes) noexcept { + m_boxes = boxes; + return *this; + } + + osmium::Box box() const { + return m_boxes.empty() ? osmium::Box() : m_boxes.front(); + } + + osmium::Box joined_boxes() const { + osmium::Box box; + for (const auto& b : m_boxes) { + box.extend(b.bottom_left()); + box.extend(b.top_right()); + } + return box; + } + + Header& add_box(const osmium::Box& box) { + m_boxes.push_back(box); + return *this; + } + + bool has_multiple_object_versions() const noexcept { + return m_has_multiple_object_versions; + } + + Header& set_has_multiple_object_versions(bool value) noexcept { + m_has_multiple_object_versions = value; + return *this; + } + + }; // class Header + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_HEADER_HPP diff --git a/include/osmium/io/input_iterator.hpp b/include/osmium/io/input_iterator.hpp new file mode 100644 index 000000000..a2e3b83b3 --- /dev/null +++ b/include/osmium/io/input_iterator.hpp @@ -0,0 +1,139 @@ +#ifndef OSMIUM_IO_INPUT_ITERATOR_HPP +#define OSMIUM_IO_INPUT_ITERATOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include +#include + +#include +#include + +namespace osmium { + + namespace io { + + /** + * This iterator class allows you to iterate over all items from a + * source. It hides all the buffer handling and makes the contents of a + * source accessible as a normal STL input iterator. + */ + template + class InputIterator { + + static_assert(std::is_base_of::value, "TItem must derive from osmium::buffer::Item"); + + typedef typename osmium::memory::Buffer::t_iterator item_iterator; + + TSource* m_source; + std::shared_ptr m_buffer; + item_iterator m_iter {}; + + void update_buffer() { + do { + m_buffer = std::make_shared(std::move(m_source->read())); + if (!m_buffer || !*m_buffer) { // end of input + m_source = nullptr; + m_buffer.reset(); + m_iter = item_iterator(); + return; + } + m_iter = m_buffer->begin(); + } while (m_iter == m_buffer->end()); + } + + public: + + typedef std::input_iterator_tag iterator_category; + typedef TItem value_type; + typedef ptrdiff_t difference_type; + typedef TItem* pointer; + typedef TItem& reference; + + explicit InputIterator(TSource& source) : + m_source(&source) { + update_buffer(); + } + + // end iterator + InputIterator() noexcept : + m_source(nullptr) { + } + + InputIterator& operator++() { + assert(m_source); + assert(m_buffer); + assert(m_iter); + ++m_iter; + if (m_iter == m_buffer->end()) { + update_buffer(); + } + return *this; + } + + InputIterator operator++(int) { + InputIterator tmp(*this); + operator++(); + return tmp; + } + + bool operator==(const InputIterator& rhs) const noexcept { + return m_source == rhs.m_source && + m_buffer == rhs.m_buffer && + m_iter == rhs.m_iter; + } + + bool operator!=(const InputIterator& rhs) const noexcept { + return !(*this == rhs); + } + + reference operator*() const { + assert(m_iter); + return static_cast(*m_iter); + } + + pointer operator->() const { + assert(m_iter); + return &static_cast(*m_iter); + } + + }; // class InputIterator + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_INPUT_ITERATOR_HPP diff --git a/include/osmium/io/opl_output.hpp b/include/osmium/io/opl_output.hpp new file mode 100644 index 000000000..46a12240b --- /dev/null +++ b/include/osmium/io/opl_output.hpp @@ -0,0 +1,39 @@ +#ifndef OSMIUM_IO_OPL_OUTPUT_HPP +#define OSMIUM_IO_OPL_OUTPUT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 // IWYU pragma: export +#include // IWYU pragma: export + +#endif // OSMIUM_IO_OPL_OUTPUT_HPP diff --git a/include/osmium/io/output_iterator.hpp b/include/osmium/io/output_iterator.hpp new file mode 100644 index 000000000..e6a9cc096 --- /dev/null +++ b/include/osmium/io/output_iterator.hpp @@ -0,0 +1,116 @@ +#ifndef OSMIUM_IO_OUTPUT_ITERATOR_HPP +#define OSMIUM_IO_OUTPUT_ITERATOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include + +#include +#include + +namespace osmium { + + namespace memory { + class Item; + } // namespace memory + + namespace io { + + template + class OutputIterator : public std::iterator { + + struct buffer_wrapper { + + osmium::memory::Buffer buffer; + + buffer_wrapper(size_t buffer_size) : + buffer(buffer_size, osmium::memory::Buffer::auto_grow::no) { + } + + }; // struct buffer_wrapper + + static constexpr size_t default_buffer_size = 10 * 1024 * 1024; + + TDest* m_destination; + + std::shared_ptr m_buffer_wrapper; + + public: + + explicit OutputIterator(TDest& destination, const size_t buffer_size = default_buffer_size) : + m_destination(&destination), + m_buffer_wrapper(std::make_shared(buffer_size)) { + } + + void flush() { + osmium::memory::Buffer buffer(m_buffer_wrapper->buffer.capacity(), osmium::memory::Buffer::auto_grow::no); + std::swap(m_buffer_wrapper->buffer, buffer); + (*m_destination)(std::move(buffer)); + } + + OutputIterator& operator=(const osmium::memory::Item& item) { + try { + m_buffer_wrapper->buffer.push_back(item); + } catch (osmium::buffer_is_full&) { + flush(); + m_buffer_wrapper->buffer.push_back(item); + } + return *this; + } + + OutputIterator& operator=(const osmium::DiffObject& diff) { + return this->operator=(diff.curr()); + } + + OutputIterator& operator*() { + return *this; + } + + OutputIterator& operator++() { + return *this; + } + + OutputIterator& operator++(int) { + return *this; + } + + }; // class OutputIterator + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_OUTPUT_ITERATOR_HPP diff --git a/include/osmium/io/overwrite.hpp b/include/osmium/io/overwrite.hpp new file mode 100644 index 000000000..f29a93228 --- /dev/null +++ b/include/osmium/io/overwrite.hpp @@ -0,0 +1,52 @@ +#ifndef OSMIUM_IO_OVERWRITE_HPP +#define OSMIUM_IO_OVERWRITE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf 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. + +*/ + +namespace osmium { + + namespace io { + + /** + * Allow overwriting of existing file. + */ + enum class overwrite : bool { + no = false, + allow = true + }; + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_OVERWRITE_HPP diff --git a/include/osmium/io/pbf_input.hpp b/include/osmium/io/pbf_input.hpp new file mode 100644 index 000000000..8426f6cf6 --- /dev/null +++ b/include/osmium/io/pbf_input.hpp @@ -0,0 +1,39 @@ +#ifndef OSMIUM_IO_PBF_INPUT_HPP +#define OSMIUM_IO_PBF_INPUT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 // IWYU pragma: export +#include // IWYU pragma: export + +#endif // OSMIUM_IO_PBF_INPUT_HPP diff --git a/include/osmium/io/pbf_output.hpp b/include/osmium/io/pbf_output.hpp new file mode 100644 index 000000000..9fd039654 --- /dev/null +++ b/include/osmium/io/pbf_output.hpp @@ -0,0 +1,39 @@ +#ifndef OSMIUM_IO_PBF_OUTPUT_HPP +#define OSMIUM_IO_PBF_OUTPUT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 // IWYU pragma: export +#include // IWYU pragma: export + +#endif // OSMIUM_IO_PBF_OUTPUT_HPP diff --git a/include/osmium/io/reader.hpp b/include/osmium/io/reader.hpp new file mode 100644 index 000000000..a9b8b954d --- /dev/null +++ b/include/osmium/io/reader.hpp @@ -0,0 +1,303 @@ +#ifndef OSMIUM_IO_READER_HPP +#define OSMIUM_IO_READER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +# include +#endif + +#ifndef _MSC_VER +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace io { + + /** + * This is the user-facing interface for reading OSM files. Instantiate + * an object of this class with a file name or osmium::io::File object + * and then call read() on it in a loop until it returns an invalid + * Buffer. + */ + class Reader { + + osmium::io::File m_file; + osmium::osm_entity_bits::type m_read_which_entities; + std::atomic m_input_done; + int m_childpid; + + osmium::thread::Queue m_input_queue; + + std::unique_ptr m_decompressor; + std::future m_read_future; + + std::unique_ptr m_input; + +#ifndef _WIN32 + /** + * Fork and execute the given command in the child. + * A pipe is created between the child and the parent. + * The child writes to the pipe, the parent reads from it. + * This function never returns in the child. + * + * @param command Command to execute in the child. + * @param filename Filename to give to command as argument. + * @returns File descriptor of pipe in the parent. + * @throws std::system_error if a system call fails. + */ + static int execute(const std::string& command, const std::string& filename, int* childpid) { + int pipefd[2]; + if (pipe(pipefd) < 0) { + throw std::system_error(errno, std::system_category(), "opening pipe failed"); + } + pid_t pid = fork(); + if (pid < 0) { + throw std::system_error(errno, std::system_category(), "fork failed"); + } + if (pid == 0) { // child + // close all file descriptors except one end of the pipe + for (int i=0; i < 32; ++i) { + if (i != pipefd[1]) { + ::close(i); + } + } + if (dup2(pipefd[1], 1) < 0) { // put end of pipe as stdout/stdin + exit(1); + } + + ::open("/dev/null", O_RDONLY); // stdin + ::open("/dev/null", O_WRONLY); // stderr + // hack: -g switches off globbing in curl which allows [] to be used in file names + // this is important for XAPI URLs + // in theory this execute() function could be used for other commands, but it is + // only used for curl at the moment, so this is okay. + if (::execlp(command.c_str(), command.c_str(), "-g", filename.c_str(), nullptr) < 0) { + exit(1); + } + } + // parent + *childpid = pid; + ::close(pipefd[1]); + return pipefd[0]; + } +#endif + + /** + * Open File for reading. Handles URLs or normal files. URLs + * are opened by executing the "curl" program (which must be installed) + * and reading from its output. + * + * @returns File descriptor of open file or pipe. + * @throws std::system_error if a system call fails. + */ + static int open_input_file_or_url(const std::string& filename, int* childpid) { + std::string protocol = filename.substr(0, filename.find_first_of(':')); + if (protocol == "http" || protocol == "https" || protocol == "ftp" || protocol == "file") { +#ifndef _WIN32 + return execute("curl", filename, childpid); +#else + throw std::runtime_error("Reading OSM files from the network currently not supported on Windows."); +#endif + } else { + return osmium::io::detail::open_for_reading(filename); + } + } + + public: + + /** + * Create new Reader object. + * + * @param file The file we want to open. + * @param read_which_entities 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. + */ + explicit Reader(const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities = osmium::osm_entity_bits::all) : + m_file(file), + m_read_which_entities(read_which_entities), + m_input_done(false), + m_childpid(0), + m_input_queue(20, "raw_input"), // XXX + m_decompressor(m_file.buffer() ? + osmium::io::CompressionFactory::instance().create_decompressor(file.compression(), m_file.buffer(), m_file.buffer_size()) : + osmium::io::CompressionFactory::instance().create_decompressor(file.compression(), open_input_file_or_url(m_file.filename(), &m_childpid))), + m_read_future(std::async(std::launch::async, detail::ReadThread(m_input_queue, m_decompressor.get(), m_input_done))), + m_input(osmium::io::detail::InputFormatFactory::instance().create_input(m_file, m_read_which_entities, m_input_queue)) { + } + + explicit Reader(const std::string& filename, osmium::osm_entity_bits::type read_types = osmium::osm_entity_bits::all) : + Reader(osmium::io::File(filename), read_types) { + } + + explicit Reader(const char* filename, osmium::osm_entity_bits::type read_types = osmium::osm_entity_bits::all) : + Reader(osmium::io::File(filename), read_types) { + } + + Reader(const Reader&) = delete; + Reader& operator=(const Reader&) = delete; + + ~Reader() { + try { + close(); + } + catch (...) { + } + } + + /** + * Close down the Reader. A call to this is optional, because the + * destructor of Reader will also call this. But if you don't call + * this function first, the destructor might throw an exception + * which is not good. + * + * @throws Some form of std::runtime_error when there is a problem. + */ + void close() { + // Signal to input child process that it should wrap up. + m_input_done = true; + + m_input->close(); + +#ifndef _WIN32 + if (m_childpid) { + int status; + pid_t pid = ::waitpid(m_childpid, &status, 0); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" + if (pid < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) { + throw std::system_error(errno, std::system_category(), "subprocess returned error"); + } +#pragma GCC diagnostic pop + m_childpid = 0; + } +#endif + + osmium::thread::wait_until_done(m_read_future); + } + + /** + * Get the header data from the file. + */ + osmium::io::Header header() const { + return m_input->header(); + } + + /** + * Reads the next buffer from the input. An invalid buffer signals + * end-of-file. After end-of-file all read() calls will return an + * invalid buffer. An invalid buffer is also always returned if + * osmium::osm_entity_bits::nothing was set when the Reader was + * constructed. + * + * @returns Buffer. + * @throws Some form of std::runtime_error if there is an error. + */ + osmium::memory::Buffer read() { + // If an exception happened in the input thread, re-throw + // it in this (the main) thread. + osmium::thread::check_for_exception(m_read_future); + + if (m_read_which_entities == osmium::osm_entity_bits::nothing || m_input_done) { + // If the caller didn't want anything but the header, it will + // always get an empty buffer here. + return osmium::memory::Buffer(); + } + + osmium::memory::Buffer buffer = m_input->read(); + if (!buffer) { + m_input_done = true; + } + return buffer; + } + + /** + * Has the end of file been reached? This is set after the last + * data has been read. It is also set by calling close(). + */ + bool eof() const { + return m_input_done; + } + + }; // class Reader + + /** + * Read contents of the given file into a buffer in one go. Takes + * the same arguments as any of the Reader constructors. + * + * The buffer can take up quite a lot of memory, so don't do this + * unless you are working with small OSM files and/or have lots of + * RAM. + */ + template + osmium::memory::Buffer read_file(TArgs&&... args) { + osmium::memory::Buffer buffer(1024*1024, osmium::memory::Buffer::auto_grow::yes); + + Reader reader(std::forward(args)...); + while (osmium::memory::Buffer read_buffer = reader.read()) { + buffer.add_buffer(read_buffer); + buffer.commit(); + } + + return buffer; + } + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_READER_HPP diff --git a/include/osmium/io/reader_iterator.hpp b/include/osmium/io/reader_iterator.hpp new file mode 100644 index 000000000..8d71418e0 --- /dev/null +++ b/include/osmium/io/reader_iterator.hpp @@ -0,0 +1,51 @@ +#ifndef OSMIUM_IO_READER_ITERATOR_HPP +#define OSMIUM_IO_READER_ITERATOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf 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 +#include + +namespace std { + + inline osmium::io::InputIterator begin(osmium::io::Reader& reader) { + return osmium::io::InputIterator(reader); + } + + inline osmium::io::InputIterator end(osmium::io::Reader&) { + return osmium::io::InputIterator(); + } + +} // namespace std + +#endif // OSMIUM_IO_READER_ITERATOR_HPP diff --git a/include/osmium/io/writer.hpp b/include/osmium/io/writer.hpp new file mode 100644 index 000000000..7e9bd1383 --- /dev/null +++ b/include/osmium/io/writer.hpp @@ -0,0 +1,145 @@ +#ifndef OSMIUM_IO_WRITER_HPP +#define OSMIUM_IO_WRITER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace io { + + /** + * This is the user-facing interface for writing OSM files. Instantiate + * an object of this class with a file name or osmium::io::File object + * and optionally the data for the header and then call operator() on it + * to write Buffers. Call close() to finish up. + */ + class Writer { + + osmium::io::File m_file; + + osmium::io::detail::data_queue_type m_output_queue; + + std::unique_ptr m_output; + + std::unique_ptr m_compressor; + + std::future m_write_future; + + public: + + /** + * The constructor of the Writer object opens a file and writes the + * header to it. + * + * @param file File (contains name and format info) to open. + * @param header Optional header data. If this is not given sensible + * defaults will be used. See the default constructor + * of osmium::io::Header for details. + * @param allow_overwrite Allow overwriting of existing file? Can be + * osmium::io::overwrite::allow or osmium::io::overwrite::no+ + * (default). + * + * @throws std::runtime_error If the file could not be opened. + * @throws std::system_error If the file could not be opened. + */ + explicit Writer(const osmium::io::File& file, const osmium::io::Header& header = osmium::io::Header(), overwrite allow_overwrite = overwrite::no) : + m_file(file), + m_output_queue(20, "raw_output"), // XXX + m_output(osmium::io::detail::OutputFormatFactory::instance().create_output(m_file, m_output_queue)), + m_compressor(osmium::io::CompressionFactory::instance().create_compressor(file.compression(), osmium::io::detail::open_for_writing(m_file.filename(), allow_overwrite))), + m_write_future(std::async(std::launch::async, detail::WriteThread(m_output_queue, m_compressor.get()))) { + assert(!m_file.buffer()); + m_output->write_header(header); + } + + explicit Writer(const std::string& filename, const osmium::io::Header& header = osmium::io::Header(), overwrite allow_overwrite = overwrite::no) : + Writer(osmium::io::File(filename), header, allow_overwrite) { + } + + explicit Writer(const char* filename, const osmium::io::Header& header = osmium::io::Header(), overwrite allow_overwrite = overwrite::no) : + Writer(osmium::io::File(filename), header, allow_overwrite) { + } + + Writer(const Writer&) = delete; + Writer& operator=(const Writer&) = delete; + + ~Writer() { + close(); + } + + /** + * Write contents of a buffer to the output file. + * + * @throws Some form of std::runtime_error when there is a problem. + */ + void operator()(osmium::memory::Buffer&& buffer) { + osmium::thread::check_for_exception(m_write_future); + if (buffer.committed() > 0) { + m_output->write_buffer(std::move(buffer)); + } + } + + /** + * Flush writes to output file and closes it. If you do not + * call this, the destructor of Writer will also do the same + * thing. But because this call might thrown an exception, + * it is better to call close() explicitly. + * + * @throws Some form of std::runtime_error when there is a problem. + */ + void close() { + m_output->close(); + osmium::thread::wait_until_done(m_write_future); + } + + }; // class Writer + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_WRITER_HPP diff --git a/include/osmium/io/xml_input.hpp b/include/osmium/io/xml_input.hpp new file mode 100644 index 000000000..f33d37ee2 --- /dev/null +++ b/include/osmium/io/xml_input.hpp @@ -0,0 +1,39 @@ +#ifndef OSMIUM_IO_XML_INPUT_HPP +#define OSMIUM_IO_XML_INPUT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 // IWYU pragma: export +#include // IWYU pragma: export + +#endif // OSMIUM_IO_XML_INPUT_HPP diff --git a/include/osmium/io/xml_output.hpp b/include/osmium/io/xml_output.hpp new file mode 100644 index 000000000..d5b839f60 --- /dev/null +++ b/include/osmium/io/xml_output.hpp @@ -0,0 +1,39 @@ +#ifndef OSMIUM_IO_XML_OUTPUT_HPP +#define OSMIUM_IO_XML_OUTPUT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 // IWYU pragma: export +#include // IWYU pragma: export + +#endif // OSMIUM_IO_XML_OUTPUT_HPP diff --git a/include/osmium/memory/buffer.hpp b/include/osmium/memory/buffer.hpp new file mode 100644 index 000000000..8c05ced21 --- /dev/null +++ b/include/osmium/memory/buffer.hpp @@ -0,0 +1,535 @@ +#ifndef OSMIUM_MEMORY_BUFFER_HPP +#define OSMIUM_MEMORY_BUFFER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace osmium { + + /** + * Exception thrown by the osmium::memory::Buffer class when somebody tries + * to write data into a buffer and it doesn't fit. Buffers with internal + * memory management will not throw this exception, but increase their size. + */ + struct buffer_is_full : public std::runtime_error { + + buffer_is_full() : + std::runtime_error("Osmium buffer is full") { + } + + }; // struct buffer_is_full + + /** + * @brief Memory management of items in buffers and iterators over this data. + */ + namespace memory { + + /** + * A memory area for storing OSM objects and other items. Each item stored + * has a type and a length. See the Item class for details. + * + * Data can be added to a buffer piece by piece using reserve_space() and + * add_item(). After all data that together forms an item is added, it must + * be committed using the commit() call. Usually this is done through the + * Builder class and its derived classes. + * + * You can iterate over all items in a buffer using the iterators returned + * by begin(), end(), cbegin(), and cend(). + * + * Buffers exist in two flavours, those with external memory management and + * those with internal memory management. If you already have some memory + * with data in it (for instance read from disk), you create a Buffer with + * external memory managment. It is your job then to free the memory once + * the buffer isn't used any more. If you don't have memory already, you can + * create a Buffer object and have it manage the memory internally. It will + * dynamically allocate memory and free it again after use. + * + * By default, if a buffer gets full it will throw a buffer_is_full exception. + * You can use the set_full_callback() method to set a callback functor + * which will be called instead of throwing an exception. + */ + class Buffer { + + public: + + enum class auto_grow : bool { + yes = true, + no = false + }; // enum class auto_grow + + private: + + std::vector m_memory; + unsigned char* m_data; + size_t m_capacity; + size_t m_written; + size_t m_committed; + auto_grow m_auto_grow {auto_grow::no}; + std::function m_full; + + public: + + typedef Item value_type; + + /** + * The constructor without any parameters creates a non-initialized + * buffer, ie an empty hull of a buffer that has no actual memory + * associated with it. It can be used to signify end-of-input. + */ + Buffer() noexcept : + m_memory(), + m_data(nullptr), + m_capacity(0), + m_written(0), + m_committed(0) { + } + + /** + * Constructs an externally memory-managed buffer using the given + * memory and size. + * + * @param data A pointer to some already initialized data. + * @param size The size of the initialized data. + * @throws std::invalid_argument When the size isn't a multiple of the alignment. + */ + explicit Buffer(unsigned char* data, size_t size) : + m_memory(), + m_data(data), + m_capacity(size), + m_written(size), + m_committed(size) { + if (size % align_bytes != 0) { + throw std::invalid_argument("buffer size needs to be multiple of alignment"); + } + } + + /** + * Constructs an externally memory-managed buffer with the given + * capacity that already contains 'committed' bytes of data. + * + * @param data A pointer to some (possibly initialized) data. + * @param capacity The size of the memory for this buffer. + * @param committed The size of the initialized data. If this is 0, the buffer startes out empty. + * @throws std::invalid_argument When the capacity or committed isn't a multiple of the alignment. + */ + explicit Buffer(unsigned char* data, size_t capacity, size_t committed) : + m_memory(), + m_data(data), + m_capacity(capacity), + m_written(committed), + m_committed(committed) { + if (capacity % align_bytes != 0) { + throw std::invalid_argument("buffer capacity needs to be multiple of alignment"); + } + if (committed % align_bytes != 0) { + throw std::invalid_argument("buffer parameter 'committed' needs to be multiple of alignment"); + } + } + + /** + * Create an internally memory-managed buffer with the given capacity. + * different in that it internally gets dynamic memory of the + * required size. The dynamic memory will be automatically + * freed when the Buffer is destroyed. + */ + explicit Buffer(size_t capacity, auto_grow auto_grow = auto_grow::yes) : + m_memory(capacity), + m_data(m_memory.data()), + m_capacity(capacity), + m_written(0), + m_committed(0), + m_auto_grow(auto_grow) { + if (capacity % align_bytes != 0) { + throw std::invalid_argument("buffer capacity needs to be multiple of alignment"); + } + } + + // buffers can not be copied + Buffer(const Buffer&) = delete; + Buffer& operator=(const Buffer&) = delete; + + // buffers can be moved + Buffer(Buffer&&) = default; + Buffer& operator=(Buffer&&) = default; + + ~Buffer() = default; + + /** + * Return a pointer to data inside the buffer. + */ + unsigned char* data() const noexcept { + return m_data; + } + + /** + * Returns the capacity of the buffer, ie how many bytes it can contain. + */ + size_t capacity() const noexcept { + return m_capacity; + } + + /** + * Returns the number of bytes already filled in this buffer. + */ + size_t committed() const noexcept { + return m_committed; + } + + /** + * Returns the number of bytes currently filled in this buffer that + * are not yet committed. + */ + size_t written() const noexcept { + return m_written; + } + + /** + * This tests if the current state of the buffer is aligned + * properly. Can be used for asserts. + */ + bool is_aligned() const noexcept { + return (m_written % align_bytes == 0) && (m_committed % align_bytes == 0); + } + + /** + * Set functor to be called whenever the buffer is full + * instead of throwing buffer_is_full. + */ + void set_full_callback(std::function full) { + m_full = full; + } + + /** + * Grow capacity of this buffer to the given size. + * This works only with internally memory-managed buffers. + * If the given size is not larger than the current capacity, nothing is done. + * Already written but not committed data is discarded. + * + * @param size New capacity. + */ + void grow(size_t size) { + if (m_memory.empty()) { + throw std::logic_error("Can't grow Buffer if it doesn't use internal memory management."); + } + if (m_capacity < size) { + if (size % align_bytes != 0) { + throw std::invalid_argument("buffer capacity needs to be multiple of alignment"); + } + m_memory.resize(size); + m_data = m_memory.data(); + m_capacity = size; + } + } + + /** + * Mark currently written bytes in the buffer as committed. + * + * @returns Last number of committed bytes before this commit. + */ + size_t commit() { + assert(is_aligned()); + + const size_t offset = m_committed; + m_committed = m_written; + return offset; + } + + /** + * Roll back changes in buffer to last committed state. + */ + void rollback() { + m_written = m_committed; + } + + /** + * Clear the buffer. + * + * @returns Number of bytes in the buffer before it was cleared. + */ + size_t clear() { + const size_t committed = m_committed; + m_written = 0; + m_committed = 0; + return committed; + } + + /** + * Get the data in the buffer at the given offset. + * + * @tparam T Type we want to the data to be interpreted as. + * @returns Reference of given type pointing to the data in the buffer. + */ + template + T& get(const size_t offset) const { + return *reinterpret_cast(&m_data[offset]); + } + + /** + * Reserve space of given size in buffer and return pointer to it. + * This is the only way of adding data to the buffer. You reserve + * the space and then fill it. + * + * Note that you have to eventually call commit() to actually + * commit this data. + * + * If there isn't enough space in the buffer, one of three things + * can happen: + * + * * If you have set a callback with set_full_callback(), it is + * called. After the call returns, you must have either grown + * the buffer or cleared it by calling buffer.clear(). + * * If no callback is defined and this buffer uses internal + * memory management, the buffers capacity is grown, so that + * the new data will fit. + * * Else the buffer_is_full exception is thrown. + * + * @param size Number of bytes to reserve. + * @returns Pointer to reserved space. Note that this pointer is + * only guaranteed to be valid until the next call to + * reserve_space(). + * @throws osmium::buffer_is_full Might be thrown if the buffer is full. + */ + unsigned char* reserve_space(const size_t size) { + if (m_written + size > m_capacity) { + if (m_full) { + m_full(*this); + } else if (!m_memory.empty() && (m_auto_grow == auto_grow::yes)) { + // double buffer size until there is enough space + size_t new_capacity = m_capacity * 2; + while (m_written + size > new_capacity) { + new_capacity *= 2; + } + grow(new_capacity); + } else { + throw osmium::buffer_is_full(); + } + } + unsigned char* data = &m_data[m_written]; + m_written += size; + return data; + } + + /** + * Add an item to the buffer. The size of the item is stored inside + * the item, so we know how much memory to copy. + * + * Note that you have to eventually call commit() to actually + * commit this data. + * + * @tparam T Class of the item to be copied. + * @param item Reference to the item to be copied. + * @returns Reference to newly copied data in the buffer. + */ + template + T& add_item(const T& item) { + unsigned char* target = reserve_space(item.padded_size()); + std::copy_n(reinterpret_cast(&item), item.padded_size(), target); + return *reinterpret_cast(target); + } + + /** + * Add committed contents of the given buffer to this buffer. + * + * Note that you have to eventually call commit() to actually + * commit this data. + */ + void add_buffer(const Buffer& buffer) { + unsigned char* target = reserve_space(buffer.committed()); + std::copy_n(reinterpret_cast(buffer.data()), buffer.committed(), target); + } + + /** + * Add an item to the buffer. This function is provided so that + * you can use std::back_inserter. + */ + void push_back(const osmium::memory::Item& item) { + add_item(item); + commit(); + } + + /** + * These iterators can be used to iterate over all items in + * a buffer. + */ + template + using t_iterator = osmium::memory::ItemIterator; + + template + using t_const_iterator = osmium::memory::ItemIterator; + + typedef t_iterator iterator; + typedef t_const_iterator const_iterator; + + template + t_iterator begin() { + return t_iterator(m_data, m_data + m_committed); + } + + iterator begin() { + return iterator(m_data, m_data + m_committed); + } + + template + t_iterator end() { + return t_iterator(m_data + m_committed, m_data + m_committed); + } + + iterator end() { + return iterator(m_data + m_committed, m_data + m_committed); + } + + template + t_const_iterator cbegin() const { + return t_const_iterator(m_data, m_data + m_committed); + } + + const_iterator cbegin() const { + return const_iterator(m_data, m_data + m_committed); + } + + template + t_const_iterator cend() const { + return t_const_iterator(m_data + m_committed, m_data + m_committed); + } + + const_iterator cend() const { + return const_iterator(m_data + m_committed, m_data + m_committed); + } + + template + t_const_iterator begin() const { + return cbegin(); + } + + const_iterator begin() const { + return cbegin(); + } + + template + t_const_iterator end() const { + return cend(); + } + + const_iterator end() const { + return cend(); + } + + /** + * In a bool context any initialized buffer is true. + */ + explicit operator bool() const { + return m_data != nullptr; + } + + friend void swap(Buffer& lhs, Buffer& rhs) { + using std::swap; + + swap(lhs.m_memory, rhs.m_memory); + swap(lhs.m_data, rhs.m_data); + swap(lhs.m_capacity, rhs.m_capacity); + swap(lhs.m_written, rhs.m_written); + swap(lhs.m_committed, rhs.m_committed); + } + + /** + * Purge removed items from the buffer. This is done by moving all + * non-removed items forward in the buffer overwriting removed + * items and then correcting the m_written and m_committed numbers. + * + * Note that calling this function invalidates all iterators on this + * buffer and all offsets in this buffer. + * + * For every non-removed item that moves its position, the function + * 'moving_in_buffer' is called on the given callback object with + * the old and new offsets in the buffer where the object used to + * be and is now, respectively. This call can be used to update any + * indexes. + */ + template + void purge_removed(TCallbackClass* callback) { + if (begin() == end()) { + return; + } + + iterator it_write = begin(); + + iterator next; + for (iterator it_read = begin(); it_read != end(); it_read = next) { + next = std::next(it_read); + if (!it_read->removed()) { + if (it_read != it_write) { + assert(it_read.data() >= data()); + assert(it_write.data() >= data()); + size_t old_offset = static_cast(it_read.data() - data()); + size_t new_offset = static_cast(it_write.data() - data()); + callback->moving_in_buffer(old_offset, new_offset); + std::memmove(it_write.data(), it_read.data(), it_read->padded_size()); + } + it_write.advance_once(); + } + } + + assert(it_write.data() >= data()); + m_written = static_cast(it_write.data() - data()); + m_committed = m_written; + } + + }; // class Buffer + + inline bool operator==(const Buffer& lhs, const Buffer& rhs) noexcept { + return lhs.data() == rhs.data() && lhs.capacity() == rhs.capacity() && lhs.committed() == rhs.committed(); + } + + inline bool operator!=(const Buffer& lhs, const Buffer& rhs) noexcept { + return ! (lhs == rhs); + } + + } // namespace memory + +} // namespace osmium + +#endif // OSMIUM_MEMORY_BUFFER_HPP diff --git a/include/osmium/memory/collection.hpp b/include/osmium/memory/collection.hpp new file mode 100644 index 000000000..b25dd64ec --- /dev/null +++ b/include/osmium/memory/collection.hpp @@ -0,0 +1,153 @@ +#ifndef OSMIUM_MEMORY_COLLECTION_HPP +#define OSMIUM_MEMORY_COLLECTION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include + +#include + +namespace osmium { + + namespace memory { + + template + class CollectionIterator : public std::iterator { + + // This data_type is either 'unsigned char*' or 'const unsigned char*' depending + // on whether TMember is const. This allows this class to be used as an iterator and + // as a const_iterator. + typedef typename std::conditional::value, const unsigned char*, unsigned char*>::type data_type; + + data_type m_data; + + public: + + CollectionIterator() noexcept : + m_data(nullptr) { + } + + CollectionIterator(data_type data) noexcept : + m_data(data) { + } + + CollectionIterator& operator++() { + m_data = reinterpret_cast(m_data)->next(); + return *static_cast*>(this); + } + + CollectionIterator operator++(int) { + CollectionIterator tmp(*this); + operator++(); + return tmp; + } + + bool operator==(const CollectionIterator& rhs) const noexcept { + return m_data == rhs.m_data; + } + + bool operator!=(const CollectionIterator& rhs) const noexcept { + return m_data != rhs.m_data; + } + + unsigned char* data() const noexcept { + return m_data; + } + + TMember& operator*() const { + return *reinterpret_cast(m_data); + } + + TMember* operator->() const { + return reinterpret_cast(m_data); + } + + template + friend std::basic_ostream& operator<<(std::basic_ostream& out, const CollectionIterator& iter) { + return out << static_cast(iter.m_data); + } + + }; // class CollectionIterator + + template + class Collection : public Item { + + public: + + typedef CollectionIterator iterator; + typedef CollectionIterator const_iterator; + typedef TMember value_type; + + static constexpr osmium::item_type itemtype = TCollectionItemType; + + Collection() : + Item(sizeof(Collection), TCollectionItemType) { + } + + bool empty() const { + return sizeof(Collection) == byte_size(); + } + + iterator begin() { + return iterator(data() + sizeof(Collection)); + } + + iterator end() { + return iterator(data() + byte_size()); + } + + const_iterator cbegin() const { + return const_iterator(data() + sizeof(Collection)); + } + + const_iterator cend() const { + return const_iterator(data() + byte_size()); + } + + const_iterator begin() const { + return cbegin(); + } + + const_iterator end() const { + return cend(); + } + + }; // class Collection + + } // namespace memory + +} // namespace osmium + +#endif // OSMIUM_MEMORY_COLLECTION_HPP diff --git a/include/osmium/memory/item.hpp b/include/osmium/memory/item.hpp new file mode 100644 index 000000000..2d22f948e --- /dev/null +++ b/include/osmium/memory/item.hpp @@ -0,0 +1,179 @@ +#ifndef OSMIUM_MEMORY_ITEM_HPP +#define OSMIUM_MEMORY_ITEM_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include + +namespace osmium { + + // forward declaration, see osmium/osm/item_type.hpp for declaration + enum class item_type : uint16_t; + + namespace builder { + class Builder; + } + + namespace memory { + + typedef uint32_t item_size_type; + + // align datastructures to this many bytes + constexpr item_size_type align_bytes = 8; + + template + inline T padded_length(T length) noexcept { + static_assert(std::is_integral::value && std::is_unsigned::value, + "Template parameter must be unsigned integral type"); + return (length + align_bytes - 1) & ~(align_bytes - 1); + } + + /** + * @brief Namespace for Osmium internal use + */ + namespace detail { + + /** + * This class contains only a helper method used in several + * other classes. + */ + class ItemHelper { + + protected: + + ItemHelper() = default; + + ~ItemHelper() = default; + + ItemHelper(const ItemHelper&) = default; + ItemHelper(ItemHelper&&) = default; + + ItemHelper& operator=(const ItemHelper&) = default; + ItemHelper& operator=(ItemHelper&&) = default; + + public: + + unsigned char* data() noexcept { + return reinterpret_cast(this); + } + + const unsigned char* data() const noexcept { + return reinterpret_cast(this); + } + + }; // class ItemHelper + + } // namespace detail + + class Item : public osmium::memory::detail::ItemHelper { + + item_size_type m_size; + item_type m_type; + uint16_t m_removed : 1; + uint16_t m_padding : 15; + + template + friend class CollectionIterator; + + template + friend class ItemIterator; + + friend class osmium::builder::Builder; + + Item& add_size(const item_size_type size) noexcept { + m_size += size; + return *this; + } + + protected: + + explicit Item(item_size_type size=0, item_type type=item_type()) noexcept : + m_size(size), + m_type(type), + m_removed(false), + m_padding(0) { + } + + Item(const Item&) = delete; + Item(Item&&) = delete; + + Item& operator=(const Item&) = delete; + Item& operator=(Item&&) = delete; + + Item& set_type(const item_type item_type) noexcept { + m_type = item_type; + return *this; + } + + public: + + unsigned char* next() noexcept { + return data() + padded_size(); + } + + const unsigned char* next() const noexcept { + return data() + padded_size(); + } + + item_size_type byte_size() const noexcept { + return m_size; + } + + item_size_type padded_size() const { + return padded_length(m_size); + } + + item_type type() const noexcept { + return m_type; + } + + bool removed() const noexcept { + return m_removed; + } + + void set_removed(bool removed) noexcept { + m_removed = removed; + } + + }; // class Item + + static_assert(sizeof(Item) == 8, "Class osmium::Item has wrong size!"); + static_assert(sizeof(Item) % align_bytes == 0, "Class osmium::Item has wrong size to be aligned properly!"); + + } // namespace memory + +} // namespace osmium + +#endif // OSMIUM_MEMORY_ITEM_HPP diff --git a/include/osmium/memory/item_iterator.hpp b/include/osmium/memory/item_iterator.hpp new file mode 100644 index 000000000..34ed60083 --- /dev/null +++ b/include/osmium/memory/item_iterator.hpp @@ -0,0 +1,234 @@ +#ifndef OSMIUM_ITEM_ITERATOR_HPP +#define OSMIUM_ITEM_ITERATOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf 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 +#include +#include +#include + +#include +#include + +namespace osmium { + + class Node; + class Way; + class Relation; + class Area; + class Changeset; + class OSMObject; + class OSMEntity; + class TagList; + class WayNodeList; + class RelationMemberList; + class InnerRing; + class OuterRing; + + namespace memory { + + namespace detail { + + template + inline bool type_is_compatible(osmium::item_type) noexcept { + return true; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) noexcept { + return t == osmium::item_type::node; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) noexcept { + return t == osmium::item_type::way; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) noexcept { + return t == osmium::item_type::relation; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) noexcept { + return t == osmium::item_type::area; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) noexcept { + return t == osmium::item_type::changeset; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) noexcept { + return t == osmium::item_type::node || t == osmium::item_type::way || t == osmium::item_type::relation || t == osmium::item_type::area; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) noexcept { + return t == osmium::item_type::node || t == osmium::item_type::way || t == osmium::item_type::relation || t == osmium::item_type::area || t == osmium::item_type::changeset; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) noexcept { + return t == osmium::item_type::tag_list; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) noexcept { + return t == osmium::item_type::way_node_list; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) noexcept { + return t == osmium::item_type::relation_member_list || t == osmium::item_type::relation_member_list_with_full_members; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) noexcept { + return t == osmium::item_type::outer_ring; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) noexcept { + return t == osmium::item_type::inner_ring; + } + + } // namespace detail + + template + class ItemIterator : public std::iterator { + + static_assert(std::is_base_of::value, "TMember must derive from osmium::memory::Item"); + + // This data_type is either 'unsigned char*' or 'const unsigned char*' depending + // on whether TMember is const. This allows this class to be used as an iterator and + // as a const_iterator. + typedef typename std::conditional::value, const unsigned char*, unsigned char*>::type data_type; + + data_type m_data; + data_type m_end; + + void advance_to_next_item_of_right_type() { + while (m_data != m_end && + !detail::type_is_compatible::type>(reinterpret_cast(m_data)->type())) { + m_data = reinterpret_cast(m_data)->next(); + } + } + + public: + + ItemIterator() noexcept : + m_data(nullptr), + m_end(nullptr) { + } + + ItemIterator(data_type data, data_type end) : + m_data(data), + m_end(end) { + advance_to_next_item_of_right_type(); + } + + template + ItemIterator cast() const { + return ItemIterator(m_data, m_end); + } + + ItemIterator& operator++() { + assert(m_data); + assert(m_data != m_end); + m_data = reinterpret_cast(m_data)->next(); + advance_to_next_item_of_right_type(); + return *static_cast*>(this); + } + + /** + * Like operator++() but will NOT skip items of unwanted + * types. Do not use this unless you know what you are + * doing. + */ + ItemIterator& advance_once() { + assert(m_data); + assert(m_data != m_end); + m_data = reinterpret_cast(m_data)->next(); + return *static_cast*>(this); + } + + ItemIterator operator++(int) { + ItemIterator tmp(*this); + operator++(); + return tmp; + } + + bool operator==(const ItemIterator& rhs) const { + return m_data == rhs.m_data && m_end == rhs.m_end; + } + + bool operator!=(const ItemIterator& rhs) const { + return !(*this == rhs); + } + + unsigned char* data() const { + assert(m_data); + return m_data; + } + + TMember& operator*() const { + assert(m_data); + assert(m_data != m_end); + return *reinterpret_cast(m_data); + } + + TMember* operator->() const { + assert(m_data); + assert(m_data != m_end); + return reinterpret_cast(m_data); + } + + explicit operator bool() const { + return m_data != nullptr; + } + + template + friend std::basic_ostream& operator<<(std::basic_ostream& out, const ItemIterator& iter) { + return out << static_cast(iter.m_data); + } + + }; // class ItemIterator + + } // namespace memory + +} // namespace osmium + +#endif // OSMIUM_ITEM_ITERATOR_HPP diff --git a/include/osmium/object_pointer_collection.hpp b/include/osmium/object_pointer_collection.hpp new file mode 100644 index 000000000..22029a149 --- /dev/null +++ b/include/osmium/object_pointer_collection.hpp @@ -0,0 +1,112 @@ +#ifndef OSMIUM_OBJECT_POINTER_COLLECTION_HPP +#define OSMIUM_OBJECT_POINTER_COLLECTION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include + +#include + +#include +#include +#include + +// IWYU pragma: no_forward_declare osmium::OSMObject +// IWYU pragma: no_forward_declare osmium::memory::Item + +namespace osmium { + + /** + * A collection of pointers to OSM objects. The pointers can be easily + * and quickly sorted or otherwise manipulated, while the objects + * themselves or the buffers they are in, do not have to be changed. + * + * An iterator is provided that can iterate over the pointers but looks + * like it is iterating over the underlying OSM objects. + * + * This class implements the visitor pattern which makes it easy to + * populate the collection from a buffer of OSM objects: + * + * osmium::ObjectPointerCollection objects; + * osmium::memory::Buffer buffer = reader.read(); + * osmium::apply(buffer, objects); + * + */ + class ObjectPointerCollection : public osmium::handler::Handler { + + std::vector m_objects; + + public: + + typedef boost::indirect_iterator::iterator, osmium::OSMObject> iterator; + typedef boost::indirect_iterator::const_iterator, const osmium::OSMObject> const_iterator; + + ObjectPointerCollection() noexcept : + m_objects() { + } + + void osm_object(osmium::OSMObject& object) { + m_objects.push_back(&object); + } + + /** + * Sort objects according to the given order functor. + */ + template + void sort(TCompare&& compare) { + std::sort(m_objects.begin(), m_objects.end(), std::forward(compare)); + } + + iterator begin() { + return iterator { m_objects.begin() }; + } + + iterator end() { + return iterator { m_objects.end() }; + } + + const_iterator cbegin() const { + return const_iterator { m_objects.cbegin() }; + } + + const_iterator cend() const { + return const_iterator { m_objects.cend() }; + } + + }; // class ObjectPointerCollection + +} // namespace osmium + +#endif // OSMIUM_OBJECT_POINTER_COLLECTION_HPP diff --git a/include/osmium/osm.hpp b/include/osmium/osm.hpp new file mode 100644 index 000000000..bf21c19dc --- /dev/null +++ b/include/osmium/osm.hpp @@ -0,0 +1,48 @@ +#ifndef OSMIUM_OSM_HPP +#define OSMIUM_OSM_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export + +/** + * @brief Namespace for everything in the Osmium library. + */ +namespace osmium { +} // namespace osmium + +#endif // OSMIUM_OSM_HPP diff --git a/include/osmium/osm/area.hpp b/include/osmium/osm/area.hpp new file mode 100644 index 000000000..a388de2e9 --- /dev/null +++ b/include/osmium/osm/area.hpp @@ -0,0 +1,193 @@ +#ifndef OSMIUM_OSM_AREA_HPP +#define OSMIUM_OSM_AREA_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace builder { + template class ObjectBuilder; + } + + /** + * An outer ring of an Area. + */ + class OuterRing : public NodeRefList { + + public: + + OuterRing(): + NodeRefList() { + } + + }; // class OuterRing + + static_assert(sizeof(OuterRing) % osmium::memory::align_bytes == 0, "Class osmium::OuterRing has wrong size to be aligned properly!"); + + /** + * An inner ring of an Area. + */ + class InnerRing : public NodeRefList { + + public: + + InnerRing(): + NodeRefList() { + } + + }; // class InnerRing + + static_assert(sizeof(InnerRing) % osmium::memory::align_bytes == 0, "Class osmium::InnerRing has wrong size to be aligned properly!"); + + /** + * Convert way or (multipolygon) relation id into unique area id. + * + * @param id Id of a way or relation + * @param type Type of object (way or relation) + * @returns Area id + */ + inline osmium::object_id_type object_id_to_area_id(osmium::object_id_type id, osmium::item_type type) { + osmium::object_id_type area_id = std::abs(id) * 2; + if (type == osmium::item_type::relation) { + ++area_id; + } + return id < 0 ? -area_id : area_id; + } + + /** + * Convert area id into id of the way or relation it was created from. + * + * @param id Area id + * @returns Way or Relation id. + */ + inline osmium::object_id_type area_id_to_object_id(osmium::object_id_type id) { + return id / 2; + } + + /** + * An OSM area created out of a closed way or a multipolygon relation. + */ + class Area : public OSMObject { + + friend class osmium::builder::ObjectBuilder; + + Area() : + OSMObject(sizeof(Area), osmium::item_type::area) { + } + + public: + + static constexpr osmium::item_type itemtype = osmium::item_type::area; + + /** + * Was this area created from a way? (In contrast to areas + * created from a relation and their members.) + */ + bool from_way() const noexcept { + return (positive_id() & 0x1) == 0; + } + + /** + * Return the Id of the way or relation this area was created from. + */ + osmium::object_id_type orig_id() const { + return osmium::area_id_to_object_id(id()); + } + + /** + * Count the number of outer and inner rings of this area. + */ + std::pair num_rings() const { + std::pair counter; + + for (auto it = cbegin(); it != cend(); ++it) { + switch (it->type()) { + case osmium::item_type::outer_ring: + ++counter.first; + break; + case osmium::item_type::inner_ring: + ++counter.second; + break; + case osmium::item_type::tag_list: + // ignore tags + break; + case osmium::item_type::undefined: + case osmium::item_type::node: + case osmium::item_type::way: + case osmium::item_type::relation: + case osmium::item_type::area: + case osmium::item_type::changeset: + case osmium::item_type::way_node_list: + case osmium::item_type::relation_member_list: + case osmium::item_type::relation_member_list_with_full_members: + assert(false && "Children of Area can only be outer/inner_ring and tag_list."); + break; + } + } + + return counter; + } + + /** + * Is this area a multipolygon, ie. has it more than one outer ring? + */ + bool is_multipolygon() const { + return num_rings().first > 1; + } + + osmium::memory::ItemIterator inner_ring_cbegin(const osmium::memory::ItemIterator& it) const { + return it.cast(); + } + + osmium::memory::ItemIterator inner_ring_cend(const osmium::memory::ItemIterator& it) const { + return std::next(it).cast(); + } + + }; // class Area + + static_assert(sizeof(Area) % osmium::memory::align_bytes == 0, "Class osmium::Area has wrong size to be aligned properly!"); + +} // namespace osmium + +#endif // OSMIUM_OSM_AREA_HPP diff --git a/include/osmium/osm/box.hpp b/include/osmium/osm/box.hpp new file mode 100644 index 000000000..2b761fefc --- /dev/null +++ b/include/osmium/osm/box.hpp @@ -0,0 +1,207 @@ +#ifndef OSMIUM_OSM_BOX_HPP +#define OSMIUM_OSM_BOX_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 + +#include +#include + +namespace osmium { + + /** + * Bounding box. + */ + class Box { + + osmium::Location m_bottom_left; + osmium::Location m_top_right; + + public: + + /** + * Create undefined Box. Use the extend() function + * to add actual bounds. + */ + constexpr Box() noexcept : + m_bottom_left(), + m_top_right() { + } + + Box(double minx, double miny, double maxx, double maxy) : + m_bottom_left(minx, miny), + m_top_right(maxx, maxy) { + } + + Box(const osmium::Location& bottom_left, const osmium::Location& top_right) : + m_bottom_left(bottom_left), + m_top_right(top_right) { + } + + Box(const Box&) = default; + Box(Box&&) = default; + Box& operator=(const Box&) = default; + Box& operator=(Box&&) = default; + ~Box() = default; + + /** + * Extend this bounding box by the given location. If the + * location is undefined, the bounding box is unchanged. + */ + Box& extend(const Location& location) noexcept { + if (location) { + if (m_bottom_left) { + if (location.x() < m_bottom_left.x()) { + m_bottom_left.set_x(location.x()); + } + if (location.x() > m_top_right.x()) { + m_top_right.set_x(location.x()); + } + if (location.y() < m_bottom_left.y()) { + m_bottom_left.set_y(location.y()); + } + if (location.y() > m_top_right.y()) { + m_top_right.set_y(location.y()); + } + } else { + m_bottom_left = location; + m_top_right = location; + } + } + return *this; + } + + /** + * Extend this bounding box by the given box. If the + * box is undefined, the bounding box is unchanged. + */ + Box& extend(const Box& box) noexcept { + extend(box.bottom_left()); + extend(box.top_right()); + return *this; + } + + /** + * Box are defined, ie. contains defined coordinates. + */ + explicit constexpr operator bool() const noexcept { + return static_cast(m_bottom_left); + } + + /** + * Box are valid, ie. defined and inside usual bounds + * (-180<=lon<=180, -90<=lat<=90). + */ + constexpr bool valid() const noexcept { + return bottom_left().valid() && top_right().valid(); + } + + /** + * Bottom-left location. + */ + OSMIUM_CONSTEXPR Location bottom_left() const noexcept { + return m_bottom_left; + } + + /** + * Bottom-left location. + */ + Location& bottom_left() noexcept { + return m_bottom_left; + } + + /** + * Top-right location. + */ + OSMIUM_CONSTEXPR Location top_right() const noexcept { + return m_top_right; + } + + /** + * Top-right location. + */ + Location& top_right() noexcept { + return m_top_right; + } + + /** + * Is the location inside the box? + */ + bool contains(const osmium::Location& location) const { + return location.x() >= bottom_left().x() && location.y() >= bottom_left().y() && + location.x() <= top_right().x() && location.y() <= top_right().y(); + } + + /** + * Calculate size of the box in square degrees. + * + * @throws osmium::invalid_location unless all coordinates are valid + */ + double size() const { + return (m_top_right.lon() - m_bottom_left.lon()) * + (m_top_right.lat() - m_bottom_left.lat()); + } + + }; // class Box + + /** + * Boxes are equal if both locations are equal. + */ + inline OSMIUM_CONSTEXPR bool operator==(const Box& lhs, const Box& rhs) noexcept { + return lhs.bottom_left() == rhs.bottom_left() && lhs.top_right() == rhs.top_right(); + } + + /** + * Output a box to a stream. + */ + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const osmium::Box& box) { + if (box) { + out << '(' + << box.bottom_left().lon() + << ',' + << box.bottom_left().lat() + << ',' + << box.top_right().lon() + << ',' + << box.top_right().lat() + << ')'; + } else { + out << "(undefined)"; + } + return out; + } +} // namespace osmium + +#endif // OSMIUM_OSM_BOX_HPP diff --git a/include/osmium/osm/changeset.hpp b/include/osmium/osm/changeset.hpp new file mode 100644 index 000000000..2b79fb5cf --- /dev/null +++ b/include/osmium/osm/changeset.hpp @@ -0,0 +1,336 @@ +#ifndef OSMIUM_OSM_CHANGESET_HPP +#define OSMIUM_OSM_CHANGESET_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace builder { + template class ObjectBuilder; + } + + /** + * \brief An OSM Changeset, a group of changes made by a single user over + * a short period of time. + * + * You can not create Changeset objects directly. Use the ChangesetBuilder + * class to create Changesets in a Buffer. + */ + class Changeset : public osmium::OSMEntity { + + friend class osmium::builder::ObjectBuilder; + + osmium::Timestamp m_created_at; + osmium::Timestamp m_closed_at; + osmium::Box m_bounds; + changeset_id_type m_id {0}; + num_changes_type m_num_changes {0}; + user_id_type m_uid {0}; + string_size_type m_user_size; + + Changeset() : + OSMEntity(sizeof(Changeset), osmium::item_type::changeset) { + } + + void set_user_size(string_size_type size) { + m_user_size = size; + } + + unsigned char* subitems_position() { + return data() + osmium::memory::padded_length(sizeof(Changeset) + m_user_size); + } + + const unsigned char* subitems_position() const { + return data() + osmium::memory::padded_length(sizeof(Changeset) + m_user_size); + } + + public: + + /// Get ID of this changeset + changeset_id_type id() const noexcept { + return m_id; + } + + /** + * Set ID of this changeset + * + * @param id The id. + * @returns Reference to changeset to make calls chainable. + */ + Changeset& set_id(changeset_id_type id) noexcept { + m_id = id; + return *this; + } + + /** + * Set ID of this changeset. + * + * @param id The id. + * @returns Reference to object to make calls chainable. + */ + Changeset& set_id(const char* id) { + return set_id(osmium::string_to_changeset_id(id)); + } + + /// Get user id. + user_id_type uid() const noexcept { + return m_uid; + } + + /** + * Set user id. + * + * @param uid The user id. + * @returns Reference to changeset to make calls chainable. + */ + Changeset& set_uid(user_id_type uid) noexcept { + m_uid = uid; + return *this; + } + + /** + * Set user id to given uid or to 0 (anonymous user) if the given + * uid is smaller than 0. + * + * @param uid The user id. + * @returns Reference to changeset to make calls chainable. + */ + Changeset& set_uid_from_signed(signed_user_id_type uid) noexcept { + m_uid = uid < 0 ? 0 : static_cast(uid); + return *this; + } + + /** + * Set user id to given uid or to 0 (anonymous user) if the given + * uid is smaller than 0. + * + * @returns Reference to changeset to make calls chainable. + */ + Changeset& set_uid(const char* uid) { + return set_uid_from_signed(string_to_user_id(uid)); + } + + /// Is this user anonymous? + bool user_is_anonymous() const noexcept { + return m_uid == 0; + } + + /// Get timestamp when this changeset was created. + osmium::Timestamp created_at() const noexcept { + return m_created_at; + } + + /** + * Get timestamp when this changeset was closed. + * + * @returns Timestamp. Will return the empty Timestamp when the + * changeset is not yet closed. + */ + osmium::Timestamp closed_at() const noexcept { + return m_closed_at; + } + + /// Is this changeset open? + bool open() const noexcept { + return m_closed_at == osmium::Timestamp(); + } + + /// Is this changeset closed? + bool closed() const noexcept { + return !open(); + } + + /** + * Set the timestamp when this changeset was created. + * + * @param timestamp Timestamp + * @returns Reference to changeset to make calls chainable. + */ + Changeset& set_created_at(const osmium::Timestamp timestamp) { + m_created_at = timestamp; + return *this; + } + + /** + * Set the timestamp when this changeset was closed. + * + * @param timestamp Timestamp + * @returns Reference to changeset to make calls chainable. + */ + Changeset& set_closed_at(const osmium::Timestamp timestamp) { + m_closed_at = timestamp; + return *this; + } + + /// Get the number of changes in this changeset + num_changes_type num_changes() const noexcept { + return m_num_changes; + } + + /// Set the number of changes in this changeset + Changeset& set_num_changes(num_changes_type num_changes) noexcept { + m_num_changes = num_changes; + return *this; + } + + /// Set the number of changes in this changeset + Changeset& set_num_changes(const char* num_changes) noexcept { + return set_num_changes(osmium::string_to_num_changes(num_changes)); + } + + /** + * Get the bounding box of this changeset. + * + * @returns Bounding box. Can be empty. + */ + osmium::Box& bounds() noexcept { + return m_bounds; + } + + /** + * Get the bounding box of this changeset. + * + * @returns Bounding box. Can be empty. + */ + const osmium::Box& bounds() const noexcept { + return m_bounds; + } + + /// Get user name. + const char* user() const { + return reinterpret_cast(data() + sizeof(Changeset)); + } + + /// Get the list of tags. + const TagList& tags() const { + return osmium::detail::subitem_of_type(cbegin(), cend()); + } + + /** + * Set named attribute. + * + * @param attr Name of the attribute (must be one of "id", "version", + * "changeset", "timestamp", "uid", "visible") + * @param value Value of the attribute + */ + void set_attribute(const char* attr, const char* value) { + if (!strcmp(attr, "id")) { + set_id(value); + } else if (!strcmp(attr, "num_changes")) { + set_num_changes(value); + } else if (!strcmp(attr, "created_at")) { + set_created_at(osmium::Timestamp(value)); + } else if (!strcmp(attr, "closed_at")) { + set_closed_at(osmium::Timestamp(value)); + } else if (!strcmp(attr, "uid")) { + set_uid(value); + } + } + + typedef osmium::memory::CollectionIterator iterator; + typedef osmium::memory::CollectionIterator const_iterator; + + iterator begin() { + return iterator(subitems_position()); + } + + iterator end() { + return iterator(data() + padded_size()); + } + + const_iterator cbegin() const { + return const_iterator(subitems_position()); + } + + const_iterator cend() const { + return const_iterator(data() + padded_size()); + } + + const_iterator begin() const { + return cbegin(); + } + + const_iterator end() const { + return cend(); + } + + }; // class Changeset + + static_assert(sizeof(Changeset) % osmium::memory::align_bytes == 0, + "Class osmium::Changeset has wrong size to be aligned properly!"); + + /** + * Changesets are equal if their IDs are equal. + */ + inline bool operator==(const Changeset& lhs, const Changeset& rhs) { + return lhs.id() == rhs.id(); + } + + inline bool operator!=(const Changeset& lhs, const Changeset& rhs) { + return ! (lhs == rhs); + } + + /** + * Changesets can be ordered by id. + */ + inline bool operator<(const Changeset& lhs, const Changeset& rhs) { + return lhs.id() < rhs.id(); + } + + inline bool operator>(const Changeset& lhs, const Changeset& rhs) { + return rhs < lhs; + } + + inline bool operator<=(const Changeset& lhs, const Changeset& rhs) { + return ! (rhs < lhs); + } + + inline bool operator>=(const Changeset& lhs, const Changeset& rhs) { + return ! (lhs < rhs); + } + +} // namespace osmium + +#endif // OSMIUM_OSM_CHANGESET_HPP diff --git a/include/osmium/osm/diff_object.hpp b/include/osmium/osm/diff_object.hpp new file mode 100644 index 000000000..a8f91ecd5 --- /dev/null +++ b/include/osmium/osm/diff_object.hpp @@ -0,0 +1,156 @@ +#ifndef OSMIUM_OSM_DIFF_OBJECT_HPP +#define OSMIUM_OSM_DIFF_OBJECT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include + +namespace osmium { + + class Node; + class Way; + class Relation; + + class DiffObject { + + protected: + + osmium::OSMObject* m_prev; + osmium::OSMObject* m_curr; + osmium::OSMObject* m_next; + + public: + + DiffObject() noexcept : + m_prev(nullptr), + m_curr(nullptr), + m_next(nullptr) { + } + + explicit DiffObject(osmium::OSMObject& prev, osmium::OSMObject& curr, osmium::OSMObject& next) noexcept : + m_prev(&prev), + m_curr(&curr), + m_next(&next) { + } + + DiffObject(const DiffObject&) = default; + DiffObject& operator=(const DiffObject&) = default; + + DiffObject(DiffObject&&) = default; + DiffObject& operator=(DiffObject&&) = default; + + const osmium::OSMObject& prev() const noexcept { + return *m_prev; + } + + const osmium::OSMObject& curr() const noexcept { + return *m_curr; + } + + const osmium::OSMObject& next() const noexcept { + return *m_next; + } + + bool first() const noexcept { + return m_prev == m_curr; + } + + bool last() const noexcept { + return m_curr == m_next; + } + + osmium::item_type type() const noexcept { + return m_curr->type(); + } + + osmium::object_id_type id() const noexcept { + return m_curr->id(); + } + + osmium::object_version_type version() const noexcept { + return m_curr->version(); + } + + osmium::changeset_id_type changeset() const noexcept { + return m_curr->changeset(); + } + + const osmium::Timestamp start_time() const noexcept { + return m_curr->timestamp(); + } + + const osmium::Timestamp end_time() const noexcept { + return last() ? osmium::Timestamp() : m_next->timestamp(); + } + + }; // class DiffObject + + template + class DiffObjectDerived : public DiffObject { + + public: + + DiffObjectDerived(T& prev, T& curr, T& next) noexcept : + DiffObject(prev, curr, next) { + } + + DiffObjectDerived(const DiffObjectDerived&) = default; + DiffObjectDerived& operator=(const DiffObjectDerived&) = default; + + DiffObjectDerived(DiffObjectDerived&&) = default; + DiffObjectDerived& operator=(DiffObjectDerived&&) = default; + + const T& prev() const noexcept { + return *static_cast(m_prev); + } + + const T& curr() const noexcept { + return *static_cast(m_curr); + } + + const T& next() const noexcept { + return *static_cast(m_next); + } + + }; // class DiffObjectDerived + + typedef DiffObjectDerived DiffNode; + typedef DiffObjectDerived DiffWay; + typedef DiffObjectDerived DiffRelation; + +} // namespace osmium + +#endif // OSMIUM_OSM_DIFF_OBJECT_HPP diff --git a/include/osmium/osm/entity.hpp b/include/osmium/osm/entity.hpp new file mode 100644 index 000000000..e37ed4c94 --- /dev/null +++ b/include/osmium/osm/entity.hpp @@ -0,0 +1,74 @@ +#ifndef OSMIUM_OSM_ENTITY_HPP +#define OSMIUM_OSM_ENTITY_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 + +namespace osmium { + + namespace detail { + + template + inline TSubitem& subitem_of_type(TIter it, TIter end) { + for (; it != end; ++it) { + if (it->type() == TSubitem::itemtype) { + return reinterpret_cast(*it); + } + } + + // If no subitem of the TSubitem type was found, + // return a default constructed one. + static TSubitem subitem; + return subitem; + } + + } // namespace detail + + /** + * \brief OSMEntity is the abstract base class for the OSMObject and + * Changeset classes. + */ + class OSMEntity : public osmium::memory::Item { + + public: + + explicit OSMEntity(osmium::memory::item_size_type size, osmium::item_type type) : + Item(size, type) { + } + + }; // class OSMEntity + +} // namespace osmium + +#endif // OSMIUM_OSM_ENTITY_HPP diff --git a/include/osmium/osm/entity_bits.hpp b/include/osmium/osm/entity_bits.hpp new file mode 100644 index 000000000..2a4d96416 --- /dev/null +++ b/include/osmium/osm/entity_bits.hpp @@ -0,0 +1,99 @@ +#ifndef OSMIUM_OSM_ENTITY_BITS_HPP +#define OSMIUM_OSM_ENTITY_BITS_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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. + +*/ + +namespace osmium { + + /** + * @brief Bitfield for OSM entity types. + */ + namespace osm_entity_bits { + + /** + * Describes zero or more OSM entities. + * + * Usage: + * + * @code{.cpp} + * osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::node | osmium::osm_entity_bits::way; + * + * entities |= osmium::osm_entity_bits::relation; + * + * assert(entities & osmium::osm_entity_bits::object); + * + * assert(! (entities & osmium::osm_entity_bits::changeset)); + * @endcode + */ + enum type : unsigned char { + + nothing = 0x00, + node = 0x01, + way = 0x02, + relation = 0x04, + nwr = 0x07, ///< node, way, or relation object + area = 0x08, + nwra = 0x0f, ///< node, way, relation, or area object + object = 0x0f, ///< node, way, relation, or area object + changeset = 0x10, + all = 0x1f ///< object or changeset + + }; // enum type + + inline type operator|(const type lhs, const type rhs) noexcept { + return static_cast(static_cast(lhs) | static_cast (rhs)); + } + + inline type& operator|=(type& lhs, const type rhs) noexcept { + lhs = lhs | rhs; + return lhs; + } + + inline type operator&(const type lhs, const type rhs) noexcept { + return static_cast(static_cast(lhs) & static_cast (rhs)); + } + + inline type operator~(const type value) noexcept { + return static_cast(~static_cast(value)); + } + + inline type operator&=(type& lhs, const type rhs) noexcept { + lhs = lhs & rhs; + return lhs; + } + + } // namespace osm_entity_bits + +} // namespace osmium + +#endif // OSMIUM_OSM_ENTITY_BITS_HPP diff --git a/include/osmium/osm/item_type.hpp b/include/osmium/osm/item_type.hpp new file mode 100644 index 000000000..d277e06c8 --- /dev/null +++ b/include/osmium/osm/item_type.hpp @@ -0,0 +1,173 @@ +#ifndef OSMIUM_OSM_ITEM_TYPE_HPP +#define OSMIUM_OSM_ITEM_TYPE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 // IWYU pragma: keep +#include +#include + +namespace osmium { + + enum class item_type : uint16_t { + + undefined = 0x00, + node = 0x01, + way = 0x02, + relation = 0x03, + area = 0x04, + changeset = 0x05, + tag_list = 0x11, + way_node_list = 0x12, + relation_member_list = 0x13, + relation_member_list_with_full_members = 0x23, + outer_ring = 0x40, + inner_ring = 0x41 + + }; // enum class item_type + + inline item_type char_to_item_type(const char c) noexcept { + switch (c) { + case 'X': + return item_type::undefined; + case 'n': + return item_type::node; + case 'w': + return item_type::way; + case 'r': + return item_type::relation; + case 'a': + return item_type::area; + case 'c': + return item_type::changeset; + case 'T': + return item_type::tag_list; + case 'N': + return item_type::way_node_list; + case 'M': + return item_type::relation_member_list; + case 'F': + return item_type::relation_member_list_with_full_members; + case 'O': + return item_type::outer_ring; + case 'I': + return item_type::inner_ring; + default: + return item_type::undefined; + } + } + +// avoid g++ false positive +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wreturn-type" + inline char item_type_to_char(const item_type type) noexcept { + switch (type) { + case item_type::undefined: + return 'X'; + case item_type::node: + return 'n'; + case item_type::way: + return 'w'; + case item_type::relation: + return 'r'; + case item_type::area: + return 'a'; + case item_type::changeset: + return 'c'; + case item_type::tag_list: + return 'T'; + case item_type::way_node_list: + return 'N'; + case item_type::relation_member_list: + return 'M'; + case item_type::relation_member_list_with_full_members: + return 'F'; + case item_type::outer_ring: + return 'O'; + case item_type::inner_ring: + return 'I'; + } + } + + inline const char* item_type_to_name(const item_type type) noexcept { + switch (type) { + case item_type::undefined: + return "undefined"; + case item_type::node: + return "node"; + case item_type::way: + return "way"; + case item_type::relation: + return "relation"; + case item_type::area: + return "area"; + case item_type::changeset: + return "changeset"; + case item_type::tag_list: + return "tag_list"; + case item_type::way_node_list: + return "way_node_list"; + case item_type::relation_member_list: + return "relation_member_list"; + case item_type::relation_member_list_with_full_members: + return "relation_member_list_with_full_members"; + case item_type::outer_ring: + return "outer_ring"; + case item_type::inner_ring: + return "inner_ring"; + } + } +#pragma GCC diagnostic pop + + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const item_type item_type) { + return out << item_type_to_char(item_type); + } + + /** + * This exception is thrown when a visitor encounters an unknown item type. + * Under usual circumstance this should not happen. If it does happen, it + * probably means the buffer contains different kinds of objects than were + * expected or that there is some kind of data corruption. + */ + struct unknown_type : public std::runtime_error { + + unknown_type() : + std::runtime_error("unknown item type") { + } + + }; // struct unknown_type + +} // namespace osmium + +#endif // OSMIUM_OSM_ITEM_TYPE_HPP diff --git a/include/osmium/osm/location.hpp b/include/osmium/osm/location.hpp new file mode 100644 index 000000000..cabecd50f --- /dev/null +++ b/include/osmium/osm/location.hpp @@ -0,0 +1,285 @@ +#ifndef OSMIUM_OSM_LOCATION_HPP +#define OSMIUM_OSM_LOCATION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include +#include + +#include + +#include +#include + +namespace osmium { + + /** + * Exception signaling an invalid location, ie a location + * outside the -180 to 180 and -90 to 90 degree range. + */ + struct invalid_location : public std::range_error { + + invalid_location(const std::string& what) : + std::range_error(what) { + } + + invalid_location(const char* what) : + std::range_error(what) { + } + + }; // struct invalid_location + + /** + * Locations define a place on earth. + * + * Locations are stored in 32 bit integers for the x and y + * coordinates, respectively. This gives you an accuracy of a few + * centimeters, good enough for OSM use. (The main OSM database + * uses the same scheme.) + * + * An undefined Location can be created by calling the constructor + * without parameters. + * + * Coordinates are never checked on whether they are inside bounds. + * Call valid() to check this. + */ + class Location { + + int32_t m_x; + int32_t m_y; + + public: + + // this value is used for a coordinate to mark it as undefined + // MSVC doesn't declare std::numeric_limits::max() as + // constexpr, so we hard code this for the time being. + // static constexpr int32_t undefined_coordinate = std::numeric_limits::max(); + static constexpr int32_t undefined_coordinate = 2147483647; + + static constexpr int coordinate_precision = 10000000; + + static int32_t double_to_fix(const double c) noexcept { + return static_cast(std::round(c * coordinate_precision)); + } + + static OSMIUM_CONSTEXPR double fix_to_double(const int32_t c) noexcept { + return static_cast(c) / coordinate_precision; + } + + /** + * Create undefined Location. + */ + explicit constexpr Location() noexcept : + m_x(undefined_coordinate), + m_y(undefined_coordinate) { + } + + /** + * Create Location with given x and y coordinates. + * Note that these coordinates are coordinate_precision + * times larger than the real coordinates. + */ + constexpr Location(const int32_t x, const int32_t y) noexcept : + m_x(x), + m_y(y) { + } + + /** + * Create Location with given x and y coordinates. + * Note that these coordinates are coordinate_precision + * times larger than the real coordinates. + */ + constexpr Location(const int64_t x, const int64_t y) noexcept : + m_x(static_cast(x)), + m_y(static_cast(y)) { + } + + /** + * Create Location with given longitude and latitude. + */ + Location(const double lon, const double lat) : + m_x(double_to_fix(lon)), + m_y(double_to_fix(lat)) { + } + + Location(const Location&) = default; + Location(Location&&) = default; + Location& operator=(const Location&) = default; + Location& operator=(Location&&) = default; + ~Location() = default; + + /** + * Check whether the coordinates of this location + * are defined. + */ + explicit constexpr operator bool() const noexcept { + return m_x != undefined_coordinate && m_y != undefined_coordinate; + } + + /** + * Check whether the coordinates are inside the + * usual bounds (-180<=lon<=180, -90<=lat<=90). + */ + constexpr bool valid() const noexcept { + return m_x >= -180 * coordinate_precision + && m_x <= 180 * coordinate_precision + && m_y >= -90 * coordinate_precision + && m_y <= 90 * coordinate_precision; + } + + constexpr int32_t x() const noexcept { + return m_x; + } + + constexpr int32_t y() const noexcept { + return m_y; + } + + Location& set_x(const int32_t x) noexcept { + m_x = x; + return *this; + } + + Location& set_y(const int32_t y) noexcept { + m_y = y; + return *this; + } + + /** + * Get longitude. + * + * @throws invalid_location if the location is invalid + */ + double lon() const { + if (!valid()) { + throw osmium::invalid_location("invalid location"); + } + return fix_to_double(m_x); + } + + /** + * Get longitude without checking the validity. + */ + double lon_without_check() const { + return fix_to_double(m_x); + } + + /** + * Get latitude. + * + * @throws invalid_location if the location is invalid + */ + double lat() const { + if (!valid()) { + throw osmium::invalid_location("invalid location"); + } + return fix_to_double(m_y); + } + + /** + * Get latitude without checking the validity. + */ + double lat_without_check() const { + return fix_to_double(m_y); + } + + Location& set_lon(double lon) noexcept { + m_x = double_to_fix(lon); + return *this; + } + + Location& set_lat(double lat) noexcept { + m_y = double_to_fix(lat); + return *this; + } + + template + T as_string(T iterator, const char separator) const { + iterator = osmium::util::double2string(iterator, lon(), 7); + *iterator++ = separator; + return osmium::util::double2string(iterator, lat(), 7); + } + + }; // class Location + + /** + * Locations are equal if both coordinates are equal. + */ + inline OSMIUM_CONSTEXPR bool operator==(const Location& lhs, const Location& rhs) noexcept { + return lhs.x() == rhs.x() && lhs.y() == rhs.y(); + } + + inline OSMIUM_CONSTEXPR bool operator!=(const Location& lhs, const Location& rhs) noexcept { + return ! (lhs == rhs); + } + + /** + * Compare two locations by comparing first the x and then + * the y coordinate. If either of the locations is + * undefined the result is undefined. + */ + inline OSMIUM_CONSTEXPR bool operator<(const Location& lhs, const Location& rhs) noexcept { + return (lhs.x() == rhs.x() && lhs.y() < rhs.y()) || lhs.x() < rhs.x(); + } + + inline OSMIUM_CONSTEXPR bool operator>(const Location& lhs, const Location& rhs) noexcept { + return rhs < lhs; + } + + inline OSMIUM_CONSTEXPR bool operator<=(const Location& lhs, const Location& rhs) noexcept { + return ! (rhs < lhs); + } + + inline OSMIUM_CONSTEXPR bool operator>=(const Location& lhs, const Location& rhs) noexcept { + return ! (lhs < rhs); + } + + /** + * Output a location to a stream. + */ + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const osmium::Location& location) { + if (location) { + out << '(' << location.lon() << ',' << location.lat() << ')'; + } else { + out << "(undefined,undefined)"; + } + return out; + } + +} // namespace osmium + +#endif // OSMIUM_OSM_LOCATION_HPP diff --git a/include/osmium/osm/node.hpp b/include/osmium/osm/node.hpp new file mode 100644 index 000000000..50146c568 --- /dev/null +++ b/include/osmium/osm/node.hpp @@ -0,0 +1,76 @@ +#ifndef OSMIUM_OSM_NODE_HPP +#define OSMIUM_OSM_NODE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include + +namespace osmium { + + namespace builder { + template class ObjectBuilder; + } + + class Node : public OSMObject { + + friend class osmium::builder::ObjectBuilder; + + osmium::Location m_location; + + Node() : + OSMObject(sizeof(Node), osmium::item_type::node) { + } + + public: + + static constexpr osmium::item_type itemtype = osmium::item_type::node; + + osmium::Location location() const noexcept { + return m_location; + } + + Node& set_location(const osmium::Location& location) { + m_location = location; + return *this; + } + + }; // class Node + + static_assert(sizeof(Node) % osmium::memory::align_bytes == 0, "Class osmium::Node has wrong size to be aligned properly!"); + +} // namespace osmium + +#endif // OSMIUM_OSM_NODE_HPP diff --git a/include/osmium/osm/node_ref.hpp b/include/osmium/osm/node_ref.hpp new file mode 100644 index 000000000..ed50b9e66 --- /dev/null +++ b/include/osmium/osm/node_ref.hpp @@ -0,0 +1,173 @@ +#ifndef OSMIUM_OSM_NODE_REF_HPP +#define OSMIUM_OSM_NODE_REF_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include + +#include +#include +#include +#include + +namespace osmium { + + /** + * This reference to a node contains a node ID and a (possibly empty) + * location. + */ + class NodeRef : public osmium::memory::detail::ItemHelper { + + osmium::object_id_type m_ref; + osmium::Location m_location; + + public: + + NodeRef(const osmium::object_id_type ref=0, const osmium::Location& location=Location()) noexcept : + m_ref(ref), + m_location(location) { + } + + osmium::object_id_type ref() const noexcept { + return m_ref; + } + + osmium::unsigned_object_id_type positive_ref() const noexcept { + return static_cast(std::abs(m_ref)); + } + + /** + * Get reference to location in this NodeRef. Can be used to update it. + */ + osmium::Location& location() noexcept { + return m_location; + } + + osmium::Location location() const noexcept { + return m_location; + } + + double lon() const { + return m_location.lon(); + } + + double lat() const { + return m_location.lat(); + } + + int32_t x() const noexcept { + return m_location.x(); + } + + int32_t y() const noexcept { + return m_location.y(); + } + + NodeRef& set_ref(const osmium::object_id_type ref) noexcept { + m_ref = ref; + return *this; + } + + NodeRef& set_location(const osmium::Location& location) noexcept { + m_location = location; + return *this; + } + + }; // class NodeRef + + inline bool operator==(const NodeRef& lhs, const NodeRef& rhs) noexcept { + return lhs.ref() == rhs.ref(); + } + + inline bool operator!=(const NodeRef& lhs, const NodeRef& rhs) noexcept { + return ! (lhs == rhs); + } + + inline bool operator<(const NodeRef& lhs, const NodeRef& rhs) noexcept { + return lhs.ref() < rhs.ref(); + } + + inline bool operator>(const NodeRef& lhs, const NodeRef& rhs) noexcept { + return rhs < lhs; + } + + inline bool operator<=(const NodeRef& lhs, const NodeRef& rhs) noexcept { + return ! (rhs < lhs); + } + + inline bool operator>=(const NodeRef& lhs, const NodeRef& rhs) noexcept { + return ! (lhs < rhs); + } + + /** + * Output a NodeRef to a stream. + */ + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const osmium::NodeRef& nr) { + return out << "<" << nr.ref() << " " << nr.location() << ">"; + } + + /** + * Functor to compare NodeRefs by Location instead of id. + */ + struct location_equal { + + bool operator()(const NodeRef& lhs, const NodeRef& rhs) const noexcept { + return lhs.location() == rhs.location(); + } + + typedef NodeRef first_argument_type; + typedef NodeRef second_argument_type; + typedef bool result_type; + + }; // struct location_equal + + /** + * Functor to compare NodeRefs by Location instead of id. + */ + struct location_less { + + bool operator()(const NodeRef& lhs, const NodeRef& rhs) const noexcept { + return lhs.location() < rhs.location(); + } + + typedef NodeRef first_argument_type; + typedef NodeRef second_argument_type; + typedef bool result_type; + + }; // struct location_less + +} // namespace osmium + +#endif // OSMIUM_OSM_NODE_REF_HPP diff --git a/include/osmium/osm/node_ref_list.hpp b/include/osmium/osm/node_ref_list.hpp new file mode 100644 index 000000000..321c952f4 --- /dev/null +++ b/include/osmium/osm/node_ref_list.hpp @@ -0,0 +1,135 @@ +#ifndef OSMIUM_OSM_NODE_REF_LIST_HPP +#define OSMIUM_OSM_NODE_REF_LIST_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include + +#include +#include +#include + +namespace osmium { + + /** + * A vector of NodeRef objects. Usually this is not instatiated directly, + * but one of its subclasses are used. + */ + template + class NodeRefList : public osmium::memory::Item { + + public: + + static constexpr osmium::item_type itemtype = TItemType; + + NodeRefList() noexcept : + osmium::memory::Item(sizeof(NodeRefList), TItemType) { + } + + bool empty() const noexcept { + return sizeof(NodeRefList) == byte_size(); + } + + size_t size() const noexcept { + assert((osmium::memory::Item::byte_size() - sizeof(NodeRefList)) % sizeof(NodeRef) == 0); + return (osmium::memory::Item::byte_size() - sizeof(NodeRefList)) / sizeof(NodeRef); + } + + const NodeRef& operator[](size_t n) const { + const NodeRef* node_ref = &*(cbegin()); + return node_ref[n]; + } + + const NodeRef& front() const { + return operator[](0); + } + + const NodeRef& back() const { + return operator[](size()-1); + } + + bool is_closed() const { + return front().ref() == back().ref(); + } + + bool ends_have_same_id() const { + return front().ref() == back().ref(); + } + + bool ends_have_same_location() const { + return front().location() == back().location(); + } + + typedef NodeRef* iterator; + typedef const NodeRef* const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + iterator begin() { + return iterator(data() + sizeof(NodeRefList)); + } + + iterator end() { + return iterator(data() + byte_size()); + } + + const_iterator cbegin() const { + return const_iterator(data() + sizeof(NodeRefList)); + } + + const_iterator cend() const { + return const_iterator(data() + byte_size()); + } + + const_iterator begin() const { + return cbegin(); + } + + const_iterator end() const { + return cend(); + } + + const_reverse_iterator crbegin() const { + return const_reverse_iterator(cend()); + } + + const_reverse_iterator crend() const { + return const_reverse_iterator(cbegin()); + } + + }; // class NodeRefList + +} // namespace osmium + +#endif // OSMIUM_OSM_NODE_REF_LIST_HPP diff --git a/include/osmium/osm/object.hpp b/include/osmium/osm/object.hpp new file mode 100644 index 000000000..9c4d60341 --- /dev/null +++ b/include/osmium/osm/object.hpp @@ -0,0 +1,437 @@ +#ifndef OSMIUM_OSM_OBJECT_HPP +#define OSMIUM_OSM_OBJECT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + /** + * OSMObject (Node, Way, Relation, or Area). + */ + class OSMObject : public osmium::OSMEntity { + + object_id_type m_id; + bool m_deleted : 1; + object_version_type m_version : 31; + osmium::Timestamp m_timestamp; + user_id_type m_uid; + changeset_id_type m_changeset; + + size_t sizeof_object() const noexcept { + return sizeof(OSMObject) + (type() == item_type::node ? sizeof(osmium::Location) : 0) + sizeof(string_size_type); + } + + unsigned char* user_position() noexcept { + return data() + sizeof_object() - sizeof(string_size_type); + } + + const unsigned char* user_position() const noexcept { + return data() + sizeof_object() - sizeof(string_size_type); + } + + string_size_type user_size() const noexcept { + return *reinterpret_cast(user_position()); + } + + unsigned char* subitems_position() { + return data() + osmium::memory::padded_length(sizeof_object() + user_size()); + } + + const unsigned char* subitems_position() const { + return data() + osmium::memory::padded_length(sizeof_object() + user_size()); + } + + protected: + + OSMObject(osmium::memory::item_size_type size, osmium::item_type type) : + OSMEntity(size, type), + m_id(0), + m_deleted(false), + m_version(0), + m_timestamp(), + m_uid(0), + m_changeset(0) { + } + + void set_user_size(string_size_type size) { + *reinterpret_cast(user_position()) = size; + } + + public: + + /// Get ID of this object. + object_id_type id() const noexcept { + return m_id; + } + + /// Get absolute value of the ID of this object. + unsigned_object_id_type positive_id() const noexcept { + return static_cast(std::abs(m_id)); + } + + /** + * Set ID of this object. + * + * @returns Reference to object to make calls chainable. + */ + OSMObject& set_id(object_id_type id) noexcept { + m_id = id; + return *this; + } + + /** + * Set ID of this object. + * + * @returns Reference to object to make calls chainable. + */ + OSMObject& set_id(const char* id) { + return set_id(osmium::string_to_object_id(id)); + } + + /// Is this object marked as deleted? + bool deleted() const noexcept { + return m_deleted; + } + + /// Is this object marked visible (ie not deleted)? + bool visible() const noexcept { + return !deleted(); + } + + /** + * Mark this object as deleted (or not). + * + * @returns Reference to object to make calls chainable. + */ + OSMObject& set_deleted(bool deleted) noexcept { + m_deleted = deleted; + return *this; + } + + /** + * Mark this object as visible (ie not deleted) (or not). + * + * @returns Reference to object to make calls chainable. + */ + OSMObject& set_visible(bool visible) noexcept { + m_deleted = !visible; + return *this; + } + + /** + * Mark this object as visible (ie not deleted) or deleted. + * + * @param visible Either "true" or "false" + * @returns Reference to object to make calls chainable. + */ + OSMObject& set_visible(const char* visible) { + if (!strcmp("true", visible)) { + set_visible(true); + } else if (!strcmp("false", visible)) { + set_visible(false); + } else { + throw std::invalid_argument("Unknown value for visible attribute (allowed is 'true' or 'false')"); + } + return *this; + } + + /// Get version of this object. + object_version_type version() const noexcept { + return m_version; + } + + /** + * Set object version. + * + * @returns Reference to object to make calls chainable. + */ + OSMObject& set_version(object_version_type version) noexcept { + m_version = version; + return *this; + } + + /** + * Set object version. + * + * @returns Reference to object to make calls chainable. + */ + OSMObject& set_version(const char* version) { + return set_version(string_to_object_version(version)); + } + + /// Get changeset id of this object. + changeset_id_type changeset() const noexcept { + return m_changeset; + } + + /** + * Set changeset id of this object. + * + * @returns Reference to object to make calls chainable. + */ + OSMObject& set_changeset(changeset_id_type changeset) noexcept { + m_changeset = changeset; + return *this; + } + + /** + * Set changeset id of this object. + * + * @returns Reference to object to make calls chainable. + */ + OSMObject& set_changeset(const char* changeset) { + return set_changeset(string_to_changeset_id(changeset)); + } + + /// Get user id of this object. + user_id_type uid() const noexcept { + return m_uid; + } + + /** + * Set user id of this object. + * + * @returns Reference to object to make calls chainable. + */ + OSMObject& set_uid(user_id_type uid) noexcept { + m_uid = uid; + return *this; + } + + /** + * Set user id of this object. + * Sets uid to 0 (anonymous) if the given uid is smaller than 0. + * + * @returns Reference to object to make calls chainable. + */ + OSMObject& set_uid_from_signed(signed_user_id_type uid) noexcept { + m_uid = uid < 0 ? 0 : static_cast(uid); + return *this; + } + + /** + * Set user id of this object. + * + * @returns Reference to object to make calls chainable. + */ + OSMObject& set_uid(const char* uid) { + return set_uid_from_signed(string_to_user_id(uid)); + } + + /// Is this user anonymous? + bool user_is_anonymous() const noexcept { + return m_uid == 0; + } + + /// Get timestamp when this object last changed. + osmium::Timestamp timestamp() const noexcept { + return m_timestamp; + } + + /** + * Set the timestamp when this object last changed. + * + * @param timestamp Timestamp + * @returns Reference to object to make calls chainable. + */ + OSMObject& set_timestamp(const osmium::Timestamp timestamp) noexcept { + m_timestamp = timestamp; + return *this; + } + + /// Get user name for this object. + const char* user() const noexcept { + return reinterpret_cast(data() + sizeof_object()); + } + + /// Get the list of tags for this object. + const TagList& tags() const { + return osmium::detail::subitem_of_type(cbegin(), cend()); + } + + /** + * Get tag value by key. + * + * Convenience function that will forward to same function on TagList + * object. + */ + const char* get_value_by_key(const char* key, const char* default_value = nullptr) const noexcept { + return tags().get_value_by_key(key, default_value); + } + + /** + * Set named attribute. + * + * @param attr Name of the attribute (must be one of "id", "version", "changeset", "timestamp", "uid", "visible") + * @param value Value of the attribute + */ + void set_attribute(const char* attr, const char* value) { + if (!strcmp(attr, "id")) { + set_id(value); + } else if (!strcmp(attr, "version")) { + set_version(value); + } else if (!strcmp(attr, "changeset")) { + set_changeset(value); + } else if (!strcmp(attr, "timestamp")) { + set_timestamp(osmium::Timestamp(value)); + } else if (!strcmp(attr, "uid")) { + set_uid(value); + } else if (!strcmp(attr, "visible")) { + set_visible(value); + } + } + + typedef osmium::memory::CollectionIterator iterator; + typedef osmium::memory::CollectionIterator const_iterator; + + iterator begin() { + return iterator(subitems_position()); + } + + iterator end() { + return iterator(next()); + } + + const_iterator cbegin() const { + return const_iterator(subitems_position()); + } + + const_iterator cend() const { + return const_iterator(next()); + } + + const_iterator begin() const { + return cbegin(); + } + + const_iterator end() const { + return cend(); + } + + template + using t_iterator = osmium::memory::ItemIterator; + + template + using t_const_iterator = osmium::memory::ItemIterator; + + template + t_iterator begin() { + return t_iterator(subitems_position(), next()); + } + + template + t_iterator end() { + return t_iterator(next(), next()); + } + + template + t_const_iterator cbegin() const { + return t_const_iterator(subitems_position(), next()); + } + + template + t_const_iterator cend() const { + return t_const_iterator(next(), next()); + } + + template + t_const_iterator begin() const { + return cbegin(); + } + + template + t_const_iterator end() const { + return cend(); + } + + }; // class OSMObject + + static_assert(sizeof(OSMObject) % osmium::memory::align_bytes == 0, "Class osmium::OSMObject has wrong size to be aligned properly!"); + + /** + * OSMObjects are equal if their type, id, and version are equal. + */ + inline bool operator==(const OSMObject& lhs, const OSMObject& rhs) noexcept { + return lhs.type() == rhs.type() && + lhs.id() == rhs.id() && + lhs.version() == rhs.version(); + } + + inline bool operator!=(const OSMObject& lhs, const OSMObject& rhs) noexcept { + return ! (lhs == rhs); + } + + /** + * OSMObjects can be ordered by type, id and version. + * Note that we use the absolute value of the id for a + * better ordering of objects with negative id. + */ + inline bool operator<(const OSMObject& lhs, const OSMObject& rhs) noexcept { + if (lhs.type() != rhs.type()) { + return lhs.type() < rhs.type(); + } + return (lhs.id() == rhs.id() && lhs.version() < rhs.version()) || + lhs.positive_id() < rhs.positive_id(); + } + + inline bool operator>(const OSMObject& lhs, const OSMObject& rhs) noexcept { + return rhs < lhs; + } + + inline bool operator<=(const OSMObject& lhs, const OSMObject& rhs) noexcept { + return ! (rhs < lhs); + } + + inline bool operator>=(const OSMObject& lhs, const OSMObject& rhs) noexcept { + return ! (lhs < rhs); + } + +} // namespace osmium + +#endif // OSMIUM_OSM_OBJECT_HPP diff --git a/include/osmium/osm/object_comparisons.hpp b/include/osmium/osm/object_comparisons.hpp new file mode 100644 index 000000000..db11b0d4c --- /dev/null +++ b/include/osmium/osm/object_comparisons.hpp @@ -0,0 +1,110 @@ +#ifndef OSMIUM_OSM_OBJECT_COMPARISONS_HPP +#define OSMIUM_OSM_OBJECT_COMPARISONS_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 + +namespace osmium { + + /** + * Function object class for comparing OSM objects for equality by type, id, and version. + */ + struct object_equal_type_id_version { + + bool operator()(const osmium::OSMObject& lhs, const osmium::OSMObject& rhs) const noexcept { + return lhs == rhs; + } + + bool operator()(const osmium::OSMObject* lhs, const osmium::OSMObject* rhs) const noexcept { + return *lhs == *rhs; + } + + }; // struct object_equal_type_id_version + + /** + * Function object class for comparing OSM objects for equality by type and id, + * ignoring the version. + */ + struct object_equal_type_id { + + bool operator()(const osmium::OSMObject& lhs, const osmium::OSMObject& rhs) const noexcept { + return lhs.type() == rhs.type() && + lhs.id() == rhs.id(); + } + + bool operator()(const osmium::OSMObject* lhs, const osmium::OSMObject* rhs) const noexcept { + return operator()(*lhs, *rhs); + } + + }; // struct object_equal_type_id + + /** + * Function object class for ordering OSM objects by type, id, and version. + */ + struct object_order_type_id_version { + + bool operator()(const osmium::OSMObject& lhs, const osmium::OSMObject& rhs) const noexcept { + return lhs < rhs; + } + + bool operator()(const osmium::OSMObject* lhs, const osmium::OSMObject* rhs) const noexcept { + return *lhs < *rhs; + } + + }; // struct object_order_type_id_version + + /** + * Function object class for ordering OSM objects by type, id, and reverse version, + * ie objects are ordered by type and id, but later versions of an object are + * ordered before earlier versions of the same object. + */ + struct object_order_type_id_reverse_version { + + bool operator()(const osmium::OSMObject& lhs, const osmium::OSMObject& rhs) const noexcept { + if (lhs.type() != rhs.type()) { + return lhs.type() < rhs.type(); + } + return (lhs.id() == rhs.id() && lhs.version() > rhs.version()) || + lhs.positive_id() < rhs.positive_id(); + } + + bool operator()(const osmium::OSMObject* lhs, const osmium::OSMObject* rhs) const noexcept { + return operator()(*lhs, *rhs); + } + + }; // struct object_order_type_id_reverse_version + +} // namespace osmium + +#endif // OSMIUM_OSM_OBJECT_COMPARISONS_HPP diff --git a/include/osmium/osm/relation.hpp b/include/osmium/osm/relation.hpp new file mode 100644 index 000000000..f5d040100 --- /dev/null +++ b/include/osmium/osm/relation.hpp @@ -0,0 +1,189 @@ +#ifndef OSMIUM_OSM_RELATION_HPP +#define OSMIUM_OSM_RELATION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include + +#include // IWYU pragma: keep +#include +#include +#include +#include + +namespace osmium { + + namespace builder { + template class ObjectBuilder; + class RelationMemberListBuilder; + } + + class RelationMember : public osmium::memory::detail::ItemHelper { + + friend class osmium::builder::RelationMemberListBuilder; + + object_id_type m_ref; + item_type m_type; + uint16_t m_flags; + string_size_type m_role_size {0}; + + RelationMember(const RelationMember&) = delete; + RelationMember(RelationMember&&) = delete; + + RelationMember& operator=(const RelationMember&) = delete; + RelationMember& operator=(RelationMember&&) = delete; + + unsigned char* endpos() { + return data() + osmium::memory::padded_length(sizeof(RelationMember) + m_role_size); + } + + const unsigned char* endpos() const { + return data() + osmium::memory::padded_length(sizeof(RelationMember) + m_role_size); + } + + template + friend class osmium::memory::CollectionIterator; + + unsigned char* next() { + if (full_member()) { + return endpos() + reinterpret_cast(endpos())->byte_size(); + } else { + return endpos(); + } + } + + unsigned const char* next() const { + if (full_member()) { + return endpos() + reinterpret_cast(endpos())->byte_size(); + } else { + return endpos(); + } + } + + void set_role_size(string_size_type size) noexcept { + m_role_size = size; + } + + public: + + static constexpr item_type collection_type = item_type::relation_member_list; + + RelationMember(const object_id_type ref=0, const item_type type=item_type(), const bool full=false) noexcept : + m_ref(ref), + m_type(type), + m_flags(full ? 1 : 0) { + } + + object_id_type ref() const noexcept { + return m_ref; + } + + RelationMember& ref(object_id_type ref) noexcept { + m_ref = ref; + return *this; + } + + unsigned_object_id_type positive_ref() const noexcept { + return static_cast(std::abs(m_ref)); + } + + item_type type() const noexcept { + return m_type; + } + + bool full_member() const noexcept { + return m_flags == 1; + } + + const char* role() const noexcept { + return reinterpret_cast(data() + sizeof(RelationMember)); + } + + OSMObject& get_object() { + return *reinterpret_cast(endpos()); + } + + const OSMObject& get_object() const { + return *reinterpret_cast(endpos()); + } + + }; // class RelationMember + + class RelationMemberList : public osmium::memory::Collection { + + public: + + typedef size_t size_type; + + RelationMemberList() : + osmium::memory::Collection() { + } + + size_type size() const noexcept { + return static_cast(std::distance(begin(), end())); + } + + }; // class RelationMemberList + + static_assert(sizeof(RelationMemberList) % osmium::memory::align_bytes == 0, "Class osmium::RelationMemberList has wrong size to be aligned properly!"); + + class Relation : public OSMObject { + + friend class osmium::builder::ObjectBuilder; + + Relation() noexcept : + OSMObject(sizeof(Relation), osmium::item_type::relation) { + } + + public: + + static constexpr osmium::item_type itemtype = osmium::item_type::relation; + + RelationMemberList& members() { + return osmium::detail::subitem_of_type(begin(), end()); + } + + const RelationMemberList& members() const { + return osmium::detail::subitem_of_type(cbegin(), cend()); + } + + }; // class Relation + + static_assert(sizeof(Relation) % osmium::memory::align_bytes == 0, "Class osmium::Relation has wrong size to be aligned properly!"); + +} // namespace osmium + +#endif // OSMIUM_OSM_RELATION_HPP diff --git a/include/osmium/osm/segment.hpp b/include/osmium/osm/segment.hpp new file mode 100644 index 000000000..205036ec6 --- /dev/null +++ b/include/osmium/osm/segment.hpp @@ -0,0 +1,105 @@ +#ifndef OSMIUM_OSM_SEGMENT_HPP +#define OSMIUM_OSM_SEGMENT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include + +#include +#include + +namespace osmium { + + /** + * A Segment is the directed connection between two Locations. + */ + class Segment { + + osmium::Location m_first; + osmium::Location m_second; + + public: + + explicit constexpr Segment(const osmium::Location& location1, const osmium::Location& location2) noexcept : + m_first(location1), + m_second(location2) { + } + + constexpr Segment(const Segment&) = default; + constexpr Segment(Segment&&) = default; + + Segment& operator=(const Segment&) = default; + Segment& operator=(Segment&&) = default; + + ~Segment() = default; + + /// Return first Location of Segment. + OSMIUM_CONSTEXPR osmium::Location first() const noexcept { + return m_first; + } + + /// Return second Location of Segment. + OSMIUM_CONSTEXPR osmium::Location second() const noexcept { + return m_second; + } + + protected: + + void swap_locations() { + using std::swap; + swap(m_first, m_second); + } + + }; // class Segment + + /// Segments are equal if both their locations are equal + inline OSMIUM_CONSTEXPR bool operator==(const Segment& lhs, const Segment& rhs) noexcept { + return lhs.first() == rhs.first() && lhs.second() == rhs.second(); + } + + inline OSMIUM_CONSTEXPR bool operator!=(const Segment& lhs, const Segment& rhs) noexcept { + return ! (lhs == rhs); + } + + /** + * Output Segment to a stream. + */ + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const osmium::Segment& segment) { + return out << segment.first() << "->" << segment.second(); + } + +} // namespace osmium + +#endif // OSMIUM_OSM_SEGMENT_HPP diff --git a/include/osmium/osm/tag.hpp b/include/osmium/osm/tag.hpp new file mode 100644 index 000000000..fe80de34f --- /dev/null +++ b/include/osmium/osm/tag.hpp @@ -0,0 +1,140 @@ +#ifndef OSMIUM_OSM_TAG_HPP +#define OSMIUM_OSM_TAG_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include +#include + +#include +#include +#include + +namespace osmium { + + class Tag : public osmium::memory::detail::ItemHelper { + + Tag(const Tag&) = delete; + Tag(Tag&&) = delete; + + Tag& operator=(const Tag&) = delete; + Tag& operator=(Tag&&) = delete; + + template + friend class osmium::memory::CollectionIterator; + + static unsigned char* after_null(unsigned char* ptr) { + return reinterpret_cast(std::strchr(reinterpret_cast(ptr), 0) + 1); + } + + static const unsigned char* after_null(const unsigned char* ptr) { + return reinterpret_cast(std::strchr(reinterpret_cast(ptr), 0) + 1); + } + + unsigned char* next() { + return after_null(after_null(data())); + } + + const unsigned char* next() const { + return after_null(after_null(data())); + } + + public: + + static constexpr item_type collection_type = item_type::tag_list; + + const char* key() const noexcept { + return reinterpret_cast(data()); + } + + const char* value() const { + return reinterpret_cast(after_null(data())); + } + + }; // class Tag + + inline bool operator==(const Tag& a, const Tag& b) { + return !std::strcmp(a.key(), b.key()) && !strcmp(a.value(), b.value()); + } + + inline bool operator<(const Tag& a, const Tag& b) { + return (!std::strcmp(a.key(), b.key()) && (std::strcmp(a.value(), b.value()) < 0)) || (std::strcmp(a.key(), b.key()) < 0); + } + + /** + * Output a Tag to a stream. + */ + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const Tag& tag) { + return out << tag.key() << '=' << tag.value(); + } + + class TagList : public osmium::memory::Collection { + + public: + + typedef size_t size_type; + + TagList() : + osmium::memory::Collection() { + } + + size_type size() const noexcept { + return static_cast(std::distance(begin(), end())); + } + + const char* get_value_by_key(const char* key, const char* default_value = nullptr) const noexcept { + auto result = std::find_if(cbegin(), cend(), [key](const Tag& tag) { + return !strcmp(tag.key(), key); + }); + if (result == cend()) { + return default_value; + } else { + return result->value(); + } + } + + const char* operator[](const char* key) const noexcept { + return get_value_by_key(key); + } + + }; // class TagList + + static_assert(sizeof(TagList) % osmium::memory::align_bytes == 0, "Class osmium::TagList has wrong size to be aligned properly!"); + +} // namespace osmium + +#endif // OSMIUM_OSM_TAG_HPP diff --git a/include/osmium/osm/timestamp.hpp b/include/osmium/osm/timestamp.hpp new file mode 100644 index 000000000..23f0ec8af --- /dev/null +++ b/include/osmium/osm/timestamp.hpp @@ -0,0 +1,171 @@ +#ifndef OSMIUM_OSM_TIMESTAMP_HPP +#define OSMIUM_OSM_TIMESTAMP_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include +#include +#include +#include + +#include + +namespace osmium { + + /** + * A timestamp. Internal representation is an unsigned 32bit integer + * holding seconds since epoch, so this will overflow in 2038. + */ + class Timestamp { + + // length of ISO timestamp string yyyy-mm-ddThh:mm:ssZ\0 + static constexpr int timestamp_length = 20 + 1; + + /** + * The timestamp format for OSM timestamps in strftime(3) format. + * This is the ISO-Format yyyy-mm-ddThh:mm:ssZ + */ + static const char* timestamp_format() { + static const char f[timestamp_length] = "%Y-%m-%dT%H:%M:%SZ"; + return f; + } + + uint32_t m_timestamp; + + public: + + constexpr Timestamp() noexcept : + m_timestamp(0) { + } + + // Not "explicit" so that conversions from time_t work + // like in node.timestamp(123); + constexpr Timestamp(time_t timestamp) noexcept : + m_timestamp(static_cast(timestamp)) { + } + + /** + * Construct timestamp from ISO date/time string. + * Throws std::invalid_argument, if the timestamp can not be parsed. + */ + explicit Timestamp(const char* timestamp) { +#ifndef _WIN32 + struct tm tm { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + if (strptime(timestamp, timestamp_format(), &tm) == nullptr) { + throw std::invalid_argument("can't parse timestamp"); + } + m_timestamp = static_cast(timegm(&tm)); +#else + struct tm tm; + int n = sscanf(timestamp, "%4d-%2d-%2dT%2d:%2d:%2dZ", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec); + if (n != 6) { + throw std::invalid_argument("can't parse timestamp"); + } + tm.tm_year -= 1900; + tm.tm_mon--; + tm.tm_wday = 0; + tm.tm_yday = 0; + tm.tm_isdst = 0; + m_timestamp = _mkgmtime(&tm); +#endif + } + + constexpr time_t seconds_since_epoch() const noexcept { + return static_cast(m_timestamp); + } + + constexpr operator time_t() const noexcept { + return static_cast(m_timestamp); + } + + template + void operator+=(T time_difference) noexcept { + m_timestamp += time_difference; + } + + template + void operator-=(T time_difference) noexcept { + m_timestamp -= time_difference; + } + + /** + * Return UTC Unix time as string in ISO date/time format. + */ + std::string to_iso() const { + std::string s; + + if (m_timestamp != 0) { + struct tm tm; + time_t sse = seconds_since_epoch(); +#ifndef _MSC_VER + gmtime_r(&sse, &tm); +#else + gmtime_s(&tm, &sse); +#endif + + s.resize(timestamp_length); + /* This const_cast is ok, because we know we have enough space + in the string for the format we are using (well at least until + the year will have 5 digits). And by setting the size + afterwards from the result of strftime we make sure thats set + right, too. */ + s.resize(strftime(const_cast(s.c_str()), timestamp_length, timestamp_format(), &tm)); + } + + return s; + } + + }; // class Timestamp + + inline OSMIUM_CONSTEXPR Timestamp start_of_time() noexcept { + return Timestamp(1); + } + + inline OSMIUM_CONSTEXPR Timestamp end_of_time() noexcept { + return Timestamp(std::numeric_limits::max()); + } + + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, Timestamp timestamp) { + out << timestamp.to_iso(); + return out; + } + +} // namespace osmium + +#endif // OSMIUM_OSM_TIMESTAMP_HPP diff --git a/include/osmium/osm/types.hpp b/include/osmium/osm/types.hpp new file mode 100644 index 000000000..532b5497c --- /dev/null +++ b/include/osmium/osm/types.hpp @@ -0,0 +1,83 @@ +#ifndef OSMIUM_OSM_TYPES_HPP +#define OSMIUM_OSM_TYPES_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include + +namespace osmium { + + /* + * The following typedefs are chosen so that they can represent all needed + * numbers and still be reasonably space efficient. As the OSM database + * needs 64 bit IDs for nodes, this size is used for all object IDs. + */ + typedef int64_t object_id_type; ///< Type for OSM object (node, way, or relation) IDs. + typedef uint64_t unsigned_object_id_type; ///< Type for OSM object (node, way, or relation) IDs where we only allow positive IDs. + typedef uint32_t object_version_type; ///< Type for OSM object version number. + typedef uint32_t changeset_id_type; ///< Type for OSM changeset IDs. + typedef uint32_t user_id_type; ///< Type for OSM user IDs. + typedef int32_t signed_user_id_type; ///< Type for signed OSM user IDs. + typedef uint32_t num_changes_type; ///< Type for changeset num_changes. + + /** + * Size for strings in OSM data such as user names, tag keys, roles, etc. + * In Osmium they can be up to 2^16 bytes long, but OSM usually has lower + * defined limits. + */ + typedef uint16_t string_size_type; + + inline object_id_type string_to_object_id(const char* string) { + return std::atoll(string); + } + + inline object_version_type string_to_object_version(const char* string) { + return static_cast(std::atol(string)); + } + + inline changeset_id_type string_to_changeset_id(const char* string) { + return static_cast(std::atol(string)); + } + + inline signed_user_id_type string_to_user_id(const char* string) { + return static_cast(std::atol(string)); + } + + inline num_changes_type string_to_num_changes(const char* string) { + return static_cast(std::atol(string)); + } + +} // namespace osmium + +#endif // OSMIUM_OSM_TYPES_HPP diff --git a/include/osmium/osm/undirected_segment.hpp b/include/osmium/osm/undirected_segment.hpp new file mode 100644 index 000000000..487e7bf32 --- /dev/null +++ b/include/osmium/osm/undirected_segment.hpp @@ -0,0 +1,100 @@ +#ifndef OSMIUM_OSM_UNDIRECTED_SEGMENT_HPP +#define OSMIUM_OSM_UNDIRECTED_SEGMENT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 + +#include +#include + +namespace osmium { + + /** + * Undirected connection between two Locations. The first Location is + * always equal or "smaller" than the second Location, ie to the left + * and down. + */ + class UndirectedSegment : public Segment { + + public: + + explicit UndirectedSegment(const osmium::Location& location1, const osmium::Location& location2) : + Segment(location1, location2) { + if (location2 < location1) { + swap_locations(); + } + } + + UndirectedSegment(const UndirectedSegment&) = default; + UndirectedSegment(UndirectedSegment&&) = default; + + UndirectedSegment& operator=(const UndirectedSegment&) = default; + UndirectedSegment& operator=(UndirectedSegment&&) = default; + + ~UndirectedSegment() = default; + + }; // class UndirectedSegment + + /** + * UndirectedSegments are "smaller" if they are to the left and down of another + * segment. The first() location is checked first() and only if they have the + * same first() location the second() location is taken into account. + */ + inline bool operator<(const UndirectedSegment& lhs, const UndirectedSegment& rhs) noexcept { + return (lhs.first() == rhs.first() && lhs.second() < rhs.second()) || lhs.first() < rhs.first(); + } + + inline bool operator>(const UndirectedSegment& lhs, const UndirectedSegment& rhs) noexcept { + return rhs < lhs; + } + + inline bool operator<=(const UndirectedSegment& lhs, const UndirectedSegment& rhs) noexcept { + return ! (rhs < lhs); + } + + inline bool operator>=(const UndirectedSegment& lhs, const UndirectedSegment& rhs) noexcept { + return ! (lhs < rhs); + } + + /** + * Output UndirectedSegment to a stream. + */ + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const osmium::UndirectedSegment& segment) { + return out << segment.first() << "--" << segment.second(); + } + +} // namespace osmium + +#endif // OSMIUM_OSM_UNDIRECTED_SEGMENT_HPP diff --git a/include/osmium/osm/way.hpp b/include/osmium/osm/way.hpp new file mode 100644 index 000000000..a30cf911f --- /dev/null +++ b/include/osmium/osm/way.hpp @@ -0,0 +1,115 @@ +#ifndef OSMIUM_OSM_WAY_HPP +#define OSMIUM_OSM_WAY_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include +#include +#include + +namespace osmium { + + namespace builder { + template class ObjectBuilder; + } + + /** + * List of node references (id and location) in a way. + */ + class WayNodeList : public NodeRefList { + + public: + + WayNodeList(): + NodeRefList() { + } + + }; // class WayNodeList + + static_assert(sizeof(WayNodeList) % osmium::memory::align_bytes == 0, "Class osmium::WayNodeList has wrong size to be aligned properly!"); + + class Way : public OSMObject { + + friend class osmium::builder::ObjectBuilder; + + Way() noexcept : + OSMObject(sizeof(Way), osmium::item_type::way) { + } + + public: + + WayNodeList& nodes() { + return osmium::detail::subitem_of_type(begin(), end()); + } + + const WayNodeList& nodes() const { + return osmium::detail::subitem_of_type(cbegin(), cend()); + } + + /** + * Update all nodes in a way with the ID of the given NodeRef with the + * location of the given NodeRef. + */ + void update_node_location(const NodeRef& new_node_ref) { + for (auto& node_ref : nodes()) { + if (node_ref.ref() == new_node_ref.ref()) { + node_ref.set_location(new_node_ref.location()); + } + } + } + + /** + * Do the nodes in this way form a closed ring? + */ + bool is_closed() const { + return nodes().is_closed(); + } + + bool ends_have_same_id() const { + return nodes().ends_have_same_id(); + } + + bool ends_have_same_location() const { + return nodes().ends_have_same_location(); + } + + }; // class Way + + static_assert(sizeof(Way) % osmium::memory::align_bytes == 0, "Class osmium::Way has wrong size to be aligned properly!"); + +} // namespace osmium + +#endif // OSMIUM_OSM_WAY_HPP diff --git a/include/osmium/relations/collector.hpp b/include/osmium/relations/collector.hpp new file mode 100644 index 000000000..60864d308 --- /dev/null +++ b/include/osmium/relations/collector.hpp @@ -0,0 +1,544 @@ +#ifndef OSMIUM_RELATIONS_COLLECTOR_HPP +#define OSMIUM_RELATIONS_COLLECTOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include // IWYU pragma: keep +#include +#include +#include +#include + +#include +#include + +namespace osmium { + + class Node; + class Way; + + /** + * @brief Code related to the assembly of OSM relations + */ + namespace relations { + + /** + * The Collector class collects members of a relation. This is a generic + * base class that can be used to assemble all kinds of relations. It has numerous + * hooks you can implement in derived classes to customize its behaviour. + * + * The collector provides two handlers (HandlerPass1 and HandlerPass2) for a first + * and second pass through an input file, respectively. In the first pass all + * relations we are interested in are stored in RelationMeta objects in the + * m_relations vector. All members we are interested in are stored in MemberMeta + * objects in the m_member_meta vectors. + * The MemberMeta objects also store the information where the relations containing + * those members are to be found. + * + * Later the m_member_meta vectors are sorted according to the + * member ids so that a binary search (with std::equal_range) can be used in the second + * pass to find the parent relations for each node, way, or relation coming along. + * The member objects are stored together with their relation and once a relation + * is complete the complete_relation() method is called which you must overwrite in + * a derived class of Collector. + * + * @tparam TCollector Derived class of this class. + * + * @tparam TNodes Are we interested in member nodes? + * + * @tparam TWays Are we interested in member ways? + * + * @tparam TRelations Are we interested in member relations? + */ + template + class Collector { + + /** + * This is the handler class for the first pass of the Collector. + */ + class HandlerPass1 : public osmium::handler::Handler { + + TCollector& m_collector; + + public: + + HandlerPass1(TCollector& collector) noexcept : + m_collector(collector) { + } + + void relation(const osmium::Relation& relation) { + if (m_collector.keep_relation(relation)) { + m_collector.add_relation(relation); + } + } + + }; // class HandlerPass1 + + public: + + /** + * This is the handler class for the second pass of the Collector. + */ + class HandlerPass2 : public osmium::handler::Handler { + + TCollector& m_collector; + + /** + * This variable is initialized with the number of different + * kinds of OSM objects we are interested in. If we only need + * way members (for instance for the multipolygon collector) + * it is intialized with 1 for instance. If node and way + * members are needed, it is initialized with 2. + * + * In the after_* methods of this handler, it is decremented + * and once it reaches 0, we know we have all members available + * that we are ever going to get. + */ + int m_want_types; + + /** + * Find this object in the member vectors and add it to all + * relations that need it. + * + * @returns true if the member was added to at least one + * relation and false otherwise + */ + bool find_and_add_object(const osmium::OSMObject& object) { + auto& mmv = m_collector.member_meta(object.type()); + auto range = std::equal_range(mmv.begin(), mmv.end(), MemberMeta(object.id())); + + if (osmium::relations::count_not_removed(range.first, range.second) == 0) { + // nothing found + return false; + } + + { + m_collector.members_buffer().add_item(object); + const size_t member_offset = m_collector.members_buffer().commit(); + + for (auto it = range.first; it != range.second; ++it) { + it->set_buffer_offset(member_offset); + } + } + + for (auto it = range.first; it != range.second; ++it) { + MemberMeta& member_meta = *it; + if (member_meta.removed()) { + break; + } + assert(member_meta.member_id() == object.id()); + assert(member_meta.relation_pos() < m_collector.m_relations.size()); + RelationMeta& relation_meta = m_collector.m_relations[member_meta.relation_pos()]; +// std::cerr << " => " << member_meta.member_pos() << " < " << m_collector.get_relation(relation_meta).members().size() << " (id=" << m_collector.get_relation(relation_meta).id() << ")\n"; + assert(member_meta.member_pos() < m_collector.get_relation(relation_meta).members().size()); +// std::cerr << " add way " << member_meta.member_id() << " to rel " << m_collector.get_relation(relation_meta).id() << " at pos " << member_meta.member_pos() << "\n"; + relation_meta.got_one_member(); + if (relation_meta.has_all_members()) { + const size_t relation_offset = member_meta.relation_pos(); + m_collector.complete_relation(relation_meta); + m_collector.m_relations[relation_offset] = RelationMeta(); + m_collector.possibly_purge_removed_members(); + } + } + + // Remove MemberMetas that were marked as removed. + mmv.erase(std::remove_if(mmv.begin(), mmv.end(), [](MemberMeta& mm) { + return mm.removed(); + }), mmv.end()); + + return true; + } + + public: + + HandlerPass2(TCollector& collector) noexcept : + m_collector(collector), + m_want_types((TNodes?1:0) + (TWays?1:0) + (TRelations?1:0)) { + } + + void node(const osmium::Node& node) { + if (TNodes) { + if (! find_and_add_object(node)) { + m_collector.node_not_in_any_relation(node); + } + } + } + + void way(const osmium::Way& way) { + if (TWays) { + if (! find_and_add_object(way)) { + m_collector.way_not_in_any_relation(way); + } + } + } + + void relation(const osmium::Relation& relation) { + if (TRelations) { + if (! find_and_add_object(relation)) { + m_collector.relation_not_in_any_relation(relation); + } + } + } + + void flush() { + m_collector.flush(); + } + + }; // class HandlerPass2 + + HandlerPass2 m_handler_pass2; + + // All relations we are interested in will be kept in this buffer + osmium::memory::Buffer m_relations_buffer; + + // All members we are interested in will be kept in this buffer + osmium::memory::Buffer m_members_buffer; + + /// Vector with all relations we are interested in + std::vector m_relations; + + /** + * One vector each for nodes, ways, and relations containing all + * mappings from member ids to their relations. + */ + std::vector m_member_meta[3]; + + int m_count_complete = 0; + + typedef std::function callback_func_type; + callback_func_type m_callback; + + static constexpr size_t initial_buffer_size = 1024 * 1024; + + public: + + /** + * Create an Collector. + */ + Collector() : + m_handler_pass2(*static_cast(this)), + m_relations_buffer(initial_buffer_size, osmium::memory::Buffer::auto_grow::yes), + m_members_buffer(initial_buffer_size, osmium::memory::Buffer::auto_grow::yes), + m_relations(), + m_member_meta() { + } + + protected: + + std::vector& member_meta(const item_type type) { + return m_member_meta[static_cast(type) - 1]; + } + + callback_func_type callback() { + return m_callback; + } + + const std::vector& relations() const { + return m_relations; + } + + /** + * This method is called from the first pass handler for every + * relation in the input, to check whether it should be kept. + * + * Overwrite this method in a child class to only add relations + * you are interested in, for instance depending on the type tag. + * Storing relations takes a lot of memory, so it makes sense to + * filter this as much as possible. + */ + bool keep_relation(const osmium::Relation& /*relation*/) const { + return true; + } + + /** + * This method is called for every member of every relation that + * should be kept. It should decide if the member is interesting or + * not and return true or false to signal that. Only interesting + * members are later added to the relation. + * + * Overwrite this method in a child class. In the MultiPolygonCollector + * this is for instance used to only keep members of type way and + * ignore all others. + */ + bool keep_member(const osmium::relations::RelationMeta& /*relation_meta*/, const osmium::RelationMember& /*member*/) const { + return true; + } + + /** + * This method is called for all nodes that are not a member of + * any relation. + * + * Overwrite this method in a child class if you are interested + * in this. + */ + void node_not_in_any_relation(const osmium::Node& /*node*/) { + } + + /** + * This method is called for all ways that are not a member of + * any relation. + * + * Overwrite this method in a child class if you are interested + * in this. + */ + void way_not_in_any_relation(const osmium::Way& /*way*/) { + } + + /** + * This method is called for all relations that are not a member of + * any relation. + * + * Overwrite this method in a child class if you are interested + * in this. + */ + void relation_not_in_any_relation(const osmium::Relation& /*relation*/) { + } + + /** + * This method is called from the 2nd pass handler when all objects + * of types we are interested in have been seen. + * + * Overwrite this method in a child class if you are interested + * in this. + * + * Note that even after this call members might be missing if they + * were not in the input file! The derived class has to handle this + * case. + */ + void flush() { + } + + /** + * This removes all relations that have already been assembled + * from the m_relations vector. + */ + void clean_assembled_relations() { + m_relations.erase( + std::remove_if(m_relations.begin(), m_relations.end(), has_all_members()), + m_relations.end() + ); + } + + const osmium::Relation& get_relation(size_t offset) const { + return m_relations_buffer.get(offset); + } + + /** + * Get the relation from a relation_meta. + */ + const osmium::Relation& get_relation(const RelationMeta& relation_meta) const { + return get_relation(relation_meta.relation_offset()); + } + + osmium::OSMObject& get_member(size_t offset) const { + return m_members_buffer.get(offset); + } + + /** + * Tell the Collector that you are interested in this relation + * and want it kept until all members have been assembled and + * it is handed back to you. + * + * The relation is copied and stored in a buffer inside the + * collector. + */ + void add_relation(const osmium::Relation& relation) { + const size_t offset = m_relations_buffer.committed(); + m_relations_buffer.add_item(relation); + + RelationMeta relation_meta(offset); + + int n=0; + for (auto& member : m_relations_buffer.get(offset).members()) { + if (static_cast(this)->keep_member(relation_meta, member)) { + member_meta(member.type()).emplace_back(member.ref(), m_relations.size(), n); + relation_meta.increment_need_members(); + } else { + member.ref(0); // set member id to zero to indicate we are not interested + } + ++n; + } + + assert(offset == m_relations_buffer.committed()); + if (relation_meta.has_all_members()) { + m_relations_buffer.rollback(); + } else { + m_relations_buffer.commit(); + m_relations.push_back(std::move(relation_meta)); +// std::cerr << "added relation id=" << relation.id() << "\n"; + } + } + + /** + * Sort the vectors with the member infos so that we can do binary + * search on them. + */ + void sort_member_meta() { +/* std::cerr << "relations: " << m_relations.size() << "\n"; + std::cerr << "node members: " << m_member_meta[0].size() << "\n"; + std::cerr << "way members: " << m_member_meta[1].size() << "\n"; + std::cerr << "relation members: " << m_member_meta[2].size() << "\n";*/ + std::sort(m_member_meta[0].begin(), m_member_meta[0].end()); + std::sort(m_member_meta[1].begin(), m_member_meta[1].end()); + std::sort(m_member_meta[2].begin(), m_member_meta[2].end()); + } + + public: + + uint64_t used_memory() const { + const uint64_t nmembers = m_member_meta[0].capacity() + m_member_meta[1].capacity() + m_member_meta[2].capacity(); + const uint64_t members = nmembers * sizeof(MemberMeta); + const uint64_t relations = m_relations.capacity() * sizeof(RelationMeta); + const uint64_t relations_buffer_capacity = m_relations_buffer.capacity(); + const uint64_t members_buffer_capacity = m_members_buffer.capacity(); + + std::cout << " nR = m_relations.capacity() ........... = " << std::setw(12) << m_relations.capacity() << "\n"; + std::cout << " nMN = m_member_meta[NODE].capacity() ... = " << std::setw(12) << m_member_meta[0].capacity() << "\n"; + std::cout << " nMW = m_member_meta[WAY].capacity() .... = " << std::setw(12) << m_member_meta[1].capacity() << "\n"; + std::cout << " nMR = m_member_meta[RELATION].capacity() = " << std::setw(12) << m_member_meta[2].capacity() << "\n"; + std::cout << " nM = m_member_meta[*].capacity() ...... = " << std::setw(12) << nmembers << "\n"; + + std::cout << " sRM = sizeof(RelationMeta) ............. = " << std::setw(12) << sizeof(RelationMeta) << "\n"; + std::cout << " sMM = sizeof(MemberMeta) ............... = " << std::setw(12) << sizeof(MemberMeta) << "\n\n"; + + std::cout << " nR * sRM ............................... = " << std::setw(12) << relations << "\n"; + std::cout << " nM * sMM ............................... = " << std::setw(12) << members << "\n"; + std::cout << " relations_buffer_capacity .............. = " << std::setw(12) << relations_buffer_capacity << "\n"; + std::cout << " members_buffer_capacity ................ = " << std::setw(12) << members_buffer_capacity << "\n"; + + const uint64_t total = relations + members + relations_buffer_capacity + members_buffer_capacity; + + std::cout << " total .................................. = " << std::setw(12) << total << "\n"; + std::cout << " =======================================================\n"; + + return relations_buffer_capacity + members_buffer_capacity + relations + members; + } + + /** + * Return reference to second pass handler. + */ + HandlerPass2& handler(const callback_func_type& callback = nullptr) { + m_callback = callback; + return m_handler_pass2; + } + + osmium::memory::Buffer& members_buffer() { + return m_members_buffer; + } + + size_t get_offset(osmium::item_type type, osmium::object_id_type id) { + const auto& mmv = member_meta(type); + const auto range = std::equal_range(mmv.cbegin(), mmv.cend(), MemberMeta(id)); + assert(range.first != range.second); + return range.first->buffer_offset(); + } + + template + void read_relations(TIter begin, TIter end) { + HandlerPass1 handler(*static_cast(this)); + osmium::apply(begin, end, handler); + sort_member_meta(); + } + + template + void read_relations(TSource& source) { + read_relations(std::begin(source), std::end(source)); + source.close(); + } + + void moving_in_buffer(size_t old_offset, size_t new_offset) { + const osmium::OSMObject& object = m_members_buffer.get(old_offset); + auto& mmv = member_meta(object.type()); + auto range = std::equal_range(mmv.begin(), mmv.end(), osmium::relations::MemberMeta(object.id())); + for (auto it = range.first; it != range.second; ++it) { + assert(it->buffer_offset() == old_offset); + it->set_buffer_offset(new_offset); + } + } + + /** + * Decide whether to purge removed members and then do it. + * + * Currently the purging is done every thousand calls. + * This could probably be improved upon. + */ + void possibly_purge_removed_members() { + ++m_count_complete; + if (m_count_complete > 10000) { // XXX + const size_t size_before = m_members_buffer.committed(); + m_members_buffer.purge_removed(this); + const size_t size_after = m_members_buffer.committed(); + double percent = size_before - size_after; + percent /= size_before; + percent *= 100; + std::cerr << "PURGE (size before=" << size_before << " after=" << size_after << " purged=" << (size_before - size_after) << " / " << static_cast(percent) << "%)\n"; + m_count_complete = 0; + } + } + + /** + * Get a vector with pointers to all Relations that could not + * be completed, because members were missing in the input + * data. + * + * Note that these pointers point into memory allocated and + * owned by the Collector object. + */ + std::vector get_incomplete_relations() const { + std::vector relations; + for (const auto& relation_meta : m_relations) { + if (!relation_meta.has_all_members()) { + relations.push_back(&get_relation(relation_meta)); + } + } + return relations; + } + + }; // class Collector + + } // namespace relations + +} // namespace osmium + +#endif // OSMIUM_RELATIONS_COLLECTOR_HPP diff --git a/include/osmium/relations/detail/member_meta.hpp b/include/osmium/relations/detail/member_meta.hpp new file mode 100644 index 000000000..5463a1cb8 --- /dev/null +++ b/include/osmium/relations/detail/member_meta.hpp @@ -0,0 +1,158 @@ +#ifndef OSMIUM_RELATIONS_DETAIL_MEMBER_META_HPP +#define OSMIUM_RELATIONS_DETAIL_MEMBER_META_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include + +#include + +namespace osmium { + + namespace relations { + + /** + * Helper class for the Collector class. + * + * Stores an object ID and information where the object should be + * stored. + */ + class MemberMeta { + + /** + * Object ID of this relation member. Can be a node, way, or relation ID. + * It depends on the vector in which this object is stored which kind of + * object is referenced here. + */ + osmium::object_id_type m_member_id; + + /** + * Position of the relation this member is a part of in the + * m_relations vector. + */ + size_t m_relation_pos; + + /** + * Position of this member in the list of members of the + * relation this member is a part of. + */ + size_t m_member_pos; + + /** + * Offset in the buffer where the object is stored. + */ + size_t m_buffer_offset { 0 }; + + bool m_removed = false; + + public: + + /** + * Create new MemberMeta. The variant with zeros for relation_pos and + * 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 : + m_member_id(member_id), + m_relation_pos(relation_pos), + m_member_pos(member_pos) { + } + + osmium::object_id_type member_id() const noexcept { + return m_member_id; + } + + size_t relation_pos() const noexcept { + return m_relation_pos; + } + + size_t member_pos() const noexcept { + return m_member_pos; + } + + size_t buffer_offset() const noexcept { + return m_buffer_offset; + } + + void set_buffer_offset(size_t offset) noexcept { + m_buffer_offset = offset; + } + + bool removed() const noexcept { + return m_removed; + } + + void remove() noexcept { + m_removed = true; + } + + }; // class MemberMeta + + /** + * Compares two MemberMeta objects by only looking at the member id. + * Used to sort a vector of MemberMeta objects and to later find + * them using binary search. + */ + inline bool operator<(const MemberMeta& a, const MemberMeta& b) noexcept { + return a.member_id() < b.member_id(); + } + + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const MemberMeta& mm) { + out << "MemberMeta(member_id=" << mm.member_id() << " relation_pos=" << mm.relation_pos() << " member_pos=" << mm.member_pos() << " buffer_offset=" << mm.buffer_offset() << ")"; + return out; + } + + /** + * Count the number of MemberMeta objects in the iterator range + * that are not marked as removed. + * + * @tparam TIter Iterator that dereferences to a MemberMeta + * @param begin Begin of iterator range + * @param end End of iterator range + */ + template + inline typename std::iterator_traits::difference_type count_not_removed(TIter begin, TIter end) { + return std::count_if(begin, end, [](MemberMeta& mm) { + return !mm.removed(); + }); + } + + } // namespace relations + +} // namespace osmium + +#endif // OSMIUM_RELATIONS_DETAIL_MEMBER_META_HPP diff --git a/include/osmium/relations/detail/relation_meta.hpp b/include/osmium/relations/detail/relation_meta.hpp new file mode 100644 index 000000000..77ca0c130 --- /dev/null +++ b/include/osmium/relations/detail/relation_meta.hpp @@ -0,0 +1,136 @@ +#ifndef OSMIUM_RELATIONS_DETAIL_RELATION_META_HPP +#define OSMIUM_RELATIONS_DETAIL_RELATION_META_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include + +namespace osmium { + + namespace relations { + + /** + * Helper class for the Collector class. + * + * Stores information needed to collect all members of a relation. This + * includes the offset of the relation in a buffer plus the information + * needed to add members to this relation. + */ + class RelationMeta { + + /// The relation we are assembling. + size_t m_relation_offset; + + /** + * The number of members still needed before the relation is + * complete. This will be set to the number of members we are + * interested in and then count down for every member we find. + * When it is 0, the relation is complete. + */ + int m_need_members = 0; + + public: + + /** + * Initialize an empty RelationMeta. This is needed to zero out + * relations that have been completed. + */ + RelationMeta() noexcept : + m_relation_offset(0) { + } + + explicit RelationMeta(size_t relation_offset) noexcept : + m_relation_offset(relation_offset) { + } + + /** + * Get offset of relation in buffer. + */ + size_t relation_offset() const noexcept { + return m_relation_offset; + } + + /** + * Increment the m_need_members counter. + */ + void increment_need_members() noexcept { + ++m_need_members; + } + + /** + * This decrements the "members needed" counter. + */ + void got_one_member() { + assert(m_need_members > 0); + --m_need_members; + } + + /** + * Returns true if all members for this relation are available. + */ + bool has_all_members() const noexcept { + return m_need_members == 0; + } + + }; // class RelationMeta + + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const RelationMeta& rm) { + out << "RelationMeta(relation_offset=" << rm.relation_offset() << " has_all_members=" << rm.has_all_members() << ")"; + return out; + } + + /** + * Function object to check if a relation is complete. + */ + struct has_all_members { + + typedef RelationMeta& argument_type; + typedef bool result_type; + + /** + * @returns true if this relation is complete, false otherwise. + */ + bool operator()(RelationMeta& relation_info) const { + return relation_info.has_all_members(); + } + + }; // struct has_all_members + + } // namespace relations + +} // namespace osmium + +#endif // OSMIUM_RELATIONS_DETAIL_RELATION_META_HPP diff --git a/include/osmium/tags/filter.hpp b/include/osmium/tags/filter.hpp new file mode 100644 index 000000000..0a0fd3b56 --- /dev/null +++ b/include/osmium/tags/filter.hpp @@ -0,0 +1,148 @@ +#ifndef OSMIUM_TAGS_FILTER_HPP +#define OSMIUM_TAGS_FILTER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include + +#include + +#include +#include + +namespace osmium { + + namespace tags { + + template + struct match_key { + bool operator()(const TKey& rule_key, const char* tag_key) { + return rule_key == tag_key; + } + }; // struct match_key + + struct match_key_prefix { + bool operator()(const std::string& rule_key, const char* tag_key) { + return rule_key.compare(0, std::string::npos, tag_key, 0, rule_key.size()) == 0; + } + }; // struct match_key_prefix + + template + struct match_value { + bool operator()(const TValue& rule_value, const char* tag_value) { + return rule_value == tag_value; + } + }; // struct match_value + + template <> + struct match_value { + bool operator()(const bool, const char*) { + return true; + } + }; // struct match_value + + template , class TValueComp=match_value> + class Filter { + + typedef TKey key_type; + typedef typename std::conditional::value, bool, TValue>::type value_type; + + struct Rule { + key_type key; + value_type value; + bool ignore_value; + bool result; + + explicit Rule(bool r, bool ignore, const key_type& k, const value_type& v) : + key(k), + value(v), + ignore_value(ignore), + result(r) { + } + + explicit Rule(bool r, bool ignore, const key_type& k) : + key(k), + value(), + ignore_value(ignore), + result(r) { + } + + }; // struct Rule + + std::vector m_rules; + bool m_default_result; + + public: + + typedef Filter filter_type; + typedef const osmium::Tag& argument_type; + typedef bool result_type; + typedef boost::filter_iterator iterator; + + explicit Filter(bool default_result = false) : + m_default_result(default_result) { + } + + template ::value, int>::type = 0> + Filter& add(bool result, const key_type& key, const value_type& value) { + m_rules.emplace_back(result, false, key, value); + return *this; + } + + Filter& add(bool result, const key_type& key) { + m_rules.emplace_back(result, true, key); + return *this; + } + + bool operator()(const osmium::Tag& tag) const { + for (const Rule& rule : m_rules) { + if (TKeyComp()(rule.key, tag.key()) && (rule.ignore_value || TValueComp()(rule.value, tag.value()))) { + return rule.result; + } + } + return m_default_result; + } + + }; // class Filter + + typedef Filter KeyValueFilter; + typedef Filter KeyFilter; + typedef Filter KeyPrefixFilter; + + } // namespace tags + +} // namespace osmium + +#endif // OSMIUM_TAGS_FILTER_HPP diff --git a/include/osmium/tags/regex_filter.hpp b/include/osmium/tags/regex_filter.hpp new file mode 100644 index 000000000..ae2703a30 --- /dev/null +++ b/include/osmium/tags/regex_filter.hpp @@ -0,0 +1,58 @@ +#ifndef OSMIUM_TAGS_REGEX_FILTER_HPP +#define OSMIUM_TAGS_REGEX_FILTER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf 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 +#include + +#include + +namespace osmium { + + namespace tags { + + template <> + struct match_value { + bool operator()(const std::regex& rule_value, const char* tag_value) { + return std::regex_match(tag_value, rule_value); + } + }; // struct match_value + + typedef Filter RegexFilter; + + } // namespace tags + +} // namespace osmium + +#endif // OSMIUM_TAGS_REGEX_FILTER_HPP diff --git a/include/osmium/tags/taglist.hpp b/include/osmium/tags/taglist.hpp new file mode 100644 index 000000000..41ef993a0 --- /dev/null +++ b/include/osmium/tags/taglist.hpp @@ -0,0 +1,67 @@ +#ifndef OSMIUM_TAGS_TAGLIST_HPP +#define OSMIUM_TAGS_TAGLIST_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf 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 +#include + +#include + +namespace osmium { + + /** + * @brief Code related to working with OSM tags + */ + namespace tags { + + template + inline bool match_any_of(const osmium::TagList& tag_list, TFilter&& filter) { + return std::any_of(tag_list.begin(), tag_list.end(), std::forward(filter)); + } + + template + inline bool match_all_of(const osmium::TagList& tag_list, TFilter&& filter) { + return std::all_of(tag_list.begin(), tag_list.end(), std::forward(filter)); + } + + template + inline bool match_none_of(const osmium::TagList& tag_list, TFilter&& filter) { + return std::none_of(tag_list.begin(), tag_list.end(), std::forward(filter)); + } + + } // namespace tags + +} // namespace osmium + +#endif // OSMIUM_TAGS_TAGLIST_HPP diff --git a/include/osmium/thread/function_wrapper.hpp b/include/osmium/thread/function_wrapper.hpp new file mode 100644 index 000000000..dbb47ff87 --- /dev/null +++ b/include/osmium/thread/function_wrapper.hpp @@ -0,0 +1,110 @@ +#ifndef OSMIUM_THREAD_FUNCTION_WRAPPER_HPP +#define OSMIUM_THREAD_FUNCTION_WRAPPER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include + +namespace osmium { + + namespace thread { + + /** + * This function wrapper can collect move-only functions unlike + * std::function which needs copyable functions. + * Taken from the book "C++ Concurrency in Action". + */ + class function_wrapper { + + struct impl_base { + + virtual ~impl_base() = default; + virtual void call() = 0; + + }; // struct impl_base + + std::unique_ptr impl; + + template + struct impl_type : impl_base { + F m_functor; + + impl_type(F&& functor) : + m_functor(std::move(functor)) { + } + + void call() override { + m_functor(); + } + }; // struct impl_type + + public: + + // Constructor must not be "explicit" for wrapper + // to work seemlessly. + template + function_wrapper(F&& f) : + impl(new impl_type(std::move(f))) { + } + + void operator()() { + impl->call(); + } + + function_wrapper() = default; + + function_wrapper(function_wrapper&& other) : + impl(std::move(other.impl)) { + } + + function_wrapper& operator=(function_wrapper&& other) { + impl = std::move(other.impl); + return *this; + } + + function_wrapper(const function_wrapper&) = delete; + function_wrapper(function_wrapper&) = delete; + function_wrapper& operator=(const function_wrapper&) = delete; + + explicit operator bool() const { + return static_cast(impl); + } + + }; // class function_wrapper + + } // namespace thread + +} // namespace osmium + +#endif // OSMIUM_THREAD_FUNCTION_WRAPPER_HPP diff --git a/include/osmium/thread/pool.hpp b/include/osmium/thread/pool.hpp new file mode 100644 index 000000000..702be66e0 --- /dev/null +++ b/include/osmium/thread/pool.hpp @@ -0,0 +1,180 @@ +#ifndef OSMIUM_THREAD_POOL_HPP +#define OSMIUM_THREAD_POOL_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace osmium { + + /** + * @brief Threading-related low-level code + */ + namespace thread { + + /** + * Thread pool. + */ + class Pool { + + /** + * This class makes sure all pool threads will be joined when + * the pool is destructed. + */ + class thread_joiner { + + std::vector& m_threads; + + public: + + explicit thread_joiner(std::vector& threads) : + m_threads(threads) { + } + + ~thread_joiner() { + for (auto& thread : m_threads) { + if (thread.joinable()) { + thread.join(); + } + } + } + + }; // class thread_joiner + + std::atomic m_done; + osmium::thread::Queue m_work_queue; + std::vector m_threads; + thread_joiner m_joiner; + int m_num_threads; + + void worker_thread() { + osmium::thread::set_thread_name("_osmium_worker"); + while (!m_done) { + function_wrapper task; + m_work_queue.wait_and_pop_with_timeout(task); + if (task) { + task(); + } + } + } + + /** + * Create thread pool with the given number of threads. If + * num_threads is 0, the number of threads is read from + * the environment variable OSMIUM_POOL_THREADS. The default + * value in that case is -2. + * + * If the number of threads is a negative number, it will be + * set to the actual number of cores on the system plus the + * given number, ie it will leave a number of cores unused. + * + * In all cases the minimum number of threads in the pool is 1. + */ + explicit Pool(int num_threads, size_t max_queue_size) : + m_done(false), + m_work_queue(max_queue_size, "work"), + m_threads(), + m_joiner(m_threads), + m_num_threads(num_threads) { + + if (m_num_threads == 0) { + m_num_threads = osmium::config::get_pool_threads(); + } + + if (m_num_threads <= 0) { + m_num_threads = std::max(1, static_cast(std::thread::hardware_concurrency()) + m_num_threads); + } + + try { + for (int i=0; i < m_num_threads; ++i) { + m_threads.push_back(std::thread(&Pool::worker_thread, this)); + } + } catch (...) { + m_done = true; + throw; + } + } + + public: + + static constexpr int default_num_threads = 0; + static constexpr size_t max_work_queue_size = 10; + + static Pool& instance() { + static Pool pool(default_num_threads, max_work_queue_size); + return pool; + } + + ~Pool() { + m_done = true; + } + + size_t queue_size() const { + return m_work_queue.size(); + } + + bool queue_empty() const { + return m_work_queue.empty(); + } + + template + std::future::type> submit(TFunction f) { + + typedef typename std::result_of::type result_type; + + std::packaged_task task(std::move(f)); + std::future future_result(task.get_future()); + m_work_queue.push(std::move(task)); + + return future_result; + } + + }; // class Pool + + } // namespace thread + +} // namespace osmium + +#endif // OSMIUM_THREAD_POOL_HPP diff --git a/include/osmium/thread/queue.hpp b/include/osmium/thread/queue.hpp new file mode 100644 index 000000000..b01dd39bf --- /dev/null +++ b/include/osmium/thread/queue.hpp @@ -0,0 +1,178 @@ +#ifndef OSMIUM_THREAD_QUEUE_HPP +#define OSMIUM_THREAD_QUEUE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace thread { + + constexpr std::chrono::milliseconds full_queue_sleep_duration { 10 }; // XXX + + /** + * A thread-safe queue. + */ + template + class Queue { + + /// Maximum size of this queue. If the queue is full pushing to + /// the queue will block. + const size_t m_max_size; + + /// Name of this queue (for debugging only). + const std::string m_name; + + mutable std::mutex m_mutex; + + std::queue m_queue; + + /// Used to signal readers when data is available in the queue. + std::condition_variable m_data_available; + +#ifdef OSMIUM_DEBUG_QUEUE_SIZE + /// The largest size the queue has been so far. + size_t m_largest_size; + + /// The number of times the queue was full and a thread pushing + /// to the queue was blocked. + std::atomic m_full_counter; +#endif + + public: + + /** + * Construct a multithreaded queue. + * + * @param max_size Maximum number of elements in the queue. Set to + * 0 for an unlimited size. + * @param name Optional name for this queue. (Used for debugging.) + */ + Queue(size_t max_size = 0, const std::string& name = "") : + m_max_size(max_size), + m_name(name), + m_mutex(), + m_queue(), + m_data_available() +#ifdef OSMIUM_DEBUG_QUEUE_SIZE + , + m_largest_size(0), + m_full_counter(0) +#endif + { + } + + ~Queue() { +#ifdef OSMIUM_DEBUG_QUEUE_SIZE + std::cerr << "queue '" << m_name << "' with max_size=" << m_max_size << " had largest size " << m_largest_size << " and was full " << m_full_counter << " times\n"; +#endif + } + + /** + * Push an element onto the queue. If the queue has a max size, this + * call will block if the queue is full. + */ + void push(T value) { + if (m_max_size) { + while (size() >= m_max_size) { + std::this_thread::sleep_for(full_queue_sleep_duration); +#ifdef OSMIUM_DEBUG_QUEUE_SIZE + ++m_full_counter; +#endif + } + } + std::lock_guard lock(m_mutex); + m_queue.push(std::move(value)); +#ifdef OSMIUM_DEBUG_QUEUE_SIZE + if (m_largest_size < m_queue.size()) { + m_largest_size = m_queue.size(); + } +#endif + m_data_available.notify_one(); + } + + void wait_and_pop(T& value) { + std::unique_lock lock(m_mutex); + m_data_available.wait(lock, [this] { + return !m_queue.empty(); + }); + value=std::move(m_queue.front()); + m_queue.pop(); + } + + void wait_and_pop_with_timeout(T& value) { + std::unique_lock lock(m_mutex); + if (!m_data_available.wait_for(lock, std::chrono::seconds(1), [this] { + return !m_queue.empty(); + })) { + return; + } + value=std::move(m_queue.front()); + m_queue.pop(); + } + + bool try_pop(T& value) { + std::lock_guard lock(m_mutex); + if (m_queue.empty()) { + return false; + } + value=std::move(m_queue.front()); + m_queue.pop(); + return true; + } + + bool empty() const { + std::lock_guard lock(m_mutex); + return m_queue.empty(); + } + + size_t size() const { + std::lock_guard lock(m_mutex); + return m_queue.size(); + } + + }; // class Queue + + } // namespace thread + +} // namespace osmium + +#endif // OSMIUM_THREAD_QUEUE_HPP diff --git a/include/osmium/thread/sorted_queue.hpp b/include/osmium/thread/sorted_queue.hpp new file mode 100644 index 000000000..e33dfe696 --- /dev/null +++ b/include/osmium/thread/sorted_queue.hpp @@ -0,0 +1,159 @@ +#ifndef OSMIUM_THREAD_SORTED_QUEUE_HPP +#define OSMIUM_THREAD_SORTED_QUEUE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include + +namespace osmium { + + namespace thread { + + /** + * This implements a sorted queue. It is a bit like a priority + * queue. We have n worker threads pushing items into the queue + * and one thread pulling them out again "in order". The order + * is defined by the monotonically increasing "num" parameter + * to the push() method. The wait_and_pop() and try_pop() methods + * will only give out the next numbered item. This way several + * workers can work in their own time on different pieces of + * some incoming data, but it all gets serialized properly again + * after the workers have done their work. + */ + template + class SortedQueue { + + typedef typename std::deque::size_type size_type; + + mutable std::mutex m_mutex; + std::deque m_queue; + std::condition_variable m_data_available; + + size_type m_offset; + + // this method expects that we already have the lock + bool empty_intern() const { + return m_queue.front() == T(); + } + + public: + + SortedQueue() : + m_mutex(), + m_queue(1), + m_data_available(), + m_offset(0) { + } + + /** + * Push an item into the queue. + * + * @param value The item to push into the queue. + * @param num Number to describe ordering for the items. + * It must increase monotonically. + */ + void push(T value, size_type num) { + std::lock_guard lock(m_mutex); + + num -= m_offset; + if (m_queue.size() <= num + 1) { + m_queue.resize(num + 2); + } + m_queue[num] = std::move(value); + + m_data_available.notify_one(); + } + + /** + * Wait until the next item becomes available and make it + * available through value. + */ + void wait_and_pop(T& value) { + std::unique_lock lock(m_mutex); + + m_data_available.wait(lock, [this] { + return !empty_intern(); + }); + value=std::move(m_queue.front()); + m_queue.pop_front(); + ++m_offset; + } + + /** + * Get next item if it is available and return true. Or + * return false otherwise. + */ + bool try_pop(T& value) { + std::lock_guard lock(m_mutex); + + if (empty_intern()) { + return false; + } + value=std::move(m_queue.front()); + m_queue.pop_front(); + ++m_offset; + return true; + } + + /** + * The queue is empty. This means try_pop() would fail if called. + * It does not mean that there is nothing on the queue. Because + * the queue is sorted, it could mean that the next item in the + * queue is not available, but other items are. + */ + bool empty() const { + std::lock_guard lock(m_mutex); + + return empty_intern(); + } + + /** + * Returns the number of items in the queue, regardless of whether + * they can be accessed. If this is =0 it + * implies empty()==true, but not the other way around. + */ + size_t size() const { + std::lock_guard lock(m_mutex); + return m_queue.size(); + } + + }; // class SortedQueue + + } // namespace thread + +} // namespace osmium + +#endif // OSMIUM_THREAD_SORTED_QUEUE_HPP diff --git a/include/osmium/thread/util.hpp b/include/osmium/thread/util.hpp new file mode 100644 index 000000000..286ea5e06 --- /dev/null +++ b/include/osmium/thread/util.hpp @@ -0,0 +1,87 @@ +#ifndef OSMIUM_THREAD_UTIL_HPP +#define OSMIUM_THREAD_UTIL_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include + +#ifdef __linux__ +# include +#endif + +namespace osmium { + + namespace thread { + + /** + * Check if the future resulted in an exception. This will re-throw + * the exception stored in the future if there was one. Otherwise it + * will just return. + */ + template + inline void check_for_exception(std::future& future) { + if (future.valid() && future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) { + future.get(); + } + } + + /** + * Wait until the given future becomes ready. Will block if the future + * is not ready. Can be called more than once unless future.get(). + */ + template + inline void wait_until_done(std::future& future) { + if (future.valid()) { + future.get(); + } + } + + /** + * Set name of current thread for debugging. This only works on Linux. + */ +#ifdef __linux__ + inline void set_thread_name(const char* name) { + prctl(PR_SET_NAME, name, 0, 0, 0); + } +#else + inline void set_thread_name(const char*) { + // intentionally left blank + } +#endif + + } // namespace thread + +} // namespace osmium + +#endif // OSMIUM_THREAD_UTIL_HPP diff --git a/include/osmium/util/cast.hpp b/include/osmium/util/cast.hpp new file mode 100644 index 000000000..750326706 --- /dev/null +++ b/include/osmium/util/cast.hpp @@ -0,0 +1,72 @@ +#ifndef OSMIUM_UTIL_CAST_HPP +#define OSMIUM_UTIL_CAST_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include + +namespace osmium { + + template ::value && std::is_integral::value && std::is_signed::value && std::is_signed::value, int>::type = 0> + inline T static_cast_with_assert(const F value) { + static_assert(sizeof(T) < sizeof(F), "unnecessary static_cast_with_assert when casting into type of equal or larger size"); + assert(value >= std::numeric_limits::min() && value <= std::numeric_limits::max()); + return static_cast(value); + } + + template ::value && std::is_integral::value && std::is_unsigned::value && std::is_signed::value, int>::type = 0> + inline T static_cast_with_assert(const F value) { + static_assert(sizeof(T) <= sizeof(F), "unnecessary static_cast_with_assert when casting into type of larger size"); + assert(value >= 0 && static_cast::type>(value) <= std::numeric_limits::max()); + return static_cast(value); + } + + template ::value && std::is_integral::value && std::is_unsigned::value && std::is_unsigned::value, int>::type = 0> + inline T static_cast_with_assert(const F value) { + static_assert(sizeof(T) < sizeof(F), "unnecessary static_cast_with_assert when casting into type of equal or larger size"); + assert(value <= std::numeric_limits::max()); + return static_cast(value); + } + + template ::value && std::is_integral::value && std::is_signed::value && std::is_unsigned::value, int>::type = 0> + inline T static_cast_with_assert(const F value) { + static_assert(sizeof(T) <= sizeof(F), "unnecessary static_cast_with_assert when casting into type of larger size"); + assert(value <= std::numeric_limits::max()); + return static_cast(value); + } + +} // namespace osmium + +#endif // OSMIUM_UTIL_CAST_HPP diff --git a/include/osmium/util/compatibility.hpp b/include/osmium/util/compatibility.hpp new file mode 100644 index 000000000..48a6db017 --- /dev/null +++ b/include/osmium/util/compatibility.hpp @@ -0,0 +1,47 @@ +#ifndef OSMIUM_UTIL_COMPATIBILITY_HPP +#define OSMIUM_UTIL_COMPATIBILITY_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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. + +*/ + +// Workarounds for MSVC which doesn't support +// * constexpr in all cases yet +// * [[noreturn]] +#ifdef _MSC_VER +# define OSMIUM_CONSTEXPR +# define OSMIUM_NORETURN __declspec(noreturn) +#else +# define OSMIUM_CONSTEXPR constexpr +# define OSMIUM_NORETURN [[noreturn]] +#endif + +#endif // OSMIUM_UTIL_COMPATIBILITY_HPP diff --git a/include/osmium/util/config.hpp b/include/osmium/util/config.hpp new file mode 100644 index 000000000..4fc8f2860 --- /dev/null +++ b/include/osmium/util/config.hpp @@ -0,0 +1,72 @@ +#ifndef OSMIUM_UTIL_CONFIG_HPP +#define OSMIUM_UTIL_CONFIG_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include + +#ifdef _MSC_VER +# define strcasecmp _stricmp +#endif + +namespace osmium { + + namespace config { + + inline int get_pool_threads() { + const char* env = getenv("OSMIUM_POOL_THREADS"); + if (env) { + return std::atoi(env); + } + return -2; + } + + inline bool use_pool_threads_for_pbf_parsing() { + const char* env = getenv("OSMIUM_USE_POOL_THREADS_FOR_PBF_PARSING"); + if (env) { + if (!strcasecmp(env, "off") || + !strcasecmp(env, "false") || + !strcasecmp(env, "no") || + !strcasecmp(env, "0")) { + return false; + } + } + return true; + } + + } // namespace config + +} // namespace osmium + +#endif // OSMIUM_UTIL_CONFIG_HPP diff --git a/include/osmium/util/double.hpp b/include/osmium/util/double.hpp new file mode 100644 index 000000000..67e997d9f --- /dev/null +++ b/include/osmium/util/double.hpp @@ -0,0 +1,93 @@ +#ifndef OSMIUM_UTIL_DOUBLE_HPP +#define OSMIUM_UTIL_DOUBLE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include +#include +#include + +namespace osmium { + + namespace util { + + constexpr int max_double_length = 20; // should fit any double + + /** + * Write double to iterator, removing superfluous '0' characters at + * the end. The decimal dot will also be removed if necessary. + * + * @tparam T iterator type + * @param iterator output iterator + * @param value the value that should be written + * @param precision max number of digits after the decimal point (must be <= 17) + */ + template + inline T double2string(T iterator, double value, int precision) { + assert(precision <= 17); + + char buffer[max_double_length]; + +#ifndef _MSC_VER + int len = snprintf(buffer, max_double_length, "%.*f", precision, value); +#else + int len = _snprintf(buffer, max_double_length, "%.*f", precision, value); +#endif + assert(len > 0 && len < max_double_length); + + while (buffer[len-1] == '0') --len; + if (buffer[len-1] == '.') --len; + + return std::copy_n(buffer, len, iterator); + } + + /** + * Write double to string, removing superfluous '0' characters at + * the end. The decimal dot will also be removed if necessary. + * + * @param out string + * @param value the value that should be written + * @param precision max number of digits after the decimal point + */ + inline void double2string(std::string& out, double value, int precision) { + double2string(std::back_inserter(out), value, precision); + } + + } // namespace util + +} // namespace osmium + +#endif // OSMIUM_UTIL_DOUBLE_HPP diff --git a/include/osmium/util/options.hpp b/include/osmium/util/options.hpp new file mode 100644 index 000000000..fc74980d1 --- /dev/null +++ b/include/osmium/util/options.hpp @@ -0,0 +1,155 @@ +#ifndef OSMIUM_UTIL_OPTIONS_HPP +#define OSMIUM_UTIL_OPTIONS_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 +#include +#include +#include + +namespace osmium { + + namespace util { + + /** + * Stores key=value type options. This class can be used stand-alone or + * as a base class. Options are stored and retrieved by key using the + * different set() and get() methods. + * + * You can iterate over all set options. Dereferencing an iterator + * yields a std::pair of the key and value strings. + */ + class Options { + + typedef std::map option_map; + option_map m_options; + + public: + + typedef option_map::iterator iterator; + typedef option_map::const_iterator const_iterator; + typedef option_map::value_type value_type; + + Options() = default; + + explicit Options(const std::initializer_list& values) : + m_options(values) { + } + + Options(const Options&) = default; + Options& operator=(const Options&) = default; + + Options(Options&&) = default; + Options& operator=(Options&&) = default; + + ~Options() = default; + + void set(const std::string& key, const std::string& value) { + m_options[key] = value; + } + + void set(const std::string& key, const char* value) { + m_options[key] = value; + } + + void set(const std::string& key, bool value) { + m_options[key] = value ? "true" : "false"; + } + + void set(std::string data) { + size_t pos = data.find_first_of('='); + if (pos == std::string::npos) { + m_options[data] = "true"; + } else { + std::string value = data.substr(pos+1); + data.erase(pos); + set(data, value); + } + } + + /** + * Get value of "key" option. If not set the default_value (or + * empty string) is returned. + */ + std::string get(const std::string& key, const std::string& default_value="") const noexcept { + auto it = m_options.find(key); + if (it == m_options.end()) { + return default_value; + } + return it->second; + } + + /** + * Is this option set to a true value ("true" or "yes")? + */ + bool is_true(const std::string& key) const noexcept { + std::string value = get(key); + return (value == "true" || value == "yes"); + } + + size_t size() const noexcept { + return m_options.size(); + } + + iterator begin() noexcept { + return m_options.begin(); + } + + iterator end() noexcept { + return m_options.end(); + } + + const_iterator begin() const noexcept { + return m_options.cbegin(); + } + + const_iterator end() const noexcept { + return m_options.cend(); + } + + const_iterator cbegin() const noexcept { + return m_options.cbegin(); + } + + const_iterator cend() const noexcept { + return m_options.cend(); + } + + }; // class Options + + } // namespace util + +} // namespace osmium + +#endif // OSMIUM_UTIL_OPTIONS_HPP diff --git a/include/osmium/util/string.hpp b/include/osmium/util/string.hpp new file mode 100644 index 000000000..54eb3616b --- /dev/null +++ b/include/osmium/util/string.hpp @@ -0,0 +1,68 @@ +#ifndef OSMIUM_UTIL_STRING_HPP +#define OSMIUM_UTIL_STRING_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013-2015 Jochen Topf 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 +#include +#include + +namespace osmium { + + /** + * Split string on the separator character. + * + * @param str The string to be split. + * @param sep The separastor character. + * @returns Vector with the parts of the string split up. + */ + inline std::vector split_string(const std::string& str, const char sep) { + std::vector tokens; + + if (!str.empty()) { + size_t pos = 0; + size_t nextpos = str.find_first_of(sep); + while (nextpos != std::string::npos) { + tokens.push_back(str.substr(pos, nextpos-pos)); + pos = nextpos + 1; + nextpos = str.find_first_of(sep, pos); + } + tokens.push_back(str.substr(pos)); + } + + return tokens; + } + +} // namespace osmium + +#endif // OSMIUM_UTIL_STRING_HPP diff --git a/include/osmium/util/verbose_output.hpp b/include/osmium/util/verbose_output.hpp new file mode 100644 index 000000000..8709441af --- /dev/null +++ b/include/osmium/util/verbose_output.hpp @@ -0,0 +1,139 @@ +#ifndef OSMIUM_UTIL_VERBOSE_OUTPUT_HPP +#define OSMIUM_UTIL_VERBOSE_OUTPUT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 + +#include +#include +#include + +namespace osmium { + + /** + * @brief Helpful utility classes and functions not strictly OSM related + */ + namespace util { + + /** + * Osmium programs often run for a long time because of the amount of + * OSM data processed. This class helps with keeping the user up to + * date by offering an easy way for programs to optionally output + * verbose information about what's going on. + * + * Use an object of this class instead of std::cerr as an output + * stream. Nothing is actually written if the object is not set to + * verbose mode. If it is set to verbose mode, each line is prepended + * with the running time, ie the time since the VerboseOutput object + * was created. + */ + class VerboseOutput { + + /// all time output will be relative to this start time + time_t m_start; + + /// is verbose mode enabled? + bool m_verbose; + + /// a newline was written, start next output with runtime + bool m_newline; + + /** + * If we remember that a newline was written as the last thing + * write out the time elapsed and reset the newline flag. + */ + void start_line() { + if (m_newline) { + time_t elapsed = runtime(); + + char old_fill = std::cerr.fill(); + std::cerr << '[' << std::setw(2) << (elapsed / 60) << ':' << std::setw(2) << std::setfill('0') << (elapsed % 60) << "] "; + std::cerr.fill(old_fill); + + m_newline = false; + } + } + + public: + + explicit VerboseOutput(bool verbose=false) noexcept : + m_start(time(NULL)), + m_verbose(verbose), + m_newline(true) { + } + + ~VerboseOutput() = default; + + VerboseOutput(const VerboseOutput&) = default; + VerboseOutput& operator=(const VerboseOutput&) = default; + VerboseOutput(VerboseOutput&&) = default; + VerboseOutput& operator=(VerboseOutput&&) = default; + + time_t runtime() const noexcept { + return time(NULL) - m_start; + } + + /// Get "verbose" setting. + bool verbose() const noexcept { + return m_verbose; + } + + /// Set "verbose" setting. + void verbose(bool verbose) noexcept { + m_verbose = verbose; + } + + template + friend VerboseOutput& operator<<(VerboseOutput& verbose_output, const T& value) { + if (verbose_output.m_verbose) { + verbose_output.start_line(); + std::cerr << value; + + // check if there was a newline a the end and remember that + std::ostringstream output_buffer; + output_buffer << value; + if (!output_buffer.str().empty() && output_buffer.str().back() == '\n') { + verbose_output.m_newline = true; + } + } + return verbose_output; + } + + }; // class VerboseOutput + + } // namespace util + +} // namespace osmium + +#endif // OSMIUM_UTIL_VERBOSE_OUTPUT_HPP diff --git a/include/osmium/visitor.hpp b/include/osmium/visitor.hpp new file mode 100644 index 000000000..d71a2e01c --- /dev/null +++ b/include/osmium/visitor.hpp @@ -0,0 +1,255 @@ +#ifndef OSMIUM_VISITOR_HPP +#define OSMIUM_VISITOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf 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 + +#include // IWYU pragma: keep +#include +#include +#include +#include + +namespace osmium { + + class TagList; + class WayNodeList; + class RelationMemberList; + class OuterRing; + class InnerRing; + + namespace memory { + class Item; + } + + namespace detail { + + template + using ConstIfConst = typename std::conditional::value, typename std::add_const::type, U>::type; + + template + inline void apply_item_recurse(TItem& item, THandler& handler) { + switch (item.type()) { + case osmium::item_type::undefined: + break; + case osmium::item_type::node: + handler.osm_object(static_cast&>(item)); + handler.node(static_cast&>(item)); + break; + case osmium::item_type::way: + handler.osm_object(static_cast&>(item)); + handler.way(static_cast&>(item)); + break; + case osmium::item_type::relation: + handler.osm_object(static_cast&>(item)); + handler.relation(static_cast&>(item)); + break; + case osmium::item_type::area: + handler.osm_object(static_cast&>(item)); + handler.area(static_cast&>(item)); + break; + case osmium::item_type::changeset: + handler.changeset(static_cast&>(item)); + break; + case osmium::item_type::tag_list: + handler.tag_list(static_cast&>(item)); + break; + case osmium::item_type::way_node_list: + handler.way_node_list(static_cast&>(item)); + break; + case osmium::item_type::relation_member_list: + case osmium::item_type::relation_member_list_with_full_members: + handler.relation_member_list(static_cast&>(item)); + break; + case osmium::item_type::outer_ring: + handler.outer_ring(static_cast&>(item)); + break; + case osmium::item_type::inner_ring: + handler.inner_ring(static_cast&>(item)); + break; + } + } + + template + inline void apply_item_recurse(const osmium::OSMEntity& item, THandler& handler) { + switch (item.type()) { + case osmium::item_type::node: + handler.osm_object(static_cast(item)); + handler.node(static_cast(item)); + break; + case osmium::item_type::way: + handler.osm_object(static_cast(item)); + handler.way(static_cast(item)); + break; + case osmium::item_type::relation: + handler.osm_object(static_cast(item)); + handler.relation(static_cast(item)); + break; + case osmium::item_type::area: + handler.osm_object(static_cast(item)); + handler.area(static_cast(item)); + break; + case osmium::item_type::changeset: + handler.changeset(static_cast(item)); + break; + default: + throw osmium::unknown_type(); + } + } + + template + inline void apply_item_recurse(osmium::OSMEntity& item, THandler& handler) { + switch (item.type()) { + case osmium::item_type::node: + handler.osm_object(static_cast(item)); + handler.node(static_cast(item)); + break; + case osmium::item_type::way: + handler.osm_object(static_cast(item)); + handler.way(static_cast(item)); + break; + case osmium::item_type::relation: + handler.osm_object(static_cast(item)); + handler.relation(static_cast(item)); + break; + case osmium::item_type::area: + handler.osm_object(static_cast(item)); + handler.area(static_cast(item)); + break; + case osmium::item_type::changeset: + handler.changeset(static_cast(item)); + break; + default: + throw osmium::unknown_type(); + } + } + + template + inline void apply_item_recurse(const osmium::OSMObject& item, THandler& handler) { + switch (item.type()) { + case osmium::item_type::node: + handler.osm_object(item); + handler.node(static_cast(item)); + break; + case osmium::item_type::way: + handler.osm_object(item); + handler.way(static_cast(item)); + break; + case osmium::item_type::relation: + handler.osm_object(item); + handler.relation(static_cast(item)); + break; + case osmium::item_type::area: + handler.osm_object(item); + handler.area(static_cast(item)); + break; + default: + throw osmium::unknown_type(); + } + } + + template + inline void apply_item_recurse(osmium::OSMObject& item, THandler& handler) { + switch (item.type()) { + case osmium::item_type::node: + handler.osm_object(item); + handler.node(static_cast(item)); + break; + case osmium::item_type::way: + handler.osm_object(item); + handler.way(static_cast(item)); + break; + case osmium::item_type::relation: + handler.osm_object(item); + handler.relation(static_cast(item)); + break; + case osmium::item_type::area: + handler.osm_object(item); + handler.area(static_cast(item)); + break; + default: + throw osmium::unknown_type(); + } + } + + template + inline void apply_item_recurse(TItem& item, THandler& handler, TRest&... more) { + apply_item_recurse(item, handler); + apply_item_recurse(item, more...); + } + + template + inline void flush_recurse(THandler& handler) { + handler.flush(); + } + + template + inline void flush_recurse(THandler& handler, TRest&... more) { + flush_recurse(handler); + flush_recurse(more...); + } + + } // namespace detail + + template + inline void apply_item(const osmium::memory::Item& item, THandlers&... handlers) { + detail::apply_item_recurse(item, handlers...); + } + + template + inline void apply_item(osmium::memory::Item& item, THandlers&... handlers) { + detail::apply_item_recurse(item, handlers...); + } + + template + inline void apply(TIterator it, TIterator end, THandlers&... handlers) { + for (; it != end; ++it) { + detail::apply_item_recurse(*it, handlers...); + } + detail::flush_recurse(handlers...); + } + + template + inline void apply(TContainer& c, THandlers&... handlers) { + apply(std::begin(c), std::end(c), handlers...); + } + + template + inline void apply(const osmium::memory::Buffer& buffer, THandlers&... handlers) { + apply(buffer.cbegin(), buffer.cend(), handlers...); + } + +} // namespace osmium + +#endif // OSMIUM_VISITOR_HPP diff --git a/make_osmium_project.sh b/make_osmium_project.sh new file mode 100755 index 000000000..ba844b85b --- /dev/null +++ b/make_osmium_project.sh @@ -0,0 +1,96 @@ +#!/bin/sh +# +# make_osmium_project.sh PROJECTNAME +# +# Creates a subdirectory named as the project in the current directory and +# adds a skeleton of files needed to begin a new project using the Osmium +# library. +# + +if [ "x$1" = "x" ]; then + echo "Usage: $0 PROJECTNAME" + exit 1 +fi + +if [ -e "$1" ]; then + echo "Directory '$1' exists" + exit 1 +fi + +mkdir $1 +cd $1 + +sed -e "s/__PROJECTNAME__/$1/g" >Makefile <<'__EOF__' +CXXFLAGS += -O3 +#CXXFLAGS += -g +CXXFLAGS += -std=c++11 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 +CXXFLAGS += -I../include + +OS:=$(shell uname -s) +ifeq ($(OS),Darwin) + CXXFLAGS += -stdlib=libc++ + LDFLAGS += -stdlib=libc++ +endif + +CXXFLAGS_WARNINGS := -Wall -Wextra -pedantic -Wredundant-decls -Wdisabled-optimization -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wsign-promo -Wold-style-cast + +LIB_EXPAT := -lexpat +LIB_PBF := -pthread -lz -lprotobuf-lite -losmpbf +LIB_GZIP := -lz +LIB_BZIP2 := -lbz2 + +LIB_IO := $(LIB_EXPAT) $(LIB_PBF) $(LIB_GZIP) $(LIB_BZIP2) + +PROGRAMS := __PROJECTNAME__ + +.PHONY: all clean + +all: $(PROGRAMS) + +__PROJECTNAME__: main.cpp + $(CXX) $(CXXFLAGS) $(CXXFLAGS_WARNINGS) -o $@ $< $(LDFLAGS) $(LIB_IO) + +clean: + rm -f *.o core $(PROGRAMS) + +__EOF__ + +cat >main.cpp <<'__EOF__' + +#include +#include +#include + +class MyHandler : public osmium::handler::Handler { + +public: + + MyHandler() : + osmium::handler::Handler() { + } + + void node(const osmium::Node& node) { + } + + void way(const osmium::Way& way) { + } + + void relation(const osmium::Relation& relation) { + } + +}; // class MyHandler + +int main(int argc, char* argv[]) { + + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " OSMFILE\n"; + exit(1); + } + + MyHandler handler; + osmium::io::Reader reader(argv[1]); + osmium::apply(reader, handler); +} + +__EOF__ + diff --git a/osmium.imp b/osmium.imp new file mode 100644 index 000000000..1f0963f11 --- /dev/null +++ b/osmium.imp @@ -0,0 +1,4 @@ +[ + { "include": ["", "private", "", "public"] }, + { "include": ["", "public", "", "public"] } +] diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 000000000..ebea16c11 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,123 @@ +message(STATUS "Configuring unit tests...") + +set(DART_TESTING_TIMEOUT 60) +include(Dart) +include_directories(include) + +# In 'Dev' mode: compile with very strict warnings and turn them into errors. +if(CMAKE_BUILD_TYPE STREQUAL "Dev") + add_definitions(-Werror ${OSMIUM_WARNING_OPTIONS} -Wno-unused-variable) +endif() + +add_library(testlib STATIC test_main.cpp) + +#---------------------------------------------------------------------- + +set(ALL_TESTS "") + +# call with parameters: +# TGROUP - test group (directory) +# TNAME - name of test +# ARGV2 - flag to enable test (optional) +# ARGV3 - libraries to add (optional) +function(add_unit_test TGROUP TNAME) + set(ALL_TESTS "${ALL_TESTS};${TGROUP}/${TNAME}" PARENT_SCOPE) + if((${ARGC} EQUAL 2) OR (${ARGV2})) + if(Osmium_DEBUG) + message("Adding test ${TGROUP}/${TNAME}") + endif() + set(TESTNAME "${TGROUP}_${TNAME}") + add_executable(${TESTNAME} t/${TGROUP}/${TNAME}.cpp) + target_link_libraries(${TESTNAME} testlib) + if((${ARGV2}) AND (DEFINED ARGV3)) + if(Osmium_DEBUG) + message(" Adding libs ${ARGV3}") + endif() + target_link_libraries(${TESTNAME} ${ARGV3}) + endif() + add_test(NAME ${TESTNAME} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND ${TESTNAME} + ) + set_tests_properties(${TESTNAME} PROPERTIES LABELS "unit;${TGROUP}") + else() + message("Skipped test ${TGROUP}/${TNAME} because a dependency was not found") + set(OSMIUM_SKIPPED_TESTS + "${OSMIUM_SKIPPED_TESTS} ${TGROUP}/${TNAME}" + CACHE STRING "Tests that were skipped because of missing dependecies") + endif() +endfunction() + +#---------------------------------------------------------------------- +# +# Add all tests. +# +#---------------------------------------------------------------------- + +add_unit_test(area test_area_id) +add_unit_test(area test_node_ref_segment) + +add_unit_test(basic test_box) +add_unit_test(basic test_changeset) +add_unit_test(basic test_entity_bits) +add_unit_test(basic test_location) +add_unit_test(basic test_node) +add_unit_test(basic test_node_ref) +add_unit_test(basic test_object_comparisons) +add_unit_test(basic test_relation) +add_unit_test(basic test_timestamp) +add_unit_test(basic test_way) + +add_unit_test(buffer test_buffer_node) +add_unit_test(buffer test_buffer_purge) + +if (GEOS_FOUND AND PROJ_FOUND) + set(GEOS_AND_PROJ_FOUND TRUE) +else() + set(GEOS_AND_PROJ_FOUND FALSE) +endif() +add_unit_test(geom test_factory_with_projection + ${GEOS_AND_PROJ_FOUND} + "${GEOS_LIBRARY};${PROJ_LIBRARY}") + +add_unit_test(geom test_geojson) +add_unit_test(geom test_geos ${GEOS_FOUND} ${GEOS_LIBRARY}) +add_unit_test(geom test_geos_wkb ${GEOS_FOUND} ${GEOS_LIBRARY}) +add_unit_test(geom test_mercator) +add_unit_test(geom test_ogr ${GDAL_FOUND} ${GDAL_LIBRARY}) +add_unit_test(geom test_projection ${PROJ_FOUND} ${PROJ_LIBRARY}) +add_unit_test(geom test_wkb) +add_unit_test(geom test_wkt) + +add_unit_test(index test_id_to_location ${SPARSEHASH_FOUND}) +add_unit_test(index test_typed_mmap) + +add_unit_test(io test_bzip2 ${BZIP2_FOUND} ${BZIP2_LIBRARIES}) +add_unit_test(io test_file_formats) +add_unit_test(io test_reader TRUE "${OSMIUM_XML_LIBRARIES}") + +add_unit_test(tags test_filter) +add_unit_test(tags test_operators) +add_unit_test(tags test_tag_list) + +add_unit_test(util test_double) +add_unit_test(util test_options) +add_unit_test(util test_string) + +#---------------------------------------------------------------------- +# +# Check that all tests available in test/t/*/test_*.cpp are run. +# +#---------------------------------------------------------------------- + +file(GLOB TESTS_IN_DIR RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/t" t/*/test_*.cpp) + +foreach(file ${TESTS_IN_DIR}) + string(REPLACE ".cpp" "" out1 ${file}) + string(REPLACE "//" "/" tname ${out1}) + list(FIND ALL_TESTS ${tname} found) + if(${found} EQUAL -1) + message(WARNING "Test '${tname}' not found in cmake config. It will not be run!") + endif() +endforeach() + diff --git a/test/README b/test/README new file mode 100644 index 000000000..dc5e51222 --- /dev/null +++ b/test/README @@ -0,0 +1,12 @@ +Osmium uses Catch (https://github.com/philsquared/Catch/) for its unit tests. + +Only one header file is needed (catch.hpp) which can be downloaded from +http://builds.catch-lib.net/ and put into the include directory. + +Osmium needs a few changes to catch.hpp, they were patched in. To be able to +compare with the original version, it is stored in include/catch_orig.hpp. + +Changes are: +* CATCH_CONFIG_CPP11_NULLPTR must be set for MSVC +* Problem with test running in loop: https://github.com/philsquared/Catch/issues/271 + diff --git a/test/include/catch.hpp b/test/include/catch.hpp new file mode 100644 index 000000000..f35378fea --- /dev/null +++ b/test/include/catch.hpp @@ -0,0 +1,8987 @@ + +// This is needed for Windows +#define CATCH_CONFIG_CPP11_NULLPTR + +/* + * CATCH v1.0 build 52 (master branch) + * Generated: 2014-07-10 09:17:43.994453 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + +#define TWOBLUECUBES_CATCH_HPP_INCLUDED + +// #included from: internal/catch_suppress_warnings.h + +#define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wglobal-constructors" +#pragma clang diagnostic ignored "-Wvariadic-macros" +#pragma clang diagnostic ignored "-Wc99-extensions" +#pragma clang diagnostic ignored "-Wunused-variable" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#pragma clang diagnostic ignored "-Wc++98-compat" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#pragma clang diagnostic ignored "-Wfloat-equal" +#endif + +#ifndef __clang__ +# pragma GCC diagnostic ignored "-Wctor-dtor-privacy" +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic ignored "-Wreturn-type" +# pragma GCC diagnostic ignored "-Wsign-promo" +# pragma GCC diagnostic ignored "-Wparentheses" +#endif + +#ifdef CATCH_CONFIG_MAIN +# define CATCH_CONFIG_RUNNER +#endif + +#ifdef CATCH_CONFIG_RUNNER +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// #included from: internal/catch_notimplemented_exception.h +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED + +// #included from: catch_common.h +#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED + +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) + +#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr +#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) + +#include +#include +#include + +// #included from: catch_compiler_capabilities.h +#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + +// Much of the following code is based on Boost (1.53) + +#ifdef __clang__ + +# if __has_feature(cxx_nullptr) +# define CATCH_CONFIG_CPP11_NULLPTR +# endif + +# if __has_feature(cxx_noexcept) +# define CATCH_CONFIG_CPP11_NOEXCEPT +# endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Borland +#ifdef __BORLANDC__ + +#if (__BORLANDC__ > 0x582 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __BORLANDC__ + +//////////////////////////////////////////////////////////////////////////////// +// EDG +#ifdef __EDG_VERSION__ + +#if (__EDG_VERSION__ > 238 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __EDG_VERSION__ + +//////////////////////////////////////////////////////////////////////////////// +// Digital Mars +#ifdef __DMC__ + +#if (__DMC__ > 0x840 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __DMC__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +#if __GNUC__ < 3 + +#if (__GNUC_MINOR__ >= 96 ) +//#define CATCH_CONFIG_SFINAE +#endif + +#elif __GNUC__ >= 3 + +// #define CATCH_CONFIG_SFINAE // Taking this out completely for now + +#endif // __GNUC__ < 3 + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) ) + +#define CATCH_CONFIG_CPP11_NULLPTR +#endif + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1310 ) // (VC++ 7.0+) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // _MSC_VER + +// Use variadic macros if the compiler supports them +#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ + ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ + ( defined __GNUC__ && __GNUC__ >= 3 ) || \ + ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) + +#ifndef CATCH_CONFIG_NO_VARIADIC_MACROS +#define CATCH_CONFIG_VARIADIC_MACROS +#endif + +#endif + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// detect language version: +#if (__cplusplus == 201103L) +# define CATCH_CPP11 +# define CATCH_CPP11_OR_GREATER +#elif (__cplusplus >= 201103L) +# define CATCH_CPP11_OR_GREATER +#endif + +// noexcept support: +#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) +# define CATCH_NOEXCEPT noexcept +# define CATCH_NOEXCEPT_IS(x) noexcept(x) +#else +# define CATCH_NOEXCEPT throw() +# define CATCH_NOEXCEPT_IS(x) +#endif + +namespace Catch { + + class NonCopyable { + NonCopyable( NonCopyable const& ); + void operator = ( NonCopyable const& ); + protected: + NonCopyable() {} + virtual ~NonCopyable(); + }; + + class SafeBool { + public: + typedef void (SafeBool::*type)() const; + + static type makeSafe( bool value ) { + return value ? &SafeBool::trueValue : 0; + } + private: + void trueValue() const {} + }; + + template + inline void deleteAll( ContainerT& container ) { + typename ContainerT::const_iterator it = container.begin(); + typename ContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete *it; + } + template + inline void deleteAllValues( AssociativeContainerT& container ) { + typename AssociativeContainerT::const_iterator it = container.begin(); + typename AssociativeContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete it->second; + } + + bool startsWith( std::string const& s, std::string const& prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; + + struct SourceLineInfo { + + SourceLineInfo(); + SourceLineInfo( char const* _file, std::size_t _line ); + SourceLineInfo( SourceLineInfo const& other ); +# ifdef CATCH_CPP11_OR_GREATER + SourceLineInfo( SourceLineInfo && ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo& operator = ( SourceLineInfo && ) = default; +# endif + bool empty() const; + bool operator == ( SourceLineInfo const& other ) const; + + std::string file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // This is just here to avoid compiler warnings with macro constants and boolean literals + inline bool isTrue( bool value ){ return value; } + inline bool alwaysTrue() { return true; } + inline bool alwaysFalse() { return false; } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() { + return std::string(); + } + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); + +#include + +namespace Catch { + + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + NotImplementedException( NotImplementedException const& ) {} + + virtual ~NotImplementedException() CATCH_NOEXCEPT {} + + virtual const char* what() const CATCH_NOEXCEPT; + + private: + std::string m_what; + SourceLineInfo m_lineInfo; + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + +// #included from: internal/catch_context.h +#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED + +// #included from: catch_interfaces_generators.h +#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED + +#include + +namespace Catch { + + struct IGeneratorInfo { + virtual ~IGeneratorInfo(); + virtual bool moveNext() = 0; + virtual std::size_t getCurrentIndex() const = 0; + }; + + struct IGeneratorsForTest { + virtual ~IGeneratorsForTest(); + + virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; + virtual bool moveNext() = 0; + }; + + IGeneratorsForTest* createGeneratorsForTest(); + +} // end namespace Catch + +// #included from: catch_ptr.hpp +#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + // An intrusive reference counting smart pointer. + // T must implement addRef() and release() methods + // typically implementing the IShared interface + template + class Ptr { + public: + Ptr() : m_p( NULL ){} + Ptr( T* p ) : m_p( p ){ + if( m_p ) + m_p->addRef(); + } + Ptr( Ptr const& other ) : m_p( other.m_p ){ + if( m_p ) + m_p->addRef(); + } + ~Ptr(){ + if( m_p ) + m_p->release(); + } + void reset() { + if( m_p ) + m_p->release(); + m_p = NULL; + } + Ptr& operator = ( T* p ){ + Ptr temp( p ); + swap( temp ); + return *this; + } + Ptr& operator = ( Ptr const& other ){ + Ptr temp( other ); + swap( temp ); + return *this; + } + void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } + T* get() { return m_p; } + const T* get() const{ return m_p; } + T& operator*() const { return *m_p; } + T* operator->() const { return m_p; } + bool operator !() const { return m_p == NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); } + + private: + T* m_p; + }; + + struct IShared : NonCopyable { + virtual ~IShared(); + virtual void addRef() const = 0; + virtual void release() const = 0; + }; + + template + struct SharedImpl : T { + + SharedImpl() : m_rc( 0 ){} + + virtual void addRef() const { + ++m_rc; + } + virtual void release() const { + if( --m_rc == 0 ) + delete this; + } + + mutable unsigned int m_rc; + }; + +} // end namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#include +#include +#include + +namespace Catch { + + class TestCase; + class Stream; + struct IResultCapture; + struct IRunner; + struct IGeneratorsForTest; + struct IConfig; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; + virtual bool advanceGeneratorsForCurrentTest() = 0; + virtual Ptr getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( Ptr const& config ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); + Stream createStream( std::string const& streamName ); + +} + +// #included from: internal/catch_test_registry.hpp +#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED + +// #included from: catch_interfaces_testcase.h +#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED + +#include + +namespace Catch { + + class TestSpec; + + struct ITestCase : IShared { + virtual void invoke () const = 0; + protected: + virtual ~ITestCase(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases ) const = 0; + + }; +} + +namespace Catch { + +template +class MethodTestCase : public SharedImpl { + +public: + MethodTestCase( void (C::*method)() ) : m_method( method ) {} + + virtual void invoke() const { + C obj; + (obj.*m_method)(); + } + +private: + virtual ~MethodTestCase() {} + + void (C::*m_method)(); +}; + +typedef void(*TestFunction)(); + +struct NameAndDesc { + NameAndDesc( const char* _name = "", const char* _description= "" ) + : name( _name ), description( _description ) + {} + + const char* name; + const char* description; +}; + +struct AutoReg { + + AutoReg( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + + template + AutoReg( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + registerTestCase( new MethodTestCase( method ), + className, + nameAndDesc, + lineInfo ); + } + + void registerTestCase( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + + ~AutoReg(); + +private: + AutoReg( AutoReg const& ); + void operator= ( AutoReg const& ); +}; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( ... ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + +#else + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + +#endif + +// #included from: internal/catch_capture.hpp +#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED + +// #included from: catch_result_builder.h +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED + +// #included from: catch_result_type.h +#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2 + + }; }; + + inline bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + inline bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x00, + + ContinueOnFailure = 0x01, // Failures fail test, but execution continues + FalseTest = 0x02, // Prefix expression with ! + SuppressFail = 0x04 // Failures are reported but do not fail the test + }; }; + + inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( static_cast( lhs ) | static_cast( rhs ) ); + } + + inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } + inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } + inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + +} // end namespace Catch + +// #included from: catch_assertionresult.h +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED + +#include + +namespace Catch { + + struct AssertionInfo + { + AssertionInfo() {} + AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ); + + std::string macroName; + SourceLineInfo lineInfo; + std::string capturedExpression; + ResultDisposition::Flags resultDisposition; + }; + + struct AssertionResultData + { + AssertionResultData() : resultType( ResultWas::Unknown ) {} + + std::string reconstructedExpression; + std::string message; + ResultWas::OfType resultType; + }; + + class AssertionResult { + public: + AssertionResult(); + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); + ~AssertionResult(); +# ifdef CATCH_CPP11_OR_GREATER + AssertionResult( AssertionResult const& ) = default; + AssertionResult( AssertionResult && ) = default; + AssertionResult& operator = ( AssertionResult const& ) = default; + AssertionResult& operator = ( AssertionResult && ) = default; +# endif + + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + std::string getMessage() const; + SourceLineInfo getSourceInfo() const; + std::string getTestMacroName() const; + + protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + +} // end namespace Catch + +namespace Catch { + + struct TestFailureException{}; + + template class ExpressionLhs; + + struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; + + struct CopyableStream { + CopyableStream() {} + CopyableStream( CopyableStream const& other ) { + oss << other.oss.str(); + } + CopyableStream& operator=( CopyableStream const& other ) { + oss.str(""); + oss << other.oss.str(); + return *this; + } + std::ostringstream oss; + }; + + class ResultBuilder { + public: + ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition ); + + template + ExpressionLhs operator->* ( T const& operand ); + ExpressionLhs operator->* ( bool value ); + + template + ResultBuilder& operator << ( T const& value ) { + m_stream.oss << value; + return *this; + } + + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + + ResultBuilder& setResultType( ResultWas::OfType result ); + ResultBuilder& setResultType( bool result ); + ResultBuilder& setLhs( std::string const& lhs ); + ResultBuilder& setRhs( std::string const& rhs ); + ResultBuilder& setOp( std::string const& op ); + + void endExpression(); + + std::string reconstructExpression() const; + AssertionResult build() const; + + void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); + void captureResult( ResultWas::OfType resultType ); + void captureExpression(); + void react(); + bool shouldDebugBreak() const; + bool allowThrows() const; + + private: + AssertionInfo m_assertionInfo; + AssertionResultData m_data; + struct ExprComponents { + ExprComponents() : testFalse( false ) {} + bool testFalse; + std::string lhs, rhs, op; + } m_exprComponents; + CopyableStream m_stream; + + bool m_shouldDebugBreak; + bool m_shouldThrow; + }; + +} // namespace Catch + +// Include after due to circular dependency: +// #included from: catch_expression_lhs.hpp +#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED + +// #included from: catch_evaluate.hpp +#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#endif + +#include + +namespace Catch { +namespace Internal { + + enum Operator { + IsEqualTo, + IsNotEqualTo, + IsLessThan, + IsGreaterThan, + IsLessThanOrEqualTo, + IsGreaterThanOrEqualTo + }; + + template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; + template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; + template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; + + template + inline T& opCast(T const& t) { return const_cast(t); } + +// nullptr_t support based on pull request #154 from Konstantin Baumann +#ifdef CATCH_CONFIG_CPP11_NULLPTR + inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } +#endif // CATCH_CONFIG_CPP11_NULLPTR + + // So the compare overloads can be operator agnostic we convey the operator as a template + // enum, which is used to specialise an Evaluator for doing the comparison. + template + class Evaluator{}; + + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs) { + return opCast( lhs ) == opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) != opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) < opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) > opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) >= opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) <= opCast( rhs ); + } + }; + + template + bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // This level of indirection allows us to specialise for integer types + // to avoid signed/ unsigned warnings + + // "base" overload + template + bool compare( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // unsigned X to int + template bool compare( unsigned int lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // unsigned X to long + template bool compare( unsigned int lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // int to unsigned X + template bool compare( int lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // long to unsigned X + template bool compare( long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long (when comparing against NULL) + template bool compare( long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + + // pointer to int (when comparing against NULL) + template bool compare( int lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, int rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + +#ifdef CATCH_CONFIG_CPP11_NULLPTR + // pointer to nullptr_t (when comparing against nullptr) + template bool compare( std::nullptr_t, T* rhs ) { + return Evaluator::evaluate( NULL, rhs ); + } + template bool compare( T* lhs, std::nullptr_t ) { + return Evaluator::evaluate( lhs, NULL ); + } +#endif // CATCH_CONFIG_CPP11_NULLPTR + +} // end of namespace Internal +} // end of namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// #included from: catch_tostring.h +#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED + +// #included from: catch_sfinae.hpp +#define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED + +// Try to detect if the current compiler supports SFINAE + +namespace Catch { + + struct TrueType { + static const bool value = true; + typedef void Enable; + char sizer[1]; + }; + struct FalseType { + static const bool value = false; + typedef void Disable; + char sizer[2]; + }; + +#ifdef CATCH_CONFIG_SFINAE + + template struct NotABooleanExpression; + + template struct If : NotABooleanExpression {}; + template<> struct If : TrueType {}; + template<> struct If : FalseType {}; + + template struct SizedIf; + template<> struct SizedIf : TrueType {}; + template<> struct SizedIf : FalseType {}; + +#endif // CATCH_CONFIG_SFINAE + +} // end namespace Catch + +#include +#include +#include +#include +#include + +#ifdef __OBJC__ +// #included from: catch_objc_arc.hpp +#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED + +#import + +#ifdef __has_feature +#define CATCH_ARC_ENABLED __has_feature(objc_arc) +#else +#define CATCH_ARC_ENABLED 0 +#endif + +void arcSafeRelease( NSObject* obj ); +id performOptionalSelector( id obj, SEL sel ); + +#if !CATCH_ARC_ENABLED +inline void arcSafeRelease( NSObject* obj ) { + [obj release]; +} +inline id performOptionalSelector( id obj, SEL sel ) { + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; + return nil; +} +#define CATCH_UNSAFE_UNRETAINED +#define CATCH_ARC_STRONG +#else +inline void arcSafeRelease( NSObject* ){} +inline id performOptionalSelector( id obj, SEL sel ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#endif + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + return nil; +} +#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained +#define CATCH_ARC_STRONG __strong +#endif + +#endif + +namespace Catch { +namespace Detail { + +// SFINAE is currently disabled by default for all compilers. +// If the non SFINAE version of IsStreamInsertable is ambiguous for you +// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE +#ifdef CATCH_CONFIG_SFINAE + + template + class IsStreamInsertableHelper { + template struct TrueIfSizeable : TrueType {}; + + template + static TrueIfSizeable dummy(T2*); + static FalseType dummy(...); + + public: + typedef SizedIf type; + }; + + template + struct IsStreamInsertable : IsStreamInsertableHelper::type {}; + +#else + + struct BorgType { + template BorgType( T const& ); + }; + + TrueType& testStreamable( std::ostream& ); + FalseType testStreamable( FalseType ); + + FalseType operator<<( std::ostream const&, BorgType const& ); + + template + struct IsStreamInsertable { + static std::ostream &s; + static T const&t; + enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; + }; + +#endif + + template + struct StringMakerBase { + template + static std::string convert( T const& ) { return "{?}"; } + }; + + template<> + struct StringMakerBase { + template + static std::string convert( T const& _value ) { + std::ostringstream oss; + oss << _value; + return oss.str(); + } + }; + + std::string rawMemoryToString( const void *object, std::size_t size ); + + template + inline std::string rawMemoryToString( const T& object ) { + return rawMemoryToString( &object, sizeof(object) ); + } + +} // end namespace Detail + +template +std::string toString( T const& value ); + +template +struct StringMaker : + Detail::StringMakerBase::value> {}; + +template +struct StringMaker { + template + static std::string convert( U* p ) { + if( !p ) + return INTERNAL_CATCH_STRINGIFY( NULL ); + else + return Detail::rawMemoryToString( p ); + } +}; + +template +struct StringMaker { + static std::string convert( R C::* p ) { + if( !p ) + return INTERNAL_CATCH_STRINGIFY( NULL ); + else + return Detail::rawMemoryToString( p ); + } +}; + +namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ); +} + +template +struct StringMaker > { + static std::string convert( std::vector const& v ) { + return Detail::rangeToString( v.begin(), v.end() ); + } +}; + +namespace Detail { + template + std::string makeString( T const& value ) { + return StringMaker::convert( value ); + } +} // end namespace Detail + +/// \brief converts any type to a string +/// +/// The default template forwards on to ostringstream - except when an +/// ostringstream overload does not exist - in which case it attempts to detect +/// that and writes {?}. +/// Overload (not specialise) this template for custom typs that you don't want +/// to provide an ostream overload for. +template +std::string toString( T const& value ) { + return StringMaker::convert( value ); +} + +// Built in overloads + +std::string toString( std::string const& value ); +std::string toString( std::wstring const& value ); +std::string toString( const char* const value ); +std::string toString( char* const value ); +std::string toString( int value ); +std::string toString( unsigned long value ); +std::string toString( unsigned int value ); +std::string toString( const double value ); +std::string toString( const float value ); +std::string toString( bool value ); +std::string toString( char value ); +std::string toString( signed char value ); +std::string toString( unsigned char value ); + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ); +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); + std::string toString( NSObject* const& nsObject ); +#endif + + namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ) { + std::ostringstream oss; + oss << "{ "; + if( first != last ) { + oss << toString( *first ); + for( ++first ; first != last ; ++first ) { + oss << ", " << toString( *first ); + } + } + oss << " }"; + return oss.str(); + } +} + +} // end namespace Catch + +namespace Catch { + +// Wraps the LHS of an expression and captures the operator and RHS (if any) - +// wrapping them all in a ResultBuilder object +template +class ExpressionLhs { + ExpressionLhs& operator = ( ExpressionLhs const& ); +# ifdef CATCH_CPP11_OR_GREATER + ExpressionLhs& operator = ( ExpressionLhs && ) = delete; +# endif + +public: + ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} +# ifdef CATCH_CPP11_OR_GREATER + ExpressionLhs( ExpressionLhs const& ) = default; + ExpressionLhs( ExpressionLhs && ) = default; +# endif + + template + ResultBuilder& operator == ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator != ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator < ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator > ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator <= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator >= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator == ( bool rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator != ( bool rhs ) { + return captureExpression( rhs ); + } + + void endExpression() { + bool value = m_lhs ? true : false; + m_rb + .setLhs( Catch::toString( value ) ) + .setResultType( value ) + .endExpression(); + } + + // Only simple binary expressions are allowed on the LHS. + // If more complex compositions are required then place the sub expression in parentheses + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + +private: + template + ResultBuilder& captureExpression( RhsT const& rhs ) { + return m_rb + .setResultType( Internal::compare( m_lhs, rhs ) ) + .setLhs( Catch::toString( m_lhs ) ) + .setRhs( Catch::toString( rhs ) ) + .setOp( Internal::OperatorTraits::getName() ); + } + +private: + ResultBuilder& m_rb; + T m_lhs; +}; + +} // end namespace Catch + + +namespace Catch { + + template + inline ExpressionLhs ResultBuilder::operator->* ( T const& operand ) { + return ExpressionLhs( *this, operand ); + } + + inline ExpressionLhs ResultBuilder::operator->* ( bool value ) { + return ExpressionLhs( *this, value ); + } + +} // namespace Catch + +// #included from: catch_message.h +#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED + +#include + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + SourceLineInfo lineInfo; + ResultWas::OfType type; + std::string message; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const { + return sequence == other.sequence; + } + bool operator < ( MessageInfo const& other ) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + + struct MessageBuilder { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + : m_info( macroName, lineInfo, type ) + {} + + template + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + MessageInfo m_info; + std::ostringstream m_stream; + }; + + class ScopedMessage { + public: + ScopedMessage( MessageBuilder const& builder ); + ScopedMessage( ScopedMessage const& other ); + ~ScopedMessage(); + + MessageInfo m_info; + }; + +} // end namespace Catch + +// #included from: catch_interfaces_capture.h +#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct MessageInfo; + class ScopedMessageBuilder; + struct Counts; + + struct IResultCapture { + + virtual ~IResultCapture(); + + virtual void assertionEnded( AssertionResult const& result ) = 0; + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0; + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + }; + + IResultCapture& getResultCapture(); +} + +// #included from: catch_debugger.h +#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED + +// #included from: catch_platform.h +#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED + +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_IPHONE +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CATCH_PLATFORM_WINDOWS +#endif + +#include + +namespace Catch{ + + bool isDebuggerActive(); + void writeToDebugConsole( std::string const& text ); +} + +#ifdef CATCH_PLATFORM_MAC + + // The following code snippet based on: + // http://cocoawithlove.com/2008/03/break-into-debugger.html + #ifdef DEBUG + #if defined(__ppc64__) || defined(__ppc__) + #define CATCH_BREAK_INTO_DEBUGGER() \ + if( Catch::isDebuggerActive() ) { \ + __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ + : : : "memory","r0","r3","r4" ); \ + } + #else + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} + #endif + #endif + +#elif defined(_MSC_VER) + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } +#endif + +#ifndef CATCH_BREAK_INTO_DEBUGGER +#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); +#endif + +// #included from: catch_interfaces_runner.h +#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED + +namespace Catch { + class TestCase; + + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// In the event of a failure works out if the debugger needs to be invoked +// and/or an exception thrown and takes appropriate action. +// This needs to be done as a macro so the debugger will stop in the user +// source code rather than in Catch library code +#define INTERNAL_CATCH_REACT( resultBuilder ) \ + if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ + resultBuilder.react(); + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + ( __catchResult->*expr ).endExpression(); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::isTrue( false && (expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( !Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( ... ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( exceptionType ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#else + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << log + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#endif + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( log, macroName ) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \ + try { \ + std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \ + __catchResult \ + .setLhs( Catch::toString( arg ) ) \ + .setRhs( matcherAsString == "{?}" ? #matcher : matcherAsString ) \ + .setOp( "matches" ) \ + .setResultType( ::Catch::Matchers::matcher.match( arg ) ); \ + __catchResult.captureExpression(); \ + } catch( ... ) { \ + __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +// #included from: internal/catch_section.h +#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED + +// #included from: catch_section_info.h +#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED + +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + +} // end namespace Catch + +// #included from: catch_totals.hpp +#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED + +#include + +namespace Catch { + + struct Counts { + Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} + + Counts operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + diff.failedButOk = failedButOk - other.failedButOk; + return diff; + } + Counts& operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; + } + + std::size_t total() const { + return passed + failed + failedButOk; + } + bool allPassed() const { + return failed == 0 && failedButOk == 0; + } + + std::size_t passed; + std::size_t failed; + std::size_t failedButOk; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else if( diff.assertions.failedButOk > 0 ) + ++diff.testCases.failedButOk; + else + ++diff.testCases.passed; + return diff; + } + + Totals& operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Counts assertions; + Counts testCases; + }; +} + +// #included from: catch_timer.h +#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED + +#ifdef CATCH_PLATFORM_WINDOWS +typedef unsigned long long uint64_t; +#else +#include +#endif + +namespace Catch { + + class Timer { + public: + Timer() : m_ticks( 0 ) {} + void start(); + unsigned int getElapsedNanoseconds() const; + unsigned int getElapsedMilliseconds() const; + double getElapsedSeconds() const; + + private: + uint64_t m_ticks; + }; + +} // namespace Catch + +#include + +namespace Catch { + + class Section { + public: + Section( SectionInfo const& info ); + ~Section(); + + // This indicates whether the section should be executed or not + operator bool() const; + + private: +#ifdef CATCH_CPP11_OR_GREATER + Section( Section const& ) = delete; + Section( Section && ) = delete; + Section& operator = ( Section const& ) = delete; + Section& operator = ( Section && ) = delete; +#else + Section( Section const& info ); + Section& operator = ( Section const& ); +#endif + SectionInfo m_info; + + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_SECTION( ... ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) +#else + #define INTERNAL_CATCH_SECTION( name, desc ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) +#endif + +// #included from: internal/catch_generators.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + +template +struct IGenerator { + virtual ~IGenerator() {} + virtual T getValue( std::size_t index ) const = 0; + virtual std::size_t size () const = 0; +}; + +template +class BetweenGenerator : public IGenerator { +public: + BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} + + virtual T getValue( std::size_t index ) const { + return m_from+static_cast( index ); + } + + virtual std::size_t size() const { + return static_cast( 1+m_to-m_from ); + } + +private: + + T m_from; + T m_to; +}; + +template +class ValuesGenerator : public IGenerator { +public: + ValuesGenerator(){} + + void add( T value ) { + m_values.push_back( value ); + } + + virtual T getValue( std::size_t index ) const { + return m_values[index]; + } + + virtual std::size_t size() const { + return m_values.size(); + } + +private: + std::vector m_values; +}; + +template +class CompositeGenerator { +public: + CompositeGenerator() : m_totalSize( 0 ) {} + + // *** Move semantics, similar to auto_ptr *** + CompositeGenerator( CompositeGenerator& other ) + : m_fileInfo( other.m_fileInfo ), + m_totalSize( 0 ) + { + move( other ); + } + + CompositeGenerator& setFileInfo( const char* fileInfo ) { + m_fileInfo = fileInfo; + return *this; + } + + ~CompositeGenerator() { + deleteAll( m_composed ); + } + + operator T () const { + size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); + + typename std::vector*>::const_iterator it = m_composed.begin(); + typename std::vector*>::const_iterator itEnd = m_composed.end(); + for( size_t index = 0; it != itEnd; ++it ) + { + const IGenerator* generator = *it; + if( overallIndex >= index && overallIndex < index + generator->size() ) + { + return generator->getValue( overallIndex-index ); + } + index += generator->size(); + } + CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); + return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so + } + + void add( const IGenerator* generator ) { + m_totalSize += generator->size(); + m_composed.push_back( generator ); + } + + CompositeGenerator& then( CompositeGenerator& other ) { + move( other ); + return *this; + } + + CompositeGenerator& then( T value ) { + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( value ); + add( valuesGen ); + return *this; + } + +private: + + void move( CompositeGenerator& other ) { + std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); + m_totalSize += other.m_totalSize; + other.m_composed.clear(); + } + + std::vector*> m_composed; + std::string m_fileInfo; + size_t m_totalSize; +}; + +namespace Generators +{ + template + CompositeGenerator between( T from, T to ) { + CompositeGenerator generators; + generators.add( new BetweenGenerator( from, to ) ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3 ){ + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3, T val4 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + valuesGen->add( val4 ); + generators.add( valuesGen ); + return generators; + } + +} // end namespace Generators + +using namespace Generators; + +} // end namespace Catch + +#define INTERNAL_CATCH_LINESTR2( line ) #line +#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) + +#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) + +// #included from: internal/catch_interfaces_exception.h +#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED + +#include +// #included from: catch_interfaces_registry_hub.h +#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; + + struct IRegistryHub { + virtual ~IRegistryHub(); + + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + }; + + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0; + virtual void registerTest( TestCase const& testInfo ) = 0; + virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + }; + + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + + +namespace Catch { + + typedef std::string(*exceptionTranslateFunction)(); + + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate() const = 0; + }; + + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + virtual std::string translate() const { + try { + throw; + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator( translateFunction ) ); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) + +// #included from: internal/catch_approx.hpp +#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED + +#include +#include + +namespace Catch { +namespace Detail { + + class Approx { + public: + explicit Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx( Approx const& other ) + : m_epsilon( other.m_epsilon ), + m_scale( other.m_scale ), + m_value( other.m_value ) + {} + + static Approx custom() { + return Approx( 0 ); + } + + Approx operator()( double value ) { + Approx approx( value ); + approx.epsilon( m_epsilon ); + approx.scale( m_scale ); + return approx; + } + + friend bool operator == ( double lhs, Approx const& rhs ) { + // Thanks to Richard Harris for his help refining this formula + return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); + } + + friend bool operator == ( Approx const& lhs, double rhs ) { + return operator==( rhs, lhs ); + } + + friend bool operator != ( double lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + friend bool operator != ( Approx const& lhs, double rhs ) { + return !operator==( rhs, lhs ); + } + + Approx& epsilon( double newEpsilon ) { + m_epsilon = newEpsilon; + return *this; + } + + Approx& scale( double newScale ) { + m_scale = newScale; + return *this; + } + + std::string toString() const { + std::ostringstream oss; + oss << "Approx( " << Catch::toString( m_value ) << " )"; + return oss.str(); + } + + private: + double m_epsilon; + double m_scale; + double m_value; + }; +} + +template<> +inline std::string toString( Detail::Approx const& value ) { + return value.toString(); +} + +} // end namespace Catch + +// #included from: internal/catch_matchers.hpp +#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED + +namespace Catch { +namespace Matchers { + namespace Impl { + + template + struct Matcher : SharedImpl + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + }; + + template + struct MatcherImpl : Matcher { + + virtual Ptr > clone() const { + return Ptr >( new DerivedT( static_cast( *this ) ) ); + } + }; + + namespace Generic { + + template + class AllOf : public MatcherImpl, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + private: + std::vector > > m_matchers; + }; + + template + class AnyOf : public MatcherImpl, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + private: + std::vector > > m_matchers; + }; + + } + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct Equals : MatcherImpl { + Equals( std::string const& str ) : m_str( str ){} + Equals( Equals const& other ) : m_str( other.m_str ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_str == expr; + } + virtual std::string toString() const { + return "equals: \"" + m_str + "\""; + } + + std::string m_str; + }; + + struct Contains : MatcherImpl { + Contains( std::string const& substr ) : m_substr( substr ){} + Contains( Contains const& other ) : m_substr( other.m_substr ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + + struct StartsWith : MatcherImpl { + StartsWith( std::string const& substr ) : m_substr( substr ){} + StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) == 0; + } + virtual std::string toString() const { + return "starts with: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + + struct EndsWith : MatcherImpl { + EndsWith( std::string const& substr ) : m_substr( substr ){} + EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) == expr.size() - m_substr.size(); + } + virtual std::string toString() const { + return "ends with: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str ) { + return Impl::StdString::Equals( str ); + } + inline Impl::StdString::Equals Equals( const char* str ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ) ); + } + inline Impl::StdString::Contains Contains( std::string const& substr ) { + return Impl::StdString::Contains( substr ); + } + inline Impl::StdString::Contains Contains( const char* substr ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + +// #included from: internal/catch_interfaces_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED + +// #included from: catch_tag_alias.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED + +#include + +namespace Catch { + + struct TagAlias { + TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} + + std::string tag; + SourceLineInfo lineInfo; + }; + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } +// #included from: catch_option.hpp +#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED + +namespace Catch { + + // An optional type + template + class Option { + public: + Option() : nullableValue( NULL ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : NULL ) + {} + + ~Option() { + reset(); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = NULL; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != NULL; } + bool none() const { return nullableValue == NULL; } + + bool operator !() const { return nullableValue == NULL; } + operator SafeBool::type() const { + return SafeBool::makeSafe( some() ); + } + + private: + T* nullableValue; + char storage[sizeof(T)]; + }; + +} // end namespace Catch + +namespace Catch { + + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + virtual Option find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + + static ITagAliasRegistry const& get(); + }; + +} // end namespace Catch + +// These files are included here so the single_include script doesn't put them +// in the conditionally compiled sections +// #included from: internal/catch_test_case_info.h +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED + +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + struct ITestCase; + + struct TestCaseInfo { + enum SpecialProperties{ + None = 0, + IsHidden = 1 << 1, + ShouldFail = 1 << 2, + MayFail = 1 << 3, + Throws = 1 << 4 + }; + + TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ); + + TestCaseInfo( TestCaseInfo const& other ); + + bool isHidden() const; + bool throws() const; + bool okToFail() const; + bool expectedToFail() const; + + std::string name; + std::string className; + std::string description; + std::set tags; + std::set lcaseTags; + std::string tagsAsString; + SourceLineInfo lineInfo; + SpecialProperties properties; + }; + + class TestCase : public TestCaseInfo { + public: + + TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( TestCase const& other ); + + TestCase withName( std::string const& _newName ) const; + + void invoke() const; + + TestCaseInfo const& getTestCaseInfo() const; + + void swap( TestCase& other ); + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + TestCase& operator = ( TestCase const& other ); + + private: + Ptr test; + }; + + TestCase makeTestCase( ITestCase* testCase, + std::string const& className, + std::string const& name, + std::string const& description, + SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + + +#ifdef __OBJC__ +// #included from: internal/catch_objc.hpp +#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED + +#import + +#include + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage + +/////////////////////////////////////////////////////////////////////////////// +// This protocol is really only here for (self) documenting purposes, since +// all its methods are optional. +@protocol OcFixture + +@optional + +-(void) setUp; +-(void) tearDown; + +@end + +namespace Catch { + + class OcMethod : public SharedImpl { + + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + + virtual void invoke() const { + id obj = [[m_cls alloc] init]; + + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); + + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; + }; + + namespace Detail{ + + inline std::string getAnnotation( Class cls, + std::string const& annotationName, + std::string const& testCaseName ) { + NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; + SEL sel = NSSelectorFromString( selStr ); + arcSafeRelease( selStr ); + id value = performOptionalSelector( cls, sel ); + if( value ) + return [(NSString*)value UTF8String]; + return ""; + } + } + + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( NULL, 0 ); + + Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); + objc_getClassList( classes, noClasses ); + + for( int c = 0; c < noClasses; c++ ) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList( cls, &count ); + for( u_int m = 0; m < count ; m++ ) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if( startsWith( methodName, "Catch_TestCase_" ) ) { + std::string testCaseName = methodName.substr( 15 ); + std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); + std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); + const char* className = class_getName( cls ); + + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + noTestMethods++; + } + } + free(methods); + } + } + return noTestMethods; + } + + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { + + template + struct StringHolder : MatcherImpl{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } + + NSString* m_substr; + }; + + struct Equals : StringHolder { + Equals( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_substr]; + } + + virtual std::string toString() const { + return "equals string: " + Catch::toString( m_substr ); + } + }; + + struct Contains : StringHolder { + Contains( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } + + virtual std::string toString() const { + return "contains string: " + Catch::toString( m_substr ); + } + }; + + struct StartsWith : StringHolder { + StartsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } + + virtual std::string toString() const { + return "starts with: " + Catch::toString( m_substr ); + } + }; + struct EndsWith : StringHolder { + EndsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } + + virtual std::string toString() const { + return "ends with: " + Catch::toString( m_substr ); + } + }; + + } // namespace NSStringMatchers + } // namespace Impl + + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } + + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } + + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } + + inline Impl::NSStringMatchers::EndsWith + EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } + + } // namespace Matchers + + using namespace Matchers; + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define OC_TEST_CASE( name, desc )\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ +{\ +return @ name; \ +}\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +{ \ +return @ desc; \ +} \ +-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) + +#endif + +#ifdef CATCH_CONFIG_RUNNER +// #included from: internal/catch_impl.hpp +#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED + +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// #included from: catch_runner.hpp +#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED + +// #included from: internal/catch_commandline.hpp +#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED + +// #included from: catch_config.hpp +#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED + +// #included from: catch_test_spec_parser.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_test_spec.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +#include +#include + +namespace Catch { + + class TestSpec { + struct Pattern : SharedImpl<> { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + class NamePattern : public Pattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) { + if( startsWith( m_name, "*" ) ) { + m_name = m_name.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_name, "*" ) ) { + m_name = m_name.substr( 0, m_name.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_name == toLower( testCase.name ); + case WildcardAtStart: + return endsWith( toLower( testCase.name ), m_name ); + case WildcardAtEnd: + return startsWith( toLower( testCase.name ), m_name ); + case WildcardAtBothEnds: + return contains( toLower( testCase.name ), m_name ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string m_name; + WildcardPosition m_wildcard; + }; + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + virtual ~TagPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); + } + private: + std::string m_tag; + }; + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr m_underlyingPattern; + }; + + struct Filter { + std::vector > m_patterns; + + bool matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) + if( !(*it)->matches( testCase ) ) + return false; + return true; + } + }; + + public: + bool hasFilters() const { + return !m_filters.empty(); + } + bool matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } + + private: + std::vector m_filters; + + friend class TestSpecParser; + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +namespace Catch { + + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag }; + Mode m_mode; + bool m_exclusion; + std::size_t m_start, m_pos; + std::string m_arg; + TestSpec::Filter m_currentFilter; + TestSpec m_testSpec; + ITagAliasRegistry const* m_tagAliases; + + public: + TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + + TestSpecParser& parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases( arg ); + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern(); + return *this; + } + TestSpec testSpec() { + addFilter(); + return m_testSpec; + } + private: + void visitChar( char c ) { + if( m_mode == None ) { + switch( c ) { + case ' ': return; + case '~': m_exclusion = true; return; + case '[': return startNewMode( Tag, ++m_pos ); + case '"': return startNewMode( QuotedName, ++m_pos ); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + startNewMode( Tag, ++m_pos ); + } + } + else if( m_mode == QuotedName && c == '"' ) + addPattern(); + else if( m_mode == Tag && c == ']' ) + addPattern(); + } + void startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + template + void addPattern() { + std::string token = subString(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr pattern = new T( token ); + if( m_exclusion ) + pattern = new TestSpec::ExcludedPattern( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + void addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + }; + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// #included from: catch_interfaces_config.h +#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct Verbosity { enum Level { + NoOutput = 0, + Quiet, + Normal + }; }; + + struct WarnAbout { enum What { + Nothing = 0x00, + NoAssertions = 0x01 + }; }; + + struct ShowDurations { enum OrNot { + DefaultForReporter, + Always, + Never + }; }; + + class TestSpec; + + struct IConfig : IShared { + + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + }; +} + +// #included from: catch_stream.h +#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED + +#include + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + class Stream { + public: + Stream(); + Stream( std::streambuf* _streamBuf, bool _isOwned ); + void release(); + + std::streambuf* streamBuf; + + private: + bool isOwned; + }; +} + +#include +#include +#include +#include + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + + struct ConfigData { + + ConfigData() + : listTests( false ), + listTags( false ), + listReporters( false ), + listTestNamesOnly( false ), + showSuccessfulTests( false ), + shouldDebugBreak( false ), + noThrow( false ), + showHelp( false ), + showInvisibles( false ), + abortAfter( -1 ), + verbosity( Verbosity::Normal ), + warnings( WarnAbout::Nothing ), + showDurations( ShowDurations::DefaultForReporter ) + {} + + bool listTests; + bool listTags; + bool listReporters; + bool listTestNamesOnly; + + bool showSuccessfulTests; + bool shouldDebugBreak; + bool noThrow; + bool showHelp; + bool showInvisibles; + + int abortAfter; + + Verbosity::Level verbosity; + WarnAbout::What warnings; + ShowDurations::OrNot showDurations; + + std::string reporterName; + std::string outputFilename; + std::string name; + std::string processName; + + std::vector testsOrTags; + }; + + class Config : public SharedImpl { + private: + Config( Config const& other ); + Config& operator = ( Config const& other ); + virtual void dummy(); + public: + + Config() + : m_os( std::cout.rdbuf() ) + {} + + Config( ConfigData const& data ) + : m_data( data ), + m_os( std::cout.rdbuf() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser( ITagAliasRegistry::get() ); + for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) + parser.parse( data.testsOrTags[i] ); + m_testSpec = parser.testSpec(); + } + } + + virtual ~Config() { + m_os.rdbuf( std::cout.rdbuf() ); + m_stream.release(); + } + + void setFilename( std::string const& filename ) { + m_data.outputFilename = filename; + } + + std::string const& getFilename() const { + return m_data.outputFilename ; + } + + bool listTests() const { return m_data.listTests; } + bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool listTags() const { return m_data.listTags; } + bool listReporters() const { return m_data.listReporters; } + + std::string getProcessName() const { return m_data.processName; } + + bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } + + void setStreamBuf( std::streambuf* buf ) { + m_os.rdbuf( buf ? buf : std::cout.rdbuf() ); + } + + void useStream( std::string const& streamName ) { + Stream stream = createStream( streamName ); + setStreamBuf( stream.streamBuf ); + m_stream.release(); + m_stream = stream; + } + + std::string getReporterName() const { return m_data.reporterName; } + + int abortAfter() const { return m_data.abortAfter; } + + TestSpec const& testSpec() const { return m_testSpec; } + + bool showHelp() const { return m_data.showHelp; } + bool showInvisibles() const { return m_data.showInvisibles; } + + // IConfig interface + virtual bool allowThrows() const { return !m_data.noThrow; } + virtual std::ostream& stream() const { return m_os; } + virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } + virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } + + private: + ConfigData m_data; + + Stream m_stream; + mutable std::ostream m_os; + TestSpec m_testSpec; + }; + +} // end namespace Catch + +// #included from: catch_clara.h +#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#undef CLARA_CONFIG_CONSOLE_WIDTH +#endif +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +// Declare Clara inside the Catch namespace +#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { +// #included from: ../external/clara.h + +// Only use header guard if we are not using an outer namespace +#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) + +#ifndef STITCH_CLARA_OPEN_NAMESPACE +#define TWOBLUECUBES_CLARA_H_INCLUDED +#define STITCH_CLARA_OPEN_NAMESPACE +#define STITCH_CLARA_CLOSE_NAMESPACE +#else +#define STITCH_CLARA_CLOSE_NAMESPACE } +#endif + +#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE + +// ----------- #included from tbc_text_format.h ----------- + +// Only use header guard if we are not using an outer namespace +#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) +#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +#define TBC_TEXT_FORMAT_H_INCLUDED +#endif + +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TBC_TEXT_FORMAT_H_INCLUDED + +// ----------- end of #include from tbc_text_format.h ----------- +// ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h + +#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE + +#include +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_CLARA_OPEN_NAMESPACE +STITCH_CLARA_OPEN_NAMESPACE +#endif + +namespace Clara { + + struct UnpositionalTag {}; + + extern UnpositionalTag _; + +#ifdef CLARA_CONFIG_MAIN + UnpositionalTag _; +#endif + + namespace Detail { + +#ifdef CLARA_CONSOLE_WIDTH + const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + using namespace Tbc; + + inline bool startsWith( std::string const& str, std::string const& prefix ) { + return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; + } + + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + + template struct IsBool { static const bool value = false; }; + template<> struct IsBool { static const bool value = true; }; + + template + void convertInto( std::string const& _source, T& _dest ) { + std::stringstream ss; + ss << _source; + ss >> _dest; + if( ss.fail() ) + throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); + } + inline void convertInto( std::string const& _source, std::string& _dest ) { + _dest = _source; + } + inline void convertInto( std::string const& _source, bool& _dest ) { + std::string sourceLC = _source; + std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower ); + if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) + _dest = true; + else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) + _dest = false; + else + throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); + } + inline void convertInto( bool _source, bool& _dest ) { + _dest = _source; + } + template + inline void convertInto( bool, T& ) { + throw std::runtime_error( "Invalid conversion" ); + } + + template + struct IArgFunction { + virtual ~IArgFunction() {} +# ifdef CATCH_CPP11_OR_GREATER + IArgFunction() = default; + IArgFunction( IArgFunction const& ) = default; +# endif + virtual void set( ConfigT& config, std::string const& value ) const = 0; + virtual void setFlag( ConfigT& config ) const = 0; + virtual bool takesArg() const = 0; + virtual IArgFunction* clone() const = 0; + }; + + template + class BoundArgFunction { + public: + BoundArgFunction() : functionObj( NULL ) {} + BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {} + BoundArgFunction& operator = ( BoundArgFunction const& other ) { + IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL; + delete functionObj; + functionObj = newFunctionObj; + return *this; + } + ~BoundArgFunction() { delete functionObj; } + + void set( ConfigT& config, std::string const& value ) const { + functionObj->set( config, value ); + } + void setFlag( ConfigT& config ) const { + functionObj->setFlag( config ); + } + bool takesArg() const { return functionObj->takesArg(); } + + bool isSet() const { + return functionObj != NULL; + } + private: + IArgFunction* functionObj; + }; + + template + struct NullBinder : IArgFunction{ + virtual void set( C&, std::string const& ) const {} + virtual void setFlag( C& ) const {} + virtual bool takesArg() const { return true; } + virtual IArgFunction* clone() const { return new NullBinder( *this ); } + }; + + template + struct BoundDataMember : IArgFunction{ + BoundDataMember( M C::* _member ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + convertInto( stringValue, p.*member ); + } + virtual void setFlag( C& p ) const { + convertInto( true, p.*member ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } + M C::* member; + }; + template + struct BoundUnaryMethod : IArgFunction{ + BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + (p.*member)( value ); + } + virtual void setFlag( C& p ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + (p.*member)( value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } + void (C::*member)( M ); + }; + template + struct BoundNullaryMethod : IArgFunction{ + BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + (p.*member)(); + } + virtual void setFlag( C& p ) const { + (p.*member)(); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } + void (C::*member)(); + }; + + template + struct BoundUnaryFunction : IArgFunction{ + BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + function( obj ); + } + virtual void setFlag( C& p ) const { + function( p ); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } + void (*function)( C& ); + }; + + template + struct BoundBinaryFunction : IArgFunction{ + BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + function( obj, value ); + } + virtual void setFlag( C& obj ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + function( obj, value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } + void (*function)( C&, T ); + }; + + } // namespace Detail + + struct Parser { + Parser() : separators( " \t=:" ) {} + + struct Token { + enum Type { Positional, ShortOpt, LongOpt }; + Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} + Type type; + std::string data; + }; + + void parseIntoTokens( int argc, char const * const * argv, std::vector& tokens ) const { + const std::string doubleDash = "--"; + for( int i = 1; i < argc && argv[i] != doubleDash; ++i ) + parseIntoTokens( argv[i] , tokens); + } + void parseIntoTokens( std::string arg, std::vector& tokens ) const { + while( !arg.empty() ) { + Parser::Token token( Parser::Token::Positional, arg ); + arg = ""; + if( token.data[0] == '-' ) { + if( token.data.size() > 1 && token.data[1] == '-' ) { + token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) ); + } + else { + token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) ); + if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) { + arg = "-" + token.data.substr( 1 ); + token.data = token.data.substr( 0, 1 ); + } + } + } + if( token.type != Parser::Token::Positional ) { + std::size_t pos = token.data.find_first_of( separators ); + if( pos != std::string::npos ) { + arg = token.data.substr( pos+1 ); + token.data = token.data.substr( 0, pos ); + } + } + tokens.push_back( token ); + } + } + std::string separators; + }; + + template + struct CommonArgProperties { + CommonArgProperties() {} + CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} + + Detail::BoundArgFunction boundField; + std::string description; + std::string detail; + std::string placeholder; // Only value if boundField takes an arg + + bool takesArg() const { + return !placeholder.empty(); + } + void validate() const { + if( !boundField.isSet() ) + throw std::logic_error( "option not bound" ); + } + }; + struct OptionArgProperties { + std::vector shortNames; + std::string longName; + + bool hasShortName( std::string const& shortName ) const { + return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); + } + bool hasLongName( std::string const& _longName ) const { + return _longName == longName; + } + }; + struct PositionalArgProperties { + PositionalArgProperties() : position( -1 ) {} + int position; // -1 means non-positional (floating) + + bool isFixedPositional() const { + return position != -1; + } + }; + + template + class CommandLine { + + struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { + Arg() {} + Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} + + using CommonArgProperties::placeholder; // !TBD + + std::string dbgName() const { + if( !longName.empty() ) + return "--" + longName; + if( !shortNames.empty() ) + return "-" + shortNames[0]; + return "positional args"; + } + std::string commands() const { + std::ostringstream oss; + bool first = true; + std::vector::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); + for(; it != itEnd; ++it ) { + if( first ) + first = false; + else + oss << ", "; + oss << "-" << *it; + } + if( !longName.empty() ) { + if( !first ) + oss << ", "; + oss << "--" << longName; + } + if( !placeholder.empty() ) + oss << " <" << placeholder << ">"; + return oss.str(); + } + }; + + // NOTE: std::auto_ptr is deprecated in c++11/c++0x +#if defined(__cplusplus) && __cplusplus > 199711L + typedef std::unique_ptr ArgAutoPtr; +#else + typedef std::auto_ptr ArgAutoPtr; +#endif + + friend void addOptName( Arg& arg, std::string const& optName ) + { + if( optName.empty() ) + return; + if( Detail::startsWith( optName, "--" ) ) { + if( !arg.longName.empty() ) + throw std::logic_error( "Only one long opt may be specified. '" + + arg.longName + + "' already specified, now attempting to add '" + + optName + "'" ); + arg.longName = optName.substr( 2 ); + } + else if( Detail::startsWith( optName, "-" ) ) + arg.shortNames.push_back( optName.substr( 1 ) ); + else + throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); + } + friend void setPositionalArg( Arg& arg, int position ) + { + arg.position = position; + } + + class ArgBuilder { + public: + ArgBuilder( Arg* arg ) : m_arg( arg ) {} + + // Bind a non-boolean data member (requires placeholder string) + template + void bind( M C::* field, std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + m_arg->placeholder = placeholder; + } + // Bind a boolean data member (no placeholder required) + template + void bind( bool C::* field ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + } + + // Bind a method taking a single, non-boolean argument (requires a placeholder string) + template + void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + m_arg->placeholder = placeholder; + } + + // Bind a method taking a single, boolean argument (no placeholder string required) + template + void bind( void (C::* unaryMethod)( bool ) ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + } + + // Bind a method that takes no arguments (will be called if opt is present) + template + void bind( void (C::* nullaryMethod)() ) { + m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); + } + + // Bind a free function taking a single argument - the object to operate on (no placeholder string required) + template + void bind( void (* unaryFunction)( C& ) ) { + m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); + } + + // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) + template + void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); + m_arg->placeholder = placeholder; + } + + ArgBuilder& describe( std::string const& description ) { + m_arg->description = description; + return *this; + } + ArgBuilder& detail( std::string const& detail ) { + m_arg->detail = detail; + return *this; + } + + protected: + Arg* m_arg; + }; + + class OptBuilder : public ArgBuilder { + public: + OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} + OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} + + OptBuilder& operator[]( std::string const& optName ) { + addOptName( *ArgBuilder::m_arg, optName ); + return *this; + } + }; + + public: + + CommandLine() + : m_boundProcessName( new Detail::NullBinder() ), + m_highestSpecifiedArgPosition( 0 ), + m_throwOnUnrecognisedTokens( false ) + {} + CommandLine( CommandLine const& other ) + : m_boundProcessName( other.m_boundProcessName ), + m_options ( other.m_options ), + m_positionalArgs( other.m_positionalArgs ), + m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), + m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) + { + if( other.m_floatingArg.get() ) + m_floatingArg = ArgAutoPtr( new Arg( *other.m_floatingArg ) ); + } + + CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { + m_throwOnUnrecognisedTokens = shouldThrow; + return *this; + } + + OptBuilder operator[]( std::string const& optName ) { + m_options.push_back( Arg() ); + addOptName( m_options.back(), optName ); + OptBuilder builder( &m_options.back() ); + return builder; + } + + ArgBuilder operator[]( int position ) { + m_positionalArgs.insert( std::make_pair( position, Arg() ) ); + if( position > m_highestSpecifiedArgPosition ) + m_highestSpecifiedArgPosition = position; + setPositionalArg( m_positionalArgs[position], position ); + ArgBuilder builder( &m_positionalArgs[position] ); + return builder; + } + + // Invoke this with the _ instance + ArgBuilder operator[]( UnpositionalTag ) { + if( m_floatingArg.get() ) + throw std::logic_error( "Only one unpositional argument can be added" ); + m_floatingArg = ArgAutoPtr( new Arg() ); + ArgBuilder builder( m_floatingArg.get() ); + return builder; + } + + template + void bindProcessName( M C::* field ) { + m_boundProcessName = new Detail::BoundDataMember( field ); + } + template + void bindProcessName( void (C::*_unaryMethod)( M ) ) { + m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); + } + + void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { + typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; + std::size_t maxWidth = 0; + for( it = itBegin; it != itEnd; ++it ) + maxWidth = (std::max)( maxWidth, it->commands().size() ); + + for( it = itBegin; it != itEnd; ++it ) { + Detail::Text usage( it->commands(), Detail::TextAttributes() + .setWidth( maxWidth+indent ) + .setIndent( indent ) ); + Detail::Text desc( it->description, Detail::TextAttributes() + .setWidth( width - maxWidth - 3 ) ); + + for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { + std::string usageCol = i < usage.size() ? usage[i] : ""; + os << usageCol; + + if( i < desc.size() && !desc[i].empty() ) + os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) + << desc[i]; + os << "\n"; + } + } + } + std::string optUsage() const { + std::ostringstream oss; + optUsage( oss ); + return oss.str(); + } + + void argSynopsis( std::ostream& os ) const { + for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { + if( i > 1 ) + os << " "; + typename std::map::const_iterator it = m_positionalArgs.find( i ); + if( it != m_positionalArgs.end() ) + os << "<" << it->second.placeholder << ">"; + else if( m_floatingArg.get() ) + os << "<" << m_floatingArg->placeholder << ">"; + else + throw std::logic_error( "non consecutive positional arguments with no floating args" ); + } + // !TBD No indication of mandatory args + if( m_floatingArg.get() ) { + if( m_highestSpecifiedArgPosition > 1 ) + os << " "; + os << "[<" << m_floatingArg->placeholder << "> ...]"; + } + } + std::string argSynopsis() const { + std::ostringstream oss; + argSynopsis( oss ); + return oss.str(); + } + + void usage( std::ostream& os, std::string const& procName ) const { + validate(); + os << "usage:\n " << procName << " "; + argSynopsis( os ); + if( !m_options.empty() ) { + os << " [options]\n\nwhere options are: \n"; + optUsage( os, 2 ); + } + os << "\n"; + } + std::string usage( std::string const& procName ) const { + std::ostringstream oss; + usage( oss, procName ); + return oss.str(); + } + + ConfigT parse( int argc, char const * const * argv ) const { + ConfigT config; + parseInto( argc, argv, config ); + return config; + } + + std::vector parseInto( int argc, char const * const * argv, ConfigT& config ) const { + std::string processName = argv[0]; + std::size_t lastSlash = processName.find_last_of( "/\\" ); + if( lastSlash != std::string::npos ) + processName = processName.substr( lastSlash+1 ); + m_boundProcessName.set( config, processName ); + std::vector tokens; + Parser parser; + parser.parseIntoTokens( argc, argv, tokens ); + return populate( tokens, config ); + } + + std::vector populate( std::vector const& tokens, ConfigT& config ) const { + validate(); + std::vector unusedTokens = populateOptions( tokens, config ); + unusedTokens = populateFixedArgs( unusedTokens, config ); + unusedTokens = populateFloatingArgs( unusedTokens, config ); + return unusedTokens; + } + + std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + std::vector errors; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); + for(; it != itEnd; ++it ) { + Arg const& arg = *it; + + try { + if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || + ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { + if( arg.takesArg() ) { + if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) + errors.push_back( "Expected argument to option: " + token.data ); + else + arg.boundField.set( config, tokens[++i].data ); + } + else { + arg.boundField.setFlag( config ); + } + break; + } + } + catch( std::exception& ex ) { + errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); + } + } + if( it == itEnd ) { + if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) + unusedTokens.push_back( token ); + else if( m_throwOnUnrecognisedTokens ) + errors.push_back( "unrecognised option: " + token.data ); + } + } + if( !errors.empty() ) { + std::ostringstream oss; + for( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); + it != itEnd; + ++it ) { + if( it != errors.begin() ) + oss << "\n"; + oss << *it; + } + throw std::runtime_error( oss.str() ); + } + return unusedTokens; + } + std::vector populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + int position = 1; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::map::const_iterator it = m_positionalArgs.find( position ); + if( it != m_positionalArgs.end() ) + it->second.boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + if( token.type == Parser::Token::Positional ) + position++; + } + return unusedTokens; + } + std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { + if( !m_floatingArg.get() ) + return tokens; + std::vector unusedTokens; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + if( token.type == Parser::Token::Positional ) + m_floatingArg->boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + } + return unusedTokens; + } + + void validate() const + { + if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) + throw std::logic_error( "No options or arguments specified" ); + + for( typename std::vector::const_iterator it = m_options.begin(), + itEnd = m_options.end(); + it != itEnd; ++it ) + it->validate(); + } + + private: + Detail::BoundArgFunction m_boundProcessName; + std::vector m_options; + std::map m_positionalArgs; + ArgAutoPtr m_floatingArg; + int m_highestSpecifiedArgPosition; + bool m_throwOnUnrecognisedTokens; + }; + +} // end namespace Clara + +STITCH_CLARA_CLOSE_NAMESPACE +#undef STITCH_CLARA_OPEN_NAMESPACE +#undef STITCH_CLARA_CLOSE_NAMESPACE + +#endif // TWOBLUECUBES_CLARA_H_INCLUDED +#undef STITCH_CLARA_OPEN_NAMESPACE + +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +#include + +namespace Catch { + + inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } + inline void abortAfterX( ConfigData& config, int x ) { + if( x < 1 ) + throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); + config.abortAfter = x; + } + inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + + inline void addWarning( ConfigData& config, std::string const& _warning ) { + if( _warning == "NoAssertions" ) + config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); + else + throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); + + } + inline void setVerbosity( ConfigData& config, int level ) { + // !TBD: accept strings? + config.verbosity = static_cast( level ); + } + inline void setShowDurations( ConfigData& config, bool _showDurations ) { + config.showDurations = _showDurations + ? ShowDurations::Always + : ShowDurations::Never; + } + inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { + std::ifstream f( _filename.c_str() ); + if( !f.is_open() ) + throw std::domain_error( "Unable to load input file: " + _filename ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, "#" ) ) + addTestOrTags( config, "\"" + line + "\"," ); + } + } + + inline Clara::CommandLine makeCommandLineParser() { + + using namespace Clara; + CommandLine cli; + + cli.bindProcessName( &ConfigData::processName ); + + cli["-?"]["-h"]["--help"] + .describe( "display usage information" ) + .bind( &ConfigData::showHelp ); + + cli["-l"]["--list-tests"] + .describe( "list all/matching test cases" ) + .bind( &ConfigData::listTests ); + + cli["-t"]["--list-tags"] + .describe( "list all/matching tags" ) + .bind( &ConfigData::listTags ); + + cli["-s"]["--success"] + .describe( "include successful tests in output" ) + .bind( &ConfigData::showSuccessfulTests ); + + cli["-b"]["--break"] + .describe( "break into debugger on failure" ) + .bind( &ConfigData::shouldDebugBreak ); + + cli["-e"]["--nothrow"] + .describe( "skip exception tests" ) + .bind( &ConfigData::noThrow ); + + cli["-i"]["--invisibles"] + .describe( "show invisibles (tabs, newlines)" ) + .bind( &ConfigData::showInvisibles ); + + cli["-o"]["--out"] + .describe( "output filename" ) + .bind( &ConfigData::outputFilename, "filename" ); + + cli["-r"]["--reporter"] +// .placeholder( "name[:filename]" ) + .describe( "reporter to use (defaults to console)" ) + .bind( &ConfigData::reporterName, "name" ); + + cli["-n"]["--name"] + .describe( "suite name" ) + .bind( &ConfigData::name, "name" ); + + cli["-a"]["--abort"] + .describe( "abort at first failure" ) + .bind( &abortAfterFirst ); + + cli["-x"]["--abortx"] + .describe( "abort after x failures" ) + .bind( &abortAfterX, "no. failures" ); + + cli["-w"]["--warn"] + .describe( "enable warnings" ) + .bind( &addWarning, "warning name" ); + +// - needs updating if reinstated +// cli.into( &setVerbosity ) +// .describe( "level of verbosity (0=no output)" ) +// .shortOpt( "v") +// .longOpt( "verbosity" ) +// .placeholder( "level" ); + + cli[_] + .describe( "which test or tests to use" ) + .bind( &addTestOrTags, "test name, pattern or tags" ); + + cli["-d"]["--durations"] + .describe( "show test durations" ) + .bind( &setShowDurations, "yes/no" ); + + cli["-f"]["--input-file"] + .describe( "load test names to run from a file" ) + .bind( &loadTestNamesFromFile, "filename" ); + + // Less common commands which don't have a short form + cli["--list-test-names-only"] + .describe( "list all/matching test cases names only" ) + .bind( &ConfigData::listTestNamesOnly ); + + cli["--list-reporters"] + .describe( "list all reporters" ) + .bind( &ConfigData::listReporters ); + + return cli; + } + +} // end namespace Catch + +// #included from: internal/catch_list.hpp +#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED + +// #included from: catch_text.h +#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED + +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +// #included from: ../external/tbc_text_format.h +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# endif +# else +# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include +#include +#include + +// Use optional outer namespace +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE + +namespace Catch { + using Tbc::Text; + using Tbc::TextAttributes; +} + +// #included from: catch_console_colour.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED + +namespace Catch { + + namespace Detail { + struct IColourImpl; + } + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + + // By intention + FileName = LightGrey, + Warning = Yellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + Colour( Colour const& other ); + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + static Detail::IColourImpl* impl(); + bool m_moved; + }; + + inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } + +} // end namespace Catch + +// #included from: catch_interfaces_reporter.h +#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED + +#include +#include +#include +#include + +namespace Catch +{ + struct ReporterConfig { + explicit ReporterConfig( Ptr const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) + : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + + std::ostream& stream() const { return *m_stream; } + Ptr fullConfig() const { return m_fullConfig; } + + private: + std::ostream* m_stream; + Ptr m_fullConfig; + }; + + struct ReporterPreferences { + ReporterPreferences() + : shouldRedirectStdOut( false ) + {} + + bool shouldRedirectStdOut; + }; + + template + struct LazyStat : Option { + LazyStat() : used( false ) {} + LazyStat& operator=( T const& _value ) { + Option::operator=( _value ); + used = false; + return *this; + } + void reset() { + Option::reset(); + used = false; + } + bool used; + }; + + struct TestRunInfo { + TestRunInfo( std::string const& _name ) : name( _name ) {} + std::string name; + }; + struct GroupInfo { + GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) + {} + + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; + + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) + { + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); + + infoMessages.push_back( builder.m_info ); + } + } + virtual ~AssertionStats(); + +# ifdef CATCH_CPP11_OR_GREATER + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; +# endif + + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; + }; + + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + virtual ~SectionStats(); +# ifdef CATCH_CPP11_OR_GREATER + SectionStats( SectionStats const& ) = default; + SectionStats( SectionStats && ) = default; + SectionStats& operator = ( SectionStats const& ) = default; + SectionStats& operator = ( SectionStats && ) = default; +# endif + + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; + }; + + struct TestCaseStats { + TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ) + : testInfo( _testInfo ), + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + virtual ~TestCaseStats(); + +# ifdef CATCH_CPP11_OR_GREATER + TestCaseStats( TestCaseStats const& ) = default; + TestCaseStats( TestCaseStats && ) = default; + TestCaseStats& operator = ( TestCaseStats const& ) = default; + TestCaseStats& operator = ( TestCaseStats && ) = default; +# endif + + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; + + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + virtual ~TestGroupStats(); + +# ifdef CATCH_CPP11_OR_GREATER + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; +# endif + + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; + + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + virtual ~TestRunStats(); + +# ifndef CATCH_CPP11_OR_GREATER + TestRunStats( TestRunStats const& _other ) + : runInfo( _other.runInfo ), + totals( _other.totals ), + aborting( _other.aborting ) + {} +# else + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; +# endif + + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; + + struct IStreamingReporter : IShared { + virtual ~IStreamingReporter(); + + // Implementing class must also provide the following static method: + // static std::string getDescription(); + + virtual ReporterPreferences getPreferences() const = 0; + + virtual void noMatchingTestCases( std::string const& spec ) = 0; + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; + virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + + virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; + virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + }; + + struct IReporterFactory { + virtual ~IReporterFactory(); + virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; + + struct IReporterRegistry { + typedef std::map FactoryMap; + + virtual ~IReporterRegistry(); + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + }; + +} + +#include +#include + +namespace Catch { + + inline std::size_t listTests( Config const& config ) { + + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + std::cout << "Matching test cases:\n"; + else { + std::cout << "All available test cases:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::size_t matchedTests = 0; + TextAttributes nameAttr, tagsAttr; + nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + tagsAttr.setIndent( 6 ); + + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Colour::Code colour = testCaseInfo.isHidden() + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard( colour ); + + std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl; + if( !testCaseInfo.tags.empty() ) + std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; + } + + if( !config.testSpec().hasFilters() ) + std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl; + else + std::cout << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; + return matchedTests; + } + + inline std::size_t listTestsNamesOnly( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( !config.testSpec().hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + std::size_t matchedTests = 0; + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + std::cout << testCaseInfo.name << std::endl; + } + return matchedTests; + } + + struct TagInfo { + TagInfo() : count ( 0 ) {} + void add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } + std::string all() const { + std::string out; + for( std::set::const_iterator it = spellings.begin(), itEnd = spellings.end(); + it != itEnd; + ++it ) + out += "[" + *it + "]"; + return out; + } + std::set spellings; + std::size_t count; + }; + + inline std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + std::cout << "Tags for matching test cases:\n"; + else { + std::cout << "All available tags:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::map tagCounts; + + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + for( std::set::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), + tagItEnd = it->getTestCaseInfo().tags.end(); + tagIt != tagItEnd; + ++tagIt ) { + std::string tagName = *tagIt; + std::string lcaseTagName = toLower( tagName ); + std::map::iterator countIt = tagCounts.find( lcaseTagName ); + if( countIt == tagCounts.end() ) + countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; + countIt->second.add( tagName ); + } + } + + for( std::map::const_iterator countIt = tagCounts.begin(), + countItEnd = tagCounts.end(); + countIt != countItEnd; + ++countIt ) { + std::ostringstream oss; + oss << " " << std::setw(2) << countIt->second.count << " "; + Text wrapper( countIt->second.all(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( oss.str().size() ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); + std::cout << oss.str() << wrapper << "\n"; + } + std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; + return tagCounts.size(); + } + + inline std::size_t listReporters( Config const& /*config*/ ) { + std::cout << "Available reports:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; + std::size_t maxNameLen = 0; + for(it = itBegin; it != itEnd; ++it ) + maxNameLen = (std::max)( maxNameLen, it->first.size() ); + + for(it = itBegin; it != itEnd; ++it ) { + Text wrapper( it->second->getDescription(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( 7+maxNameLen ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); + std::cout << " " + << it->first + << ":" + << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << wrapper << "\n"; + } + std::cout << std::endl; + return factories.size(); + } + + inline Option list( Config const& config ) { + Option listedCount; + if( config.listTests() ) + listedCount = listedCount.valueOr(0) + listTests( config ); + if( config.listTestNamesOnly() ) + listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); + if( config.listTags() ) + listedCount = listedCount.valueOr(0) + listTags( config ); + if( config.listReporters() ) + listedCount = listedCount.valueOr(0) + listReporters( config ); + return listedCount; + } + +} // end namespace Catch + +// #included from: internal/catch_runner_impl.hpp +#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED + +// #included from: catch_test_case_tracker.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { +namespace SectionTracking { + + class TrackedSection { + + typedef std::map TrackedSections; + + public: + enum RunState { + NotStarted, + Executing, + ExecutingChildren, + Completed + }; + + TrackedSection( std::string const& name, TrackedSection* parent ) + : m_name( name ), m_runState( NotStarted ), m_parent( parent ) + {} + + RunState runState() const { return m_runState; } + + TrackedSection* findChild( std::string const& childName ) { + TrackedSections::iterator it = m_children.find( childName ); + return it != m_children.end() + ? &it->second + : NULL; + } + TrackedSection* acquireChild( std::string const& childName ) { + if( TrackedSection* child = findChild( childName ) ) + return child; + m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) ); + return findChild( childName ); + } + void enter() { + if( m_runState == NotStarted ) + m_runState = Executing; + } + void leave() { + for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end(); + it != itEnd; + ++it ) + if( it->second.runState() != Completed ) { + m_runState = ExecutingChildren; + return; + } + m_runState = Completed; + } + TrackedSection* getParent() { + return m_parent; + } + bool hasChildren() const { + return !m_children.empty(); + } + + private: + std::string m_name; + RunState m_runState; + TrackedSections m_children; + TrackedSection* m_parent; + + }; + + class TestCaseTracker { + public: + TestCaseTracker( std::string const& testCaseName ) + : m_testCase( testCaseName, NULL ), + m_currentSection( &m_testCase ), + m_completedASectionThisRun( false ) + {} + + bool enterSection( std::string const& name ) { + TrackedSection* child = m_currentSection->acquireChild( name ); + if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed ) + return false; + + m_currentSection = child; + m_currentSection->enter(); + return true; + } + void leaveSection() { + m_currentSection->leave(); + m_currentSection = m_currentSection->getParent(); + assert( m_currentSection != NULL ); + m_completedASectionThisRun = true; + } + + bool currentSectionHasChildren() const { + return m_currentSection->hasChildren(); + } + bool isCompleted() const { + return m_testCase.runState() == TrackedSection::Completed; + } + + class Guard { + public: + Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) { + m_tracker.enterTestCase(); + } + ~Guard() { + m_tracker.leaveTestCase(); + } + private: + Guard( Guard const& ); + void operator = ( Guard const& ); + TestCaseTracker& m_tracker; + }; + + private: + void enterTestCase() { + m_currentSection = &m_testCase; + m_completedASectionThisRun = false; + m_testCase.enter(); + } + void leaveTestCase() { + m_testCase.leave(); + } + + TrackedSection m_testCase; + TrackedSection* m_currentSection; + bool m_completedASectionThisRun; + }; + +} // namespace SectionTracking + +using SectionTracking::TestCaseTracker; + +} // namespace Catch + +#include +#include + +namespace Catch { + + class StreamRedirect { + + public: + StreamRedirect( std::ostream& stream, std::string& targetString ) + : m_stream( stream ), + m_prevBuf( stream.rdbuf() ), + m_targetString( targetString ) + { + stream.rdbuf( m_oss.rdbuf() ); + } + + ~StreamRedirect() { + m_targetString += m_oss.str(); + m_stream.rdbuf( m_prevBuf ); + } + + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + RunContext( RunContext const& ); + void operator =( RunContext const& ); + + public: + + explicit RunContext( Ptr const& config, Ptr const& reporter ) + : m_runInfo( config->name() ), + m_context( getCurrentMutableContext() ), + m_activeTestCase( NULL ), + m_config( config ), + m_reporter( reporter ), + m_prevRunner( m_context.getRunner() ), + m_prevResultCapture( m_context.getResultCapture() ), + m_prevConfig( m_context.getConfig() ) + { + m_context.setRunner( this ); + m_context.setConfig( m_config ); + m_context.setResultCapture( this ); + m_reporter->testRunStarting( m_runInfo ); + } + + virtual ~RunContext() { + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); + m_context.setRunner( m_prevRunner ); + m_context.setConfig( NULL ); + m_context.setResultCapture( m_prevResultCapture ); + m_context.setConfig( m_prevConfig ); + } + + void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); + } + void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); + } + + Totals runTest( TestCase const& testCase ) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + TestCaseInfo testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting( testInfo ); + + m_activeTestCase = &testCase; + m_testCaseTracker = TestCaseTracker( testInfo.name ); + + do { + do { + runCurrentTest( redirectedCout, redirectedCerr ); + } + while( !m_testCaseTracker->isCompleted() && !aborting() ); + } + while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); + + Totals deltaTotals = m_totals.delta( prevTotals ); + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting() ) ); + + m_activeTestCase = NULL; + m_testCaseTracker.reset(); + + return deltaTotals; + } + + Ptr config() const { + return m_config; + } + + private: // IResultCapture + + virtual void assertionEnded( AssertionResult const& result ) { + if( result.getResultType() == ResultWas::Ok ) { + m_totals.assertions.passed++; + } + else if( !result.isOk() ) { + m_totals.assertions.failed++; + } + + if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) + m_messages.clear(); + + // Reset working state + m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + m_lastResult = result; + } + + virtual bool sectionStarted ( + SectionInfo const& sectionInfo, + Counts& assertions + ) + { + std::ostringstream oss; + oss << sectionInfo.name << "@" << sectionInfo.lineInfo; + + if( !m_testCaseTracker->enterSection( oss.str() ) ) + return false; + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting( sectionInfo ); + + assertions = m_totals.assertions; + + return true; + } + bool testForMissingAssertions( Counts& assertions ) { + if( assertions.total() != 0 || + !m_config->warnAboutMissingAssertions() || + m_testCaseTracker->currentSectionHasChildren() ) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) { + /*if( std::uncaught_exception() ) { // XXX Hack that makes Catch not run in loop in certain situations + m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) ); + return; + }*/ + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + m_testCaseTracker->leaveSection(); + + m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) ); + m_messages.clear(); + } + + virtual void pushScopedMessage( MessageInfo const& message ) { + m_messages.push_back( message ); + } + + virtual void popScopedMessage( MessageInfo const& message ) { + m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); + } + + virtual std::string getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : ""; + } + + virtual const AssertionResult* getLastResult() const { + return &m_lastResult; + } + + public: + // !TBD We need to do this another way! + bool aborting() const { + return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); + } + + private: + + void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + m_reporter->sectionStarting( testCaseSection ); + Counts prevAssertions = m_totals.assertions; + double duration = 0; + try { + m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); + TestCaseTracker::Guard guard( *m_testCaseTracker ); + + Timer timer; + timer.start(); + if( m_reporter->getPreferences().shouldRedirectStdOut ) { + StreamRedirect coutRedir( std::cout, redirectedCout ); + StreamRedirect cerrRedir( std::cerr, redirectedCerr ); + m_activeTestCase->invoke(); + } + else { + m_activeTestCase->invoke(); + } + duration = timer.getElapsedSeconds(); + } + catch( TestFailureException& ) { + // This just means the test was aborted due to failure + } + catch(...) { + ResultBuilder exResult( m_lastAssertionInfo.macroName.c_str(), + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression.c_str(), + m_lastAssertionInfo.resultDisposition ); + exResult.useActiveException(); + } + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it ) + sectionEnded( it->info, it->prevAssertions, it->durationInSeconds ); + m_unfinishedSections.clear(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( testCaseInfo.okToFail() ) { + std::swap( assertions.failedButOk, assertions.failed ); + m_totals.assertions.failed -= assertions.failedButOk; + m_totals.assertions.failedButOk += assertions.failedButOk; + } + + SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); + m_reporter->sectionEnded( testCaseSectionStats ); + } + + private: + struct UnfinishedSections { + UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds ) + : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo info; + Counts prevAssertions; + double durationInSeconds; + }; + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase; + Option m_testCaseTracker; + AssertionResult m_lastResult; + + Ptr m_config; + Totals m_totals; + Ptr m_reporter; + std::vector m_messages; + IRunner* m_prevRunner; + IResultCapture* m_prevResultCapture; + Ptr m_prevConfig; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + }; + + IResultCapture& getResultCapture() { + if( IResultCapture* capture = getCurrentContext().getResultCapture() ) + return *capture; + else + throw std::logic_error( "No result capture instance" ); + } + +} // end namespace Catch + +// #included from: internal/catch_version.h +#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED + +namespace Catch { + + // Versioning information + struct Version { + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _buildNumber, + char const* const _branchName ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + buildNumber( _buildNumber ), + branchName( _branchName ) + {} + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const buildNumber; + char const* const branchName; + + private: + void operator=( Version const& ); + }; + + extern Version libraryVersion; +} + +#include +#include +#include + +namespace Catch { + + class Runner { + + public: + Runner( Ptr const& config ) + : m_config( config ) + { + openStream(); + makeReporter(); + } + + Totals runTests() { + + RunContext context( m_config.get(), m_reporter ); + + Totals totals; + + context.testGroupStarting( "", 1, 1 ); // deprecated? + + TestSpec testSpec = m_config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector testCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases ); + + int testsRunForGroup = 0; + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) { + testsRunForGroup++; + if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) { + + if( context.aborting() ) + break; + + totals += context.runTest( *it ); + m_testsAlreadyRun.insert( *it ); + } + } + context.testGroupEnded( "", totals, 1, 1 ); + return totals; + } + + private: + void openStream() { + // Open output file, if specified + if( !m_config->getFilename().empty() ) { + m_ofs.open( m_config->getFilename().c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << m_config->getFilename() << "'"; + throw std::domain_error( oss.str() ); + } + m_config->setStreamBuf( m_ofs.rdbuf() ); + } + } + void makeReporter() { + std::string reporterName = m_config->getReporterName().empty() + ? "console" + : m_config->getReporterName(); + + m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() ); + if( !m_reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); + } + } + + private: + Ptr m_config; + std::ofstream m_ofs; + Ptr m_reporter; + std::set m_testsAlreadyRun; + }; + + class Session { + static bool alreadyInstantiated; + + public: + + struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; + + Session() + : m_cli( makeCommandLineParser() ) { + if( alreadyInstantiated ) { + std::string msg = "Only one instance of Catch::Session can ever be used"; + std::cerr << msg << std::endl; + throw std::logic_error( msg ); + } + alreadyInstantiated = true; + } + ~Session() { + Catch::cleanUp(); + } + + void showHelp( std::string const& processName ) { + std::cout << "\nCatch v" << libraryVersion.majorVersion << "." + << libraryVersion.minorVersion << " build " + << libraryVersion.buildNumber; + if( libraryVersion.branchName != std::string( "master" ) ) + std::cout << " (" << libraryVersion.branchName << " branch)"; + std::cout << "\n"; + + m_cli.usage( std::cout, processName ); + std::cout << "For more detail usage please see the project docs\n" << std::endl; + } + + int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + try { + m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); + m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); + if( m_configData.showHelp ) + showHelp( m_configData.processName ); + m_config.reset(); + } + catch( std::exception& ex ) { + { + Colour colourGuard( Colour::Red ); + std::cerr << "\nError(s) in input:\n" + << Text( ex.what(), TextAttributes().setIndent(2) ) + << "\n\n"; + } + m_cli.usage( std::cout, m_configData.processName ); + return (std::numeric_limits::max)(); + } + return 0; + } + + void useConfigData( ConfigData const& _configData ) { + m_configData = _configData; + m_config.reset(); + } + + int run( int argc, char* const argv[] ) { + + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + + int run() { + if( m_configData.showHelp ) + return 0; + + try + { + config(); // Force config to be constructed + Runner runner( m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + return static_cast( runner.runTests().assertions.failed ); + } + catch( std::exception& ex ) { + std::cerr << ex.what() << std::endl; + return (std::numeric_limits::max)(); + } + } + + Clara::CommandLine const& cli() const { + return m_cli; + } + std::vector const& unusedTokens() const { + return m_unusedTokens; + } + ConfigData& configData() { + return m_configData; + } + Config& config() { + if( !m_config ) + m_config = new Config( m_configData ); + return *m_config; + } + + private: + Clara::CommandLine m_cli; + std::vector m_unusedTokens; + ConfigData m_configData; + Ptr m_config; + }; + + bool Session::alreadyInstantiated = false; + +} // end namespace Catch + +// #included from: catch_registry_hub.hpp +#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED + +// #included from: catch_test_case_registry_impl.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + class TestRegistry : public ITestCaseRegistry { + public: + TestRegistry() : m_unnamedCount( 0 ) {} + virtual ~TestRegistry(); + + virtual void registerTest( TestCase const& testCase ) { + std::string name = testCase.getTestCaseInfo().name; + if( name == "" ) { + std::ostringstream oss; + oss << "Anonymous test case " << ++m_unnamedCount; + return registerTest( testCase.withName( oss.str() ) ); + } + + if( m_functions.find( testCase ) == m_functions.end() ) { + m_functions.insert( testCase ); + m_functionsInOrder.push_back( testCase ); + if( !testCase.isHidden() ) + m_nonHiddenFunctions.push_back( testCase ); + } + else { + TestCase const& prev = *m_functions.find( testCase ); + { + Colour colourGuard( Colour::Red ); + std::cerr << "error: TEST_CASE( \"" << name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl; + } + exit(1); + } + } + + virtual std::vector const& getAllTests() const { + return m_functionsInOrder; + } + + virtual std::vector const& getAllNonHiddenTests() const { + return m_nonHiddenFunctions; + } + + virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases ) const { + for( std::vector::const_iterator it = m_functionsInOrder.begin(), + itEnd = m_functionsInOrder.end(); + it != itEnd; + ++it ) { + if( testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ) ) + matchingTestCases.push_back( *it ); + } + } + + private: + + std::set m_functions; + std::vector m_functionsInOrder; + std::vector m_nonHiddenFunctions; + size_t m_unnamedCount; + }; + + /////////////////////////////////////////////////////////////////////////// + + class FreeFunctionTestCase : public SharedImpl { + public: + + FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} + + virtual void invoke() const { + m_fun(); + } + + private: + virtual ~FreeFunctionTestCase(); + + TestFunction m_fun; + }; + + inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { + std::string className = classOrQualifiedMethodName; + if( startsWith( className, "&" ) ) + { + std::size_t lastColons = className.rfind( "::" ); + std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); + if( penultimateColons == std::string::npos ) + penultimateColons = 1; + className = className.substr( penultimateColons, lastColons-penultimateColons ); + } + return className; + } + + /////////////////////////////////////////////////////////////////////////// + + AutoReg::AutoReg( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + } + + AutoReg::~AutoReg() {} + + void AutoReg::registerTestCase( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + getMutableRegistryHub().registerTest + ( makeTestCase( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + +} // end namespace Catch + +// #included from: catch_reporter_registry.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED + +#include + +namespace Catch { + + class ReporterRegistry : public IReporterRegistry { + + public: + + virtual ~ReporterRegistry() { + deleteAllValues( m_factories ); + } + + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const { + FactoryMap::const_iterator it = m_factories.find( name ); + if( it == m_factories.end() ) + return NULL; + return it->second->create( ReporterConfig( config ) ); + } + + void registerReporter( std::string const& name, IReporterFactory* factory ) { + m_factories.insert( std::make_pair( name, factory ) ); + } + + FactoryMap const& getFactories() const { + return m_factories; + } + + private: + FactoryMap m_factories; + }; +} + +// #included from: catch_exception_translator_registry.hpp +#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED + +#ifdef __OBJC__ +#import "Foundation/Foundation.h" +#endif + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry() { + deleteAll( m_translators ); + } + + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( translator ); + } + + virtual std::string translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + throw; + } + @catch (NSException *exception) { + return toString( [exception description] ); + } +#else + throw; +#endif + } + catch( TestFailureException& ) { + throw; + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return tryTranslators( m_translators.begin() ); + } + } + + std::string tryTranslators( std::vector::const_iterator it ) const { + if( it == m_translators.end() ) + return "Unknown exception"; + + try { + return (*it)->translate(); + } + catch(...) { + return tryTranslators( it+1 ); + } + } + + private: + std::vector m_translators; + }; +} + +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub { + + RegistryHub( RegistryHub const& ); + void operator=( RegistryHub const& ); + + public: // IRegistryHub + RegistryHub() { + } + virtual IReporterRegistry const& getReporterRegistry() const { + return m_reporterRegistry; + } + virtual ITestCaseRegistry const& getTestCaseRegistry() const { + return m_testCaseRegistry; + } + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() { + return m_exceptionTranslatorRegistry; + } + + public: // IMutableRegistryHub + virtual void registerReporter( std::string const& name, IReporterFactory* factory ) { + m_reporterRegistry.registerReporter( name, factory ); + } + virtual void registerTest( TestCase const& testInfo ) { + m_testCaseRegistry.registerTest( testInfo ); + } + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + }; + + // Single, global, instance + inline RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = NULL; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = NULL; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + +} // end namespace Catch + +// #included from: catch_notimplemented_exception.hpp +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED + +#include + +namespace Catch { + + NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) + : m_lineInfo( lineInfo ) { + std::ostringstream oss; + oss << lineInfo << ": function "; + oss << "not implemented"; + m_what = oss.str(); + } + + const char* NotImplementedException::what() const CATCH_NOEXCEPT { + return m_what.c_str(); + } + +} // end namespace Catch + +// #included from: catch_context_impl.hpp +#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED + +// #included from: catch_stream.hpp +#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED + +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED + +#include + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() CATCH_NOEXCEPT; + }; +} + +#include +#include + +namespace Catch { + + template + class StreamBufImpl : public StreamBufBase { + char data[bufferSize]; + WriterF m_writer; + + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); + } + + ~StreamBufImpl() CATCH_NOEXCEPT { + sync(); + } + + private: + int overflow( int c ) { + sync(); + + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast( c ) ) ); + else + sputc( static_cast( c ) ); + } + return 0; + } + + int sync() { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + Stream::Stream() + : streamBuf( NULL ), isOwned( false ) + {} + + Stream::Stream( std::streambuf* _streamBuf, bool _isOwned ) + : streamBuf( _streamBuf ), isOwned( _isOwned ) + {} + + void Stream::release() { + if( isOwned ) { + delete streamBuf; + streamBuf = NULL; + isOwned = false; + } + } +} + +namespace Catch { + + class Context : public IMutableContext { + + Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {} + Context( Context const& ); + void operator=( Context const& ); + + public: // IContext + virtual IResultCapture* getResultCapture() { + return m_resultCapture; + } + virtual IRunner* getRunner() { + return m_runner; + } + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { + return getGeneratorsForCurrentTest() + .getGeneratorInfo( fileInfo, totalSize ) + .getCurrentIndex(); + } + virtual bool advanceGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + return generators && generators->moveNext(); + } + + virtual Ptr getConfig() const { + return m_config; + } + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ) { + m_resultCapture = resultCapture; + } + virtual void setRunner( IRunner* runner ) { + m_runner = runner; + } + virtual void setConfig( Ptr const& config ) { + m_config = config; + } + + friend IMutableContext& getCurrentMutableContext(); + + private: + IGeneratorsForTest* findGeneratorsForCurrentTest() { + std::string testName = getResultCapture()->getCurrentTestName(); + + std::map::const_iterator it = + m_generatorsByTestName.find( testName ); + return it != m_generatorsByTestName.end() + ? it->second + : NULL; + } + + IGeneratorsForTest& getGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + if( !generators ) { + std::string testName = getResultCapture()->getCurrentTestName(); + generators = createGeneratorsForTest(); + m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); + } + return *generators; + } + + private: + Ptr m_config; + IRunner* m_runner; + IResultCapture* m_resultCapture; + std::map m_generatorsByTestName; + }; + + namespace { + Context* currentContext = NULL; + } + IMutableContext& getCurrentMutableContext() { + if( !currentContext ) + currentContext = new Context(); + return *currentContext; + } + IContext& getCurrentContext() { + return getCurrentMutableContext(); + } + + Stream createStream( std::string const& streamName ) { + if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false ); + if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false ); + if( streamName == "debug" ) return Stream( new StreamBufImpl, true ); + + throw std::domain_error( "Unknown stream: " + streamName ); + } + + void cleanUpContext() { + delete currentContext; + currentContext = NULL; + } +} + +// #included from: catch_console_colour_impl.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED + +namespace Catch { namespace Detail { + struct IColourImpl { + virtual ~IColourImpl() {} + virtual void use( Colour::Code _colourCode ) = 0; + }; +}} + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +namespace Catch { +namespace { + + class Win32ColourImpl : public Detail::IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalAttributes = csbiInfo.wAttributes; + } + + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalAttributes ); + case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::Red: return setTextAttribute( FOREGROUND_RED ); + case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); + case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); + case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); + case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::Grey: return setTextAttribute( 0 ); + + case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); + case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); + case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); + case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + + private: + void setTextAttribute( WORD _textAttribute ) { + SetConsoleTextAttribute( stdoutHandle, _textAttribute ); + } + HANDLE stdoutHandle; + WORD originalAttributes; + }; + + inline bool shouldUseColourForPlatform() { + return true; + } + + static Detail::IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + return &s_instance; + } + +} // end anon namespace +} // end namespace Catch + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +#include + +namespace Catch { +namespace { + + // use POSIX/ ANSI console terminal codes + // Thanks to Adam Strzelecki for original contribution + // (http://github.com/nanoant) + // https://github.com/philsquared/Catch/pull/131 + class PosixColourImpl : public Detail::IColourImpl { + public: + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: + case Colour::White: return setColour( "[0m" ); + case Colour::Red: return setColour( "[0;31m" ); + case Colour::Green: return setColour( "[0;32m" ); + case Colour::Blue: return setColour( "[0:34m" ); + case Colour::Cyan: return setColour( "[0;36m" ); + case Colour::Yellow: return setColour( "[0;33m" ); + case Colour::Grey: return setColour( "[1;30m" ); + + case Colour::LightGrey: return setColour( "[0;37m" ); + case Colour::BrightRed: return setColour( "[1;31m" ); + case Colour::BrightGreen: return setColour( "[1;32m" ); + case Colour::BrightWhite: return setColour( "[1;37m" ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + private: + void setColour( const char* _escapeCode ) { + std::cout << '\033' << _escapeCode; + } + }; + + inline bool shouldUseColourForPlatform() { + return isatty(STDOUT_FILENO); + } + + static Detail::IColourImpl* platformColourInstance() { + static PosixColourImpl s_instance; + return &s_instance; + } + +} // end anon namespace +} // end namespace Catch + +#endif // not Windows + +namespace Catch { + + namespace { + struct NoColourImpl : Detail::IColourImpl { + void use( Colour::Code ) {} + + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + static bool shouldUseColour() { + return shouldUseColourForPlatform() && !isDebuggerActive(); + } + } + + Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } + Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } + Colour::~Colour(){ if( !m_moved ) use( None ); } + void Colour::use( Code _colourCode ) { + impl()->use( _colourCode ); + } + + Detail::IColourImpl* Colour::impl() { + return shouldUseColour() + ? platformColourInstance() + : NoColourImpl::instance(); + } + +} // end namespace Catch + +// #included from: catch_generators_impl.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct GeneratorInfo : IGeneratorInfo { + + GeneratorInfo( std::size_t size ) + : m_size( size ), + m_currentIndex( 0 ) + {} + + bool moveNext() { + if( ++m_currentIndex == m_size ) { + m_currentIndex = 0; + return false; + } + return true; + } + + std::size_t getCurrentIndex() const { + return m_currentIndex; + } + + std::size_t m_size; + std::size_t m_currentIndex; + }; + + /////////////////////////////////////////////////////////////////////////// + + class GeneratorsForTest : public IGeneratorsForTest { + + public: + ~GeneratorsForTest() { + deleteAll( m_generatorsInOrder ); + } + + IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { + std::map::const_iterator it = m_generatorsByName.find( fileInfo ); + if( it == m_generatorsByName.end() ) { + IGeneratorInfo* info = new GeneratorInfo( size ); + m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); + m_generatorsInOrder.push_back( info ); + return *info; + } + return *it->second; + } + + bool moveNext() { + std::vector::const_iterator it = m_generatorsInOrder.begin(); + std::vector::const_iterator itEnd = m_generatorsInOrder.end(); + for(; it != itEnd; ++it ) { + if( (*it)->moveNext() ) + return true; + } + return false; + } + + private: + std::map m_generatorsByName; + std::vector m_generatorsInOrder; + }; + + IGeneratorsForTest* createGeneratorsForTest() + { + return new GeneratorsForTest(); + } + +} // end namespace Catch + +// #included from: catch_assertionresult.hpp +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED + +namespace Catch { + + AssertionInfo::AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + capturedExpression( _capturedExpression ), + resultDisposition( _resultDisposition ) + {} + + AssertionResult::AssertionResult() {} + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + AssertionResult::~AssertionResult() {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return !m_info.capturedExpression.empty(); + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if( isFalseTest( m_info.resultDisposition ) ) + return "!" + m_info.capturedExpression; + else + return m_info.capturedExpression; + } + std::string AssertionResult::getExpressionInMacro() const { + if( m_info.macroName.empty() ) + return m_info.capturedExpression; + else + return m_info.macroName + "( " + m_info.capturedExpression + " )"; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + return m_resultData.reconstructedExpression; + } + + std::string AssertionResult::getMessage() const { + return m_resultData.message; + } + SourceLineInfo AssertionResult::getSourceInfo() const { + return m_info.lineInfo; + } + + std::string AssertionResult::getTestMacroName() const { + return m_info.macroName; + } + +} // end namespace Catch + +// #included from: catch_test_case_info.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED + +namespace Catch { + + inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { + if( tag == "." || + tag == "hide" || + tag == "!hide" ) + return TestCaseInfo::IsHidden; + else if( tag == "!throws" ) + return TestCaseInfo::Throws; + else if( tag == "!shouldfail" ) + return TestCaseInfo::ShouldFail; + else if( tag == "!mayfail" ) + return TestCaseInfo::MayFail; + else + return TestCaseInfo::None; + } + inline bool isReservedTag( std::string const& tag ) { + return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] ); + } + inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + if( isReservedTag( tag ) ) { + { + Colour colourGuard( Colour::Red ); + std::cerr + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n"; + } + { + Colour colourGuard( Colour::FileName ); + std::cerr << _lineInfo << std::endl; + } + exit(1); + } + } + + TestCase makeTestCase( ITestCase* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden( startsWith( _name, "./" ) ); // Legacy support + + // Parse out tags + std::set tags; + std::string desc, tag; + bool inTag = false; + for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { + char c = _descOrTags[i]; + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; + } + else { + if( c == ']' ) { + enforceNotReservedTag( tag, _lineInfo ); + + inTag = false; + if( tag == "hide" || tag == "." ) + isHidden = true; + else + tags.insert( tag ); + tag.clear(); + } + else + tag += c; + } + } + if( isHidden ) { + tags.insert( "hide" ); + tags.insert( "." ); + } + + TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); + return TestCase( _testCase, info ); + } + + TestCaseInfo::TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ) + : name( _name ), + className( _className ), + description( _description ), + tags( _tags ), + lineInfo( _lineInfo ), + properties( None ) + { + std::ostringstream oss; + for( std::set::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + std::string lcaseTag = toLower( *it ); + properties = static_cast( properties | parseSpecialTag( lcaseTag ) ); + lcaseTags.insert( lcaseTag ); + } + tagsAsString = oss.str(); + } + + TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) + : name( other.name ), + className( other.className ), + description( other.description ), + tags( other.tags ), + lcaseTags( other.lcaseTags ), + tagsAsString( other.tagsAsString ), + lineInfo( other.lineInfo ), + properties( other.properties ) + {} + + bool TestCaseInfo::isHidden() const { + return ( properties & IsHidden ) != 0; + } + bool TestCaseInfo::throws() const { + return ( properties & Throws ) != 0; + } + bool TestCaseInfo::okToFail() const { + return ( properties & (ShouldFail | MayFail ) ) != 0; + } + bool TestCaseInfo::expectedToFail() const { + return ( properties & (ShouldFail ) ) != 0; + } + + TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + + TestCase::TestCase( TestCase const& other ) + : TestCaseInfo( other ), + test( other.test ) + {} + + TestCase TestCase::withName( std::string const& _newName ) const { + TestCase other( *this ); + other.name = _newName; + return other; + } + + void TestCase::swap( TestCase& other ) { + test.swap( other.test ); + name.swap( other.name ); + className.swap( other.className ); + description.swap( other.description ); + tags.swap( other.tags ); + lcaseTags.swap( other.lcaseTags ); + tagsAsString.swap( other.tagsAsString ); + std::swap( TestCaseInfo::properties, static_cast( other ).properties ); + std::swap( lineInfo, other.lineInfo ); + } + + void TestCase::invoke() const { + test->invoke(); + } + + bool TestCase::operator == ( TestCase const& other ) const { + return test.get() == other.test.get() && + name == other.name && + className == other.className; + } + + bool TestCase::operator < ( TestCase const& other ) const { + return name < other.name; + } + TestCase& TestCase::operator = ( TestCase const& other ) { + TestCase temp( other ); + swap( temp ); + return *this; + } + + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } + +} // end namespace Catch + +// #included from: catch_version.hpp +#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED + +namespace Catch { + + // These numbers are maintained by a script + Version libraryVersion( 1, 0, 52, "master" ); +} + +// #included from: catch_message.hpp +#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + ScopedMessage::ScopedMessage( ScopedMessage const& other ) + : m_info( other.m_info ) + {} + + ScopedMessage::~ScopedMessage() { + getResultCapture().popScopedMessage( m_info ); + } + +} // end namespace Catch + +// #included from: catch_legacy_reporter_adapter.hpp +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED + +// #included from: catch_legacy_reporter_adapter.h +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED + +namespace Catch +{ + // Deprecated + struct IReporter : IShared { + virtual ~IReporter(); + + virtual bool shouldRedirectStdout() const = 0; + + virtual void StartTesting() = 0; + virtual void EndTesting( Totals const& totals ) = 0; + virtual void StartGroup( std::string const& groupName ) = 0; + virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; + virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; + virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; + virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; + virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; + virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; + virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; + virtual void Aborted() = 0; + virtual void Result( AssertionResult const& result ) = 0; + }; + + class LegacyReporterAdapter : public SharedImpl + { + public: + LegacyReporterAdapter( Ptr const& legacyReporter ); + virtual ~LegacyReporterAdapter(); + + virtual ReporterPreferences getPreferences() const; + virtual void noMatchingTestCases( std::string const& ); + virtual void testRunStarting( TestRunInfo const& ); + virtual void testGroupStarting( GroupInfo const& groupInfo ); + virtual void testCaseStarting( TestCaseInfo const& testInfo ); + virtual void sectionStarting( SectionInfo const& sectionInfo ); + virtual void assertionStarting( AssertionInfo const& ); + virtual bool assertionEnded( AssertionStats const& assertionStats ); + virtual void sectionEnded( SectionStats const& sectionStats ); + virtual void testCaseEnded( TestCaseStats const& testCaseStats ); + virtual void testGroupEnded( TestGroupStats const& testGroupStats ); + virtual void testRunEnded( TestRunStats const& testRunStats ); + + private: + Ptr m_legacyReporter; + }; +} + +namespace Catch +{ + LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) + : m_legacyReporter( legacyReporter ) + {} + LegacyReporterAdapter::~LegacyReporterAdapter() {} + + ReporterPreferences LegacyReporterAdapter::getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); + return prefs; + } + + void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} + void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { + m_legacyReporter->StartTesting(); + } + void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { + m_legacyReporter->StartGroup( groupInfo.name ); + } + void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { + m_legacyReporter->StartTestCase( testInfo ); + } + void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { + m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); + } + void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { + // Not on legacy interface + } + + bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); + rb << it->message; + rb.setResultType( ResultWas::Info ); + AssertionResult result = rb.build(); + m_legacyReporter->Result( result ); + } + } + } + m_legacyReporter->Result( assertionStats.assertionResult ); + return true; + } + void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { + if( sectionStats.missingAssertions ) + m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); + m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); + } + void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { + m_legacyReporter->EndTestCase + ( testCaseStats.testInfo, + testCaseStats.totals, + testCaseStats.stdOut, + testCaseStats.stdErr ); + } + void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { + if( testGroupStats.aborting ) + m_legacyReporter->Aborted(); + m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); + } + void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { + m_legacyReporter->EndTesting( testRunStats.totals ); + } +} + +// #included from: catch_timer.hpp + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-long-long" +#endif + +#ifdef CATCH_PLATFORM_WINDOWS +#include +#else +#include +#endif + +namespace Catch { + + namespace { +#ifdef CATCH_PLATFORM_WINDOWS + uint64_t getCurrentTicks() { + static uint64_t hz=0, hzo=0; + if (!hz) { + QueryPerformanceFrequency((LARGE_INTEGER*)&hz); + QueryPerformanceCounter((LARGE_INTEGER*)&hzo); + } + uint64_t t; + QueryPerformanceCounter((LARGE_INTEGER*)&t); + return ((t-hzo)*1000000)/hz; + } +#else + uint64_t getCurrentTicks() { + timeval t; + gettimeofday(&t,NULL); + return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); + } +#endif + } + + void Timer::start() { + m_ticks = getCurrentTicks(); + } + unsigned int Timer::getElapsedNanoseconds() const { + return static_cast(getCurrentTicks() - m_ticks); + } + unsigned int Timer::getElapsedMilliseconds() const { + return static_cast((getCurrentTicks() - m_ticks)/1000); + } + double Timer::getElapsedSeconds() const { + return (getCurrentTicks() - m_ticks)/1000000.0; + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +// #included from: catch_common.hpp +#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), ::tolower ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << " " << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << "s"; + return os; + } + + SourceLineInfo::SourceLineInfo() : line( 0 ){} + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) + : file( _file ), + line( _line ) + {} + SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) + : file( other.file ), + line( other.line ) + {} + bool SourceLineInfo::empty() const { + return file.empty(); + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { + return line == other.line && file == other.file; + } + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { +#ifndef __GNUG__ + os << info.file << "(" << info.line << ")"; +#else + os << info.file << ":" << info.line; +#endif + return os; + } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { + std::ostringstream oss; + oss << locationInfo << ": Internal Catch error: '" << message << "'"; + if( alwaysTrue() ) + throw std::logic_error( oss.str() ); + } +} + +// #included from: catch_section.hpp +#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED + +namespace Catch { + + SectionInfo::SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + Section::Section( SectionInfo const& info ) + : m_info( info ), + m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) + { + m_timer.start(); + } + + Section::~Section() { + if( m_sectionIncluded ) + getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); + } + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } + +} // end namespace Catch + +// #included from: catch_debugger.hpp +#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED + +#include + +#ifdef CATCH_PLATFORM_MAC + + #include + #include + #include + #include + #include + + namespace Catch{ + + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive(){ + + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) { + std::cerr << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; + return false; + } + + // We're being debugged if the P_TRACED flag is set. + + return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + } + } // namespace Catch + +#elif defined(_MSC_VER) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#else + namespace Catch { + inline bool isDebuggerActive() { return false; } + } +#endif // Platform + +#ifdef CATCH_PLATFORM_WINDOWS + extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + std::cout << text; + } + } +#endif // Platform + +// #included from: catch_tostring.hpp +#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED + +namespace Catch { + +namespace Detail { + + namespace { + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + } + + std::string rawMemoryToString( const void *object, std::size_t size ) + { + // Reverse order for little endian architectures + int i = 0, end = static_cast( size ), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + + unsigned char const *bytes = static_cast(object); + std::ostringstream os; + os << "0x" << std::setfill('0') << std::hex; + for( ; i != end; i += inc ) + os << std::setw(2) << static_cast(bytes[i]); + return os.str(); + } +} + +std::string toString( std::string const& value ) { + std::string s = value; + if( getCurrentContext().getConfig()->showInvisibles() ) { + for(size_t i = 0; i < s.size(); ++i ) { + std::string subs; + switch( s[i] ) { + case '\n': subs = "\\n"; break; + case '\t': subs = "\\t"; break; + default: break; + } + if( !subs.empty() ) { + s = s.substr( 0, i ) + subs + s.substr( i+1 ); + ++i; + } + } + } + return "\"" + s + "\""; +} +std::string toString( std::wstring const& value ) { + + std::string s; + s.reserve( value.size() ); + for(size_t i = 0; i < value.size(); ++i ) + s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; + return toString( s ); +} + +std::string toString( const char* const value ) { + return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); +} + +std::string toString( char* const value ) { + return Catch::toString( static_cast( value ) ); +} + +std::string toString( int value ) { + std::ostringstream oss; + oss << value; + return oss.str(); +} + +std::string toString( unsigned long value ) { + std::ostringstream oss; + if( value > 8192 ) + oss << "0x" << std::hex << value; + else + oss << value; + return oss.str(); +} + +std::string toString( unsigned int value ) { + return toString( static_cast( value ) ); +} + +template +std::string fpToString( T value, int precision ) { + std::ostringstream oss; + oss << std::setprecision( precision ) + << std::fixed + << value; + std::string d = oss.str(); + std::size_t i = d.find_last_not_of( '0' ); + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) + i++; + d = d.substr( 0, i+1 ); + } + return d; +} + +std::string toString( const double value ) { + return fpToString( value, 10 ); +} +std::string toString( const float value ) { + return fpToString( value, 5 ) + "f"; +} + +std::string toString( bool value ) { + return value ? "true" : "false"; +} + +std::string toString( char value ) { + return value < ' ' + ? toString( static_cast( value ) ) + : Detail::makeString( value ); +} + +std::string toString( signed char value ) { + return toString( static_cast( value ) ); +} + +std::string toString( unsigned char value ) { + return toString( static_cast( value ) ); +} + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ) { + return "nullptr"; +} +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSObject* const& nsObject ) { + return toString( [nsObject description] ); + } +#endif + +} // end namespace Catch + +// #included from: catch_result_builder.hpp +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED + +namespace Catch { + + ResultBuilder::ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition ) + : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition ), + m_shouldDebugBreak( false ), + m_shouldThrow( false ) + {} + + ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { + m_data.resultType = result; + return *this; + } + ResultBuilder& ResultBuilder::setResultType( bool result ) { + m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; + return *this; + } + ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) { + m_exprComponents.lhs = lhs; + return *this; + } + ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) { + m_exprComponents.rhs = rhs; + return *this; + } + ResultBuilder& ResultBuilder::setOp( std::string const& op ) { + m_exprComponents.op = op; + return *this; + } + + void ResultBuilder::endExpression() { + m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition ); + captureExpression(); + } + + void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { + m_assertionInfo.resultDisposition = resultDisposition; + m_stream.oss << Catch::translateActiveException(); + captureResult( ResultWas::ThrewException ); + } + + void ResultBuilder::captureResult( ResultWas::OfType resultType ) { + setResultType( resultType ); + captureExpression(); + } + + void ResultBuilder::captureExpression() { + AssertionResult result = build(); + getResultCapture().assertionEnded( result ); + + if( !result.isOk() ) { + if( getCurrentContext().getConfig()->shouldDebugBreak() ) + m_shouldDebugBreak = true; + if( getCurrentContext().getRunner()->aborting() || m_assertionInfo.resultDisposition == ResultDisposition::Normal ) + m_shouldThrow = true; + } + } + void ResultBuilder::react() { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } + bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } + + AssertionResult ResultBuilder::build() const + { + assert( m_data.resultType != ResultWas::Unknown ); + + AssertionResultData data = m_data; + + // Flip bool results if testFalse is set + if( m_exprComponents.testFalse ) { + if( data.resultType == ResultWas::Ok ) + data.resultType = ResultWas::ExpressionFailed; + else if( data.resultType == ResultWas::ExpressionFailed ) + data.resultType = ResultWas::Ok; + } + + data.message = m_stream.oss.str(); + data.reconstructedExpression = reconstructExpression(); + if( m_exprComponents.testFalse ) { + if( m_exprComponents.op == "" ) + data.reconstructedExpression = "!" + data.reconstructedExpression; + else + data.reconstructedExpression = "!(" + data.reconstructedExpression + ")"; + } + return AssertionResult( m_assertionInfo, data ); + } + std::string ResultBuilder::reconstructExpression() const { + if( m_exprComponents.op == "" ) + return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs; + else if( m_exprComponents.op == "matches" ) + return m_exprComponents.lhs + " " + m_exprComponents.rhs; + else if( m_exprComponents.op != "!" ) { + if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && + m_exprComponents.lhs.find("\n") == std::string::npos && + m_exprComponents.rhs.find("\n") == std::string::npos ) + return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; + else + return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; + } + else + return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}"; + } + +} // end namespace Catch + +// #included from: catch_tag_alias_registry.hpp +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED + +// #included from: catch_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED + +#include + +namespace Catch { + + class TagAliasRegistry : public ITagAliasRegistry { + public: + virtual ~TagAliasRegistry(); + virtual Option find( std::string const& alias ) const; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; + void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + static TagAliasRegistry& get(); + + private: + std::map m_registry; + }; + +} // end namespace Catch + +#include +#include + +namespace Catch { + + TagAliasRegistry::~TagAliasRegistry() {} + + Option TagAliasRegistry::find( std::string const& alias ) const { + std::map::const_iterator it = m_registry.find( alias ); + if( it != m_registry.end() ) + return it->second; + else + return Option(); + } + + std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { + std::string expandedTestSpec = unexpandedTestSpec; + for( std::map::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); + it != itEnd; + ++it ) { + std::size_t pos = expandedTestSpec.find( it->first ); + if( pos != std::string::npos ) { + expandedTestSpec = expandedTestSpec.substr( 0, pos ) + + it->second.tag + + expandedTestSpec.substr( pos + it->first.size() ); + } + } + return expandedTestSpec; + } + + void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + + if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" already registered.\n" + << "\tFirst seen at " << find(alias)->lineInfo << "\n" + << "\tRedefined at " << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + } + + TagAliasRegistry& TagAliasRegistry::get() { + static TagAliasRegistry instance; + return instance; + + } + + ITagAliasRegistry::~ITagAliasRegistry() {} + ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); } + + RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + try { + TagAliasRegistry::get().add( alias, tag, lineInfo ); + } + catch( std::exception& ex ) { + Colour colourGuard( Colour::Red ); + std::cerr << ex.what() << std::endl; + exit(1); + } + } + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_xml.hpp +#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED + +// #included from: catch_reporter_bases.hpp +#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED + +namespace Catch { + + struct StreamingReporterBase : SharedImpl { + + StreamingReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + {} + + virtual ~StreamingReporterBase(); + + virtual void noMatchingTestCases( std::string const& ) {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) { + currentTestRunInfo = _testRunInfo; + } + virtual void testGroupStarting( GroupInfo const& _groupInfo ) { + currentGroupInfo = _groupInfo; + } + + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) { + currentTestCaseInfo = _testInfo; + } + virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + m_sectionStack.push_back( _sectionInfo ); + } + + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) { + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) { + currentTestCaseInfo.reset(); + assert( m_sectionStack.empty() ); + } + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) { + currentGroupInfo.reset(); + } + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + Ptr m_config; + std::ostream& stream; + + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; + + std::vector m_sectionStack; + }; + + struct CumulativeReporterBase : SharedImpl { + template + struct Node : SharedImpl<> { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} + + typedef std::vector > ChildNodes; + T value; + ChildNodes children; + }; + struct SectionNode : SharedImpl<> { + explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} + virtual ~SectionNode(); + + bool operator == ( SectionNode const& other ) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + bool operator == ( Ptr const& other ) const { + return operator==( *other ); + } + + SectionStats stats; + typedef std::vector > ChildSections; + typedef std::vector Assertions; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + + struct BySectionInfo { + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} + bool operator() ( Ptr const& node ) const { + return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + } + private: + void operator=( BySectionInfo const& ); + SectionInfo const& m_other; + }; + + typedef Node TestCaseNode; + typedef Node TestGroupNode; + typedef Node TestRunNode; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + {} + ~CumulativeReporterBase(); + + virtual void testRunStarting( TestRunInfo const& ) {} + virtual void testGroupStarting( GroupInfo const& ) {} + + virtual void testCaseStarting( TestCaseInfo const& ) {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + Ptr node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = new SectionNode( incompleteStats ); + node = m_rootSection; + } + else { + SectionNode& parentNode = *m_sectionStack.back(); + SectionNode::ChildSections::const_iterator it = + std::find_if( parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo( sectionInfo ) ); + if( it == parentNode.childSections.end() ) { + node = new SectionNode( incompleteStats ); + parentNode.childSections.push_back( node ); + } + else + node = *it; + } + m_sectionStack.push_back( node ); + m_deepestSection = node; + } + + virtual void assertionStarting( AssertionInfo const& ) {} + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back( assertionStats ); + return true; + } + virtual void sectionEnded( SectionStats const& sectionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + Ptr node = new TestCaseNode( testCaseStats ); + assert( m_sectionStack.size() == 0 ); + node->children.push_back( m_rootSection ); + m_testCases.push_back( node ); + m_rootSection.reset(); + + assert( m_deepestSection ); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + Ptr node = new TestGroupNode( testGroupStats ); + node->children.swap( m_testCases ); + m_testGroups.push_back( node ); + } + virtual void testRunEnded( TestRunStats const& testRunStats ) { + Ptr node = new TestRunNode( testRunStats ); + node->children.swap( m_testGroups ); + m_testRuns.push_back( node ); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + Ptr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector > > m_sections; + std::vector > m_testCases; + std::vector > m_testGroups; + + std::vector > m_testRuns; + + Ptr m_rootSection; + Ptr m_deepestSection; + std::vector > m_sectionStack; + + }; + +} // end namespace Catch + +// #included from: ../internal/catch_reporter_registrars.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED + +namespace Catch { + + template + class LegacyReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new LegacyReporterAdapter( new T( config ) ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + LegacyReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + class ReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + + // *** Please Note ***: + // - If you end up here looking at a compiler error because it's trying to register + // your custom reporter class be aware that the native reporter interface has changed + // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via + // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. + // However please consider updating to the new interface as the old one is now + // deprecated and will probably be removed quite soon! + // Please contact me via github if you have any questions at all about this. + // In fact, ideally, please contact me anyway to let me know you've hit this - as I have + // no idea who is actually using custom reporters at all (possibly no-one!). + // The new interface is designed to minimise exposure to interface changes in the future. + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; +} + +#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ + namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +// #included from: ../internal/catch_xmlwriter.hpp +#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = NULL; + } + + ~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + ScopedElement& writeText( std::string const& text, bool indent = true ) { + m_writer->writeText( text, indent ); + return *this; + } + + template + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer; + }; + + XmlWriter() + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &std::cout ) + {} + + XmlWriter( std::ostream& os ) + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &os ) + {} + + ~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + +//# ifndef CATCH_CPP11_OR_GREATER +// XmlWriter& operator = ( XmlWriter const& other ) { +// XmlWriter temp( other ); +// swap( temp ); +// return *this; +// } +//# else +// XmlWriter( XmlWriter const& ) = default; +// XmlWriter( XmlWriter && ) = default; +// XmlWriter& operator = ( XmlWriter const& ) = default; +// XmlWriter& operator = ( XmlWriter && ) = default; +//# endif +// +// void swap( XmlWriter& other ) { +// std::swap( m_tagIsOpen, other.m_tagIsOpen ); +// std::swap( m_needsNewline, other.m_needsNewline ); +// std::swap( m_tags, other.m_tags ); +// std::swap( m_indent, other.m_indent ); +// std::swap( m_os, other.m_os ); +// } + + XmlWriter& startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + stream() << m_indent << "<" << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + ScopedElement scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + stream() << "/>\n"; + m_tagIsOpen = false; + } + else { + stream() << m_indent << "\n"; + } + m_tags.pop_back(); + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) { + stream() << " " << name << "=\""; + writeEncodedText( attribute ); + stream() << "\""; + } + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, bool attribute ) { + stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; + return *this; + } + + template + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + if( !name.empty() ) + stream() << " " << name << "=\"" << attribute << "\""; + return *this; + } + + XmlWriter& writeText( std::string const& text, bool indent = true ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + stream() << m_indent; + writeEncodedText( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& writeComment( std::string const& text ) { + ensureTagClosed(); + stream() << m_indent << ""; + m_needsNewline = true; + return *this; + } + + XmlWriter& writeBlankLine() { + ensureTagClosed(); + stream() << "\n"; + return *this; + } + + void setStream( std::ostream& os ) { + m_os = &os; + } + + private: + XmlWriter( XmlWriter const& ); + void operator=( XmlWriter const& ); + + std::ostream& stream() { + return *m_os; + } + + void ensureTagClosed() { + if( m_tagIsOpen ) { + stream() << ">\n"; + m_tagIsOpen = false; + } + } + + void newlineIfNecessary() { + if( m_needsNewline ) { + stream() << "\n"; + m_needsNewline = false; + } + } + + void writeEncodedText( std::string const& text ) { + static const char* charsToEncode = "<&\""; + std::string mtext = text; + std::string::size_type pos = mtext.find_first_of( charsToEncode ); + while( pos != std::string::npos ) { + stream() << mtext.substr( 0, pos ); + + switch( mtext[pos] ) { + case '<': + stream() << "<"; + break; + case '&': + stream() << "&"; + break; + case '\"': + stream() << """; + break; + } + mtext = mtext.substr( pos+1 ); + pos = mtext.find_first_of( charsToEncode ); + } + stream() << mtext; + } + + bool m_tagIsOpen; + bool m_needsNewline; + std::vector m_tags; + std::string m_indent; + std::ostream* m_os; + }; + +} +namespace Catch { + class XmlReporter : public SharedImpl { + public: + XmlReporter( ReporterConfig const& config ) : m_config( config ), m_sectionDepth( 0 ) {} + + static std::string getDescription() { + return "Reports test results as an XML document"; + } + virtual ~XmlReporter(); + + private: // IReporter + + virtual bool shouldRedirectStdout() const { + return true; + } + + virtual void StartTesting() { + m_xml.setStream( m_config.stream() ); + m_xml.startElement( "Catch" ); + if( !m_config.fullConfig()->name().empty() ) + m_xml.writeAttribute( "name", m_config.fullConfig()->name() ); + } + + virtual void EndTesting( const Totals& totals ) { + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", totals.assertions.passed ) + .writeAttribute( "failures", totals.assertions.failed ) + .writeAttribute( "expectedFailures", totals.assertions.failedButOk ); + m_xml.endElement(); + } + + virtual void StartGroup( const std::string& groupName ) { + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupName ); + } + + virtual void EndGroup( const std::string&, const Totals& totals ) { + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", totals.assertions.passed ) + .writeAttribute( "failures", totals.assertions.failed ) + .writeAttribute( "expectedFailures", totals.assertions.failedButOk ); + m_xml.endElement(); + } + + virtual void StartSection( const std::string& sectionName, const std::string& description ) { + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionName ) ) + .writeAttribute( "description", description ); + } + } + virtual void NoAssertionsInSection( const std::string& ) {} + virtual void NoAssertionsInTestCase( const std::string& ) {} + + virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) { + if( --m_sectionDepth > 0 ) { + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", assertions.passed ) + .writeAttribute( "failures", assertions.failed ) + .writeAttribute( "expectedFailures", assertions.failedButOk ); + m_xml.endElement(); + } + } + + virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) { + m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); + m_currentTestSuccess = true; + } + + virtual void Result( const Catch::AssertionResult& assertionResult ) { + if( !m_config.fullConfig()->includeSuccessfulResults() && assertionResult.getResultType() == ResultWas::Ok ) + return; + + if( assertionResult.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", assertionResult.succeeded() ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ); + + m_xml.scopedElement( "Original" ) + .writeText( assertionResult.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( assertionResult.getExpandedExpression() ); + m_currentTestSuccess &= assertionResult.succeeded(); + } + + switch( assertionResult.getResultType() ) { + case ResultWas::ThrewException: + m_xml.scopedElement( "Exception" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + m_currentTestSuccess = false; + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Warning: + m_xml.scopedElement( "Warning" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::ExplicitFailure: + m_xml.scopedElement( "Failure" ) + .writeText( assertionResult.getMessage() ); + m_currentTestSuccess = false; + break; + case ResultWas::Unknown: + case ResultWas::Ok: + case ResultWas::FailureBit: + case ResultWas::ExpressionFailed: + case ResultWas::Exception: + case ResultWas::DidntThrowException: + break; + } + if( assertionResult.hasExpression() ) + m_xml.endElement(); + } + + virtual void Aborted() { + // !TBD + } + + virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) { + m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess ); + m_xml.endElement(); + } + + private: + ReporterConfig m_config; + bool m_currentTestSuccess; + XmlWriter m_xml; + int m_sectionDepth; + }; + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_junit.hpp +#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED + +#include + +namespace Catch { + + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter( ReporterConfig const& _config ) + : CumulativeReporterBase( _config ), + xml( _config.stream() ) + {} + + ~JunitReporter(); + + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + virtual void noMatchingTestCases( std::string const& /*spec*/ ) {} + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = true; + return prefs; + } + + virtual void testRunStarting( TestRunInfo const& runInfo ) { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + virtual void testRunEndedCumulative() { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", "tbd" ); // !TBD + + // Write test cases + for( TestGroupNode::ChildNodes::const_iterator + it = groupNode.children.begin(), itEnd = groupNode.children.end(); + it != itEnd; + ++it ) + writeTestCase( **it ); + + xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); + xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); + } + + void writeTestCase( TestCaseNode const& testCaseNode ) { + TestCaseStats const& stats = testCaseNode.value; + + // All test cases have exactly one section - which represents the + // test case itself. That section may have 0-n nested sections + assert( testCaseNode.children.size() == 1 ); + SectionNode const& rootSection = *testCaseNode.children.front(); + + std::string className = stats.testInfo.className; + + if( className.empty() ) { + if( rootSection.childSections.empty() ) + className = "global"; + } + writeSection( className, "", rootSection ); + } + + void writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode ) { + std::string name = trim( sectionNode.stats.sectionInfo.name ); + if( !rootName.empty() ) + name = rootName + "/" + name; + + if( !sectionNode.assertions.empty() || + !sectionNode.stdOut.empty() || + !sectionNode.stdErr.empty() ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); + if( className.empty() ) { + xml.writeAttribute( "classname", name ); + xml.writeAttribute( "name", "root" ); + } + else { + xml.writeAttribute( "classname", className ); + xml.writeAttribute( "name", name ); + } + xml.writeAttribute( "time", toString( sectionNode.stats.durationInSeconds ) ); + + writeAssertions( sectionNode ); + + if( !sectionNode.stdOut.empty() ) + xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); + if( !sectionNode.stdErr.empty() ) + xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); + } + for( SectionNode::ChildSections::const_iterator + it = sectionNode.childSections.begin(), + itEnd = sectionNode.childSections.end(); + it != itEnd; + ++it ) + if( className.empty() ) + writeSection( name, "", **it ); + else + writeSection( className, name, **it ); + } + + void writeAssertions( SectionNode const& sectionNode ) { + for( SectionNode::Assertions::const_iterator + it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); + it != itEnd; + ++it ) + writeAssertion( *it ); + } + void writeAssertion( AssertionStats const& stats ) { + AssertionResult const& result = stats.assertionResult; + if( !result.isOk() ) { + std::string elementName; + switch( result.getResultType() ) { + case ResultWas::ThrewException: + elementName = "error"; + break; + case ResultWas::ExplicitFailure: + elementName = "failure"; + break; + case ResultWas::ExpressionFailed: + elementName = "failure"; + break; + case ResultWas::DidntThrowException: + elementName = "failure"; + break; + + // We should never see these here: + case ResultWas::Info: + case ResultWas::Warning: + case ResultWas::Ok: + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + elementName = "internalError"; + break; + } + + XmlWriter::ScopedElement e = xml.scopedElement( elementName ); + + xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "type", result.getTestMacroName() ); + + std::ostringstream oss; + if( !result.getMessage().empty() ) + oss << result.getMessage() << "\n"; + for( std::vector::const_iterator + it = stats.infoMessages.begin(), + itEnd = stats.infoMessages.end(); + it != itEnd; + ++it ) + if( it->type == ResultWas::Info ) + oss << it->message << "\n"; + + oss << "at " << result.getSourceInfo(); + xml.writeText( oss.str(), false ); + } + } + + XmlWriter xml; + Timer suiteTimer; + std::ostringstream stdOutForSuite; + std::ostringstream stdErrForSuite; + unsigned int unexpectedExceptions; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_console.hpp +#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED + +#include + +namespace Catch { + + struct ConsoleReporter : StreamingReporterBase { + ConsoleReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_headerPrinted( false ) + {} + + virtual ~ConsoleReporter(); + static std::string getDescription() { + return "Reports test results as plain lines of text"; + } + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + lazyPrint(); + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + stream << std::endl; + return true; + } + + virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting( _sectionInfo ); + } + virtual void sectionEnded( SectionStats const& _sectionStats ) { + if( _sectionStats.missingAssertions ) { + lazyPrint(); + Colour colour( Colour::ResultError ); + if( m_sectionStack.size() > 1 ) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if( m_headerPrinted ) { + if( m_config->showDurations() == ShowDurations::Always ) + stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + m_headerPrinted = false; + } + else { + if( m_config->showDurations() == ShowDurations::Always ) + stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + } + StreamingReporterBase::sectionEnded( _sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) { + StreamingReporterBase::testCaseEnded( _testCaseStats ); + m_headerPrinted = false; + } + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) { + if( currentGroupInfo.used ) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals( _testGroupStats.totals ); + stream << "\n" << std::endl; + } + StreamingReporterBase::testGroupEnded( _testGroupStats ); + } + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotalsDivider( _testRunStats.totals ); + printTotals( _testRunStats.totals ); + stream << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ), + stats( _stats ), + result( _stats.assertionResult ), + colour( Colour::None ), + message( result.getMessage() ), + messages( _stats.infoMessages ), + printInfoMessages( _printInfoMessages ) + { + switch( result.getResultType() ) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + //if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; + } + else { + colour = Colour::Error; + passOrFail = "FAILED"; + } + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with message"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if( _stats.infoMessages.size() == 1 ) + messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; + } + } + + void print() const { + printSourceInfo(); + if( stats.totals.assertions.total() > 0 ) { + if( result.isOk() ) + stream << "\n"; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } + else { + stream << "\n"; + } + printMessage(); + } + + private: + void printResultType() const { + if( !passOrFail.empty() ) { + Colour colourGuard( colour ); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if( result.hasExpression() ) { + Colour colourGuard( Colour::OriginalExpression ); + stream << " "; + stream << result.getExpressionInMacro(); + stream << "\n"; + } + } + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + stream << "with expansion:\n"; + Colour colourGuard( Colour::ReconstructedExpression ); + stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n"; + } + } + void printMessage() const { + if( !messageLabel.empty() ) + stream << messageLabel << ":" << "\n"; + for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); + it != itEnd; + ++it ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || it->type != ResultWas::Info ) + stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n"; + } + } + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector messages; + bool printInfoMessages; + }; + + void lazyPrint() { + + if( !currentTestRunInfo.used ) + lazyPrintRunInfo(); + if( !currentGroupInfo.used ) + lazyPrintGroupInfo(); + + if( !m_headerPrinted ) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } + } + void lazyPrintRunInfo() { + stream << "\n" << getLineOfChars<'~'>() << "\n"; + Colour colour( Colour::SecondaryText ); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion.majorVersion << "." + << libraryVersion.minorVersion << " b" + << libraryVersion.buildNumber; + if( libraryVersion.branchName != std::string( "master" ) ) + stream << " (" << libraryVersion.branchName << ")"; + stream << " host application.\n" + << "Run with -? for options\n\n"; + + currentTestRunInfo.used = true; + } + void lazyPrintGroupInfo() { + if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { + printClosedHeader( "Group: " + currentGroupInfo->name ); + currentGroupInfo.used = true; + } + } + void printTestCaseAndSectionHeader() { + assert( !m_sectionStack.empty() ); + printOpenHeader( currentTestCaseInfo->name ); + + if( m_sectionStack.size() > 1 ) { + Colour colourGuard( Colour::Headers ); + + std::vector::const_iterator + it = m_sectionStack.begin()+1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for( ; it != itEnd; ++it ) + printHeaderString( it->name, 2 ); + } + + SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; + + if( !lineInfo.empty() ){ + stream << getLineOfChars<'-'>() << "\n"; + Colour colourGuard( Colour::FileName ); + stream << lineInfo << "\n"; + } + stream << getLineOfChars<'.'>() << "\n" << std::endl; + } + + void printClosedHeader( std::string const& _name ) { + printOpenHeader( _name ); + stream << getLineOfChars<'.'>() << "\n"; + } + void printOpenHeader( std::string const& _name ) { + stream << getLineOfChars<'-'>() << "\n"; + { + Colour colourGuard( Colour::Headers ); + printHeaderString( _name ); + } + } + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { + std::size_t i = _string.find( ": " ); + if( i != std::string::npos ) + i+=2; + else + i = 0; + stream << Text( _string, TextAttributes() + .setIndent( indent+i) + .setInitialIndent( indent ) ) << "\n"; + } + + struct SummaryColumn { + + SummaryColumn( std::string const& _label, Colour::Code _colour ) + : label( _label ), + colour( _colour ) + {} + SummaryColumn addRow( std::size_t count ) { + std::ostringstream oss; + oss << count; + std::string row = oss.str(); + for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { + while( it->size() < row.size() ) + *it = " " + *it; + while( it->size() > row.size() ) + row = " " + row; + } + rows.push_back( row ); + return *this; + } + + std::string label; + Colour::Code colour; + std::vector rows; + + }; + + void printTotals( Totals const& totals ) { + if( totals.testCases.total() == 0 ) { + stream << Colour( Colour::Warning ) << "No tests ran\n"; + } + else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) { + stream << Colour( Colour::ResultSuccess ) << "All tests passed"; + stream << " (" + << pluralise( totals.assertions.passed, "assertion" ) << " in " + << pluralise( totals.testCases.passed, "test case" ) << ")" + << "\n"; + } + else { + + std::vector columns; + columns.push_back( SummaryColumn( "", Colour::None ) + .addRow( totals.testCases.total() ) + .addRow( totals.assertions.total() ) ); + columns.push_back( SummaryColumn( "passed", Colour::Success ) + .addRow( totals.testCases.passed ) + .addRow( totals.assertions.passed ) ); + columns.push_back( SummaryColumn( "failed", Colour::ResultError ) + .addRow( totals.testCases.failed ) + .addRow( totals.assertions.failed ) ); + columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) + .addRow( totals.testCases.failedButOk ) + .addRow( totals.assertions.failedButOk ) ); + + printSummaryRow( "test cases", columns, 0 ); + printSummaryRow( "assertions", columns, 1 ); + } + } + void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { + for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { + std::string value = it->rows[row]; + if( it->label.empty() ) { + stream << label << ": "; + if( value != "0" ) + stream << value; + else + stream << Colour( Colour::Warning ) << "- none -"; + } + else if( value != "0" ) { + stream << Colour( Colour::LightGrey ) << " | "; + stream << Colour( it->colour ) + << value << " " << it->label; + } + } + stream << "\n"; + } + + static std::size_t makeRatio( std::size_t number, std::size_t total ) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; + return ( ratio == 0 && number > 0 ) ? 1 : ratio; + } + static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { + if( i > j && i > k ) + return i; + else if( j > k ) + return j; + else + return k; + } + + void printTotalsDivider( Totals const& totals ) { + if( totals.testCases.total() > 0 ) { + std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); + std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); + std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); + while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )++; + while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )--; + + stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); + stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); + if( totals.testCases.allPassed() ) + stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); + else + stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); + } + else { + stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); + } + stream << "\n"; + } + void printSummaryDivider() { + stream << getLineOfChars<'-'>() << "\n"; + } + template + static char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; + } + + private: + bool m_headerPrinted; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_compact.hpp +#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + CompactReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual ~CompactReporter(); + + static std::string getDescription() { + return "Reports test results on a single line, suitable for IDEs"; + } + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; + } + + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotals( _testRunStats.totals ); + stream << "\n" << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , stats( _stats ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + + switch( result.getResultType() ) { + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType( Colour::None, "warning" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType( Colour::Error, failedString() ); + printIssue( "explicitly" ); + printRemainingMessages( Colour::None ); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType( Colour::Error, "** internal error **" ); + break; + } + } + + private: + // Colour::LightGrey + + static Colour::Code dimColour() { return Colour::FileName; } + +#ifdef CATCH_PLATFORM_MAC + static const char* failedString() { return "FAILED"; } + static const char* passedString() { return "PASSED"; } +#else + static const char* failedString() { return "failed"; } + static const char* passedString() { return "passed"; } +#endif + + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ":"; + } + + void printResultType( Colour::Code colour, std::string passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << " " << passOrFail; + } + stream << ":"; + } + } + + void printIssue( std::string issue ) const { + stream << " " << issue; + } + + void printExpressionWas() { + if( result.hasExpression() ) { + stream << ";"; + { + Colour colour( dimColour() ); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if( result.hasExpression() ) { + stream << " " << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + { + Colour colour( dimColour() ); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if ( itMessage != messages.end() ) { + stream << " '" << itMessage->message << "'"; + ++itMessage; + } + } + + void printRemainingMessages( Colour::Code colour = dimColour() ) { + if ( itMessage == messages.end() ) + return; + + // using messages.end() directly yields compilation error: + std::vector::const_iterator itEnd = messages.end(); + const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); + + { + Colour colourGuard( colour ); + stream << " with " << pluralise( N, "message" ) << ":"; + } + + for(; itMessage != itEnd; ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || itMessage->type != ResultWas::Info ) { + stream << " '" << itMessage->message << "'"; + if ( ++itMessage != itEnd ) { + Colour colourGuard( dimColour() ); + stream << " and"; + } + } + } + } + + private: + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + std::vector messages; + std::vector::const_iterator itMessage; + bool printInfoMessages; + }; + + // Colour, message variants: + // - white: No tests ran. + // - red: Failed [both/all] N test cases, failed [both/all] M assertions. + // - white: Passed [both/all] N test cases (no assertions). + // - red: Failed N tests cases, failed M assertions. + // - green: Passed [both/all] N tests cases with M assertions. + + std::string bothOrAll( std::size_t count ) const { + return count == 1 ? "" : count == 2 ? "both " : "all " ; + } + + void printTotals( const Totals& totals ) const { + if( totals.testCases.total() == 0 ) { + stream << "No tests ran."; + } + else if( totals.testCases.failed == totals.testCases.total() ) { + Colour colour( Colour::ResultError ); + const std::string qualify_assertions_failed = + totals.assertions.failed == totals.assertions.total() ? + bothOrAll( totals.assertions.failed ) : ""; + stream << + "Failed " << bothOrAll( totals.testCases.failed ) + << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << qualify_assertions_failed << + pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else if( totals.assertions.total() == 0 ) { + stream << + "Passed " << bothOrAll( totals.testCases.total() ) + << pluralise( totals.testCases.total(), "test case" ) + << " (no assertions)."; + } + else if( totals.assertions.failed ) { + Colour colour( Colour::ResultError ); + stream << + "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else { + Colour colour( Colour::ResultSuccess ); + stream << + "Passed " << bothOrAll( totals.testCases.passed ) + << pluralise( totals.testCases.passed, "test case" ) << + " with " << pluralise( totals.assertions.passed, "assertion" ) << "."; + } + } + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch + +namespace Catch { + NonCopyable::~NonCopyable() {} + IShared::~IShared() {} + StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} + IContext::~IContext() {} + IResultCapture::~IResultCapture() {} + ITestCase::~ITestCase() {} + ITestCaseRegistry::~ITestCaseRegistry() {} + IRegistryHub::~IRegistryHub() {} + IMutableRegistryHub::~IMutableRegistryHub() {} + IExceptionTranslator::~IExceptionTranslator() {} + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} + IReporter::~IReporter() {} + IReporterFactory::~IReporterFactory() {} + IReporterRegistry::~IReporterRegistry() {} + IStreamingReporter::~IStreamingReporter() {} + AssertionStats::~AssertionStats() {} + SectionStats::~SectionStats() {} + TestCaseStats::~TestCaseStats() {} + TestGroupStats::~TestGroupStats() {} + TestRunStats::~TestRunStats() {} + CumulativeReporterBase::SectionNode::~SectionNode() {} + CumulativeReporterBase::~CumulativeReporterBase() {} + + StreamingReporterBase::~StreamingReporterBase() {} + ConsoleReporter::~ConsoleReporter() {} + CompactReporter::~CompactReporter() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + XmlReporter::~XmlReporter() {} + JunitReporter::~JunitReporter() {} + TestRegistry::~TestRegistry() {} + FreeFunctionTestCase::~FreeFunctionTestCase() {} + IGeneratorInfo::~IGeneratorInfo() {} + IGeneratorsForTest::~IGeneratorsForTest() {} + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} + + Matchers::Impl::StdString::Equals::~Equals() {} + Matchers::Impl::StdString::Contains::~Contains() {} + Matchers::Impl::StdString::StartsWith::~StartsWith() {} + Matchers::Impl::StdString::EndsWith::~EndsWith() {} + + void Config::dummy() {} + + INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter ) +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif + +#ifdef CATCH_CONFIG_MAIN +// #included from: internal/catch_default_main.hpp +#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED + +#ifndef __OBJC__ + +// Standard C/C++ main entry point +int main (int argc, char * const argv[]) { + return Catch::Session().run( argc, argv ); +} + +#else // __OBJC__ + +// Objective-C entry point +int main (int argc, char * const argv[]) { +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int result = Catch::Session().run( argc, (char* const*)argv ); + +#if !CATCH_ARC_ENABLED + [pool drain]; +#endif + + return result; +} + +#endif // __OBJC__ + +#endif + +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +# undef CLARA_CONFIG_MAIN +#endif + +////// + +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) +#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) + +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) + +#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) +#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" ) +#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) +#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) +#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) + +#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) + +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) +#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) +#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) + #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) +#else + #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) + #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) +#endif +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#else +#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#endif +#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) +#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) + +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "REQUIRE_THROWS" ) +#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) + +#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) +#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) +#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) + +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" ) +#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) + +#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) +#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) +#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) + #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) +#else + #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) + #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) +#endif +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#else +#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#endif +#define GIVEN( desc ) SECTION( " Given: " desc, "" ) +#define WHEN( desc ) SECTION( " When: " desc, "" ) +#define AND_WHEN( desc ) SECTION( "And when: " desc, "" ) +#define THEN( desc ) SECTION( " Then: " desc, "" ) +#define AND_THEN( desc ) SECTION( " And: " desc, "" ) + +using Catch::Detail::Approx; + +// #included from: internal/catch_reenable_warnings.h + +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + diff --git a/test/include/catch_orig.hpp b/test/include/catch_orig.hpp new file mode 100644 index 000000000..1fba6a34e --- /dev/null +++ b/test/include/catch_orig.hpp @@ -0,0 +1,8974 @@ +/* + * CATCH v1.0 build 52 (master branch) + * Generated: 2014-07-10 09:17:43.994453 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + +#define TWOBLUECUBES_CATCH_HPP_INCLUDED + +// #included from: internal/catch_suppress_warnings.h + +#define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wglobal-constructors" +#pragma clang diagnostic ignored "-Wvariadic-macros" +#pragma clang diagnostic ignored "-Wc99-extensions" +#pragma clang diagnostic ignored "-Wunused-variable" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#pragma clang diagnostic ignored "-Wc++98-compat" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + +#ifdef CATCH_CONFIG_MAIN +# define CATCH_CONFIG_RUNNER +#endif + +#ifdef CATCH_CONFIG_RUNNER +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// #included from: internal/catch_notimplemented_exception.h +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED + +// #included from: catch_common.h +#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED + +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) + +#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr +#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) + +#include +#include +#include + +// #included from: catch_compiler_capabilities.h +#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + +// Much of the following code is based on Boost (1.53) + +#ifdef __clang__ + +# if __has_feature(cxx_nullptr) +# define CATCH_CONFIG_CPP11_NULLPTR +# endif + +# if __has_feature(cxx_noexcept) +# define CATCH_CONFIG_CPP11_NOEXCEPT +# endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Borland +#ifdef __BORLANDC__ + +#if (__BORLANDC__ > 0x582 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __BORLANDC__ + +//////////////////////////////////////////////////////////////////////////////// +// EDG +#ifdef __EDG_VERSION__ + +#if (__EDG_VERSION__ > 238 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __EDG_VERSION__ + +//////////////////////////////////////////////////////////////////////////////// +// Digital Mars +#ifdef __DMC__ + +#if (__DMC__ > 0x840 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __DMC__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +#if __GNUC__ < 3 + +#if (__GNUC_MINOR__ >= 96 ) +//#define CATCH_CONFIG_SFINAE +#endif + +#elif __GNUC__ >= 3 + +// #define CATCH_CONFIG_SFINAE // Taking this out completely for now + +#endif // __GNUC__ < 3 + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) ) + +#define CATCH_CONFIG_CPP11_NULLPTR +#endif + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1310 ) // (VC++ 7.0+) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // _MSC_VER + +// Use variadic macros if the compiler supports them +#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ + ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ + ( defined __GNUC__ && __GNUC__ >= 3 ) || \ + ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) + +#ifndef CATCH_CONFIG_NO_VARIADIC_MACROS +#define CATCH_CONFIG_VARIADIC_MACROS +#endif + +#endif + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// detect language version: +#if (__cplusplus == 201103L) +# define CATCH_CPP11 +# define CATCH_CPP11_OR_GREATER +#elif (__cplusplus >= 201103L) +# define CATCH_CPP11_OR_GREATER +#endif + +// noexcept support: +#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) +# define CATCH_NOEXCEPT noexcept +# define CATCH_NOEXCEPT_IS(x) noexcept(x) +#else +# define CATCH_NOEXCEPT throw() +# define CATCH_NOEXCEPT_IS(x) +#endif + +namespace Catch { + + class NonCopyable { + NonCopyable( NonCopyable const& ); + void operator = ( NonCopyable const& ); + protected: + NonCopyable() {} + virtual ~NonCopyable(); + }; + + class SafeBool { + public: + typedef void (SafeBool::*type)() const; + + static type makeSafe( bool value ) { + return value ? &SafeBool::trueValue : 0; + } + private: + void trueValue() const {} + }; + + template + inline void deleteAll( ContainerT& container ) { + typename ContainerT::const_iterator it = container.begin(); + typename ContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete *it; + } + template + inline void deleteAllValues( AssociativeContainerT& container ) { + typename AssociativeContainerT::const_iterator it = container.begin(); + typename AssociativeContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete it->second; + } + + bool startsWith( std::string const& s, std::string const& prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; + + struct SourceLineInfo { + + SourceLineInfo(); + SourceLineInfo( char const* _file, std::size_t _line ); + SourceLineInfo( SourceLineInfo const& other ); +# ifdef CATCH_CPP11_OR_GREATER + SourceLineInfo( SourceLineInfo && ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo& operator = ( SourceLineInfo && ) = default; +# endif + bool empty() const; + bool operator == ( SourceLineInfo const& other ) const; + + std::string file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // This is just here to avoid compiler warnings with macro constants and boolean literals + inline bool isTrue( bool value ){ return value; } + inline bool alwaysTrue() { return true; } + inline bool alwaysFalse() { return false; } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() { + return std::string(); + } + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); + +#include + +namespace Catch { + + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + NotImplementedException( NotImplementedException const& ) {} + + virtual ~NotImplementedException() CATCH_NOEXCEPT {} + + virtual const char* what() const CATCH_NOEXCEPT; + + private: + std::string m_what; + SourceLineInfo m_lineInfo; + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + +// #included from: internal/catch_context.h +#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED + +// #included from: catch_interfaces_generators.h +#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED + +#include + +namespace Catch { + + struct IGeneratorInfo { + virtual ~IGeneratorInfo(); + virtual bool moveNext() = 0; + virtual std::size_t getCurrentIndex() const = 0; + }; + + struct IGeneratorsForTest { + virtual ~IGeneratorsForTest(); + + virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; + virtual bool moveNext() = 0; + }; + + IGeneratorsForTest* createGeneratorsForTest(); + +} // end namespace Catch + +// #included from: catch_ptr.hpp +#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + // An intrusive reference counting smart pointer. + // T must implement addRef() and release() methods + // typically implementing the IShared interface + template + class Ptr { + public: + Ptr() : m_p( NULL ){} + Ptr( T* p ) : m_p( p ){ + if( m_p ) + m_p->addRef(); + } + Ptr( Ptr const& other ) : m_p( other.m_p ){ + if( m_p ) + m_p->addRef(); + } + ~Ptr(){ + if( m_p ) + m_p->release(); + } + void reset() { + if( m_p ) + m_p->release(); + m_p = NULL; + } + Ptr& operator = ( T* p ){ + Ptr temp( p ); + swap( temp ); + return *this; + } + Ptr& operator = ( Ptr const& other ){ + Ptr temp( other ); + swap( temp ); + return *this; + } + void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } + T* get() { return m_p; } + const T* get() const{ return m_p; } + T& operator*() const { return *m_p; } + T* operator->() const { return m_p; } + bool operator !() const { return m_p == NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); } + + private: + T* m_p; + }; + + struct IShared : NonCopyable { + virtual ~IShared(); + virtual void addRef() const = 0; + virtual void release() const = 0; + }; + + template + struct SharedImpl : T { + + SharedImpl() : m_rc( 0 ){} + + virtual void addRef() const { + ++m_rc; + } + virtual void release() const { + if( --m_rc == 0 ) + delete this; + } + + mutable unsigned int m_rc; + }; + +} // end namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#include +#include +#include + +namespace Catch { + + class TestCase; + class Stream; + struct IResultCapture; + struct IRunner; + struct IGeneratorsForTest; + struct IConfig; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; + virtual bool advanceGeneratorsForCurrentTest() = 0; + virtual Ptr getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( Ptr const& config ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); + Stream createStream( std::string const& streamName ); + +} + +// #included from: internal/catch_test_registry.hpp +#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED + +// #included from: catch_interfaces_testcase.h +#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED + +#include + +namespace Catch { + + class TestSpec; + + struct ITestCase : IShared { + virtual void invoke () const = 0; + protected: + virtual ~ITestCase(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases ) const = 0; + + }; +} + +namespace Catch { + +template +class MethodTestCase : public SharedImpl { + +public: + MethodTestCase( void (C::*method)() ) : m_method( method ) {} + + virtual void invoke() const { + C obj; + (obj.*m_method)(); + } + +private: + virtual ~MethodTestCase() {} + + void (C::*m_method)(); +}; + +typedef void(*TestFunction)(); + +struct NameAndDesc { + NameAndDesc( const char* _name = "", const char* _description= "" ) + : name( _name ), description( _description ) + {} + + const char* name; + const char* description; +}; + +struct AutoReg { + + AutoReg( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + + template + AutoReg( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + registerTestCase( new MethodTestCase( method ), + className, + nameAndDesc, + lineInfo ); + } + + void registerTestCase( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + + ~AutoReg(); + +private: + AutoReg( AutoReg const& ); + void operator= ( AutoReg const& ); +}; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( ... ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + +#else + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + +#endif + +// #included from: internal/catch_capture.hpp +#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED + +// #included from: catch_result_builder.h +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED + +// #included from: catch_result_type.h +#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2 + + }; }; + + inline bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + inline bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x00, + + ContinueOnFailure = 0x01, // Failures fail test, but execution continues + FalseTest = 0x02, // Prefix expression with ! + SuppressFail = 0x04 // Failures are reported but do not fail the test + }; }; + + inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( static_cast( lhs ) | static_cast( rhs ) ); + } + + inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } + inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } + inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + +} // end namespace Catch + +// #included from: catch_assertionresult.h +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED + +#include + +namespace Catch { + + struct AssertionInfo + { + AssertionInfo() {} + AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ); + + std::string macroName; + SourceLineInfo lineInfo; + std::string capturedExpression; + ResultDisposition::Flags resultDisposition; + }; + + struct AssertionResultData + { + AssertionResultData() : resultType( ResultWas::Unknown ) {} + + std::string reconstructedExpression; + std::string message; + ResultWas::OfType resultType; + }; + + class AssertionResult { + public: + AssertionResult(); + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); + ~AssertionResult(); +# ifdef CATCH_CPP11_OR_GREATER + AssertionResult( AssertionResult const& ) = default; + AssertionResult( AssertionResult && ) = default; + AssertionResult& operator = ( AssertionResult const& ) = default; + AssertionResult& operator = ( AssertionResult && ) = default; +# endif + + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + std::string getMessage() const; + SourceLineInfo getSourceInfo() const; + std::string getTestMacroName() const; + + protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + +} // end namespace Catch + +namespace Catch { + + struct TestFailureException{}; + + template class ExpressionLhs; + + struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; + + struct CopyableStream { + CopyableStream() {} + CopyableStream( CopyableStream const& other ) { + oss << other.oss.str(); + } + CopyableStream& operator=( CopyableStream const& other ) { + oss.str(""); + oss << other.oss.str(); + return *this; + } + std::ostringstream oss; + }; + + class ResultBuilder { + public: + ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition ); + + template + ExpressionLhs operator->* ( T const& operand ); + ExpressionLhs operator->* ( bool value ); + + template + ResultBuilder& operator << ( T const& value ) { + m_stream.oss << value; + return *this; + } + + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + + ResultBuilder& setResultType( ResultWas::OfType result ); + ResultBuilder& setResultType( bool result ); + ResultBuilder& setLhs( std::string const& lhs ); + ResultBuilder& setRhs( std::string const& rhs ); + ResultBuilder& setOp( std::string const& op ); + + void endExpression(); + + std::string reconstructExpression() const; + AssertionResult build() const; + + void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); + void captureResult( ResultWas::OfType resultType ); + void captureExpression(); + void react(); + bool shouldDebugBreak() const; + bool allowThrows() const; + + private: + AssertionInfo m_assertionInfo; + AssertionResultData m_data; + struct ExprComponents { + ExprComponents() : testFalse( false ) {} + bool testFalse; + std::string lhs, rhs, op; + } m_exprComponents; + CopyableStream m_stream; + + bool m_shouldDebugBreak; + bool m_shouldThrow; + }; + +} // namespace Catch + +// Include after due to circular dependency: +// #included from: catch_expression_lhs.hpp +#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED + +// #included from: catch_evaluate.hpp +#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#endif + +#include + +namespace Catch { +namespace Internal { + + enum Operator { + IsEqualTo, + IsNotEqualTo, + IsLessThan, + IsGreaterThan, + IsLessThanOrEqualTo, + IsGreaterThanOrEqualTo + }; + + template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; + template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; + template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; + + template + inline T& opCast(T const& t) { return const_cast(t); } + +// nullptr_t support based on pull request #154 from Konstantin Baumann +#ifdef CATCH_CONFIG_CPP11_NULLPTR + inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } +#endif // CATCH_CONFIG_CPP11_NULLPTR + + // So the compare overloads can be operator agnostic we convey the operator as a template + // enum, which is used to specialise an Evaluator for doing the comparison. + template + class Evaluator{}; + + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs) { + return opCast( lhs ) == opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) != opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) < opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) > opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) >= opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) <= opCast( rhs ); + } + }; + + template + bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // This level of indirection allows us to specialise for integer types + // to avoid signed/ unsigned warnings + + // "base" overload + template + bool compare( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // unsigned X to int + template bool compare( unsigned int lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // unsigned X to long + template bool compare( unsigned int lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // int to unsigned X + template bool compare( int lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // long to unsigned X + template bool compare( long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long (when comparing against NULL) + template bool compare( long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + + // pointer to int (when comparing against NULL) + template bool compare( int lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, int rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + +#ifdef CATCH_CONFIG_CPP11_NULLPTR + // pointer to nullptr_t (when comparing against nullptr) + template bool compare( std::nullptr_t, T* rhs ) { + return Evaluator::evaluate( NULL, rhs ); + } + template bool compare( T* lhs, std::nullptr_t ) { + return Evaluator::evaluate( lhs, NULL ); + } +#endif // CATCH_CONFIG_CPP11_NULLPTR + +} // end of namespace Internal +} // end of namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// #included from: catch_tostring.h +#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED + +// #included from: catch_sfinae.hpp +#define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED + +// Try to detect if the current compiler supports SFINAE + +namespace Catch { + + struct TrueType { + static const bool value = true; + typedef void Enable; + char sizer[1]; + }; + struct FalseType { + static const bool value = false; + typedef void Disable; + char sizer[2]; + }; + +#ifdef CATCH_CONFIG_SFINAE + + template struct NotABooleanExpression; + + template struct If : NotABooleanExpression {}; + template<> struct If : TrueType {}; + template<> struct If : FalseType {}; + + template struct SizedIf; + template<> struct SizedIf : TrueType {}; + template<> struct SizedIf : FalseType {}; + +#endif // CATCH_CONFIG_SFINAE + +} // end namespace Catch + +#include +#include +#include +#include +#include + +#ifdef __OBJC__ +// #included from: catch_objc_arc.hpp +#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED + +#import + +#ifdef __has_feature +#define CATCH_ARC_ENABLED __has_feature(objc_arc) +#else +#define CATCH_ARC_ENABLED 0 +#endif + +void arcSafeRelease( NSObject* obj ); +id performOptionalSelector( id obj, SEL sel ); + +#if !CATCH_ARC_ENABLED +inline void arcSafeRelease( NSObject* obj ) { + [obj release]; +} +inline id performOptionalSelector( id obj, SEL sel ) { + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; + return nil; +} +#define CATCH_UNSAFE_UNRETAINED +#define CATCH_ARC_STRONG +#else +inline void arcSafeRelease( NSObject* ){} +inline id performOptionalSelector( id obj, SEL sel ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#endif + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + return nil; +} +#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained +#define CATCH_ARC_STRONG __strong +#endif + +#endif + +namespace Catch { +namespace Detail { + +// SFINAE is currently disabled by default for all compilers. +// If the non SFINAE version of IsStreamInsertable is ambiguous for you +// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE +#ifdef CATCH_CONFIG_SFINAE + + template + class IsStreamInsertableHelper { + template struct TrueIfSizeable : TrueType {}; + + template + static TrueIfSizeable dummy(T2*); + static FalseType dummy(...); + + public: + typedef SizedIf type; + }; + + template + struct IsStreamInsertable : IsStreamInsertableHelper::type {}; + +#else + + struct BorgType { + template BorgType( T const& ); + }; + + TrueType& testStreamable( std::ostream& ); + FalseType testStreamable( FalseType ); + + FalseType operator<<( std::ostream const&, BorgType const& ); + + template + struct IsStreamInsertable { + static std::ostream &s; + static T const&t; + enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; + }; + +#endif + + template + struct StringMakerBase { + template + static std::string convert( T const& ) { return "{?}"; } + }; + + template<> + struct StringMakerBase { + template + static std::string convert( T const& _value ) { + std::ostringstream oss; + oss << _value; + return oss.str(); + } + }; + + std::string rawMemoryToString( const void *object, std::size_t size ); + + template + inline std::string rawMemoryToString( const T& object ) { + return rawMemoryToString( &object, sizeof(object) ); + } + +} // end namespace Detail + +template +std::string toString( T const& value ); + +template +struct StringMaker : + Detail::StringMakerBase::value> {}; + +template +struct StringMaker { + template + static std::string convert( U* p ) { + if( !p ) + return INTERNAL_CATCH_STRINGIFY( NULL ); + else + return Detail::rawMemoryToString( p ); + } +}; + +template +struct StringMaker { + static std::string convert( R C::* p ) { + if( !p ) + return INTERNAL_CATCH_STRINGIFY( NULL ); + else + return Detail::rawMemoryToString( p ); + } +}; + +namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ); +} + +template +struct StringMaker > { + static std::string convert( std::vector const& v ) { + return Detail::rangeToString( v.begin(), v.end() ); + } +}; + +namespace Detail { + template + std::string makeString( T const& value ) { + return StringMaker::convert( value ); + } +} // end namespace Detail + +/// \brief converts any type to a string +/// +/// The default template forwards on to ostringstream - except when an +/// ostringstream overload does not exist - in which case it attempts to detect +/// that and writes {?}. +/// Overload (not specialise) this template for custom typs that you don't want +/// to provide an ostream overload for. +template +std::string toString( T const& value ) { + return StringMaker::convert( value ); +} + +// Built in overloads + +std::string toString( std::string const& value ); +std::string toString( std::wstring const& value ); +std::string toString( const char* const value ); +std::string toString( char* const value ); +std::string toString( int value ); +std::string toString( unsigned long value ); +std::string toString( unsigned int value ); +std::string toString( const double value ); +std::string toString( const float value ); +std::string toString( bool value ); +std::string toString( char value ); +std::string toString( signed char value ); +std::string toString( unsigned char value ); + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ); +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); + std::string toString( NSObject* const& nsObject ); +#endif + + namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ) { + std::ostringstream oss; + oss << "{ "; + if( first != last ) { + oss << toString( *first ); + for( ++first ; first != last ; ++first ) { + oss << ", " << toString( *first ); + } + } + oss << " }"; + return oss.str(); + } +} + +} // end namespace Catch + +namespace Catch { + +// Wraps the LHS of an expression and captures the operator and RHS (if any) - +// wrapping them all in a ResultBuilder object +template +class ExpressionLhs { + ExpressionLhs& operator = ( ExpressionLhs const& ); +# ifdef CATCH_CPP11_OR_GREATER + ExpressionLhs& operator = ( ExpressionLhs && ) = delete; +# endif + +public: + ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} +# ifdef CATCH_CPP11_OR_GREATER + ExpressionLhs( ExpressionLhs const& ) = default; + ExpressionLhs( ExpressionLhs && ) = default; +# endif + + template + ResultBuilder& operator == ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator != ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator < ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator > ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator <= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator >= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator == ( bool rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator != ( bool rhs ) { + return captureExpression( rhs ); + } + + void endExpression() { + bool value = m_lhs ? true : false; + m_rb + .setLhs( Catch::toString( value ) ) + .setResultType( value ) + .endExpression(); + } + + // Only simple binary expressions are allowed on the LHS. + // If more complex compositions are required then place the sub expression in parentheses + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + +private: + template + ResultBuilder& captureExpression( RhsT const& rhs ) { + return m_rb + .setResultType( Internal::compare( m_lhs, rhs ) ) + .setLhs( Catch::toString( m_lhs ) ) + .setRhs( Catch::toString( rhs ) ) + .setOp( Internal::OperatorTraits::getName() ); + } + +private: + ResultBuilder& m_rb; + T m_lhs; +}; + +} // end namespace Catch + + +namespace Catch { + + template + inline ExpressionLhs ResultBuilder::operator->* ( T const& operand ) { + return ExpressionLhs( *this, operand ); + } + + inline ExpressionLhs ResultBuilder::operator->* ( bool value ) { + return ExpressionLhs( *this, value ); + } + +} // namespace Catch + +// #included from: catch_message.h +#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED + +#include + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + SourceLineInfo lineInfo; + ResultWas::OfType type; + std::string message; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const { + return sequence == other.sequence; + } + bool operator < ( MessageInfo const& other ) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + + struct MessageBuilder { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + : m_info( macroName, lineInfo, type ) + {} + + template + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + MessageInfo m_info; + std::ostringstream m_stream; + }; + + class ScopedMessage { + public: + ScopedMessage( MessageBuilder const& builder ); + ScopedMessage( ScopedMessage const& other ); + ~ScopedMessage(); + + MessageInfo m_info; + }; + +} // end namespace Catch + +// #included from: catch_interfaces_capture.h +#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct MessageInfo; + class ScopedMessageBuilder; + struct Counts; + + struct IResultCapture { + + virtual ~IResultCapture(); + + virtual void assertionEnded( AssertionResult const& result ) = 0; + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0; + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + }; + + IResultCapture& getResultCapture(); +} + +// #included from: catch_debugger.h +#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED + +// #included from: catch_platform.h +#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED + +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_IPHONE +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CATCH_PLATFORM_WINDOWS +#endif + +#include + +namespace Catch{ + + bool isDebuggerActive(); + void writeToDebugConsole( std::string const& text ); +} + +#ifdef CATCH_PLATFORM_MAC + + // The following code snippet based on: + // http://cocoawithlove.com/2008/03/break-into-debugger.html + #ifdef DEBUG + #if defined(__ppc64__) || defined(__ppc__) + #define CATCH_BREAK_INTO_DEBUGGER() \ + if( Catch::isDebuggerActive() ) { \ + __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ + : : : "memory","r0","r3","r4" ); \ + } + #else + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} + #endif + #endif + +#elif defined(_MSC_VER) + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } +#endif + +#ifndef CATCH_BREAK_INTO_DEBUGGER +#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); +#endif + +// #included from: catch_interfaces_runner.h +#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED + +namespace Catch { + class TestCase; + + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// In the event of a failure works out if the debugger needs to be invoked +// and/or an exception thrown and takes appropriate action. +// This needs to be done as a macro so the debugger will stop in the user +// source code rather than in Catch library code +#define INTERNAL_CATCH_REACT( resultBuilder ) \ + if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ + resultBuilder.react(); + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + ( __catchResult->*expr ).endExpression(); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::isTrue( false && (expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( !Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( ... ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( exceptionType ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#else + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << log + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#endif + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( log, macroName ) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \ + try { \ + std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \ + __catchResult \ + .setLhs( Catch::toString( arg ) ) \ + .setRhs( matcherAsString == "{?}" ? #matcher : matcherAsString ) \ + .setOp( "matches" ) \ + .setResultType( ::Catch::Matchers::matcher.match( arg ) ); \ + __catchResult.captureExpression(); \ + } catch( ... ) { \ + __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +// #included from: internal/catch_section.h +#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED + +// #included from: catch_section_info.h +#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED + +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + +} // end namespace Catch + +// #included from: catch_totals.hpp +#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED + +#include + +namespace Catch { + + struct Counts { + Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} + + Counts operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + diff.failedButOk = failedButOk - other.failedButOk; + return diff; + } + Counts& operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; + } + + std::size_t total() const { + return passed + failed + failedButOk; + } + bool allPassed() const { + return failed == 0 && failedButOk == 0; + } + + std::size_t passed; + std::size_t failed; + std::size_t failedButOk; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else if( diff.assertions.failedButOk > 0 ) + ++diff.testCases.failedButOk; + else + ++diff.testCases.passed; + return diff; + } + + Totals& operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Counts assertions; + Counts testCases; + }; +} + +// #included from: catch_timer.h +#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED + +#ifdef CATCH_PLATFORM_WINDOWS +typedef unsigned long long uint64_t; +#else +#include +#endif + +namespace Catch { + + class Timer { + public: + Timer() : m_ticks( 0 ) {} + void start(); + unsigned int getElapsedNanoseconds() const; + unsigned int getElapsedMilliseconds() const; + double getElapsedSeconds() const; + + private: + uint64_t m_ticks; + }; + +} // namespace Catch + +#include + +namespace Catch { + + class Section { + public: + Section( SectionInfo const& info ); + ~Section(); + + // This indicates whether the section should be executed or not + operator bool() const; + + private: +#ifdef CATCH_CPP11_OR_GREATER + Section( Section const& ) = delete; + Section( Section && ) = delete; + Section& operator = ( Section const& ) = delete; + Section& operator = ( Section && ) = delete; +#else + Section( Section const& info ); + Section& operator = ( Section const& ); +#endif + SectionInfo m_info; + + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_SECTION( ... ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) +#else + #define INTERNAL_CATCH_SECTION( name, desc ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) +#endif + +// #included from: internal/catch_generators.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + +template +struct IGenerator { + virtual ~IGenerator() {} + virtual T getValue( std::size_t index ) const = 0; + virtual std::size_t size () const = 0; +}; + +template +class BetweenGenerator : public IGenerator { +public: + BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} + + virtual T getValue( std::size_t index ) const { + return m_from+static_cast( index ); + } + + virtual std::size_t size() const { + return static_cast( 1+m_to-m_from ); + } + +private: + + T m_from; + T m_to; +}; + +template +class ValuesGenerator : public IGenerator { +public: + ValuesGenerator(){} + + void add( T value ) { + m_values.push_back( value ); + } + + virtual T getValue( std::size_t index ) const { + return m_values[index]; + } + + virtual std::size_t size() const { + return m_values.size(); + } + +private: + std::vector m_values; +}; + +template +class CompositeGenerator { +public: + CompositeGenerator() : m_totalSize( 0 ) {} + + // *** Move semantics, similar to auto_ptr *** + CompositeGenerator( CompositeGenerator& other ) + : m_fileInfo( other.m_fileInfo ), + m_totalSize( 0 ) + { + move( other ); + } + + CompositeGenerator& setFileInfo( const char* fileInfo ) { + m_fileInfo = fileInfo; + return *this; + } + + ~CompositeGenerator() { + deleteAll( m_composed ); + } + + operator T () const { + size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); + + typename std::vector*>::const_iterator it = m_composed.begin(); + typename std::vector*>::const_iterator itEnd = m_composed.end(); + for( size_t index = 0; it != itEnd; ++it ) + { + const IGenerator* generator = *it; + if( overallIndex >= index && overallIndex < index + generator->size() ) + { + return generator->getValue( overallIndex-index ); + } + index += generator->size(); + } + CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); + return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so + } + + void add( const IGenerator* generator ) { + m_totalSize += generator->size(); + m_composed.push_back( generator ); + } + + CompositeGenerator& then( CompositeGenerator& other ) { + move( other ); + return *this; + } + + CompositeGenerator& then( T value ) { + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( value ); + add( valuesGen ); + return *this; + } + +private: + + void move( CompositeGenerator& other ) { + std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); + m_totalSize += other.m_totalSize; + other.m_composed.clear(); + } + + std::vector*> m_composed; + std::string m_fileInfo; + size_t m_totalSize; +}; + +namespace Generators +{ + template + CompositeGenerator between( T from, T to ) { + CompositeGenerator generators; + generators.add( new BetweenGenerator( from, to ) ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3 ){ + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3, T val4 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + valuesGen->add( val4 ); + generators.add( valuesGen ); + return generators; + } + +} // end namespace Generators + +using namespace Generators; + +} // end namespace Catch + +#define INTERNAL_CATCH_LINESTR2( line ) #line +#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) + +#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) + +// #included from: internal/catch_interfaces_exception.h +#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED + +#include +// #included from: catch_interfaces_registry_hub.h +#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; + + struct IRegistryHub { + virtual ~IRegistryHub(); + + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + }; + + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0; + virtual void registerTest( TestCase const& testInfo ) = 0; + virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + }; + + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + + +namespace Catch { + + typedef std::string(*exceptionTranslateFunction)(); + + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate() const = 0; + }; + + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + virtual std::string translate() const { + try { + throw; + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator( translateFunction ) ); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) + +// #included from: internal/catch_approx.hpp +#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED + +#include +#include + +namespace Catch { +namespace Detail { + + class Approx { + public: + explicit Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx( Approx const& other ) + : m_epsilon( other.m_epsilon ), + m_scale( other.m_scale ), + m_value( other.m_value ) + {} + + static Approx custom() { + return Approx( 0 ); + } + + Approx operator()( double value ) { + Approx approx( value ); + approx.epsilon( m_epsilon ); + approx.scale( m_scale ); + return approx; + } + + friend bool operator == ( double lhs, Approx const& rhs ) { + // Thanks to Richard Harris for his help refining this formula + return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); + } + + friend bool operator == ( Approx const& lhs, double rhs ) { + return operator==( rhs, lhs ); + } + + friend bool operator != ( double lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + friend bool operator != ( Approx const& lhs, double rhs ) { + return !operator==( rhs, lhs ); + } + + Approx& epsilon( double newEpsilon ) { + m_epsilon = newEpsilon; + return *this; + } + + Approx& scale( double newScale ) { + m_scale = newScale; + return *this; + } + + std::string toString() const { + std::ostringstream oss; + oss << "Approx( " << Catch::toString( m_value ) << " )"; + return oss.str(); + } + + private: + double m_epsilon; + double m_scale; + double m_value; + }; +} + +template<> +inline std::string toString( Detail::Approx const& value ) { + return value.toString(); +} + +} // end namespace Catch + +// #included from: internal/catch_matchers.hpp +#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED + +namespace Catch { +namespace Matchers { + namespace Impl { + + template + struct Matcher : SharedImpl + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + }; + + template + struct MatcherImpl : Matcher { + + virtual Ptr > clone() const { + return Ptr >( new DerivedT( static_cast( *this ) ) ); + } + }; + + namespace Generic { + + template + class AllOf : public MatcherImpl, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + private: + std::vector > > m_matchers; + }; + + template + class AnyOf : public MatcherImpl, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + private: + std::vector > > m_matchers; + }; + + } + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct Equals : MatcherImpl { + Equals( std::string const& str ) : m_str( str ){} + Equals( Equals const& other ) : m_str( other.m_str ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_str == expr; + } + virtual std::string toString() const { + return "equals: \"" + m_str + "\""; + } + + std::string m_str; + }; + + struct Contains : MatcherImpl { + Contains( std::string const& substr ) : m_substr( substr ){} + Contains( Contains const& other ) : m_substr( other.m_substr ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + + struct StartsWith : MatcherImpl { + StartsWith( std::string const& substr ) : m_substr( substr ){} + StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) == 0; + } + virtual std::string toString() const { + return "starts with: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + + struct EndsWith : MatcherImpl { + EndsWith( std::string const& substr ) : m_substr( substr ){} + EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) == expr.size() - m_substr.size(); + } + virtual std::string toString() const { + return "ends with: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str ) { + return Impl::StdString::Equals( str ); + } + inline Impl::StdString::Equals Equals( const char* str ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ) ); + } + inline Impl::StdString::Contains Contains( std::string const& substr ) { + return Impl::StdString::Contains( substr ); + } + inline Impl::StdString::Contains Contains( const char* substr ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + +// #included from: internal/catch_interfaces_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED + +// #included from: catch_tag_alias.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED + +#include + +namespace Catch { + + struct TagAlias { + TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} + + std::string tag; + SourceLineInfo lineInfo; + }; + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } +// #included from: catch_option.hpp +#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED + +namespace Catch { + + // An optional type + template + class Option { + public: + Option() : nullableValue( NULL ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : NULL ) + {} + + ~Option() { + reset(); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = NULL; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != NULL; } + bool none() const { return nullableValue == NULL; } + + bool operator !() const { return nullableValue == NULL; } + operator SafeBool::type() const { + return SafeBool::makeSafe( some() ); + } + + private: + T* nullableValue; + char storage[sizeof(T)]; + }; + +} // end namespace Catch + +namespace Catch { + + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + virtual Option find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + + static ITagAliasRegistry const& get(); + }; + +} // end namespace Catch + +// These files are included here so the single_include script doesn't put them +// in the conditionally compiled sections +// #included from: internal/catch_test_case_info.h +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED + +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + struct ITestCase; + + struct TestCaseInfo { + enum SpecialProperties{ + None = 0, + IsHidden = 1 << 1, + ShouldFail = 1 << 2, + MayFail = 1 << 3, + Throws = 1 << 4 + }; + + TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ); + + TestCaseInfo( TestCaseInfo const& other ); + + bool isHidden() const; + bool throws() const; + bool okToFail() const; + bool expectedToFail() const; + + std::string name; + std::string className; + std::string description; + std::set tags; + std::set lcaseTags; + std::string tagsAsString; + SourceLineInfo lineInfo; + SpecialProperties properties; + }; + + class TestCase : public TestCaseInfo { + public: + + TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( TestCase const& other ); + + TestCase withName( std::string const& _newName ) const; + + void invoke() const; + + TestCaseInfo const& getTestCaseInfo() const; + + void swap( TestCase& other ); + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + TestCase& operator = ( TestCase const& other ); + + private: + Ptr test; + }; + + TestCase makeTestCase( ITestCase* testCase, + std::string const& className, + std::string const& name, + std::string const& description, + SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + + +#ifdef __OBJC__ +// #included from: internal/catch_objc.hpp +#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED + +#import + +#include + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage + +/////////////////////////////////////////////////////////////////////////////// +// This protocol is really only here for (self) documenting purposes, since +// all its methods are optional. +@protocol OcFixture + +@optional + +-(void) setUp; +-(void) tearDown; + +@end + +namespace Catch { + + class OcMethod : public SharedImpl { + + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + + virtual void invoke() const { + id obj = [[m_cls alloc] init]; + + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); + + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; + }; + + namespace Detail{ + + inline std::string getAnnotation( Class cls, + std::string const& annotationName, + std::string const& testCaseName ) { + NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; + SEL sel = NSSelectorFromString( selStr ); + arcSafeRelease( selStr ); + id value = performOptionalSelector( cls, sel ); + if( value ) + return [(NSString*)value UTF8String]; + return ""; + } + } + + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( NULL, 0 ); + + Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); + objc_getClassList( classes, noClasses ); + + for( int c = 0; c < noClasses; c++ ) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList( cls, &count ); + for( u_int m = 0; m < count ; m++ ) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if( startsWith( methodName, "Catch_TestCase_" ) ) { + std::string testCaseName = methodName.substr( 15 ); + std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); + std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); + const char* className = class_getName( cls ); + + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + noTestMethods++; + } + } + free(methods); + } + } + return noTestMethods; + } + + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { + + template + struct StringHolder : MatcherImpl{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } + + NSString* m_substr; + }; + + struct Equals : StringHolder { + Equals( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_substr]; + } + + virtual std::string toString() const { + return "equals string: " + Catch::toString( m_substr ); + } + }; + + struct Contains : StringHolder { + Contains( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } + + virtual std::string toString() const { + return "contains string: " + Catch::toString( m_substr ); + } + }; + + struct StartsWith : StringHolder { + StartsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } + + virtual std::string toString() const { + return "starts with: " + Catch::toString( m_substr ); + } + }; + struct EndsWith : StringHolder { + EndsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } + + virtual std::string toString() const { + return "ends with: " + Catch::toString( m_substr ); + } + }; + + } // namespace NSStringMatchers + } // namespace Impl + + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } + + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } + + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } + + inline Impl::NSStringMatchers::EndsWith + EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } + + } // namespace Matchers + + using namespace Matchers; + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define OC_TEST_CASE( name, desc )\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ +{\ +return @ name; \ +}\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +{ \ +return @ desc; \ +} \ +-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) + +#endif + +#ifdef CATCH_CONFIG_RUNNER +// #included from: internal/catch_impl.hpp +#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED + +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// #included from: catch_runner.hpp +#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED + +// #included from: internal/catch_commandline.hpp +#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED + +// #included from: catch_config.hpp +#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED + +// #included from: catch_test_spec_parser.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_test_spec.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +#include +#include + +namespace Catch { + + class TestSpec { + struct Pattern : SharedImpl<> { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + class NamePattern : public Pattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) { + if( startsWith( m_name, "*" ) ) { + m_name = m_name.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_name, "*" ) ) { + m_name = m_name.substr( 0, m_name.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_name == toLower( testCase.name ); + case WildcardAtStart: + return endsWith( toLower( testCase.name ), m_name ); + case WildcardAtEnd: + return startsWith( toLower( testCase.name ), m_name ); + case WildcardAtBothEnds: + return contains( toLower( testCase.name ), m_name ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string m_name; + WildcardPosition m_wildcard; + }; + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + virtual ~TagPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); + } + private: + std::string m_tag; + }; + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr m_underlyingPattern; + }; + + struct Filter { + std::vector > m_patterns; + + bool matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) + if( !(*it)->matches( testCase ) ) + return false; + return true; + } + }; + + public: + bool hasFilters() const { + return !m_filters.empty(); + } + bool matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } + + private: + std::vector m_filters; + + friend class TestSpecParser; + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +namespace Catch { + + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag }; + Mode m_mode; + bool m_exclusion; + std::size_t m_start, m_pos; + std::string m_arg; + TestSpec::Filter m_currentFilter; + TestSpec m_testSpec; + ITagAliasRegistry const* m_tagAliases; + + public: + TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + + TestSpecParser& parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases( arg ); + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern(); + return *this; + } + TestSpec testSpec() { + addFilter(); + return m_testSpec; + } + private: + void visitChar( char c ) { + if( m_mode == None ) { + switch( c ) { + case ' ': return; + case '~': m_exclusion = true; return; + case '[': return startNewMode( Tag, ++m_pos ); + case '"': return startNewMode( QuotedName, ++m_pos ); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + startNewMode( Tag, ++m_pos ); + } + } + else if( m_mode == QuotedName && c == '"' ) + addPattern(); + else if( m_mode == Tag && c == ']' ) + addPattern(); + } + void startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + template + void addPattern() { + std::string token = subString(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr pattern = new T( token ); + if( m_exclusion ) + pattern = new TestSpec::ExcludedPattern( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + void addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + }; + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// #included from: catch_interfaces_config.h +#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct Verbosity { enum Level { + NoOutput = 0, + Quiet, + Normal + }; }; + + struct WarnAbout { enum What { + Nothing = 0x00, + NoAssertions = 0x01 + }; }; + + struct ShowDurations { enum OrNot { + DefaultForReporter, + Always, + Never + }; }; + + class TestSpec; + + struct IConfig : IShared { + + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + }; +} + +// #included from: catch_stream.h +#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED + +#include + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + class Stream { + public: + Stream(); + Stream( std::streambuf* _streamBuf, bool _isOwned ); + void release(); + + std::streambuf* streamBuf; + + private: + bool isOwned; + }; +} + +#include +#include +#include +#include + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + + struct ConfigData { + + ConfigData() + : listTests( false ), + listTags( false ), + listReporters( false ), + listTestNamesOnly( false ), + showSuccessfulTests( false ), + shouldDebugBreak( false ), + noThrow( false ), + showHelp( false ), + showInvisibles( false ), + abortAfter( -1 ), + verbosity( Verbosity::Normal ), + warnings( WarnAbout::Nothing ), + showDurations( ShowDurations::DefaultForReporter ) + {} + + bool listTests; + bool listTags; + bool listReporters; + bool listTestNamesOnly; + + bool showSuccessfulTests; + bool shouldDebugBreak; + bool noThrow; + bool showHelp; + bool showInvisibles; + + int abortAfter; + + Verbosity::Level verbosity; + WarnAbout::What warnings; + ShowDurations::OrNot showDurations; + + std::string reporterName; + std::string outputFilename; + std::string name; + std::string processName; + + std::vector testsOrTags; + }; + + class Config : public SharedImpl { + private: + Config( Config const& other ); + Config& operator = ( Config const& other ); + virtual void dummy(); + public: + + Config() + : m_os( std::cout.rdbuf() ) + {} + + Config( ConfigData const& data ) + : m_data( data ), + m_os( std::cout.rdbuf() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser( ITagAliasRegistry::get() ); + for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) + parser.parse( data.testsOrTags[i] ); + m_testSpec = parser.testSpec(); + } + } + + virtual ~Config() { + m_os.rdbuf( std::cout.rdbuf() ); + m_stream.release(); + } + + void setFilename( std::string const& filename ) { + m_data.outputFilename = filename; + } + + std::string const& getFilename() const { + return m_data.outputFilename ; + } + + bool listTests() const { return m_data.listTests; } + bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool listTags() const { return m_data.listTags; } + bool listReporters() const { return m_data.listReporters; } + + std::string getProcessName() const { return m_data.processName; } + + bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } + + void setStreamBuf( std::streambuf* buf ) { + m_os.rdbuf( buf ? buf : std::cout.rdbuf() ); + } + + void useStream( std::string const& streamName ) { + Stream stream = createStream( streamName ); + setStreamBuf( stream.streamBuf ); + m_stream.release(); + m_stream = stream; + } + + std::string getReporterName() const { return m_data.reporterName; } + + int abortAfter() const { return m_data.abortAfter; } + + TestSpec const& testSpec() const { return m_testSpec; } + + bool showHelp() const { return m_data.showHelp; } + bool showInvisibles() const { return m_data.showInvisibles; } + + // IConfig interface + virtual bool allowThrows() const { return !m_data.noThrow; } + virtual std::ostream& stream() const { return m_os; } + virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } + virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } + + private: + ConfigData m_data; + + Stream m_stream; + mutable std::ostream m_os; + TestSpec m_testSpec; + }; + +} // end namespace Catch + +// #included from: catch_clara.h +#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#undef CLARA_CONFIG_CONSOLE_WIDTH +#endif +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +// Declare Clara inside the Catch namespace +#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { +// #included from: ../external/clara.h + +// Only use header guard if we are not using an outer namespace +#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) + +#ifndef STITCH_CLARA_OPEN_NAMESPACE +#define TWOBLUECUBES_CLARA_H_INCLUDED +#define STITCH_CLARA_OPEN_NAMESPACE +#define STITCH_CLARA_CLOSE_NAMESPACE +#else +#define STITCH_CLARA_CLOSE_NAMESPACE } +#endif + +#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE + +// ----------- #included from tbc_text_format.h ----------- + +// Only use header guard if we are not using an outer namespace +#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) +#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +#define TBC_TEXT_FORMAT_H_INCLUDED +#endif + +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TBC_TEXT_FORMAT_H_INCLUDED + +// ----------- end of #include from tbc_text_format.h ----------- +// ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h + +#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE + +#include +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_CLARA_OPEN_NAMESPACE +STITCH_CLARA_OPEN_NAMESPACE +#endif + +namespace Clara { + + struct UnpositionalTag {}; + + extern UnpositionalTag _; + +#ifdef CLARA_CONFIG_MAIN + UnpositionalTag _; +#endif + + namespace Detail { + +#ifdef CLARA_CONSOLE_WIDTH + const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + using namespace Tbc; + + inline bool startsWith( std::string const& str, std::string const& prefix ) { + return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; + } + + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + + template struct IsBool { static const bool value = false; }; + template<> struct IsBool { static const bool value = true; }; + + template + void convertInto( std::string const& _source, T& _dest ) { + std::stringstream ss; + ss << _source; + ss >> _dest; + if( ss.fail() ) + throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); + } + inline void convertInto( std::string const& _source, std::string& _dest ) { + _dest = _source; + } + inline void convertInto( std::string const& _source, bool& _dest ) { + std::string sourceLC = _source; + std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower ); + if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) + _dest = true; + else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) + _dest = false; + else + throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); + } + inline void convertInto( bool _source, bool& _dest ) { + _dest = _source; + } + template + inline void convertInto( bool, T& ) { + throw std::runtime_error( "Invalid conversion" ); + } + + template + struct IArgFunction { + virtual ~IArgFunction() {} +# ifdef CATCH_CPP11_OR_GREATER + IArgFunction() = default; + IArgFunction( IArgFunction const& ) = default; +# endif + virtual void set( ConfigT& config, std::string const& value ) const = 0; + virtual void setFlag( ConfigT& config ) const = 0; + virtual bool takesArg() const = 0; + virtual IArgFunction* clone() const = 0; + }; + + template + class BoundArgFunction { + public: + BoundArgFunction() : functionObj( NULL ) {} + BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {} + BoundArgFunction& operator = ( BoundArgFunction const& other ) { + IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL; + delete functionObj; + functionObj = newFunctionObj; + return *this; + } + ~BoundArgFunction() { delete functionObj; } + + void set( ConfigT& config, std::string const& value ) const { + functionObj->set( config, value ); + } + void setFlag( ConfigT& config ) const { + functionObj->setFlag( config ); + } + bool takesArg() const { return functionObj->takesArg(); } + + bool isSet() const { + return functionObj != NULL; + } + private: + IArgFunction* functionObj; + }; + + template + struct NullBinder : IArgFunction{ + virtual void set( C&, std::string const& ) const {} + virtual void setFlag( C& ) const {} + virtual bool takesArg() const { return true; } + virtual IArgFunction* clone() const { return new NullBinder( *this ); } + }; + + template + struct BoundDataMember : IArgFunction{ + BoundDataMember( M C::* _member ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + convertInto( stringValue, p.*member ); + } + virtual void setFlag( C& p ) const { + convertInto( true, p.*member ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } + M C::* member; + }; + template + struct BoundUnaryMethod : IArgFunction{ + BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + (p.*member)( value ); + } + virtual void setFlag( C& p ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + (p.*member)( value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } + void (C::*member)( M ); + }; + template + struct BoundNullaryMethod : IArgFunction{ + BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + (p.*member)(); + } + virtual void setFlag( C& p ) const { + (p.*member)(); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } + void (C::*member)(); + }; + + template + struct BoundUnaryFunction : IArgFunction{ + BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + function( obj ); + } + virtual void setFlag( C& p ) const { + function( p ); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } + void (*function)( C& ); + }; + + template + struct BoundBinaryFunction : IArgFunction{ + BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + function( obj, value ); + } + virtual void setFlag( C& obj ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + function( obj, value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } + void (*function)( C&, T ); + }; + + } // namespace Detail + + struct Parser { + Parser() : separators( " \t=:" ) {} + + struct Token { + enum Type { Positional, ShortOpt, LongOpt }; + Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} + Type type; + std::string data; + }; + + void parseIntoTokens( int argc, char const * const * argv, std::vector& tokens ) const { + const std::string doubleDash = "--"; + for( int i = 1; i < argc && argv[i] != doubleDash; ++i ) + parseIntoTokens( argv[i] , tokens); + } + void parseIntoTokens( std::string arg, std::vector& tokens ) const { + while( !arg.empty() ) { + Parser::Token token( Parser::Token::Positional, arg ); + arg = ""; + if( token.data[0] == '-' ) { + if( token.data.size() > 1 && token.data[1] == '-' ) { + token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) ); + } + else { + token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) ); + if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) { + arg = "-" + token.data.substr( 1 ); + token.data = token.data.substr( 0, 1 ); + } + } + } + if( token.type != Parser::Token::Positional ) { + std::size_t pos = token.data.find_first_of( separators ); + if( pos != std::string::npos ) { + arg = token.data.substr( pos+1 ); + token.data = token.data.substr( 0, pos ); + } + } + tokens.push_back( token ); + } + } + std::string separators; + }; + + template + struct CommonArgProperties { + CommonArgProperties() {} + CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} + + Detail::BoundArgFunction boundField; + std::string description; + std::string detail; + std::string placeholder; // Only value if boundField takes an arg + + bool takesArg() const { + return !placeholder.empty(); + } + void validate() const { + if( !boundField.isSet() ) + throw std::logic_error( "option not bound" ); + } + }; + struct OptionArgProperties { + std::vector shortNames; + std::string longName; + + bool hasShortName( std::string const& shortName ) const { + return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); + } + bool hasLongName( std::string const& _longName ) const { + return _longName == longName; + } + }; + struct PositionalArgProperties { + PositionalArgProperties() : position( -1 ) {} + int position; // -1 means non-positional (floating) + + bool isFixedPositional() const { + return position != -1; + } + }; + + template + class CommandLine { + + struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { + Arg() {} + Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} + + using CommonArgProperties::placeholder; // !TBD + + std::string dbgName() const { + if( !longName.empty() ) + return "--" + longName; + if( !shortNames.empty() ) + return "-" + shortNames[0]; + return "positional args"; + } + std::string commands() const { + std::ostringstream oss; + bool first = true; + std::vector::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); + for(; it != itEnd; ++it ) { + if( first ) + first = false; + else + oss << ", "; + oss << "-" << *it; + } + if( !longName.empty() ) { + if( !first ) + oss << ", "; + oss << "--" << longName; + } + if( !placeholder.empty() ) + oss << " <" << placeholder << ">"; + return oss.str(); + } + }; + + // NOTE: std::auto_ptr is deprecated in c++11/c++0x +#if defined(__cplusplus) && __cplusplus > 199711L + typedef std::unique_ptr ArgAutoPtr; +#else + typedef std::auto_ptr ArgAutoPtr; +#endif + + friend void addOptName( Arg& arg, std::string const& optName ) + { + if( optName.empty() ) + return; + if( Detail::startsWith( optName, "--" ) ) { + if( !arg.longName.empty() ) + throw std::logic_error( "Only one long opt may be specified. '" + + arg.longName + + "' already specified, now attempting to add '" + + optName + "'" ); + arg.longName = optName.substr( 2 ); + } + else if( Detail::startsWith( optName, "-" ) ) + arg.shortNames.push_back( optName.substr( 1 ) ); + else + throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); + } + friend void setPositionalArg( Arg& arg, int position ) + { + arg.position = position; + } + + class ArgBuilder { + public: + ArgBuilder( Arg* arg ) : m_arg( arg ) {} + + // Bind a non-boolean data member (requires placeholder string) + template + void bind( M C::* field, std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + m_arg->placeholder = placeholder; + } + // Bind a boolean data member (no placeholder required) + template + void bind( bool C::* field ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + } + + // Bind a method taking a single, non-boolean argument (requires a placeholder string) + template + void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + m_arg->placeholder = placeholder; + } + + // Bind a method taking a single, boolean argument (no placeholder string required) + template + void bind( void (C::* unaryMethod)( bool ) ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + } + + // Bind a method that takes no arguments (will be called if opt is present) + template + void bind( void (C::* nullaryMethod)() ) { + m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); + } + + // Bind a free function taking a single argument - the object to operate on (no placeholder string required) + template + void bind( void (* unaryFunction)( C& ) ) { + m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); + } + + // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) + template + void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); + m_arg->placeholder = placeholder; + } + + ArgBuilder& describe( std::string const& description ) { + m_arg->description = description; + return *this; + } + ArgBuilder& detail( std::string const& detail ) { + m_arg->detail = detail; + return *this; + } + + protected: + Arg* m_arg; + }; + + class OptBuilder : public ArgBuilder { + public: + OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} + OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} + + OptBuilder& operator[]( std::string const& optName ) { + addOptName( *ArgBuilder::m_arg, optName ); + return *this; + } + }; + + public: + + CommandLine() + : m_boundProcessName( new Detail::NullBinder() ), + m_highestSpecifiedArgPosition( 0 ), + m_throwOnUnrecognisedTokens( false ) + {} + CommandLine( CommandLine const& other ) + : m_boundProcessName( other.m_boundProcessName ), + m_options ( other.m_options ), + m_positionalArgs( other.m_positionalArgs ), + m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), + m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) + { + if( other.m_floatingArg.get() ) + m_floatingArg = ArgAutoPtr( new Arg( *other.m_floatingArg ) ); + } + + CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { + m_throwOnUnrecognisedTokens = shouldThrow; + return *this; + } + + OptBuilder operator[]( std::string const& optName ) { + m_options.push_back( Arg() ); + addOptName( m_options.back(), optName ); + OptBuilder builder( &m_options.back() ); + return builder; + } + + ArgBuilder operator[]( int position ) { + m_positionalArgs.insert( std::make_pair( position, Arg() ) ); + if( position > m_highestSpecifiedArgPosition ) + m_highestSpecifiedArgPosition = position; + setPositionalArg( m_positionalArgs[position], position ); + ArgBuilder builder( &m_positionalArgs[position] ); + return builder; + } + + // Invoke this with the _ instance + ArgBuilder operator[]( UnpositionalTag ) { + if( m_floatingArg.get() ) + throw std::logic_error( "Only one unpositional argument can be added" ); + m_floatingArg = ArgAutoPtr( new Arg() ); + ArgBuilder builder( m_floatingArg.get() ); + return builder; + } + + template + void bindProcessName( M C::* field ) { + m_boundProcessName = new Detail::BoundDataMember( field ); + } + template + void bindProcessName( void (C::*_unaryMethod)( M ) ) { + m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); + } + + void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { + typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; + std::size_t maxWidth = 0; + for( it = itBegin; it != itEnd; ++it ) + maxWidth = (std::max)( maxWidth, it->commands().size() ); + + for( it = itBegin; it != itEnd; ++it ) { + Detail::Text usage( it->commands(), Detail::TextAttributes() + .setWidth( maxWidth+indent ) + .setIndent( indent ) ); + Detail::Text desc( it->description, Detail::TextAttributes() + .setWidth( width - maxWidth - 3 ) ); + + for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { + std::string usageCol = i < usage.size() ? usage[i] : ""; + os << usageCol; + + if( i < desc.size() && !desc[i].empty() ) + os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) + << desc[i]; + os << "\n"; + } + } + } + std::string optUsage() const { + std::ostringstream oss; + optUsage( oss ); + return oss.str(); + } + + void argSynopsis( std::ostream& os ) const { + for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { + if( i > 1 ) + os << " "; + typename std::map::const_iterator it = m_positionalArgs.find( i ); + if( it != m_positionalArgs.end() ) + os << "<" << it->second.placeholder << ">"; + else if( m_floatingArg.get() ) + os << "<" << m_floatingArg->placeholder << ">"; + else + throw std::logic_error( "non consecutive positional arguments with no floating args" ); + } + // !TBD No indication of mandatory args + if( m_floatingArg.get() ) { + if( m_highestSpecifiedArgPosition > 1 ) + os << " "; + os << "[<" << m_floatingArg->placeholder << "> ...]"; + } + } + std::string argSynopsis() const { + std::ostringstream oss; + argSynopsis( oss ); + return oss.str(); + } + + void usage( std::ostream& os, std::string const& procName ) const { + validate(); + os << "usage:\n " << procName << " "; + argSynopsis( os ); + if( !m_options.empty() ) { + os << " [options]\n\nwhere options are: \n"; + optUsage( os, 2 ); + } + os << "\n"; + } + std::string usage( std::string const& procName ) const { + std::ostringstream oss; + usage( oss, procName ); + return oss.str(); + } + + ConfigT parse( int argc, char const * const * argv ) const { + ConfigT config; + parseInto( argc, argv, config ); + return config; + } + + std::vector parseInto( int argc, char const * const * argv, ConfigT& config ) const { + std::string processName = argv[0]; + std::size_t lastSlash = processName.find_last_of( "/\\" ); + if( lastSlash != std::string::npos ) + processName = processName.substr( lastSlash+1 ); + m_boundProcessName.set( config, processName ); + std::vector tokens; + Parser parser; + parser.parseIntoTokens( argc, argv, tokens ); + return populate( tokens, config ); + } + + std::vector populate( std::vector const& tokens, ConfigT& config ) const { + validate(); + std::vector unusedTokens = populateOptions( tokens, config ); + unusedTokens = populateFixedArgs( unusedTokens, config ); + unusedTokens = populateFloatingArgs( unusedTokens, config ); + return unusedTokens; + } + + std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + std::vector errors; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); + for(; it != itEnd; ++it ) { + Arg const& arg = *it; + + try { + if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || + ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { + if( arg.takesArg() ) { + if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) + errors.push_back( "Expected argument to option: " + token.data ); + else + arg.boundField.set( config, tokens[++i].data ); + } + else { + arg.boundField.setFlag( config ); + } + break; + } + } + catch( std::exception& ex ) { + errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); + } + } + if( it == itEnd ) { + if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) + unusedTokens.push_back( token ); + else if( m_throwOnUnrecognisedTokens ) + errors.push_back( "unrecognised option: " + token.data ); + } + } + if( !errors.empty() ) { + std::ostringstream oss; + for( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); + it != itEnd; + ++it ) { + if( it != errors.begin() ) + oss << "\n"; + oss << *it; + } + throw std::runtime_error( oss.str() ); + } + return unusedTokens; + } + std::vector populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + int position = 1; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::map::const_iterator it = m_positionalArgs.find( position ); + if( it != m_positionalArgs.end() ) + it->second.boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + if( token.type == Parser::Token::Positional ) + position++; + } + return unusedTokens; + } + std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { + if( !m_floatingArg.get() ) + return tokens; + std::vector unusedTokens; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + if( token.type == Parser::Token::Positional ) + m_floatingArg->boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + } + return unusedTokens; + } + + void validate() const + { + if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) + throw std::logic_error( "No options or arguments specified" ); + + for( typename std::vector::const_iterator it = m_options.begin(), + itEnd = m_options.end(); + it != itEnd; ++it ) + it->validate(); + } + + private: + Detail::BoundArgFunction m_boundProcessName; + std::vector m_options; + std::map m_positionalArgs; + ArgAutoPtr m_floatingArg; + int m_highestSpecifiedArgPosition; + bool m_throwOnUnrecognisedTokens; + }; + +} // end namespace Clara + +STITCH_CLARA_CLOSE_NAMESPACE +#undef STITCH_CLARA_OPEN_NAMESPACE +#undef STITCH_CLARA_CLOSE_NAMESPACE + +#endif // TWOBLUECUBES_CLARA_H_INCLUDED +#undef STITCH_CLARA_OPEN_NAMESPACE + +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +#include + +namespace Catch { + + inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } + inline void abortAfterX( ConfigData& config, int x ) { + if( x < 1 ) + throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); + config.abortAfter = x; + } + inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + + inline void addWarning( ConfigData& config, std::string const& _warning ) { + if( _warning == "NoAssertions" ) + config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); + else + throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); + + } + inline void setVerbosity( ConfigData& config, int level ) { + // !TBD: accept strings? + config.verbosity = static_cast( level ); + } + inline void setShowDurations( ConfigData& config, bool _showDurations ) { + config.showDurations = _showDurations + ? ShowDurations::Always + : ShowDurations::Never; + } + inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { + std::ifstream f( _filename.c_str() ); + if( !f.is_open() ) + throw std::domain_error( "Unable to load input file: " + _filename ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, "#" ) ) + addTestOrTags( config, "\"" + line + "\"," ); + } + } + + inline Clara::CommandLine makeCommandLineParser() { + + using namespace Clara; + CommandLine cli; + + cli.bindProcessName( &ConfigData::processName ); + + cli["-?"]["-h"]["--help"] + .describe( "display usage information" ) + .bind( &ConfigData::showHelp ); + + cli["-l"]["--list-tests"] + .describe( "list all/matching test cases" ) + .bind( &ConfigData::listTests ); + + cli["-t"]["--list-tags"] + .describe( "list all/matching tags" ) + .bind( &ConfigData::listTags ); + + cli["-s"]["--success"] + .describe( "include successful tests in output" ) + .bind( &ConfigData::showSuccessfulTests ); + + cli["-b"]["--break"] + .describe( "break into debugger on failure" ) + .bind( &ConfigData::shouldDebugBreak ); + + cli["-e"]["--nothrow"] + .describe( "skip exception tests" ) + .bind( &ConfigData::noThrow ); + + cli["-i"]["--invisibles"] + .describe( "show invisibles (tabs, newlines)" ) + .bind( &ConfigData::showInvisibles ); + + cli["-o"]["--out"] + .describe( "output filename" ) + .bind( &ConfigData::outputFilename, "filename" ); + + cli["-r"]["--reporter"] +// .placeholder( "name[:filename]" ) + .describe( "reporter to use (defaults to console)" ) + .bind( &ConfigData::reporterName, "name" ); + + cli["-n"]["--name"] + .describe( "suite name" ) + .bind( &ConfigData::name, "name" ); + + cli["-a"]["--abort"] + .describe( "abort at first failure" ) + .bind( &abortAfterFirst ); + + cli["-x"]["--abortx"] + .describe( "abort after x failures" ) + .bind( &abortAfterX, "no. failures" ); + + cli["-w"]["--warn"] + .describe( "enable warnings" ) + .bind( &addWarning, "warning name" ); + +// - needs updating if reinstated +// cli.into( &setVerbosity ) +// .describe( "level of verbosity (0=no output)" ) +// .shortOpt( "v") +// .longOpt( "verbosity" ) +// .placeholder( "level" ); + + cli[_] + .describe( "which test or tests to use" ) + .bind( &addTestOrTags, "test name, pattern or tags" ); + + cli["-d"]["--durations"] + .describe( "show test durations" ) + .bind( &setShowDurations, "yes/no" ); + + cli["-f"]["--input-file"] + .describe( "load test names to run from a file" ) + .bind( &loadTestNamesFromFile, "filename" ); + + // Less common commands which don't have a short form + cli["--list-test-names-only"] + .describe( "list all/matching test cases names only" ) + .bind( &ConfigData::listTestNamesOnly ); + + cli["--list-reporters"] + .describe( "list all reporters" ) + .bind( &ConfigData::listReporters ); + + return cli; + } + +} // end namespace Catch + +// #included from: internal/catch_list.hpp +#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED + +// #included from: catch_text.h +#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED + +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +// #included from: ../external/tbc_text_format.h +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# endif +# else +# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include +#include +#include + +// Use optional outer namespace +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE + +namespace Catch { + using Tbc::Text; + using Tbc::TextAttributes; +} + +// #included from: catch_console_colour.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED + +namespace Catch { + + namespace Detail { + struct IColourImpl; + } + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + + // By intention + FileName = LightGrey, + Warning = Yellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + Colour( Colour const& other ); + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + static Detail::IColourImpl* impl(); + bool m_moved; + }; + + inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } + +} // end namespace Catch + +// #included from: catch_interfaces_reporter.h +#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED + +#include +#include +#include +#include + +namespace Catch +{ + struct ReporterConfig { + explicit ReporterConfig( Ptr const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) + : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + + std::ostream& stream() const { return *m_stream; } + Ptr fullConfig() const { return m_fullConfig; } + + private: + std::ostream* m_stream; + Ptr m_fullConfig; + }; + + struct ReporterPreferences { + ReporterPreferences() + : shouldRedirectStdOut( false ) + {} + + bool shouldRedirectStdOut; + }; + + template + struct LazyStat : Option { + LazyStat() : used( false ) {} + LazyStat& operator=( T const& _value ) { + Option::operator=( _value ); + used = false; + return *this; + } + void reset() { + Option::reset(); + used = false; + } + bool used; + }; + + struct TestRunInfo { + TestRunInfo( std::string const& _name ) : name( _name ) {} + std::string name; + }; + struct GroupInfo { + GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) + {} + + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; + + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) + { + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); + + infoMessages.push_back( builder.m_info ); + } + } + virtual ~AssertionStats(); + +# ifdef CATCH_CPP11_OR_GREATER + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; +# endif + + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; + }; + + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + virtual ~SectionStats(); +# ifdef CATCH_CPP11_OR_GREATER + SectionStats( SectionStats const& ) = default; + SectionStats( SectionStats && ) = default; + SectionStats& operator = ( SectionStats const& ) = default; + SectionStats& operator = ( SectionStats && ) = default; +# endif + + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; + }; + + struct TestCaseStats { + TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ) + : testInfo( _testInfo ), + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + virtual ~TestCaseStats(); + +# ifdef CATCH_CPP11_OR_GREATER + TestCaseStats( TestCaseStats const& ) = default; + TestCaseStats( TestCaseStats && ) = default; + TestCaseStats& operator = ( TestCaseStats const& ) = default; + TestCaseStats& operator = ( TestCaseStats && ) = default; +# endif + + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; + + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + virtual ~TestGroupStats(); + +# ifdef CATCH_CPP11_OR_GREATER + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; +# endif + + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; + + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + virtual ~TestRunStats(); + +# ifndef CATCH_CPP11_OR_GREATER + TestRunStats( TestRunStats const& _other ) + : runInfo( _other.runInfo ), + totals( _other.totals ), + aborting( _other.aborting ) + {} +# else + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; +# endif + + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; + + struct IStreamingReporter : IShared { + virtual ~IStreamingReporter(); + + // Implementing class must also provide the following static method: + // static std::string getDescription(); + + virtual ReporterPreferences getPreferences() const = 0; + + virtual void noMatchingTestCases( std::string const& spec ) = 0; + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; + virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + + virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; + virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + }; + + struct IReporterFactory { + virtual ~IReporterFactory(); + virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; + + struct IReporterRegistry { + typedef std::map FactoryMap; + + virtual ~IReporterRegistry(); + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + }; + +} + +#include +#include + +namespace Catch { + + inline std::size_t listTests( Config const& config ) { + + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + std::cout << "Matching test cases:\n"; + else { + std::cout << "All available test cases:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::size_t matchedTests = 0; + TextAttributes nameAttr, tagsAttr; + nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + tagsAttr.setIndent( 6 ); + + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Colour::Code colour = testCaseInfo.isHidden() + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard( colour ); + + std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl; + if( !testCaseInfo.tags.empty() ) + std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; + } + + if( !config.testSpec().hasFilters() ) + std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl; + else + std::cout << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; + return matchedTests; + } + + inline std::size_t listTestsNamesOnly( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( !config.testSpec().hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + std::size_t matchedTests = 0; + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + std::cout << testCaseInfo.name << std::endl; + } + return matchedTests; + } + + struct TagInfo { + TagInfo() : count ( 0 ) {} + void add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } + std::string all() const { + std::string out; + for( std::set::const_iterator it = spellings.begin(), itEnd = spellings.end(); + it != itEnd; + ++it ) + out += "[" + *it + "]"; + return out; + } + std::set spellings; + std::size_t count; + }; + + inline std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + std::cout << "Tags for matching test cases:\n"; + else { + std::cout << "All available tags:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::map tagCounts; + + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + for( std::set::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), + tagItEnd = it->getTestCaseInfo().tags.end(); + tagIt != tagItEnd; + ++tagIt ) { + std::string tagName = *tagIt; + std::string lcaseTagName = toLower( tagName ); + std::map::iterator countIt = tagCounts.find( lcaseTagName ); + if( countIt == tagCounts.end() ) + countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; + countIt->second.add( tagName ); + } + } + + for( std::map::const_iterator countIt = tagCounts.begin(), + countItEnd = tagCounts.end(); + countIt != countItEnd; + ++countIt ) { + std::ostringstream oss; + oss << " " << std::setw(2) << countIt->second.count << " "; + Text wrapper( countIt->second.all(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( oss.str().size() ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); + std::cout << oss.str() << wrapper << "\n"; + } + std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; + return tagCounts.size(); + } + + inline std::size_t listReporters( Config const& /*config*/ ) { + std::cout << "Available reports:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; + std::size_t maxNameLen = 0; + for(it = itBegin; it != itEnd; ++it ) + maxNameLen = (std::max)( maxNameLen, it->first.size() ); + + for(it = itBegin; it != itEnd; ++it ) { + Text wrapper( it->second->getDescription(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( 7+maxNameLen ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); + std::cout << " " + << it->first + << ":" + << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << wrapper << "\n"; + } + std::cout << std::endl; + return factories.size(); + } + + inline Option list( Config const& config ) { + Option listedCount; + if( config.listTests() ) + listedCount = listedCount.valueOr(0) + listTests( config ); + if( config.listTestNamesOnly() ) + listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); + if( config.listTags() ) + listedCount = listedCount.valueOr(0) + listTags( config ); + if( config.listReporters() ) + listedCount = listedCount.valueOr(0) + listReporters( config ); + return listedCount; + } + +} // end namespace Catch + +// #included from: internal/catch_runner_impl.hpp +#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED + +// #included from: catch_test_case_tracker.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { +namespace SectionTracking { + + class TrackedSection { + + typedef std::map TrackedSections; + + public: + enum RunState { + NotStarted, + Executing, + ExecutingChildren, + Completed + }; + + TrackedSection( std::string const& name, TrackedSection* parent ) + : m_name( name ), m_runState( NotStarted ), m_parent( parent ) + {} + + RunState runState() const { return m_runState; } + + TrackedSection* findChild( std::string const& childName ) { + TrackedSections::iterator it = m_children.find( childName ); + return it != m_children.end() + ? &it->second + : NULL; + } + TrackedSection* acquireChild( std::string const& childName ) { + if( TrackedSection* child = findChild( childName ) ) + return child; + m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) ); + return findChild( childName ); + } + void enter() { + if( m_runState == NotStarted ) + m_runState = Executing; + } + void leave() { + for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end(); + it != itEnd; + ++it ) + if( it->second.runState() != Completed ) { + m_runState = ExecutingChildren; + return; + } + m_runState = Completed; + } + TrackedSection* getParent() { + return m_parent; + } + bool hasChildren() const { + return !m_children.empty(); + } + + private: + std::string m_name; + RunState m_runState; + TrackedSections m_children; + TrackedSection* m_parent; + + }; + + class TestCaseTracker { + public: + TestCaseTracker( std::string const& testCaseName ) + : m_testCase( testCaseName, NULL ), + m_currentSection( &m_testCase ), + m_completedASectionThisRun( false ) + {} + + bool enterSection( std::string const& name ) { + TrackedSection* child = m_currentSection->acquireChild( name ); + if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed ) + return false; + + m_currentSection = child; + m_currentSection->enter(); + return true; + } + void leaveSection() { + m_currentSection->leave(); + m_currentSection = m_currentSection->getParent(); + assert( m_currentSection != NULL ); + m_completedASectionThisRun = true; + } + + bool currentSectionHasChildren() const { + return m_currentSection->hasChildren(); + } + bool isCompleted() const { + return m_testCase.runState() == TrackedSection::Completed; + } + + class Guard { + public: + Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) { + m_tracker.enterTestCase(); + } + ~Guard() { + m_tracker.leaveTestCase(); + } + private: + Guard( Guard const& ); + void operator = ( Guard const& ); + TestCaseTracker& m_tracker; + }; + + private: + void enterTestCase() { + m_currentSection = &m_testCase; + m_completedASectionThisRun = false; + m_testCase.enter(); + } + void leaveTestCase() { + m_testCase.leave(); + } + + TrackedSection m_testCase; + TrackedSection* m_currentSection; + bool m_completedASectionThisRun; + }; + +} // namespace SectionTracking + +using SectionTracking::TestCaseTracker; + +} // namespace Catch + +#include +#include + +namespace Catch { + + class StreamRedirect { + + public: + StreamRedirect( std::ostream& stream, std::string& targetString ) + : m_stream( stream ), + m_prevBuf( stream.rdbuf() ), + m_targetString( targetString ) + { + stream.rdbuf( m_oss.rdbuf() ); + } + + ~StreamRedirect() { + m_targetString += m_oss.str(); + m_stream.rdbuf( m_prevBuf ); + } + + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + RunContext( RunContext const& ); + void operator =( RunContext const& ); + + public: + + explicit RunContext( Ptr const& config, Ptr const& reporter ) + : m_runInfo( config->name() ), + m_context( getCurrentMutableContext() ), + m_activeTestCase( NULL ), + m_config( config ), + m_reporter( reporter ), + m_prevRunner( m_context.getRunner() ), + m_prevResultCapture( m_context.getResultCapture() ), + m_prevConfig( m_context.getConfig() ) + { + m_context.setRunner( this ); + m_context.setConfig( m_config ); + m_context.setResultCapture( this ); + m_reporter->testRunStarting( m_runInfo ); + } + + virtual ~RunContext() { + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); + m_context.setRunner( m_prevRunner ); + m_context.setConfig( NULL ); + m_context.setResultCapture( m_prevResultCapture ); + m_context.setConfig( m_prevConfig ); + } + + void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); + } + void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); + } + + Totals runTest( TestCase const& testCase ) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + TestCaseInfo testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting( testInfo ); + + m_activeTestCase = &testCase; + m_testCaseTracker = TestCaseTracker( testInfo.name ); + + do { + do { + runCurrentTest( redirectedCout, redirectedCerr ); + } + while( !m_testCaseTracker->isCompleted() && !aborting() ); + } + while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); + + Totals deltaTotals = m_totals.delta( prevTotals ); + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting() ) ); + + m_activeTestCase = NULL; + m_testCaseTracker.reset(); + + return deltaTotals; + } + + Ptr config() const { + return m_config; + } + + private: // IResultCapture + + virtual void assertionEnded( AssertionResult const& result ) { + if( result.getResultType() == ResultWas::Ok ) { + m_totals.assertions.passed++; + } + else if( !result.isOk() ) { + m_totals.assertions.failed++; + } + + if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) + m_messages.clear(); + + // Reset working state + m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + m_lastResult = result; + } + + virtual bool sectionStarted ( + SectionInfo const& sectionInfo, + Counts& assertions + ) + { + std::ostringstream oss; + oss << sectionInfo.name << "@" << sectionInfo.lineInfo; + + if( !m_testCaseTracker->enterSection( oss.str() ) ) + return false; + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting( sectionInfo ); + + assertions = m_totals.assertions; + + return true; + } + bool testForMissingAssertions( Counts& assertions ) { + if( assertions.total() != 0 || + !m_config->warnAboutMissingAssertions() || + m_testCaseTracker->currentSectionHasChildren() ) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) { + if( std::uncaught_exception() ) { + m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) ); + return; + } + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + m_testCaseTracker->leaveSection(); + + m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) ); + m_messages.clear(); + } + + virtual void pushScopedMessage( MessageInfo const& message ) { + m_messages.push_back( message ); + } + + virtual void popScopedMessage( MessageInfo const& message ) { + m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); + } + + virtual std::string getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : ""; + } + + virtual const AssertionResult* getLastResult() const { + return &m_lastResult; + } + + public: + // !TBD We need to do this another way! + bool aborting() const { + return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); + } + + private: + + void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + m_reporter->sectionStarting( testCaseSection ); + Counts prevAssertions = m_totals.assertions; + double duration = 0; + try { + m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); + TestCaseTracker::Guard guard( *m_testCaseTracker ); + + Timer timer; + timer.start(); + if( m_reporter->getPreferences().shouldRedirectStdOut ) { + StreamRedirect coutRedir( std::cout, redirectedCout ); + StreamRedirect cerrRedir( std::cerr, redirectedCerr ); + m_activeTestCase->invoke(); + } + else { + m_activeTestCase->invoke(); + } + duration = timer.getElapsedSeconds(); + } + catch( TestFailureException& ) { + // This just means the test was aborted due to failure + } + catch(...) { + ResultBuilder exResult( m_lastAssertionInfo.macroName.c_str(), + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression.c_str(), + m_lastAssertionInfo.resultDisposition ); + exResult.useActiveException(); + } + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it ) + sectionEnded( it->info, it->prevAssertions, it->durationInSeconds ); + m_unfinishedSections.clear(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( testCaseInfo.okToFail() ) { + std::swap( assertions.failedButOk, assertions.failed ); + m_totals.assertions.failed -= assertions.failedButOk; + m_totals.assertions.failedButOk += assertions.failedButOk; + } + + SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); + m_reporter->sectionEnded( testCaseSectionStats ); + } + + private: + struct UnfinishedSections { + UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds ) + : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo info; + Counts prevAssertions; + double durationInSeconds; + }; + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase; + Option m_testCaseTracker; + AssertionResult m_lastResult; + + Ptr m_config; + Totals m_totals; + Ptr m_reporter; + std::vector m_messages; + IRunner* m_prevRunner; + IResultCapture* m_prevResultCapture; + Ptr m_prevConfig; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + }; + + IResultCapture& getResultCapture() { + if( IResultCapture* capture = getCurrentContext().getResultCapture() ) + return *capture; + else + throw std::logic_error( "No result capture instance" ); + } + +} // end namespace Catch + +// #included from: internal/catch_version.h +#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED + +namespace Catch { + + // Versioning information + struct Version { + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _buildNumber, + char const* const _branchName ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + buildNumber( _buildNumber ), + branchName( _branchName ) + {} + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const buildNumber; + char const* const branchName; + + private: + void operator=( Version const& ); + }; + + extern Version libraryVersion; +} + +#include +#include +#include + +namespace Catch { + + class Runner { + + public: + Runner( Ptr const& config ) + : m_config( config ) + { + openStream(); + makeReporter(); + } + + Totals runTests() { + + RunContext context( m_config.get(), m_reporter ); + + Totals totals; + + context.testGroupStarting( "", 1, 1 ); // deprecated? + + TestSpec testSpec = m_config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector testCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases ); + + int testsRunForGroup = 0; + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) { + testsRunForGroup++; + if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) { + + if( context.aborting() ) + break; + + totals += context.runTest( *it ); + m_testsAlreadyRun.insert( *it ); + } + } + context.testGroupEnded( "", totals, 1, 1 ); + return totals; + } + + private: + void openStream() { + // Open output file, if specified + if( !m_config->getFilename().empty() ) { + m_ofs.open( m_config->getFilename().c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << m_config->getFilename() << "'"; + throw std::domain_error( oss.str() ); + } + m_config->setStreamBuf( m_ofs.rdbuf() ); + } + } + void makeReporter() { + std::string reporterName = m_config->getReporterName().empty() + ? "console" + : m_config->getReporterName(); + + m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() ); + if( !m_reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); + } + } + + private: + Ptr m_config; + std::ofstream m_ofs; + Ptr m_reporter; + std::set m_testsAlreadyRun; + }; + + class Session { + static bool alreadyInstantiated; + + public: + + struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; + + Session() + : m_cli( makeCommandLineParser() ) { + if( alreadyInstantiated ) { + std::string msg = "Only one instance of Catch::Session can ever be used"; + std::cerr << msg << std::endl; + throw std::logic_error( msg ); + } + alreadyInstantiated = true; + } + ~Session() { + Catch::cleanUp(); + } + + void showHelp( std::string const& processName ) { + std::cout << "\nCatch v" << libraryVersion.majorVersion << "." + << libraryVersion.minorVersion << " build " + << libraryVersion.buildNumber; + if( libraryVersion.branchName != std::string( "master" ) ) + std::cout << " (" << libraryVersion.branchName << " branch)"; + std::cout << "\n"; + + m_cli.usage( std::cout, processName ); + std::cout << "For more detail usage please see the project docs\n" << std::endl; + } + + int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + try { + m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); + m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); + if( m_configData.showHelp ) + showHelp( m_configData.processName ); + m_config.reset(); + } + catch( std::exception& ex ) { + { + Colour colourGuard( Colour::Red ); + std::cerr << "\nError(s) in input:\n" + << Text( ex.what(), TextAttributes().setIndent(2) ) + << "\n\n"; + } + m_cli.usage( std::cout, m_configData.processName ); + return (std::numeric_limits::max)(); + } + return 0; + } + + void useConfigData( ConfigData const& _configData ) { + m_configData = _configData; + m_config.reset(); + } + + int run( int argc, char* const argv[] ) { + + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + + int run() { + if( m_configData.showHelp ) + return 0; + + try + { + config(); // Force config to be constructed + Runner runner( m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + return static_cast( runner.runTests().assertions.failed ); + } + catch( std::exception& ex ) { + std::cerr << ex.what() << std::endl; + return (std::numeric_limits::max)(); + } + } + + Clara::CommandLine const& cli() const { + return m_cli; + } + std::vector const& unusedTokens() const { + return m_unusedTokens; + } + ConfigData& configData() { + return m_configData; + } + Config& config() { + if( !m_config ) + m_config = new Config( m_configData ); + return *m_config; + } + + private: + Clara::CommandLine m_cli; + std::vector m_unusedTokens; + ConfigData m_configData; + Ptr m_config; + }; + + bool Session::alreadyInstantiated = false; + +} // end namespace Catch + +// #included from: catch_registry_hub.hpp +#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED + +// #included from: catch_test_case_registry_impl.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + class TestRegistry : public ITestCaseRegistry { + public: + TestRegistry() : m_unnamedCount( 0 ) {} + virtual ~TestRegistry(); + + virtual void registerTest( TestCase const& testCase ) { + std::string name = testCase.getTestCaseInfo().name; + if( name == "" ) { + std::ostringstream oss; + oss << "Anonymous test case " << ++m_unnamedCount; + return registerTest( testCase.withName( oss.str() ) ); + } + + if( m_functions.find( testCase ) == m_functions.end() ) { + m_functions.insert( testCase ); + m_functionsInOrder.push_back( testCase ); + if( !testCase.isHidden() ) + m_nonHiddenFunctions.push_back( testCase ); + } + else { + TestCase const& prev = *m_functions.find( testCase ); + { + Colour colourGuard( Colour::Red ); + std::cerr << "error: TEST_CASE( \"" << name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl; + } + exit(1); + } + } + + virtual std::vector const& getAllTests() const { + return m_functionsInOrder; + } + + virtual std::vector const& getAllNonHiddenTests() const { + return m_nonHiddenFunctions; + } + + virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases ) const { + for( std::vector::const_iterator it = m_functionsInOrder.begin(), + itEnd = m_functionsInOrder.end(); + it != itEnd; + ++it ) { + if( testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ) ) + matchingTestCases.push_back( *it ); + } + } + + private: + + std::set m_functions; + std::vector m_functionsInOrder; + std::vector m_nonHiddenFunctions; + size_t m_unnamedCount; + }; + + /////////////////////////////////////////////////////////////////////////// + + class FreeFunctionTestCase : public SharedImpl { + public: + + FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} + + virtual void invoke() const { + m_fun(); + } + + private: + virtual ~FreeFunctionTestCase(); + + TestFunction m_fun; + }; + + inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { + std::string className = classOrQualifiedMethodName; + if( startsWith( className, "&" ) ) + { + std::size_t lastColons = className.rfind( "::" ); + std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); + if( penultimateColons == std::string::npos ) + penultimateColons = 1; + className = className.substr( penultimateColons, lastColons-penultimateColons ); + } + return className; + } + + /////////////////////////////////////////////////////////////////////////// + + AutoReg::AutoReg( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + } + + AutoReg::~AutoReg() {} + + void AutoReg::registerTestCase( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + getMutableRegistryHub().registerTest + ( makeTestCase( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + +} // end namespace Catch + +// #included from: catch_reporter_registry.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED + +#include + +namespace Catch { + + class ReporterRegistry : public IReporterRegistry { + + public: + + virtual ~ReporterRegistry() { + deleteAllValues( m_factories ); + } + + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const { + FactoryMap::const_iterator it = m_factories.find( name ); + if( it == m_factories.end() ) + return NULL; + return it->second->create( ReporterConfig( config ) ); + } + + void registerReporter( std::string const& name, IReporterFactory* factory ) { + m_factories.insert( std::make_pair( name, factory ) ); + } + + FactoryMap const& getFactories() const { + return m_factories; + } + + private: + FactoryMap m_factories; + }; +} + +// #included from: catch_exception_translator_registry.hpp +#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED + +#ifdef __OBJC__ +#import "Foundation/Foundation.h" +#endif + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry() { + deleteAll( m_translators ); + } + + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( translator ); + } + + virtual std::string translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + throw; + } + @catch (NSException *exception) { + return toString( [exception description] ); + } +#else + throw; +#endif + } + catch( TestFailureException& ) { + throw; + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return tryTranslators( m_translators.begin() ); + } + } + + std::string tryTranslators( std::vector::const_iterator it ) const { + if( it == m_translators.end() ) + return "Unknown exception"; + + try { + return (*it)->translate(); + } + catch(...) { + return tryTranslators( it+1 ); + } + } + + private: + std::vector m_translators; + }; +} + +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub { + + RegistryHub( RegistryHub const& ); + void operator=( RegistryHub const& ); + + public: // IRegistryHub + RegistryHub() { + } + virtual IReporterRegistry const& getReporterRegistry() const { + return m_reporterRegistry; + } + virtual ITestCaseRegistry const& getTestCaseRegistry() const { + return m_testCaseRegistry; + } + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() { + return m_exceptionTranslatorRegistry; + } + + public: // IMutableRegistryHub + virtual void registerReporter( std::string const& name, IReporterFactory* factory ) { + m_reporterRegistry.registerReporter( name, factory ); + } + virtual void registerTest( TestCase const& testInfo ) { + m_testCaseRegistry.registerTest( testInfo ); + } + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + }; + + // Single, global, instance + inline RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = NULL; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = NULL; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + +} // end namespace Catch + +// #included from: catch_notimplemented_exception.hpp +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED + +#include + +namespace Catch { + + NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) + : m_lineInfo( lineInfo ) { + std::ostringstream oss; + oss << lineInfo << ": function "; + oss << "not implemented"; + m_what = oss.str(); + } + + const char* NotImplementedException::what() const CATCH_NOEXCEPT { + return m_what.c_str(); + } + +} // end namespace Catch + +// #included from: catch_context_impl.hpp +#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED + +// #included from: catch_stream.hpp +#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED + +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED + +#include + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() CATCH_NOEXCEPT; + }; +} + +#include +#include + +namespace Catch { + + template + class StreamBufImpl : public StreamBufBase { + char data[bufferSize]; + WriterF m_writer; + + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); + } + + ~StreamBufImpl() CATCH_NOEXCEPT { + sync(); + } + + private: + int overflow( int c ) { + sync(); + + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast( c ) ) ); + else + sputc( static_cast( c ) ); + } + return 0; + } + + int sync() { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + Stream::Stream() + : streamBuf( NULL ), isOwned( false ) + {} + + Stream::Stream( std::streambuf* _streamBuf, bool _isOwned ) + : streamBuf( _streamBuf ), isOwned( _isOwned ) + {} + + void Stream::release() { + if( isOwned ) { + delete streamBuf; + streamBuf = NULL; + isOwned = false; + } + } +} + +namespace Catch { + + class Context : public IMutableContext { + + Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {} + Context( Context const& ); + void operator=( Context const& ); + + public: // IContext + virtual IResultCapture* getResultCapture() { + return m_resultCapture; + } + virtual IRunner* getRunner() { + return m_runner; + } + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { + return getGeneratorsForCurrentTest() + .getGeneratorInfo( fileInfo, totalSize ) + .getCurrentIndex(); + } + virtual bool advanceGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + return generators && generators->moveNext(); + } + + virtual Ptr getConfig() const { + return m_config; + } + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ) { + m_resultCapture = resultCapture; + } + virtual void setRunner( IRunner* runner ) { + m_runner = runner; + } + virtual void setConfig( Ptr const& config ) { + m_config = config; + } + + friend IMutableContext& getCurrentMutableContext(); + + private: + IGeneratorsForTest* findGeneratorsForCurrentTest() { + std::string testName = getResultCapture()->getCurrentTestName(); + + std::map::const_iterator it = + m_generatorsByTestName.find( testName ); + return it != m_generatorsByTestName.end() + ? it->second + : NULL; + } + + IGeneratorsForTest& getGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + if( !generators ) { + std::string testName = getResultCapture()->getCurrentTestName(); + generators = createGeneratorsForTest(); + m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); + } + return *generators; + } + + private: + Ptr m_config; + IRunner* m_runner; + IResultCapture* m_resultCapture; + std::map m_generatorsByTestName; + }; + + namespace { + Context* currentContext = NULL; + } + IMutableContext& getCurrentMutableContext() { + if( !currentContext ) + currentContext = new Context(); + return *currentContext; + } + IContext& getCurrentContext() { + return getCurrentMutableContext(); + } + + Stream createStream( std::string const& streamName ) { + if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false ); + if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false ); + if( streamName == "debug" ) return Stream( new StreamBufImpl, true ); + + throw std::domain_error( "Unknown stream: " + streamName ); + } + + void cleanUpContext() { + delete currentContext; + currentContext = NULL; + } +} + +// #included from: catch_console_colour_impl.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED + +namespace Catch { namespace Detail { + struct IColourImpl { + virtual ~IColourImpl() {} + virtual void use( Colour::Code _colourCode ) = 0; + }; +}} + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +namespace Catch { +namespace { + + class Win32ColourImpl : public Detail::IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalAttributes = csbiInfo.wAttributes; + } + + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalAttributes ); + case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::Red: return setTextAttribute( FOREGROUND_RED ); + case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); + case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); + case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); + case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::Grey: return setTextAttribute( 0 ); + + case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); + case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); + case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); + case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + + private: + void setTextAttribute( WORD _textAttribute ) { + SetConsoleTextAttribute( stdoutHandle, _textAttribute ); + } + HANDLE stdoutHandle; + WORD originalAttributes; + }; + + inline bool shouldUseColourForPlatform() { + return true; + } + + static Detail::IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + return &s_instance; + } + +} // end anon namespace +} // end namespace Catch + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +#include + +namespace Catch { +namespace { + + // use POSIX/ ANSI console terminal codes + // Thanks to Adam Strzelecki for original contribution + // (http://github.com/nanoant) + // https://github.com/philsquared/Catch/pull/131 + class PosixColourImpl : public Detail::IColourImpl { + public: + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: + case Colour::White: return setColour( "[0m" ); + case Colour::Red: return setColour( "[0;31m" ); + case Colour::Green: return setColour( "[0;32m" ); + case Colour::Blue: return setColour( "[0:34m" ); + case Colour::Cyan: return setColour( "[0;36m" ); + case Colour::Yellow: return setColour( "[0;33m" ); + case Colour::Grey: return setColour( "[1;30m" ); + + case Colour::LightGrey: return setColour( "[0;37m" ); + case Colour::BrightRed: return setColour( "[1;31m" ); + case Colour::BrightGreen: return setColour( "[1;32m" ); + case Colour::BrightWhite: return setColour( "[1;37m" ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + private: + void setColour( const char* _escapeCode ) { + std::cout << '\033' << _escapeCode; + } + }; + + inline bool shouldUseColourForPlatform() { + return isatty(STDOUT_FILENO); + } + + static Detail::IColourImpl* platformColourInstance() { + static PosixColourImpl s_instance; + return &s_instance; + } + +} // end anon namespace +} // end namespace Catch + +#endif // not Windows + +namespace Catch { + + namespace { + struct NoColourImpl : Detail::IColourImpl { + void use( Colour::Code ) {} + + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + static bool shouldUseColour() { + return shouldUseColourForPlatform() && !isDebuggerActive(); + } + } + + Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } + Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } + Colour::~Colour(){ if( !m_moved ) use( None ); } + void Colour::use( Code _colourCode ) { + impl()->use( _colourCode ); + } + + Detail::IColourImpl* Colour::impl() { + return shouldUseColour() + ? platformColourInstance() + : NoColourImpl::instance(); + } + +} // end namespace Catch + +// #included from: catch_generators_impl.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct GeneratorInfo : IGeneratorInfo { + + GeneratorInfo( std::size_t size ) + : m_size( size ), + m_currentIndex( 0 ) + {} + + bool moveNext() { + if( ++m_currentIndex == m_size ) { + m_currentIndex = 0; + return false; + } + return true; + } + + std::size_t getCurrentIndex() const { + return m_currentIndex; + } + + std::size_t m_size; + std::size_t m_currentIndex; + }; + + /////////////////////////////////////////////////////////////////////////// + + class GeneratorsForTest : public IGeneratorsForTest { + + public: + ~GeneratorsForTest() { + deleteAll( m_generatorsInOrder ); + } + + IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { + std::map::const_iterator it = m_generatorsByName.find( fileInfo ); + if( it == m_generatorsByName.end() ) { + IGeneratorInfo* info = new GeneratorInfo( size ); + m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); + m_generatorsInOrder.push_back( info ); + return *info; + } + return *it->second; + } + + bool moveNext() { + std::vector::const_iterator it = m_generatorsInOrder.begin(); + std::vector::const_iterator itEnd = m_generatorsInOrder.end(); + for(; it != itEnd; ++it ) { + if( (*it)->moveNext() ) + return true; + } + return false; + } + + private: + std::map m_generatorsByName; + std::vector m_generatorsInOrder; + }; + + IGeneratorsForTest* createGeneratorsForTest() + { + return new GeneratorsForTest(); + } + +} // end namespace Catch + +// #included from: catch_assertionresult.hpp +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED + +namespace Catch { + + AssertionInfo::AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + capturedExpression( _capturedExpression ), + resultDisposition( _resultDisposition ) + {} + + AssertionResult::AssertionResult() {} + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + AssertionResult::~AssertionResult() {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return !m_info.capturedExpression.empty(); + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if( isFalseTest( m_info.resultDisposition ) ) + return "!" + m_info.capturedExpression; + else + return m_info.capturedExpression; + } + std::string AssertionResult::getExpressionInMacro() const { + if( m_info.macroName.empty() ) + return m_info.capturedExpression; + else + return m_info.macroName + "( " + m_info.capturedExpression + " )"; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + return m_resultData.reconstructedExpression; + } + + std::string AssertionResult::getMessage() const { + return m_resultData.message; + } + SourceLineInfo AssertionResult::getSourceInfo() const { + return m_info.lineInfo; + } + + std::string AssertionResult::getTestMacroName() const { + return m_info.macroName; + } + +} // end namespace Catch + +// #included from: catch_test_case_info.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED + +namespace Catch { + + inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { + if( tag == "." || + tag == "hide" || + tag == "!hide" ) + return TestCaseInfo::IsHidden; + else if( tag == "!throws" ) + return TestCaseInfo::Throws; + else if( tag == "!shouldfail" ) + return TestCaseInfo::ShouldFail; + else if( tag == "!mayfail" ) + return TestCaseInfo::MayFail; + else + return TestCaseInfo::None; + } + inline bool isReservedTag( std::string const& tag ) { + return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] ); + } + inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + if( isReservedTag( tag ) ) { + { + Colour colourGuard( Colour::Red ); + std::cerr + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n"; + } + { + Colour colourGuard( Colour::FileName ); + std::cerr << _lineInfo << std::endl; + } + exit(1); + } + } + + TestCase makeTestCase( ITestCase* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden( startsWith( _name, "./" ) ); // Legacy support + + // Parse out tags + std::set tags; + std::string desc, tag; + bool inTag = false; + for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { + char c = _descOrTags[i]; + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; + } + else { + if( c == ']' ) { + enforceNotReservedTag( tag, _lineInfo ); + + inTag = false; + if( tag == "hide" || tag == "." ) + isHidden = true; + else + tags.insert( tag ); + tag.clear(); + } + else + tag += c; + } + } + if( isHidden ) { + tags.insert( "hide" ); + tags.insert( "." ); + } + + TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); + return TestCase( _testCase, info ); + } + + TestCaseInfo::TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ) + : name( _name ), + className( _className ), + description( _description ), + tags( _tags ), + lineInfo( _lineInfo ), + properties( None ) + { + std::ostringstream oss; + for( std::set::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + std::string lcaseTag = toLower( *it ); + properties = static_cast( properties | parseSpecialTag( lcaseTag ) ); + lcaseTags.insert( lcaseTag ); + } + tagsAsString = oss.str(); + } + + TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) + : name( other.name ), + className( other.className ), + description( other.description ), + tags( other.tags ), + lcaseTags( other.lcaseTags ), + tagsAsString( other.tagsAsString ), + lineInfo( other.lineInfo ), + properties( other.properties ) + {} + + bool TestCaseInfo::isHidden() const { + return ( properties & IsHidden ) != 0; + } + bool TestCaseInfo::throws() const { + return ( properties & Throws ) != 0; + } + bool TestCaseInfo::okToFail() const { + return ( properties & (ShouldFail | MayFail ) ) != 0; + } + bool TestCaseInfo::expectedToFail() const { + return ( properties & (ShouldFail ) ) != 0; + } + + TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + + TestCase::TestCase( TestCase const& other ) + : TestCaseInfo( other ), + test( other.test ) + {} + + TestCase TestCase::withName( std::string const& _newName ) const { + TestCase other( *this ); + other.name = _newName; + return other; + } + + void TestCase::swap( TestCase& other ) { + test.swap( other.test ); + name.swap( other.name ); + className.swap( other.className ); + description.swap( other.description ); + tags.swap( other.tags ); + lcaseTags.swap( other.lcaseTags ); + tagsAsString.swap( other.tagsAsString ); + std::swap( TestCaseInfo::properties, static_cast( other ).properties ); + std::swap( lineInfo, other.lineInfo ); + } + + void TestCase::invoke() const { + test->invoke(); + } + + bool TestCase::operator == ( TestCase const& other ) const { + return test.get() == other.test.get() && + name == other.name && + className == other.className; + } + + bool TestCase::operator < ( TestCase const& other ) const { + return name < other.name; + } + TestCase& TestCase::operator = ( TestCase const& other ) { + TestCase temp( other ); + swap( temp ); + return *this; + } + + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } + +} // end namespace Catch + +// #included from: catch_version.hpp +#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED + +namespace Catch { + + // These numbers are maintained by a script + Version libraryVersion( 1, 0, 52, "master" ); +} + +// #included from: catch_message.hpp +#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + ScopedMessage::ScopedMessage( ScopedMessage const& other ) + : m_info( other.m_info ) + {} + + ScopedMessage::~ScopedMessage() { + getResultCapture().popScopedMessage( m_info ); + } + +} // end namespace Catch + +// #included from: catch_legacy_reporter_adapter.hpp +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED + +// #included from: catch_legacy_reporter_adapter.h +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED + +namespace Catch +{ + // Deprecated + struct IReporter : IShared { + virtual ~IReporter(); + + virtual bool shouldRedirectStdout() const = 0; + + virtual void StartTesting() = 0; + virtual void EndTesting( Totals const& totals ) = 0; + virtual void StartGroup( std::string const& groupName ) = 0; + virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; + virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; + virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; + virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; + virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; + virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; + virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; + virtual void Aborted() = 0; + virtual void Result( AssertionResult const& result ) = 0; + }; + + class LegacyReporterAdapter : public SharedImpl + { + public: + LegacyReporterAdapter( Ptr const& legacyReporter ); + virtual ~LegacyReporterAdapter(); + + virtual ReporterPreferences getPreferences() const; + virtual void noMatchingTestCases( std::string const& ); + virtual void testRunStarting( TestRunInfo const& ); + virtual void testGroupStarting( GroupInfo const& groupInfo ); + virtual void testCaseStarting( TestCaseInfo const& testInfo ); + virtual void sectionStarting( SectionInfo const& sectionInfo ); + virtual void assertionStarting( AssertionInfo const& ); + virtual bool assertionEnded( AssertionStats const& assertionStats ); + virtual void sectionEnded( SectionStats const& sectionStats ); + virtual void testCaseEnded( TestCaseStats const& testCaseStats ); + virtual void testGroupEnded( TestGroupStats const& testGroupStats ); + virtual void testRunEnded( TestRunStats const& testRunStats ); + + private: + Ptr m_legacyReporter; + }; +} + +namespace Catch +{ + LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) + : m_legacyReporter( legacyReporter ) + {} + LegacyReporterAdapter::~LegacyReporterAdapter() {} + + ReporterPreferences LegacyReporterAdapter::getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); + return prefs; + } + + void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} + void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { + m_legacyReporter->StartTesting(); + } + void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { + m_legacyReporter->StartGroup( groupInfo.name ); + } + void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { + m_legacyReporter->StartTestCase( testInfo ); + } + void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { + m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); + } + void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { + // Not on legacy interface + } + + bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); + rb << it->message; + rb.setResultType( ResultWas::Info ); + AssertionResult result = rb.build(); + m_legacyReporter->Result( result ); + } + } + } + m_legacyReporter->Result( assertionStats.assertionResult ); + return true; + } + void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { + if( sectionStats.missingAssertions ) + m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); + m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); + } + void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { + m_legacyReporter->EndTestCase + ( testCaseStats.testInfo, + testCaseStats.totals, + testCaseStats.stdOut, + testCaseStats.stdErr ); + } + void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { + if( testGroupStats.aborting ) + m_legacyReporter->Aborted(); + m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); + } + void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { + m_legacyReporter->EndTesting( testRunStats.totals ); + } +} + +// #included from: catch_timer.hpp + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-long-long" +#endif + +#ifdef CATCH_PLATFORM_WINDOWS +#include +#else +#include +#endif + +namespace Catch { + + namespace { +#ifdef CATCH_PLATFORM_WINDOWS + uint64_t getCurrentTicks() { + static uint64_t hz=0, hzo=0; + if (!hz) { + QueryPerformanceFrequency((LARGE_INTEGER*)&hz); + QueryPerformanceCounter((LARGE_INTEGER*)&hzo); + } + uint64_t t; + QueryPerformanceCounter((LARGE_INTEGER*)&t); + return ((t-hzo)*1000000)/hz; + } +#else + uint64_t getCurrentTicks() { + timeval t; + gettimeofday(&t,NULL); + return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); + } +#endif + } + + void Timer::start() { + m_ticks = getCurrentTicks(); + } + unsigned int Timer::getElapsedNanoseconds() const { + return static_cast(getCurrentTicks() - m_ticks); + } + unsigned int Timer::getElapsedMilliseconds() const { + return static_cast((getCurrentTicks() - m_ticks)/1000); + } + double Timer::getElapsedSeconds() const { + return (getCurrentTicks() - m_ticks)/1000000.0; + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +// #included from: catch_common.hpp +#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), ::tolower ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << " " << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << "s"; + return os; + } + + SourceLineInfo::SourceLineInfo() : line( 0 ){} + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) + : file( _file ), + line( _line ) + {} + SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) + : file( other.file ), + line( other.line ) + {} + bool SourceLineInfo::empty() const { + return file.empty(); + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { + return line == other.line && file == other.file; + } + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { +#ifndef __GNUG__ + os << info.file << "(" << info.line << ")"; +#else + os << info.file << ":" << info.line; +#endif + return os; + } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { + std::ostringstream oss; + oss << locationInfo << ": Internal Catch error: '" << message << "'"; + if( alwaysTrue() ) + throw std::logic_error( oss.str() ); + } +} + +// #included from: catch_section.hpp +#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED + +namespace Catch { + + SectionInfo::SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + Section::Section( SectionInfo const& info ) + : m_info( info ), + m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) + { + m_timer.start(); + } + + Section::~Section() { + if( m_sectionIncluded ) + getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); + } + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } + +} // end namespace Catch + +// #included from: catch_debugger.hpp +#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED + +#include + +#ifdef CATCH_PLATFORM_MAC + + #include + #include + #include + #include + #include + + namespace Catch{ + + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive(){ + + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) { + std::cerr << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; + return false; + } + + // We're being debugged if the P_TRACED flag is set. + + return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + } + } // namespace Catch + +#elif defined(_MSC_VER) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#else + namespace Catch { + inline bool isDebuggerActive() { return false; } + } +#endif // Platform + +#ifdef CATCH_PLATFORM_WINDOWS + extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + std::cout << text; + } + } +#endif // Platform + +// #included from: catch_tostring.hpp +#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED + +namespace Catch { + +namespace Detail { + + namespace { + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + } + + std::string rawMemoryToString( const void *object, std::size_t size ) + { + // Reverse order for little endian architectures + int i = 0, end = static_cast( size ), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + + unsigned char const *bytes = static_cast(object); + std::ostringstream os; + os << "0x" << std::setfill('0') << std::hex; + for( ; i != end; i += inc ) + os << std::setw(2) << static_cast(bytes[i]); + return os.str(); + } +} + +std::string toString( std::string const& value ) { + std::string s = value; + if( getCurrentContext().getConfig()->showInvisibles() ) { + for(size_t i = 0; i < s.size(); ++i ) { + std::string subs; + switch( s[i] ) { + case '\n': subs = "\\n"; break; + case '\t': subs = "\\t"; break; + default: break; + } + if( !subs.empty() ) { + s = s.substr( 0, i ) + subs + s.substr( i+1 ); + ++i; + } + } + } + return "\"" + s + "\""; +} +std::string toString( std::wstring const& value ) { + + std::string s; + s.reserve( value.size() ); + for(size_t i = 0; i < value.size(); ++i ) + s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; + return toString( s ); +} + +std::string toString( const char* const value ) { + return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); +} + +std::string toString( char* const value ) { + return Catch::toString( static_cast( value ) ); +} + +std::string toString( int value ) { + std::ostringstream oss; + oss << value; + return oss.str(); +} + +std::string toString( unsigned long value ) { + std::ostringstream oss; + if( value > 8192 ) + oss << "0x" << std::hex << value; + else + oss << value; + return oss.str(); +} + +std::string toString( unsigned int value ) { + return toString( static_cast( value ) ); +} + +template +std::string fpToString( T value, int precision ) { + std::ostringstream oss; + oss << std::setprecision( precision ) + << std::fixed + << value; + std::string d = oss.str(); + std::size_t i = d.find_last_not_of( '0' ); + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) + i++; + d = d.substr( 0, i+1 ); + } + return d; +} + +std::string toString( const double value ) { + return fpToString( value, 10 ); +} +std::string toString( const float value ) { + return fpToString( value, 5 ) + "f"; +} + +std::string toString( bool value ) { + return value ? "true" : "false"; +} + +std::string toString( char value ) { + return value < ' ' + ? toString( static_cast( value ) ) + : Detail::makeString( value ); +} + +std::string toString( signed char value ) { + return toString( static_cast( value ) ); +} + +std::string toString( unsigned char value ) { + return toString( static_cast( value ) ); +} + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ) { + return "nullptr"; +} +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSObject* const& nsObject ) { + return toString( [nsObject description] ); + } +#endif + +} // end namespace Catch + +// #included from: catch_result_builder.hpp +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED + +namespace Catch { + + ResultBuilder::ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition ) + : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition ), + m_shouldDebugBreak( false ), + m_shouldThrow( false ) + {} + + ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { + m_data.resultType = result; + return *this; + } + ResultBuilder& ResultBuilder::setResultType( bool result ) { + m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; + return *this; + } + ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) { + m_exprComponents.lhs = lhs; + return *this; + } + ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) { + m_exprComponents.rhs = rhs; + return *this; + } + ResultBuilder& ResultBuilder::setOp( std::string const& op ) { + m_exprComponents.op = op; + return *this; + } + + void ResultBuilder::endExpression() { + m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition ); + captureExpression(); + } + + void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { + m_assertionInfo.resultDisposition = resultDisposition; + m_stream.oss << Catch::translateActiveException(); + captureResult( ResultWas::ThrewException ); + } + + void ResultBuilder::captureResult( ResultWas::OfType resultType ) { + setResultType( resultType ); + captureExpression(); + } + + void ResultBuilder::captureExpression() { + AssertionResult result = build(); + getResultCapture().assertionEnded( result ); + + if( !result.isOk() ) { + if( getCurrentContext().getConfig()->shouldDebugBreak() ) + m_shouldDebugBreak = true; + if( getCurrentContext().getRunner()->aborting() || m_assertionInfo.resultDisposition == ResultDisposition::Normal ) + m_shouldThrow = true; + } + } + void ResultBuilder::react() { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } + bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } + + AssertionResult ResultBuilder::build() const + { + assert( m_data.resultType != ResultWas::Unknown ); + + AssertionResultData data = m_data; + + // Flip bool results if testFalse is set + if( m_exprComponents.testFalse ) { + if( data.resultType == ResultWas::Ok ) + data.resultType = ResultWas::ExpressionFailed; + else if( data.resultType == ResultWas::ExpressionFailed ) + data.resultType = ResultWas::Ok; + } + + data.message = m_stream.oss.str(); + data.reconstructedExpression = reconstructExpression(); + if( m_exprComponents.testFalse ) { + if( m_exprComponents.op == "" ) + data.reconstructedExpression = "!" + data.reconstructedExpression; + else + data.reconstructedExpression = "!(" + data.reconstructedExpression + ")"; + } + return AssertionResult( m_assertionInfo, data ); + } + std::string ResultBuilder::reconstructExpression() const { + if( m_exprComponents.op == "" ) + return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs; + else if( m_exprComponents.op == "matches" ) + return m_exprComponents.lhs + " " + m_exprComponents.rhs; + else if( m_exprComponents.op != "!" ) { + if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && + m_exprComponents.lhs.find("\n") == std::string::npos && + m_exprComponents.rhs.find("\n") == std::string::npos ) + return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; + else + return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; + } + else + return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}"; + } + +} // end namespace Catch + +// #included from: catch_tag_alias_registry.hpp +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED + +// #included from: catch_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED + +#include + +namespace Catch { + + class TagAliasRegistry : public ITagAliasRegistry { + public: + virtual ~TagAliasRegistry(); + virtual Option find( std::string const& alias ) const; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; + void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + static TagAliasRegistry& get(); + + private: + std::map m_registry; + }; + +} // end namespace Catch + +#include +#include + +namespace Catch { + + TagAliasRegistry::~TagAliasRegistry() {} + + Option TagAliasRegistry::find( std::string const& alias ) const { + std::map::const_iterator it = m_registry.find( alias ); + if( it != m_registry.end() ) + return it->second; + else + return Option(); + } + + std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { + std::string expandedTestSpec = unexpandedTestSpec; + for( std::map::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); + it != itEnd; + ++it ) { + std::size_t pos = expandedTestSpec.find( it->first ); + if( pos != std::string::npos ) { + expandedTestSpec = expandedTestSpec.substr( 0, pos ) + + it->second.tag + + expandedTestSpec.substr( pos + it->first.size() ); + } + } + return expandedTestSpec; + } + + void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + + if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" already registered.\n" + << "\tFirst seen at " << find(alias)->lineInfo << "\n" + << "\tRedefined at " << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + } + + TagAliasRegistry& TagAliasRegistry::get() { + static TagAliasRegistry instance; + return instance; + + } + + ITagAliasRegistry::~ITagAliasRegistry() {} + ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); } + + RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + try { + TagAliasRegistry::get().add( alias, tag, lineInfo ); + } + catch( std::exception& ex ) { + Colour colourGuard( Colour::Red ); + std::cerr << ex.what() << std::endl; + exit(1); + } + } + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_xml.hpp +#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED + +// #included from: catch_reporter_bases.hpp +#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED + +namespace Catch { + + struct StreamingReporterBase : SharedImpl { + + StreamingReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + {} + + virtual ~StreamingReporterBase(); + + virtual void noMatchingTestCases( std::string const& ) {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) { + currentTestRunInfo = _testRunInfo; + } + virtual void testGroupStarting( GroupInfo const& _groupInfo ) { + currentGroupInfo = _groupInfo; + } + + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) { + currentTestCaseInfo = _testInfo; + } + virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + m_sectionStack.push_back( _sectionInfo ); + } + + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) { + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) { + currentTestCaseInfo.reset(); + assert( m_sectionStack.empty() ); + } + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) { + currentGroupInfo.reset(); + } + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + Ptr m_config; + std::ostream& stream; + + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; + + std::vector m_sectionStack; + }; + + struct CumulativeReporterBase : SharedImpl { + template + struct Node : SharedImpl<> { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} + + typedef std::vector > ChildNodes; + T value; + ChildNodes children; + }; + struct SectionNode : SharedImpl<> { + explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} + virtual ~SectionNode(); + + bool operator == ( SectionNode const& other ) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + bool operator == ( Ptr const& other ) const { + return operator==( *other ); + } + + SectionStats stats; + typedef std::vector > ChildSections; + typedef std::vector Assertions; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + + struct BySectionInfo { + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} + bool operator() ( Ptr const& node ) const { + return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + } + private: + void operator=( BySectionInfo const& ); + SectionInfo const& m_other; + }; + + typedef Node TestCaseNode; + typedef Node TestGroupNode; + typedef Node TestRunNode; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + {} + ~CumulativeReporterBase(); + + virtual void testRunStarting( TestRunInfo const& ) {} + virtual void testGroupStarting( GroupInfo const& ) {} + + virtual void testCaseStarting( TestCaseInfo const& ) {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + Ptr node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = new SectionNode( incompleteStats ); + node = m_rootSection; + } + else { + SectionNode& parentNode = *m_sectionStack.back(); + SectionNode::ChildSections::const_iterator it = + std::find_if( parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo( sectionInfo ) ); + if( it == parentNode.childSections.end() ) { + node = new SectionNode( incompleteStats ); + parentNode.childSections.push_back( node ); + } + else + node = *it; + } + m_sectionStack.push_back( node ); + m_deepestSection = node; + } + + virtual void assertionStarting( AssertionInfo const& ) {} + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back( assertionStats ); + return true; + } + virtual void sectionEnded( SectionStats const& sectionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + Ptr node = new TestCaseNode( testCaseStats ); + assert( m_sectionStack.size() == 0 ); + node->children.push_back( m_rootSection ); + m_testCases.push_back( node ); + m_rootSection.reset(); + + assert( m_deepestSection ); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + Ptr node = new TestGroupNode( testGroupStats ); + node->children.swap( m_testCases ); + m_testGroups.push_back( node ); + } + virtual void testRunEnded( TestRunStats const& testRunStats ) { + Ptr node = new TestRunNode( testRunStats ); + node->children.swap( m_testGroups ); + m_testRuns.push_back( node ); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + Ptr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector > > m_sections; + std::vector > m_testCases; + std::vector > m_testGroups; + + std::vector > m_testRuns; + + Ptr m_rootSection; + Ptr m_deepestSection; + std::vector > m_sectionStack; + + }; + +} // end namespace Catch + +// #included from: ../internal/catch_reporter_registrars.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED + +namespace Catch { + + template + class LegacyReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new LegacyReporterAdapter( new T( config ) ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + LegacyReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + class ReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + + // *** Please Note ***: + // - If you end up here looking at a compiler error because it's trying to register + // your custom reporter class be aware that the native reporter interface has changed + // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via + // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. + // However please consider updating to the new interface as the old one is now + // deprecated and will probably be removed quite soon! + // Please contact me via github if you have any questions at all about this. + // In fact, ideally, please contact me anyway to let me know you've hit this - as I have + // no idea who is actually using custom reporters at all (possibly no-one!). + // The new interface is designed to minimise exposure to interface changes in the future. + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; +} + +#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ + namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +// #included from: ../internal/catch_xmlwriter.hpp +#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = NULL; + } + + ~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + ScopedElement& writeText( std::string const& text, bool indent = true ) { + m_writer->writeText( text, indent ); + return *this; + } + + template + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer; + }; + + XmlWriter() + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &std::cout ) + {} + + XmlWriter( std::ostream& os ) + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &os ) + {} + + ~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + +//# ifndef CATCH_CPP11_OR_GREATER +// XmlWriter& operator = ( XmlWriter const& other ) { +// XmlWriter temp( other ); +// swap( temp ); +// return *this; +// } +//# else +// XmlWriter( XmlWriter const& ) = default; +// XmlWriter( XmlWriter && ) = default; +// XmlWriter& operator = ( XmlWriter const& ) = default; +// XmlWriter& operator = ( XmlWriter && ) = default; +//# endif +// +// void swap( XmlWriter& other ) { +// std::swap( m_tagIsOpen, other.m_tagIsOpen ); +// std::swap( m_needsNewline, other.m_needsNewline ); +// std::swap( m_tags, other.m_tags ); +// std::swap( m_indent, other.m_indent ); +// std::swap( m_os, other.m_os ); +// } + + XmlWriter& startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + stream() << m_indent << "<" << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + ScopedElement scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + stream() << "/>\n"; + m_tagIsOpen = false; + } + else { + stream() << m_indent << "\n"; + } + m_tags.pop_back(); + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) { + stream() << " " << name << "=\""; + writeEncodedText( attribute ); + stream() << "\""; + } + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, bool attribute ) { + stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; + return *this; + } + + template + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + if( !name.empty() ) + stream() << " " << name << "=\"" << attribute << "\""; + return *this; + } + + XmlWriter& writeText( std::string const& text, bool indent = true ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + stream() << m_indent; + writeEncodedText( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& writeComment( std::string const& text ) { + ensureTagClosed(); + stream() << m_indent << ""; + m_needsNewline = true; + return *this; + } + + XmlWriter& writeBlankLine() { + ensureTagClosed(); + stream() << "\n"; + return *this; + } + + void setStream( std::ostream& os ) { + m_os = &os; + } + + private: + XmlWriter( XmlWriter const& ); + void operator=( XmlWriter const& ); + + std::ostream& stream() { + return *m_os; + } + + void ensureTagClosed() { + if( m_tagIsOpen ) { + stream() << ">\n"; + m_tagIsOpen = false; + } + } + + void newlineIfNecessary() { + if( m_needsNewline ) { + stream() << "\n"; + m_needsNewline = false; + } + } + + void writeEncodedText( std::string const& text ) { + static const char* charsToEncode = "<&\""; + std::string mtext = text; + std::string::size_type pos = mtext.find_first_of( charsToEncode ); + while( pos != std::string::npos ) { + stream() << mtext.substr( 0, pos ); + + switch( mtext[pos] ) { + case '<': + stream() << "<"; + break; + case '&': + stream() << "&"; + break; + case '\"': + stream() << """; + break; + } + mtext = mtext.substr( pos+1 ); + pos = mtext.find_first_of( charsToEncode ); + } + stream() << mtext; + } + + bool m_tagIsOpen; + bool m_needsNewline; + std::vector m_tags; + std::string m_indent; + std::ostream* m_os; + }; + +} +namespace Catch { + class XmlReporter : public SharedImpl { + public: + XmlReporter( ReporterConfig const& config ) : m_config( config ), m_sectionDepth( 0 ) {} + + static std::string getDescription() { + return "Reports test results as an XML document"; + } + virtual ~XmlReporter(); + + private: // IReporter + + virtual bool shouldRedirectStdout() const { + return true; + } + + virtual void StartTesting() { + m_xml.setStream( m_config.stream() ); + m_xml.startElement( "Catch" ); + if( !m_config.fullConfig()->name().empty() ) + m_xml.writeAttribute( "name", m_config.fullConfig()->name() ); + } + + virtual void EndTesting( const Totals& totals ) { + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", totals.assertions.passed ) + .writeAttribute( "failures", totals.assertions.failed ) + .writeAttribute( "expectedFailures", totals.assertions.failedButOk ); + m_xml.endElement(); + } + + virtual void StartGroup( const std::string& groupName ) { + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupName ); + } + + virtual void EndGroup( const std::string&, const Totals& totals ) { + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", totals.assertions.passed ) + .writeAttribute( "failures", totals.assertions.failed ) + .writeAttribute( "expectedFailures", totals.assertions.failedButOk ); + m_xml.endElement(); + } + + virtual void StartSection( const std::string& sectionName, const std::string& description ) { + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionName ) ) + .writeAttribute( "description", description ); + } + } + virtual void NoAssertionsInSection( const std::string& ) {} + virtual void NoAssertionsInTestCase( const std::string& ) {} + + virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) { + if( --m_sectionDepth > 0 ) { + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", assertions.passed ) + .writeAttribute( "failures", assertions.failed ) + .writeAttribute( "expectedFailures", assertions.failedButOk ); + m_xml.endElement(); + } + } + + virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) { + m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); + m_currentTestSuccess = true; + } + + virtual void Result( const Catch::AssertionResult& assertionResult ) { + if( !m_config.fullConfig()->includeSuccessfulResults() && assertionResult.getResultType() == ResultWas::Ok ) + return; + + if( assertionResult.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", assertionResult.succeeded() ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ); + + m_xml.scopedElement( "Original" ) + .writeText( assertionResult.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( assertionResult.getExpandedExpression() ); + m_currentTestSuccess &= assertionResult.succeeded(); + } + + switch( assertionResult.getResultType() ) { + case ResultWas::ThrewException: + m_xml.scopedElement( "Exception" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + m_currentTestSuccess = false; + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Warning: + m_xml.scopedElement( "Warning" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::ExplicitFailure: + m_xml.scopedElement( "Failure" ) + .writeText( assertionResult.getMessage() ); + m_currentTestSuccess = false; + break; + case ResultWas::Unknown: + case ResultWas::Ok: + case ResultWas::FailureBit: + case ResultWas::ExpressionFailed: + case ResultWas::Exception: + case ResultWas::DidntThrowException: + break; + } + if( assertionResult.hasExpression() ) + m_xml.endElement(); + } + + virtual void Aborted() { + // !TBD + } + + virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) { + m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess ); + m_xml.endElement(); + } + + private: + ReporterConfig m_config; + bool m_currentTestSuccess; + XmlWriter m_xml; + int m_sectionDepth; + }; + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_junit.hpp +#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED + +#include + +namespace Catch { + + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter( ReporterConfig const& _config ) + : CumulativeReporterBase( _config ), + xml( _config.stream() ) + {} + + ~JunitReporter(); + + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + virtual void noMatchingTestCases( std::string const& /*spec*/ ) {} + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = true; + return prefs; + } + + virtual void testRunStarting( TestRunInfo const& runInfo ) { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + virtual void testRunEndedCumulative() { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", "tbd" ); // !TBD + + // Write test cases + for( TestGroupNode::ChildNodes::const_iterator + it = groupNode.children.begin(), itEnd = groupNode.children.end(); + it != itEnd; + ++it ) + writeTestCase( **it ); + + xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); + xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); + } + + void writeTestCase( TestCaseNode const& testCaseNode ) { + TestCaseStats const& stats = testCaseNode.value; + + // All test cases have exactly one section - which represents the + // test case itself. That section may have 0-n nested sections + assert( testCaseNode.children.size() == 1 ); + SectionNode const& rootSection = *testCaseNode.children.front(); + + std::string className = stats.testInfo.className; + + if( className.empty() ) { + if( rootSection.childSections.empty() ) + className = "global"; + } + writeSection( className, "", rootSection ); + } + + void writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode ) { + std::string name = trim( sectionNode.stats.sectionInfo.name ); + if( !rootName.empty() ) + name = rootName + "/" + name; + + if( !sectionNode.assertions.empty() || + !sectionNode.stdOut.empty() || + !sectionNode.stdErr.empty() ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); + if( className.empty() ) { + xml.writeAttribute( "classname", name ); + xml.writeAttribute( "name", "root" ); + } + else { + xml.writeAttribute( "classname", className ); + xml.writeAttribute( "name", name ); + } + xml.writeAttribute( "time", toString( sectionNode.stats.durationInSeconds ) ); + + writeAssertions( sectionNode ); + + if( !sectionNode.stdOut.empty() ) + xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); + if( !sectionNode.stdErr.empty() ) + xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); + } + for( SectionNode::ChildSections::const_iterator + it = sectionNode.childSections.begin(), + itEnd = sectionNode.childSections.end(); + it != itEnd; + ++it ) + if( className.empty() ) + writeSection( name, "", **it ); + else + writeSection( className, name, **it ); + } + + void writeAssertions( SectionNode const& sectionNode ) { + for( SectionNode::Assertions::const_iterator + it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); + it != itEnd; + ++it ) + writeAssertion( *it ); + } + void writeAssertion( AssertionStats const& stats ) { + AssertionResult const& result = stats.assertionResult; + if( !result.isOk() ) { + std::string elementName; + switch( result.getResultType() ) { + case ResultWas::ThrewException: + elementName = "error"; + break; + case ResultWas::ExplicitFailure: + elementName = "failure"; + break; + case ResultWas::ExpressionFailed: + elementName = "failure"; + break; + case ResultWas::DidntThrowException: + elementName = "failure"; + break; + + // We should never see these here: + case ResultWas::Info: + case ResultWas::Warning: + case ResultWas::Ok: + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + elementName = "internalError"; + break; + } + + XmlWriter::ScopedElement e = xml.scopedElement( elementName ); + + xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "type", result.getTestMacroName() ); + + std::ostringstream oss; + if( !result.getMessage().empty() ) + oss << result.getMessage() << "\n"; + for( std::vector::const_iterator + it = stats.infoMessages.begin(), + itEnd = stats.infoMessages.end(); + it != itEnd; + ++it ) + if( it->type == ResultWas::Info ) + oss << it->message << "\n"; + + oss << "at " << result.getSourceInfo(); + xml.writeText( oss.str(), false ); + } + } + + XmlWriter xml; + Timer suiteTimer; + std::ostringstream stdOutForSuite; + std::ostringstream stdErrForSuite; + unsigned int unexpectedExceptions; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_console.hpp +#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED + +#include + +namespace Catch { + + struct ConsoleReporter : StreamingReporterBase { + ConsoleReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_headerPrinted( false ) + {} + + virtual ~ConsoleReporter(); + static std::string getDescription() { + return "Reports test results as plain lines of text"; + } + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + lazyPrint(); + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + stream << std::endl; + return true; + } + + virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting( _sectionInfo ); + } + virtual void sectionEnded( SectionStats const& _sectionStats ) { + if( _sectionStats.missingAssertions ) { + lazyPrint(); + Colour colour( Colour::ResultError ); + if( m_sectionStack.size() > 1 ) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if( m_headerPrinted ) { + if( m_config->showDurations() == ShowDurations::Always ) + stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + m_headerPrinted = false; + } + else { + if( m_config->showDurations() == ShowDurations::Always ) + stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + } + StreamingReporterBase::sectionEnded( _sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) { + StreamingReporterBase::testCaseEnded( _testCaseStats ); + m_headerPrinted = false; + } + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) { + if( currentGroupInfo.used ) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals( _testGroupStats.totals ); + stream << "\n" << std::endl; + } + StreamingReporterBase::testGroupEnded( _testGroupStats ); + } + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotalsDivider( _testRunStats.totals ); + printTotals( _testRunStats.totals ); + stream << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ), + stats( _stats ), + result( _stats.assertionResult ), + colour( Colour::None ), + message( result.getMessage() ), + messages( _stats.infoMessages ), + printInfoMessages( _printInfoMessages ) + { + switch( result.getResultType() ) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + //if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; + } + else { + colour = Colour::Error; + passOrFail = "FAILED"; + } + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with message"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if( _stats.infoMessages.size() == 1 ) + messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; + } + } + + void print() const { + printSourceInfo(); + if( stats.totals.assertions.total() > 0 ) { + if( result.isOk() ) + stream << "\n"; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } + else { + stream << "\n"; + } + printMessage(); + } + + private: + void printResultType() const { + if( !passOrFail.empty() ) { + Colour colourGuard( colour ); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if( result.hasExpression() ) { + Colour colourGuard( Colour::OriginalExpression ); + stream << " "; + stream << result.getExpressionInMacro(); + stream << "\n"; + } + } + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + stream << "with expansion:\n"; + Colour colourGuard( Colour::ReconstructedExpression ); + stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n"; + } + } + void printMessage() const { + if( !messageLabel.empty() ) + stream << messageLabel << ":" << "\n"; + for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); + it != itEnd; + ++it ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || it->type != ResultWas::Info ) + stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n"; + } + } + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector messages; + bool printInfoMessages; + }; + + void lazyPrint() { + + if( !currentTestRunInfo.used ) + lazyPrintRunInfo(); + if( !currentGroupInfo.used ) + lazyPrintGroupInfo(); + + if( !m_headerPrinted ) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } + } + void lazyPrintRunInfo() { + stream << "\n" << getLineOfChars<'~'>() << "\n"; + Colour colour( Colour::SecondaryText ); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion.majorVersion << "." + << libraryVersion.minorVersion << " b" + << libraryVersion.buildNumber; + if( libraryVersion.branchName != std::string( "master" ) ) + stream << " (" << libraryVersion.branchName << ")"; + stream << " host application.\n" + << "Run with -? for options\n\n"; + + currentTestRunInfo.used = true; + } + void lazyPrintGroupInfo() { + if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { + printClosedHeader( "Group: " + currentGroupInfo->name ); + currentGroupInfo.used = true; + } + } + void printTestCaseAndSectionHeader() { + assert( !m_sectionStack.empty() ); + printOpenHeader( currentTestCaseInfo->name ); + + if( m_sectionStack.size() > 1 ) { + Colour colourGuard( Colour::Headers ); + + std::vector::const_iterator + it = m_sectionStack.begin()+1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for( ; it != itEnd; ++it ) + printHeaderString( it->name, 2 ); + } + + SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; + + if( !lineInfo.empty() ){ + stream << getLineOfChars<'-'>() << "\n"; + Colour colourGuard( Colour::FileName ); + stream << lineInfo << "\n"; + } + stream << getLineOfChars<'.'>() << "\n" << std::endl; + } + + void printClosedHeader( std::string const& _name ) { + printOpenHeader( _name ); + stream << getLineOfChars<'.'>() << "\n"; + } + void printOpenHeader( std::string const& _name ) { + stream << getLineOfChars<'-'>() << "\n"; + { + Colour colourGuard( Colour::Headers ); + printHeaderString( _name ); + } + } + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { + std::size_t i = _string.find( ": " ); + if( i != std::string::npos ) + i+=2; + else + i = 0; + stream << Text( _string, TextAttributes() + .setIndent( indent+i) + .setInitialIndent( indent ) ) << "\n"; + } + + struct SummaryColumn { + + SummaryColumn( std::string const& _label, Colour::Code _colour ) + : label( _label ), + colour( _colour ) + {} + SummaryColumn addRow( std::size_t count ) { + std::ostringstream oss; + oss << count; + std::string row = oss.str(); + for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { + while( it->size() < row.size() ) + *it = " " + *it; + while( it->size() > row.size() ) + row = " " + row; + } + rows.push_back( row ); + return *this; + } + + std::string label; + Colour::Code colour; + std::vector rows; + + }; + + void printTotals( Totals const& totals ) { + if( totals.testCases.total() == 0 ) { + stream << Colour( Colour::Warning ) << "No tests ran\n"; + } + else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) { + stream << Colour( Colour::ResultSuccess ) << "All tests passed"; + stream << " (" + << pluralise( totals.assertions.passed, "assertion" ) << " in " + << pluralise( totals.testCases.passed, "test case" ) << ")" + << "\n"; + } + else { + + std::vector columns; + columns.push_back( SummaryColumn( "", Colour::None ) + .addRow( totals.testCases.total() ) + .addRow( totals.assertions.total() ) ); + columns.push_back( SummaryColumn( "passed", Colour::Success ) + .addRow( totals.testCases.passed ) + .addRow( totals.assertions.passed ) ); + columns.push_back( SummaryColumn( "failed", Colour::ResultError ) + .addRow( totals.testCases.failed ) + .addRow( totals.assertions.failed ) ); + columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) + .addRow( totals.testCases.failedButOk ) + .addRow( totals.assertions.failedButOk ) ); + + printSummaryRow( "test cases", columns, 0 ); + printSummaryRow( "assertions", columns, 1 ); + } + } + void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { + for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { + std::string value = it->rows[row]; + if( it->label.empty() ) { + stream << label << ": "; + if( value != "0" ) + stream << value; + else + stream << Colour( Colour::Warning ) << "- none -"; + } + else if( value != "0" ) { + stream << Colour( Colour::LightGrey ) << " | "; + stream << Colour( it->colour ) + << value << " " << it->label; + } + } + stream << "\n"; + } + + static std::size_t makeRatio( std::size_t number, std::size_t total ) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; + return ( ratio == 0 && number > 0 ) ? 1 : ratio; + } + static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { + if( i > j && i > k ) + return i; + else if( j > k ) + return j; + else + return k; + } + + void printTotalsDivider( Totals const& totals ) { + if( totals.testCases.total() > 0 ) { + std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); + std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); + std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); + while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )++; + while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )--; + + stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); + stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); + if( totals.testCases.allPassed() ) + stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); + else + stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); + } + else { + stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); + } + stream << "\n"; + } + void printSummaryDivider() { + stream << getLineOfChars<'-'>() << "\n"; + } + template + static char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; + } + + private: + bool m_headerPrinted; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_compact.hpp +#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + CompactReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual ~CompactReporter(); + + static std::string getDescription() { + return "Reports test results on a single line, suitable for IDEs"; + } + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; + } + + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotals( _testRunStats.totals ); + stream << "\n" << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , stats( _stats ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + + switch( result.getResultType() ) { + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType( Colour::None, "warning" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType( Colour::Error, failedString() ); + printIssue( "explicitly" ); + printRemainingMessages( Colour::None ); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType( Colour::Error, "** internal error **" ); + break; + } + } + + private: + // Colour::LightGrey + + static Colour::Code dimColour() { return Colour::FileName; } + +#ifdef CATCH_PLATFORM_MAC + static const char* failedString() { return "FAILED"; } + static const char* passedString() { return "PASSED"; } +#else + static const char* failedString() { return "failed"; } + static const char* passedString() { return "passed"; } +#endif + + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ":"; + } + + void printResultType( Colour::Code colour, std::string passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << " " << passOrFail; + } + stream << ":"; + } + } + + void printIssue( std::string issue ) const { + stream << " " << issue; + } + + void printExpressionWas() { + if( result.hasExpression() ) { + stream << ";"; + { + Colour colour( dimColour() ); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if( result.hasExpression() ) { + stream << " " << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + { + Colour colour( dimColour() ); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if ( itMessage != messages.end() ) { + stream << " '" << itMessage->message << "'"; + ++itMessage; + } + } + + void printRemainingMessages( Colour::Code colour = dimColour() ) { + if ( itMessage == messages.end() ) + return; + + // using messages.end() directly yields compilation error: + std::vector::const_iterator itEnd = messages.end(); + const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); + + { + Colour colourGuard( colour ); + stream << " with " << pluralise( N, "message" ) << ":"; + } + + for(; itMessage != itEnd; ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || itMessage->type != ResultWas::Info ) { + stream << " '" << itMessage->message << "'"; + if ( ++itMessage != itEnd ) { + Colour colourGuard( dimColour() ); + stream << " and"; + } + } + } + } + + private: + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + std::vector messages; + std::vector::const_iterator itMessage; + bool printInfoMessages; + }; + + // Colour, message variants: + // - white: No tests ran. + // - red: Failed [both/all] N test cases, failed [both/all] M assertions. + // - white: Passed [both/all] N test cases (no assertions). + // - red: Failed N tests cases, failed M assertions. + // - green: Passed [both/all] N tests cases with M assertions. + + std::string bothOrAll( std::size_t count ) const { + return count == 1 ? "" : count == 2 ? "both " : "all " ; + } + + void printTotals( const Totals& totals ) const { + if( totals.testCases.total() == 0 ) { + stream << "No tests ran."; + } + else if( totals.testCases.failed == totals.testCases.total() ) { + Colour colour( Colour::ResultError ); + const std::string qualify_assertions_failed = + totals.assertions.failed == totals.assertions.total() ? + bothOrAll( totals.assertions.failed ) : ""; + stream << + "Failed " << bothOrAll( totals.testCases.failed ) + << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << qualify_assertions_failed << + pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else if( totals.assertions.total() == 0 ) { + stream << + "Passed " << bothOrAll( totals.testCases.total() ) + << pluralise( totals.testCases.total(), "test case" ) + << " (no assertions)."; + } + else if( totals.assertions.failed ) { + Colour colour( Colour::ResultError ); + stream << + "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else { + Colour colour( Colour::ResultSuccess ); + stream << + "Passed " << bothOrAll( totals.testCases.passed ) + << pluralise( totals.testCases.passed, "test case" ) << + " with " << pluralise( totals.assertions.passed, "assertion" ) << "."; + } + } + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch + +namespace Catch { + NonCopyable::~NonCopyable() {} + IShared::~IShared() {} + StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} + IContext::~IContext() {} + IResultCapture::~IResultCapture() {} + ITestCase::~ITestCase() {} + ITestCaseRegistry::~ITestCaseRegistry() {} + IRegistryHub::~IRegistryHub() {} + IMutableRegistryHub::~IMutableRegistryHub() {} + IExceptionTranslator::~IExceptionTranslator() {} + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} + IReporter::~IReporter() {} + IReporterFactory::~IReporterFactory() {} + IReporterRegistry::~IReporterRegistry() {} + IStreamingReporter::~IStreamingReporter() {} + AssertionStats::~AssertionStats() {} + SectionStats::~SectionStats() {} + TestCaseStats::~TestCaseStats() {} + TestGroupStats::~TestGroupStats() {} + TestRunStats::~TestRunStats() {} + CumulativeReporterBase::SectionNode::~SectionNode() {} + CumulativeReporterBase::~CumulativeReporterBase() {} + + StreamingReporterBase::~StreamingReporterBase() {} + ConsoleReporter::~ConsoleReporter() {} + CompactReporter::~CompactReporter() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + XmlReporter::~XmlReporter() {} + JunitReporter::~JunitReporter() {} + TestRegistry::~TestRegistry() {} + FreeFunctionTestCase::~FreeFunctionTestCase() {} + IGeneratorInfo::~IGeneratorInfo() {} + IGeneratorsForTest::~IGeneratorsForTest() {} + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} + + Matchers::Impl::StdString::Equals::~Equals() {} + Matchers::Impl::StdString::Contains::~Contains() {} + Matchers::Impl::StdString::StartsWith::~StartsWith() {} + Matchers::Impl::StdString::EndsWith::~EndsWith() {} + + void Config::dummy() {} + + INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter ) +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif + +#ifdef CATCH_CONFIG_MAIN +// #included from: internal/catch_default_main.hpp +#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED + +#ifndef __OBJC__ + +// Standard C/C++ main entry point +int main (int argc, char * const argv[]) { + return Catch::Session().run( argc, argv ); +} + +#else // __OBJC__ + +// Objective-C entry point +int main (int argc, char * const argv[]) { +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int result = Catch::Session().run( argc, (char* const*)argv ); + +#if !CATCH_ARC_ENABLED + [pool drain]; +#endif + + return result; +} + +#endif // __OBJC__ + +#endif + +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +# undef CLARA_CONFIG_MAIN +#endif + +////// + +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) +#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) + +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) + +#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) +#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" ) +#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) +#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) +#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) + +#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) + +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) +#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) +#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) + #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) +#else + #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) + #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) +#endif +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#else +#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#endif +#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) +#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) + +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "REQUIRE_THROWS" ) +#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) + +#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) +#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) +#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) + +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" ) +#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) + +#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) +#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) +#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) + #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) +#else + #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) + #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) +#endif +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#else +#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#endif +#define GIVEN( desc ) SECTION( " Given: " desc, "" ) +#define WHEN( desc ) SECTION( " When: " desc, "" ) +#define AND_WHEN( desc ) SECTION( "And when: " desc, "" ) +#define THEN( desc ) SECTION( " Then: " desc, "" ) +#define AND_THEN( desc ) SECTION( " And: " desc, "" ) + +using Catch::Detail::Approx; + +// #included from: internal/catch_reenable_warnings.h + +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + diff --git a/test/include/win_mkstemp.hpp b/test/include/win_mkstemp.hpp new file mode 100644 index 000000000..693c266f3 --- /dev/null +++ b/test/include/win_mkstemp.hpp @@ -0,0 +1,42 @@ +/* + * mkstemp.c + * + * Provides a trivial replacement for the POSIX `mkstemp()' function, + * suitable for use in MinGW (Win32) applications. + * + * This file is part of the MinGW32 package set. + * + * Contributed by Keith Marshall + * Patched to VS2013 by alex85k + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef WIN_MKSTEMP_H +#define WIN_MKSTEMP_H + +#include +#include +#include + +inline int mkstemp( char *templ ) +{ + int maxtry = 26, rtn = -1; + + while( maxtry-- && (rtn < 0) ) + { + char *r = _mktemp( templ ); + if( r == NULL ) + return -1; + rtn = sopen( r, O_RDWR | O_CREAT | O_EXCL | O_BINARY, SH_DENYRW, 0600 ); + } + return rtn; +} +#endif diff --git a/test/osm-testdata/.gitignore b/test/osm-testdata/.gitignore new file mode 100644 index 000000000..98df22eda --- /dev/null +++ b/test/osm-testdata/.gitignore @@ -0,0 +1 @@ +multipolygon.qgs~ diff --git a/test/osm-testdata/CMakeLists.txt b/test/osm-testdata/CMakeLists.txt new file mode 100644 index 000000000..b29510ce4 --- /dev/null +++ b/test/osm-testdata/CMakeLists.txt @@ -0,0 +1,87 @@ +message(STATUS "Configuring osm-testdata tests...") + +if(NOT GDAL_FOUND OR + NOT EXPAT_FOUND) + message("Sorry, building osm-testdata tests needs GDAL and Expat") + return() +endif() + +set(DART_TESTING_TIMEOUT 300) +include(Dart) + +include_directories("include") +include_directories("../include") + +# In 'Dev' mode: compile with very strict warnings and turn them into errors. +if(CMAKE_BUILD_TYPE STREQUAL "Dev") + add_definitions(-Werror ${OSMIUM_WARNING_OPTIONS} -Wno-unused-variable) +endif() + +get_filename_component(TESTDATA_DIR ../../../osm-testdata ABSOLUTE) +if(NOT EXISTS ${TESTDATA_DIR}) + execute_process(COMMAND git clone https://github.com/osmcode/osm-testdata.git ${TESTDATA_DIR}) +endif() + +#---------------------------------------------------------------------- + +file(GLOB TESTCASE_CPPS testcases/*.cpp) +add_executable(testdata-testcases testdata-testcases.cpp ${TESTCASE_CPPS}) +target_link_libraries(testdata-testcases + ${OSMIUM_XML_LIBRARIES} +) +add_test(NAME testdata-testcases + COMMAND testdata-testcases +) +set_tests_properties(testdata-testcases + PROPERTIES ENVIRONMENT "TESTCASES_DIR=${TESTDATA_DIR}/grid/data") + +#---------------------------------------------------------------------- + +add_executable(testdata-overview testdata-overview.cpp) +target_link_libraries(testdata-overview + ${OSMIUM_XML_LIBRARIES} + ${GDAL_LIBRARIES} +) +add_test(NAME testdata-overview + COMMAND testdata-overview ${TESTDATA_DIR}/grid/data/all.osm +) + +#---------------------------------------------------------------------- + +add_executable(testdata-xml testdata-xml.cpp) +target_link_libraries(testdata-xml + ${OSMIUM_XML_LIBRARIES} +) +add_test(NAME testdata-xml + COMMAND testdata-xml +) +set_tests_properties(testdata-xml + PROPERTIES ENVIRONMENT "TESTDIR=${TESTDATA_DIR}/xml/data") + +#---------------------------------------------------------------------- + +add_executable(testdata-multipolygon testdata-multipolygon.cpp) +target_link_libraries(testdata-multipolygon + ${OSMIUM_XML_LIBRARIES} + ${GDAL_LIBRARIES} +) + +if(WIN32) + set(MULTIPOLYGON_TEST_SCRIPT "run-testdata-multipolygon.bat") +else() + set(MULTIPOLYGON_TEST_SCRIPT "run-testdata-multipolygon.sh") +endif() + +if(MSVC) + set(EXE_DIR ${CMAKE_BUILD_TYPE}) +else() + set(EXE_DIR .) +endif() + +add_test(NAME testdata-multipolygon + COMMAND ${CMAKE_SOURCE_DIR}/test/osm-testdata/${MULTIPOLYGON_TEST_SCRIPT} + ${TESTDATA_DIR} + ${EXE_DIR} +) + +#---------------------------------------------------------------------- diff --git a/test/osm-testdata/README.md b/test/osm-testdata/README.md new file mode 100644 index 000000000..d381f6540 --- /dev/null +++ b/test/osm-testdata/README.md @@ -0,0 +1,23 @@ +# OSM Testdata + +This directory contains software that can be used with the osm-testdata +repository at https://github.com/osmcode/osm-testdata . To use it, clone +the `osm-testdata` repository in the same directory where you cloned the +`libosmium` repository. + +## Overview + +The `testdata-overview` program can be used to create a Spatialite file +containing all the nodes and ways from the test data files. + +Compile it by running `make testdata-overview`, run it my calling +`make overview`. + +## Running the Tests + +Actual tests are in `testcases` subdirectory, one per test from the +osm-testdata repository. + +To compile the tests, call `make runtests`, to run them call +`make test`. + diff --git a/test/osm-testdata/include/check_basics_handler.hpp b/test/osm-testdata/include/check_basics_handler.hpp new file mode 100644 index 000000000..757ab4d3f --- /dev/null +++ b/test/osm-testdata/include/check_basics_handler.hpp @@ -0,0 +1,92 @@ +#ifndef CHECK_BASICS_HANDLER_HPP +#define CHECK_BASICS_HANDLER_HPP + +#include +#include + +#include +#include + +/** + * Check some basics of the input data: + * + * 1. Correct number of nodes, ways, and relations + * 2. Correct ID space used by nodes, ways, and relations + * 3. No ID used more than once + */ +class CheckBasicsHandler : public osmium::handler::Handler { + + // Lower bound for the id range allowed in this test. + int m_id_range; + + // In the beginning these contains the number of nodes, ways, and relations + // supposedly in the data.osm file. They will be decremented on each object + // and have to be 0 at the end. + int m_num_nodes; + int m_num_ways; + int m_num_relations; + + // All IDs encountered in the data.osm file will be stored in this set and + // checked for duplicates. + std::unordered_set m_ids; + + // Check id is in range [min, max] and that it isn't more than once in input. + void id_check(osmium::object_id_type id, osmium::object_id_type min, osmium::object_id_type max) { + if (id < m_id_range + min || id > m_id_range + max) { + std::cerr << " id " << id << " out of range for this test case\n"; + exit(1); + } + + auto r = m_ids.insert(id); + if (!r.second) { + std::cerr << " id " << id << " contained twice in data.osm\n"; + exit(1); + } + } + +public: + + static const int ids_per_testcase = 1000; + + CheckBasicsHandler(int testcase, int nodes, int ways, int relations) : + osmium::handler::Handler(), + m_id_range(testcase * ids_per_testcase), + m_num_nodes(nodes), + m_num_ways(ways), + m_num_relations(relations) { + } + + ~CheckBasicsHandler() { + if (m_num_nodes != 0) { + std::cerr << " wrong number of nodes in data.osm\n"; + exit(1); + } + if (m_num_ways != 0) { + std::cerr << " wrong number of ways in data.osm\n"; + exit(1); + } + if (m_num_relations != 0) { + std::cerr << " wrong number of relations in data.osm\n"; + exit(1); + } + } + + void node(const osmium::Node& node) { + id_check(node.id(), 0, 799); + --m_num_nodes; + } + + void way(const osmium::Way& way) { + id_check(way.id(), 800, 899); + --m_num_ways; + } + + void relations(const osmium::Relation& relation) { + id_check(relation.id(), 900, 999); + --m_num_relations; + } + +}; // CheckBasicsHandler + + +#endif // CHECK_BASICS_HANDLER_HPP diff --git a/test/osm-testdata/include/check_wkt_handler.hpp b/test/osm-testdata/include/check_wkt_handler.hpp new file mode 100644 index 000000000..fe0199e0a --- /dev/null +++ b/test/osm-testdata/include/check_wkt_handler.hpp @@ -0,0 +1,86 @@ +#ifndef CHECK_WKT_HANDLER_HPP +#define CHECK_WKT_HANDLER_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include + +class CheckWKTHandler : public osmium::handler::Handler { + + std::map m_geometries; + osmium::geom::WKTFactory<> m_factory; + + void read_wkt_file(const std::string& filename) { + std::ifstream in(filename, std::ifstream::in); + if (in) { + osmium::object_id_type id; + std::string line; + while (std::getline(in, line)) { + size_t pos = line.find_first_of(' '); + + if (pos == std::string::npos) { + std::cerr << filename << " not formatted correctly\n"; + exit(1); + } + + std::string id_str = line.substr(0, pos); + std::istringstream iss(id_str); + iss >> id; + + if (m_geometries.find(id) != m_geometries.end()) { + std::cerr << filename + " contains id " << id << "twice\n"; + exit(1); + } + + m_geometries[id] = line.substr(pos+1); + } + } + } + +public: + + CheckWKTHandler(const std::string& dirname, int test_id) : + osmium::handler::Handler() { + + std::string filename = dirname + "/" + std::to_string(test_id / 100) + "/" + std::to_string(test_id) + "/"; + read_wkt_file(filename + "nodes.wkt"); + read_wkt_file(filename + "ways.wkt"); + } + + ~CheckWKTHandler() { + if (!m_geometries.empty()) { + for (const auto& geom : m_geometries) { + std::cerr << "geometry id " << geom.first << " not in data.osm.\n"; + } + exit(1); + } + } + + void node(const osmium::Node& node) { + const std::string wkt = m_geometries[node.id()]; + assert(wkt != "" && "Missing geometry for node in nodes.wkt"); + + std::string this_wkt = m_factory.create_point(node.location()); + assert(wkt == this_wkt && "wkt geometries don't match"); + m_geometries.erase(node.id()); + } + + void way(const osmium::Way& way) { + const std::string wkt = m_geometries[way.id()]; + assert(wkt != "" && "Missing geometry for way in ways.wkt"); + + std::string this_wkt = m_factory.create_linestring(way); + assert(wkt == this_wkt && "wkt geometries don't match"); + m_geometries.erase(way.id()); + } + +}; // CheckWKTHandler + + +#endif // CHECK_WKT_HANDLER_HPP diff --git a/test/osm-testdata/include/common.hpp b/test/osm-testdata/include/common.hpp new file mode 100644 index 000000000..0f6957056 --- /dev/null +++ b/test/osm-testdata/include/common.hpp @@ -0,0 +1,21 @@ +#ifndef COMMON_HPP +#define COMMON_HPP + +#include +#include +#include +#include +#include +#include +#include + +typedef osmium::index::map::Dummy index_neg_type; +typedef osmium::index::map::SparseMapMem index_pos_type; +typedef osmium::handler::NodeLocationsForWays location_handler_type; + +#include "check_basics_handler.hpp" +#include "check_wkt_handler.hpp" + +#include "testdata-testcases.hpp" + +#endif // COMMON_HPP diff --git a/test/osm-testdata/include/testdata-testcases.hpp b/test/osm-testdata/include/testdata-testcases.hpp new file mode 100644 index 000000000..d7d0c01d7 --- /dev/null +++ b/test/osm-testdata/include/testdata-testcases.hpp @@ -0,0 +1,10 @@ +#ifndef TESTDATA_TESTCASES_HPP +#define TESTDATA_TESTCASES_HPP + +#include + +#include + +extern std::string dirname; + +#endif // TESTDATA_TESTCASES_HPP diff --git a/test/osm-testdata/multipolygon.qgs b/test/osm-testdata/multipolygon.qgs new file mode 100644 index 000000000..5553670bb --- /dev/null +++ b/test/osm-testdata/multipolygon.qgs @@ -0,0 +1,880 @@ + + + + + + degrees + + 0.77500024999999972 + -0.84791712574962541 + 10.22498975000000065 + 3.94791712574962572 + + 0 + + + +proj=longlat +datum=WGS84 +no_defs + 3452 + 4326 + EPSG:4326 + WGS 84 + longlat + WGS84 + true + + + + + + + + + + + + + + + + + + + + lerrors20140228172357933 + dbname='./multipolygon.db' table="lerrors" (GEOMETRY) sql= + + + + + + Error Lines + + + +proj=longlat +datum=WGS84 +no_defs + 3452 + 4326 + EPSG:4326 + WGS 84 + longlat + WGS84 + true + + + spatialite + COALESCE( "OGC_FID", '<NULL>' ) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 0 + OGC_FID + + + + + + + + + + + + . + + 0 + . + generatedlayout + + + + + + multipolygons20140221151811742 + dbname='./multipolygon.db' table="multipolygons" (GEOMETRY) sql= + + + + + + multipolygons + + + +proj=longlat +datum=WGS84 +no_defs + 3452 + 4326 + EPSG:4326 + WGS 84 + longlat + WGS84 + true + + + spatialite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 0 + OGC_FID + + + + + + + + + . + + 0 + . + generatedlayout + + + + + + perrors20140228163658956 + dbname='./multipolygon.db' table="perrors" (GEOMETRY) sql= + + + + + + Error Points + + + +proj=longlat +datum=WGS84 +no_defs + 3452 + 4326 + EPSG:4326 + WGS 84 + longlat + WGS84 + true + + + spatialite + COALESCE( "OGC_FID", '<NULL>' ) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 0 + OGC_FID + + + + + + + + + + + + . + + 0 + . + generatedlayout + + + + + + + + + + + 0.82500024999999999 + -0.35415386986094277 + 8.17498974999999994 + 3.45415386986094308 + + + + + + + false + + mp test + + + + 2 + true + D + + + + true + + false + + NONE + + + + + + + + 0 + 255 + 255 + 255 + 255 + 255 + 255 + + + + + + + + + + + EPSG:4326 + + + + + + true + 255 + + + + + + diff --git a/test/osm-testdata/run-testdata-multipolygon.bat b/test/osm-testdata/run-testdata-multipolygon.bat new file mode 100644 index 000000000..838ce9f7f --- /dev/null +++ b/test/osm-testdata/run-testdata-multipolygon.bat @@ -0,0 +1,7 @@ +set TESTDATA_DIR=%1 + +del multipolygon.db multipolygon-tests.json +%2\testdata-multipolygon %TESTDATA_DIR%\grid\data\all.osm >multipolygon.log 2>&1 +if ERRORLEVEL 1 (exit /b 1) +ruby %TESTDATA_DIR%\bin\compare-areas.rb %TESTDATA_DIR%\grid\data\tests.json multipolygon-tests.json +if ERRORLEVEL 1 (exit /b 1) diff --git a/test/osm-testdata/run-testdata-multipolygon.sh b/test/osm-testdata/run-testdata-multipolygon.sh new file mode 100755 index 000000000..dcd57a84a --- /dev/null +++ b/test/osm-testdata/run-testdata-multipolygon.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +# helper script needed by cmake to run test + +TESTDATA_DIR=$1 + +rm -f multipolygon.db multipolygon-tests.json +./testdata-multipolygon ${TESTDATA_DIR}/grid/data/all.osm >multipolygon.log 2>&1 && + ${TESTDATA_DIR}/bin/compare-areas.rb ${TESTDATA_DIR}/grid/data/tests.json multipolygon-tests.json + diff --git a/test/osm-testdata/testcases/test-100.cpp b/test/osm-testdata/testcases/test-100.cpp new file mode 100644 index 000000000..feafe771a --- /dev/null +++ b/test/osm-testdata/testcases/test-100.cpp @@ -0,0 +1,41 @@ + +#include "common.hpp" + +class TestHandler100 : public osmium::handler::Handler { + +public: + + TestHandler100() : + osmium::handler::Handler() { + } + + void node(osmium::Node& node) { + if (node.id() == 100000) { + REQUIRE(node.version() == 1); + REQUIRE(node.timestamp() == osmium::Timestamp("2014-01-01T00:00:00Z")); + REQUIRE(node.uid() == 1); + REQUIRE(!strcmp(node.user(), "test")); + REQUIRE(node.changeset() == 1); + REQUIRE(node.location().lon() == 1.02); + REQUIRE(node.location().lat() == 1.02); + } else { + throw std::runtime_error("Unknown ID"); + } + } + +}; // class TestHandler100 + +TEST_CASE("100") { + + SECTION("test 100") { + osmium::io::Reader reader(dirname + "/1/100/data.osm"); + + CheckBasicsHandler check_basics_handler(100, 1, 0, 0); + CheckWKTHandler check_wkt_handler(dirname, 100); + TestHandler100 test_handler; + + osmium::apply(reader, check_basics_handler, check_wkt_handler, test_handler); + } + +} + diff --git a/test/osm-testdata/testcases/test-101.cpp b/test/osm-testdata/testcases/test-101.cpp new file mode 100644 index 000000000..de2a5fdb7 --- /dev/null +++ b/test/osm-testdata/testcases/test-101.cpp @@ -0,0 +1,43 @@ + +#include "common.hpp" + +class TestHandler101 : public osmium::handler::Handler { + +public: + + TestHandler101() : + osmium::handler::Handler() { + } + + void node(osmium::Node& node) { + if (node.id() == 101000) { + REQUIRE(node.version() == 1); + REQUIRE(node.location().lon() == 1.12); + REQUIRE(node.location().lat() == 1.02); + } else if (node.id() == 101001) { + REQUIRE(node.version() == 1); + REQUIRE(node.location().lon() == 1.12); + REQUIRE(node.location().lat() == 1.03); + } else if (node.id() == 101002) { + } else if (node.id() == 101003) { + } else { + throw std::runtime_error("Unknown ID"); + } + } + +}; // class TestHandler101 + +TEST_CASE("101") { + + SECTION("test 101") { + osmium::io::Reader reader(dirname + "/1/101/data.osm"); + + CheckBasicsHandler check_basics_handler(101, 4, 0, 0); + CheckWKTHandler check_wkt_handler(dirname, 101); + TestHandler101 test_handler; + + osmium::apply(reader, check_basics_handler, check_wkt_handler, test_handler); + } + +} + diff --git a/test/osm-testdata/testcases/test-110.cpp b/test/osm-testdata/testcases/test-110.cpp new file mode 100644 index 000000000..16b039b1b --- /dev/null +++ b/test/osm-testdata/testcases/test-110.cpp @@ -0,0 +1,58 @@ + +#include "common.hpp" + +class TestHandler110 : public osmium::handler::Handler { + +public: + + TestHandler110() : + osmium::handler::Handler() { + } + + void node(const osmium::Node& node) { + if (node.id() == 110000) { + REQUIRE(node.location().lon() == 1.02); + REQUIRE(node.location().lat() == 1.12); + } else if (node.id() == 110001) { + REQUIRE(node.location().lon() == 1.07); + REQUIRE(node.location().lat() == 1.13); + } else { + throw std::runtime_error("Unknown ID"); + } + } + + void way(const osmium::Way& way) { + if (way.id() == 110800) { + REQUIRE(way.version() == 1); + REQUIRE(way.nodes().size() == 2); + REQUIRE(!way.is_closed()); + + const char *test_id = way.tags().get_value_by_key("test:id"); + REQUIRE(test_id); + REQUIRE(!strcmp(test_id, "110")); + } else { + throw std::runtime_error("Unknown ID"); + } + } + +}; // class TestHandler110 + +TEST_CASE("110") { + + SECTION("test 110") { + osmium::io::Reader reader(dirname + "/1/110/data.osm"); + + index_pos_type index_pos; + index_neg_type index_neg; + location_handler_type location_handler(index_pos, index_neg); + location_handler.ignore_errors(); + + CheckBasicsHandler check_basics_handler(110, 2, 1, 0); + CheckWKTHandler check_wkt_handler(dirname, 110); + TestHandler110 test_handler; + + osmium::apply(reader, location_handler, check_basics_handler, check_wkt_handler, test_handler); + } + +} + diff --git a/test/osm-testdata/testdata-multipolygon.cpp b/test/osm-testdata/testdata-multipolygon.cpp new file mode 100644 index 000000000..d732566c4 --- /dev/null +++ b/test/osm-testdata/testdata-multipolygon.cpp @@ -0,0 +1,305 @@ + +#include +#include +#include + +#pragma GCC diagnostic push +#ifdef __clang__ +# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" +#endif +#pragma GCC diagnostic ignored "-Wfloat-equal" +#pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Wpadded" +#pragma GCC diagnostic ignored "-Wredundant-decls" +#pragma GCC diagnostic ignored "-Wshadow" +# include +# include +#pragma GCC diagnostic pop + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef osmium::index::map::SparseMapMem index_type; + +typedef osmium::handler::NodeLocationsForWays location_handler_type; + +struct less_charptr { + + bool operator()(const char* a, const char* b) const { + return std::strcmp(a, b) < 0; + } + +}; // less_charptr + +typedef std::map tagmap_type; + +inline tagmap_type create_map(const osmium::TagList& taglist) { + tagmap_type map; + + for (auto& tag : taglist) { + map[tag.key()] = tag.value(); + } + + return map; +} + +class TestHandler : public osmium::handler::Handler { + + OGRDataSource* m_data_source; + OGRLayer* m_layer_point; + OGRLayer* m_layer_linestring; + OGRLayer* m_layer_polygon; + + osmium::geom::OGRFactory<> m_ogr_factory; + osmium::geom::WKTFactory<> m_wkt_factory; + + std::ofstream m_out; + + bool m_first_out {true}; + +public: + + TestHandler(OGRDataSource* data_source) : + m_data_source(data_source), + m_out("multipolygon-tests.json") { + + OGRSpatialReference sparef; + sparef.SetWellKnownGeogCS("WGS84"); + + /**************/ + + m_layer_point = m_data_source->CreateLayer("points", &sparef, wkbPoint, nullptr); + if (!m_layer_point) { + std::cerr << "Layer creation failed.\n"; + exit(1); + } + + OGRFieldDefn layer_point_field_id("id", OFTReal); + layer_point_field_id.SetWidth(10); + + if (m_layer_point->CreateField(&layer_point_field_id) != OGRERR_NONE) { + std::cerr << "Creating id field failed.\n"; + exit(1); + } + + OGRFieldDefn layer_point_field_type("type", OFTString); + layer_point_field_type.SetWidth(30); + + if (m_layer_point->CreateField(&layer_point_field_type) != OGRERR_NONE) { + std::cerr << "Creating type field failed.\n"; + exit(1); + } + + /**************/ + + m_layer_linestring = m_data_source->CreateLayer("lines", &sparef, wkbLineString, nullptr); + if (!m_layer_linestring) { + std::cerr << "Layer creation failed.\n"; + exit(1); + } + + OGRFieldDefn layer_linestring_field_id("id", OFTReal); + layer_linestring_field_id.SetWidth(10); + + if (m_layer_linestring->CreateField(&layer_linestring_field_id) != OGRERR_NONE) { + std::cerr << "Creating id field failed.\n"; + exit(1); + } + + OGRFieldDefn layer_linestring_field_type("type", OFTString); + layer_linestring_field_type.SetWidth(30); + + if (m_layer_linestring->CreateField(&layer_linestring_field_type) != OGRERR_NONE) { + std::cerr << "Creating type field failed.\n"; + exit(1); + } + + /**************/ + + m_layer_polygon = m_data_source->CreateLayer("multipolygons", &sparef, wkbMultiPolygon, nullptr); + if (!m_layer_polygon) { + std::cerr << "Layer creation failed.\n"; + exit(1); + } + + OGRFieldDefn layer_polygon_field_id("id", OFTInteger); + layer_polygon_field_id.SetWidth(10); + + if (m_layer_polygon->CreateField(&layer_polygon_field_id) != OGRERR_NONE) { + std::cerr << "Creating id field failed.\n"; + exit(1); + } + + OGRFieldDefn layer_polygon_field_from_type("from_type", OFTString); + layer_polygon_field_from_type.SetWidth(1); + + if (m_layer_polygon->CreateField(&layer_polygon_field_from_type) != OGRERR_NONE) { + std::cerr << "Creating from_type field failed.\n"; + exit(1); + } + } + + ~TestHandler() { + m_out << "\n]\n"; + } + + void node(const osmium::Node& node) { + OGRFeature* feature = OGRFeature::CreateFeature(m_layer_point->GetLayerDefn()); + std::unique_ptr ogr_point = m_ogr_factory.create_point(node); + feature->SetGeometry(ogr_point.get()); + feature->SetField("id", static_cast(node.id())); + feature->SetField("type", node.tags().get_value_by_key("type")); + + if (m_layer_point->CreateFeature(feature) != OGRERR_NONE) { + std::cerr << "Failed to create feature.\n"; + exit(1); + } + + OGRFeature::DestroyFeature(feature); + } + + void way(const osmium::Way& way) { + try { + std::unique_ptr ogr_linestring = m_ogr_factory.create_linestring(way); + OGRFeature* feature = OGRFeature::CreateFeature(m_layer_linestring->GetLayerDefn()); + feature->SetGeometry(ogr_linestring.get()); + feature->SetField("id", static_cast(way.id())); + feature->SetField("type", way.tags().get_value_by_key("type")); + + if (m_layer_linestring->CreateFeature(feature) != OGRERR_NONE) { + std::cerr << "Failed to create feature.\n"; + exit(1); + } + + OGRFeature::DestroyFeature(feature); + } catch (osmium::geometry_error&) { + std::cerr << "Ignoring illegal geometry for way " << way.id() << ".\n"; + } + } + + void area(const osmium::Area& area) { + if (m_first_out) { + m_out << "[\n"; + m_first_out = false; + } else { + m_out << ",\n"; + } + m_out << "{\n \"test_id\": " << (area.orig_id() / 1000) << ",\n \"area_id\": " << area.id() << ",\n \"from_id\": " << area.orig_id() << ",\n \"from_type\": \"" << (area.from_way() ? "way" : "relation") << "\",\n \"wkt\": \""; + try { + std::string wkt = m_wkt_factory.create_multipolygon(area); + m_out << wkt << "\",\n \"tags\": {"; + + auto tagmap = create_map(area.tags()); + bool first = true; + for (auto& tag : tagmap) { + if (first) { + first = false; + } else { + m_out << ", "; + } + m_out << '"' << tag.first << "\": \"" << tag.second << '"'; + } + m_out << "}\n}"; + } catch (osmium::geometry_error&) { + m_out << "INVALID\"\n}"; + } + try { + std::unique_ptr ogr_polygon = m_ogr_factory.create_multipolygon(area); + OGRFeature* feature = OGRFeature::CreateFeature(m_layer_polygon->GetLayerDefn()); + feature->SetGeometry(ogr_polygon.get()); + feature->SetField("id", static_cast(area.orig_id())); + + std::string from_type; + if (area.from_way()) { + from_type = "w"; + } else { + from_type = "r"; + } + feature->SetField("from_type", from_type.c_str()); + + if (m_layer_polygon->CreateFeature(feature) != OGRERR_NONE) { + std::cerr << "Failed to create feature.\n"; + exit(1); + } + + OGRFeature::DestroyFeature(feature); + } catch (osmium::geometry_error&) { + std::cerr << "Ignoring illegal geometry for area " << area.id() << " created from " << (area.from_way() ? "way" : "relation") << " with id=" << area.orig_id() << ".\n"; + } + } + +}; // class TestHandler + +/* ================================================== */ + +OGRDataSource* initialize_database(const std::string& output_format, const std::string& output_filename) { + OGRRegisterAll(); + + OGRSFDriver* driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(output_format.c_str()); + if (!driver) { + std::cerr << output_format << " driver not available.\n"; + exit(1); + } + + CPLSetConfigOption("OGR_SQLITE_SYNCHRONOUS", "FALSE"); + const char* options[] = { "SPATIALITE=TRUE", nullptr }; + OGRDataSource* data_source = driver->CreateDataSource(output_filename.c_str(), const_cast(options)); + if (!data_source) { + std::cerr << "Creation of output file failed.\n"; + exit(1); + } + + return data_source; +} + +int main(int argc, char* argv[]) { + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " INFILE\n"; + exit(1); + } + + std::string output_format("SQLite"); + std::string input_filename(argv[1]); + std::string output_filename("multipolygon.db"); + + OGRDataSource* data_source = initialize_database(output_format, output_filename); + + osmium::area::ProblemReporterOGR problem_reporter(data_source); + osmium::area::Assembler::config_type assembler_config(&problem_reporter); + assembler_config.enable_debug_output(); + osmium::area::MultipolygonCollector collector(assembler_config); + + std::cerr << "Pass 1...\n"; + osmium::io::Reader reader1(input_filename); + collector.read_relations(reader1); + reader1.close(); + std::cerr << "Pass 1 done\n"; + + index_type index_pos; + index_type index_neg; + location_handler_type location_handler(index_pos, index_neg); + location_handler.ignore_errors(); + + TestHandler test_handler(data_source); + + std::cerr << "Pass 2...\n"; + osmium::io::Reader reader2(input_filename); + osmium::apply(reader2, location_handler, test_handler, collector.handler([&test_handler](const osmium::memory::Buffer& area_buffer) { + osmium::apply(area_buffer, test_handler); + })); + reader2.close(); + std::cerr << "Pass 2 done\n"; + + OGRDataSource::DestroyDataSource(data_source); + OGRCleanupAll(); +} + diff --git a/test/osm-testdata/testdata-overview.cpp b/test/osm-testdata/testdata-overview.cpp new file mode 100644 index 000000000..b56781268 --- /dev/null +++ b/test/osm-testdata/testdata-overview.cpp @@ -0,0 +1,212 @@ +/* The code in this file is released into the Public Domain. */ + +#include + +#pragma GCC diagnostic push +#ifdef __clang__ +# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" +#endif +#pragma GCC diagnostic ignored "-Wfloat-equal" +#pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Wpadded" +#pragma GCC diagnostic ignored "-Wredundant-decls" +#pragma GCC diagnostic ignored "-Wshadow" +# include +# include +#pragma GCC diagnostic pop + +#include +#include +#include +#include +#include +#include +#include + +typedef osmium::index::map::Dummy index_neg_type; +typedef osmium::index::map::SparseMapMem index_pos_type; +typedef osmium::handler::NodeLocationsForWays location_handler_type; + +class TestOverviewHandler : public osmium::handler::Handler { + + OGRDataSource* m_data_source; + + OGRLayer* m_layer_nodes; + OGRLayer* m_layer_labels; + OGRLayer* m_layer_ways; + + osmium::geom::OGRFactory<> m_factory; + +public: + + TestOverviewHandler(const std::string& driver_name, const std::string& filename) { + + OGRRegisterAll(); + + OGRSFDriver* driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(driver_name.c_str()); + if (!driver) { + std::cerr << driver_name << " driver not available.\n"; + exit(1); + } + + CPLSetConfigOption("OGR_SQLITE_SYNCHRONOUS", "FALSE"); + const char* options[] = { "SPATIALITE=TRUE", nullptr }; + m_data_source = driver->CreateDataSource(filename.c_str(), const_cast(options)); + if (!m_data_source) { + std::cerr << "Creation of output file failed.\n"; + exit(1); + } + + OGRSpatialReference sparef; + sparef.SetWellKnownGeogCS("WGS84"); + + // nodes layer + + m_layer_nodes = m_data_source->CreateLayer("nodes", &sparef, wkbPoint, nullptr); + if (!m_layer_nodes) { + std::cerr << "Layer creation failed.\n"; + exit(1); + } + + OGRFieldDefn layer_nodes_field_id("id", OFTReal); + layer_nodes_field_id.SetWidth(10); + + if (m_layer_nodes->CreateField(&layer_nodes_field_id) != OGRERR_NONE) { + std::cerr << "Creating id field failed.\n"; + exit(1); + } + + // labels layer + + m_layer_labels = m_data_source->CreateLayer("labels", &sparef, wkbPoint, nullptr); + if (!m_layer_labels) { + std::cerr << "Layer creation failed.\n"; + exit(1); + } + + OGRFieldDefn layer_labels_field_id("id", OFTReal); + layer_labels_field_id.SetWidth(10); + + if (m_layer_labels->CreateField(&layer_labels_field_id) != OGRERR_NONE) { + std::cerr << "Creating id field failed.\n"; + exit(1); + } + + OGRFieldDefn layer_labels_field_label("label", OFTString); + layer_labels_field_label.SetWidth(30); + + if (m_layer_labels->CreateField(&layer_labels_field_label) != OGRERR_NONE) { + std::cerr << "Creating label field failed.\n"; + exit(1); + } + + // ways layer + + m_layer_ways = m_data_source->CreateLayer("ways", &sparef, wkbLineString, nullptr); + if (!m_layer_ways) { + std::cerr << "Layer creation failed.\n"; + exit(1); + } + + OGRFieldDefn layer_way_field_id("id", OFTReal); + layer_way_field_id.SetWidth(10); + + if (m_layer_ways->CreateField(&layer_way_field_id) != OGRERR_NONE) { + std::cerr << "Creating id field failed.\n"; + exit(1); + } + + OGRFieldDefn layer_way_field_test("test", OFTInteger); + layer_way_field_test.SetWidth(3); + + if (m_layer_ways->CreateField(&layer_way_field_test) != OGRERR_NONE) { + std::cerr << "Creating test field failed.\n"; + exit(1); + } + } + + ~TestOverviewHandler() { + OGRDataSource::DestroyDataSource(m_data_source); + OGRCleanupAll(); + } + + void node(const osmium::Node& node) { + const char* label = node.tags().get_value_by_key("label"); + if (label) { + OGRFeature* feature = OGRFeature::CreateFeature(m_layer_labels->GetLayerDefn()); + std::unique_ptr ogr_point = m_factory.create_point(node); + feature->SetGeometry(ogr_point.get()); + feature->SetField("id", static_cast(node.id())); + feature->SetField("label", label); + + if (m_layer_labels->CreateFeature(feature) != OGRERR_NONE) { + std::cerr << "Failed to create feature.\n"; + exit(1); + } + + OGRFeature::DestroyFeature(feature); + } else { + OGRFeature* feature = OGRFeature::CreateFeature(m_layer_nodes->GetLayerDefn()); + std::unique_ptr ogr_point = m_factory.create_point(node); + feature->SetGeometry(ogr_point.get()); + feature->SetField("id", static_cast(node.id())); + + if (m_layer_nodes->CreateFeature(feature) != OGRERR_NONE) { + std::cerr << "Failed to create feature.\n"; + exit(1); + } + OGRFeature::DestroyFeature(feature); + } + } + + void way(const osmium::Way& way) { + try { + std::unique_ptr ogr_linestring = m_factory.create_linestring(way); + OGRFeature* feature = OGRFeature::CreateFeature(m_layer_ways->GetLayerDefn()); + feature->SetGeometry(ogr_linestring.get()); + feature->SetField("id", static_cast(way.id())); + + const char* test = way.tags().get_value_by_key("test"); + if (test) { + feature->SetField("test", test); + } + + if (m_layer_ways->CreateFeature(feature) != OGRERR_NONE) { + std::cerr << "Failed to create feature.\n"; + exit(1); + } + + OGRFeature::DestroyFeature(feature); + } catch (osmium::geometry_error&) { + std::cerr << "Ignoring illegal geometry for way " << way.id() << ".\n"; + } + } + +}; + +/* ================================================== */ + +int main(int argc, char* argv[]) { + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " INFILE\n"; + exit(1); + } + + std::string output_format("SQLite"); + std::string input_filename(argv[1]); + std::string output_filename("testdata-overview.db"); + ::unlink(output_filename.c_str()); + + osmium::io::Reader reader(input_filename); + + index_pos_type index_pos; + index_neg_type index_neg; + location_handler_type location_handler(index_pos, index_neg); + location_handler.ignore_errors(); + + TestOverviewHandler handler(output_format, output_filename); + + osmium::apply(reader, location_handler, handler); + reader.close(); +} + diff --git a/test/osm-testdata/testdata-testcases.cpp b/test/osm-testdata/testdata-testcases.cpp new file mode 100644 index 000000000..6ed6ae91a --- /dev/null +++ b/test/osm-testdata/testdata-testcases.cpp @@ -0,0 +1,27 @@ + +#include +#include + +#define CATCH_CONFIG_RUNNER + +#include "testdata-testcases.hpp" + +#include + +std::string dirname; + +int main(int argc, char* argv[]) { + const char* testcases_dir = getenv("TESTCASES_DIR"); + if (testcases_dir) { + dirname = testcases_dir; + std::cerr << "Running tests from '" << dirname << "' (from TESTCASES_DIR environment variable)\n"; + } else { + std::cerr << "Please set TESTCASES_DIR environment variable.\n"; + exit(1); + } + + int result = Catch::Session().run(argc, argv); + + return result; +} + diff --git a/test/osm-testdata/testdata-xml.cpp b/test/osm-testdata/testdata-xml.cpp new file mode 100644 index 000000000..e4c1716d4 --- /dev/null +++ b/test/osm-testdata/testdata-xml.cpp @@ -0,0 +1,372 @@ +/* The code in this file is released into the Public Domain. */ + +#define CATCH_CONFIG_MAIN + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" +#include "catch.hpp" +#pragma GCC diagnostic pop + +#include +#include +#include +#include + +#include +#include +#include + +std::string filename(const char* test_id, const char* suffix = "osm") { + const char* testdir = getenv("TESTDIR"); + if (!testdir) { + std::cerr << "You have to set TESTDIR environment variable before running testdata-xml\n"; + exit(2); + } + + std::string f; + f += testdir; + f += "/"; + f += test_id; + f += "/data."; + f += suffix; + return f; +} + +struct header_buffer_type { + osmium::io::Header header; + osmium::memory::Buffer buffer; +}; + +// ============================================= + +// The following helper functions are used to call different parts of the +// Osmium internals used to read and parse XML files. This way those parts +// can be tested individually. These function can not be used in normal +// operations, because they make certain assumptions, for instance that +// file contents fit into small buffers. + +std::string read_file(const char* test_id) { + int fd = osmium::io::detail::open_for_reading(filename(test_id)); + assert(fd >= 0); + + std::string input(10000, '\0'); + ssize_t n = ::read(fd, reinterpret_cast(const_cast(input.data())), 10000); + assert(n >= 0); + input.resize(static_cast(n)); + + close(fd); + + return input; +} + +std::string read_gz_file(const char* test_id, const char* suffix) { + int fd = osmium::io::detail::open_for_reading(filename(test_id, suffix)); + assert(fd >= 0); + + osmium::io::GzipDecompressor gzip_decompressor(fd); + std::string input = gzip_decompressor.read(); + gzip_decompressor.close(); + + return input; +} + + +header_buffer_type parse_xml(std::string input) { + osmium::thread::Queue input_queue; + osmium::thread::Queue output_queue; + std::promise header_promise; + std::atomic done {false}; + input_queue.push(input); + input_queue.push(std::string()); // EOF marker + + osmium::io::detail::XMLParser parser(input_queue, output_queue, header_promise, osmium::osm_entity_bits::all, done); + parser(); + + header_buffer_type result; + result.header = header_promise.get_future().get(); + output_queue.wait_and_pop(result.buffer); + + if (result.buffer) { + osmium::memory::Buffer buffer; + output_queue.wait_and_pop(buffer); + assert(!buffer); + } + + return result; +} + +header_buffer_type read_xml(const char* test_id) { + std::string input = read_file(test_id); + return parse_xml(input); +} + +// ============================================= + +TEST_CASE("Reading OSM XML 100") { + + SECTION("Direct") { + header_buffer_type r = read_xml("100-correct_but_no_data"); + + REQUIRE(r.header.get("generator") == "testdata"); + REQUIRE(0 == r.buffer.committed()); + REQUIRE(! r.buffer); + } + + SECTION("Using Reader") { + osmium::io::Reader reader(filename("100-correct_but_no_data")); + + osmium::io::Header header = reader.header(); + REQUIRE(header.get("generator") == "testdata"); + + osmium::memory::Buffer buffer = reader.read(); + REQUIRE(0 == buffer.committed()); + REQUIRE(! buffer); + reader.close(); + } + + SECTION("Using Reader asking for header only") { + osmium::io::Reader reader(filename("100-correct_but_no_data"), osmium::osm_entity_bits::nothing); + + osmium::io::Header header = reader.header(); + REQUIRE(header.get("generator") == "testdata"); + reader.close(); + } + +} + +// ============================================= + +TEST_CASE("Reading OSM XML 101") { + + SECTION("Direct") { + REQUIRE_THROWS_AS(read_xml("101-missing_version"), osmium::format_version_error); + try { + read_xml("101-missing_version"); + } catch (osmium::format_version_error& e) { + REQUIRE(e.version.empty()); + } + } + + SECTION("Using Reader") { + REQUIRE_THROWS_AS({ + osmium::io::Reader reader(filename("101-missing_version")); + osmium::io::Header header = reader.header(); + osmium::memory::Buffer buffer = reader.read(); + reader.close(); + }, osmium::format_version_error); + } + +} + +// ============================================= + +TEST_CASE("Reading OSM XML 102") { + + SECTION("Direct") { + REQUIRE_THROWS_AS(read_xml("102-wrong_version"), osmium::format_version_error); + try { + read_xml("102-wrong_version"); + } catch (osmium::format_version_error& e) { + REQUIRE(e.version == "0.1"); + } + } + + SECTION("Using Reader") { + REQUIRE_THROWS_AS({ + osmium::io::Reader reader(filename("102-wrong_version")); + + osmium::io::Header header = reader.header(); + osmium::memory::Buffer buffer = reader.read(); + reader.close(); + }, osmium::format_version_error); + } + +} + +// ============================================= + +TEST_CASE("Reading OSM XML 103") { + + SECTION("Direct") { + REQUIRE_THROWS_AS(read_xml("103-old_version"), osmium::format_version_error); + try { + read_xml("103-old_version"); + } catch (osmium::format_version_error& e) { + REQUIRE(e.version == "0.5"); + } + } + + SECTION("Using Reader") { + REQUIRE_THROWS_AS({ + osmium::io::Reader reader(filename("103-old_version")); + osmium::io::Header header = reader.header(); + osmium::memory::Buffer buffer = reader.read(); + reader.close(); + }, osmium::format_version_error); + } + +} + +// ============================================= + +TEST_CASE("Reading OSM XML 104") { + + SECTION("Direct") { + REQUIRE_THROWS_AS(read_xml("104-empty_file"), osmium::xml_error); + try { + read_xml("104-empty_file"); + } catch (osmium::xml_error& e) { + REQUIRE(e.line == 1); + REQUIRE(e.column == 0); + } + } + + SECTION("Using Reader") { + REQUIRE_THROWS_AS({ + osmium::io::Reader reader(filename("104-empty_file")); + osmium::io::Header header = reader.header(); + osmium::memory::Buffer buffer = reader.read(); + reader.close(); + }, osmium::xml_error); + } +} + +// ============================================= + +TEST_CASE("Reading OSM XML 105") { + + SECTION("Direct") { + REQUIRE_THROWS_AS(read_xml("105-incomplete_xml_file"), osmium::xml_error); + } + + SECTION("Using Reader") { + REQUIRE_THROWS_AS({ + osmium::io::Reader reader(filename("105-incomplete_xml_file")); + osmium::io::Header header = reader.header(); + osmium::memory::Buffer buffer = reader.read(); + reader.close(); + }, osmium::xml_error); + } + +} + +// ============================================= + +TEST_CASE("Reading OSM XML 120") { + + SECTION("Direct") { + std::string data = read_gz_file("120-correct_gzip_file_without_data", "osm.gz"); + + REQUIRE(data.size() == 102); + + header_buffer_type r = parse_xml(data); + REQUIRE(r.header.get("generator") == "testdata"); + REQUIRE(0 == r.buffer.committed()); + REQUIRE(! r.buffer); + } + + SECTION("Using Reader") { + osmium::io::Reader reader(filename("120-correct_gzip_file_without_data", "osm.gz")); + + osmium::io::Header header = reader.header(); + REQUIRE(header.get("generator") == "testdata"); + + osmium::memory::Buffer buffer = reader.read(); + REQUIRE(0 == buffer.committed()); + REQUIRE(! buffer); + reader.close(); + } + +} + +// ============================================= + +TEST_CASE("Reading OSM XML 121") { + + SECTION("Direct") { + REQUIRE_THROWS_AS( { + read_gz_file("121-truncated_gzip_file", "osm.gz"); + }, osmium::gzip_error); + } + +#if 0 + SECTION("Using Reader") { + REQUIRE_THROWS_AS({ + osmium::io::Reader reader(filename("121-truncated_gzip_file", "osm.gz")); + osmium::io::Header header = reader.header(); + osmium::memory::Buffer buffer = reader.read(); + reader.close(); + }, osmium::gzip_error); + } +#endif + +} + +// ============================================= + +TEST_CASE("Reading OSM XML 200") { + + SECTION("Direct") { + header_buffer_type r = read_xml("200-nodes"); + + REQUIRE(r.header.get("generator") == "testdata"); + REQUIRE(r.buffer.committed() > 0); + REQUIRE(r.buffer.get(0).type() == osmium::item_type::node); + REQUIRE(r.buffer.get(0).id() == 36966060); + REQUIRE(std::distance(r.buffer.begin(), r.buffer.end()) == 3); + } + + SECTION("Using Reader") { + osmium::io::Reader reader(filename("200-nodes")); + + osmium::io::Header header = reader.header(); + REQUIRE(header.get("generator") == "testdata"); + + osmium::memory::Buffer buffer = reader.read(); + REQUIRE(buffer.committed() > 0); + REQUIRE(buffer.get(0).type() == osmium::item_type::node); + REQUIRE(buffer.get(0).id() == 36966060); + REQUIRE(std::distance(buffer.begin(), buffer.end()) == 3); + reader.close(); + } + + SECTION("Using Reader asking for nodes") { + osmium::io::Reader reader(filename("200-nodes"), osmium::osm_entity_bits::node); + + osmium::io::Header header = reader.header(); + REQUIRE(header.get("generator") == "testdata"); + + osmium::memory::Buffer buffer = reader.read(); + REQUIRE(buffer.committed() > 0); + REQUIRE(buffer.get(0).type() == osmium::item_type::node); + REQUIRE(buffer.get(0).id() == 36966060); + REQUIRE(std::distance(buffer.begin(), buffer.end()) == 3); + reader.close(); + } + + SECTION("Using Reader asking for header only") { + osmium::io::Reader reader(filename("200-nodes"), osmium::osm_entity_bits::nothing); + + osmium::io::Header header = reader.header(); + REQUIRE(header.get("generator") == "testdata"); + + osmium::memory::Buffer buffer = reader.read(); + REQUIRE(0 == buffer.committed()); + REQUIRE(! buffer); + reader.close(); + } + + SECTION("Using Reader asking for ways") { + osmium::io::Reader reader(filename("200-nodes"), osmium::osm_entity_bits::way); + + osmium::io::Header header = reader.header(); + REQUIRE(header.get("generator") == "testdata"); + + osmium::memory::Buffer buffer = reader.read(); + REQUIRE(0 == buffer.committed()); + REQUIRE(! buffer); + reader.close(); + } + +} + diff --git a/test/t/area/test_area_id.cpp b/test/t/area/test_area_id.cpp new file mode 100644 index 000000000..45bf87cbe --- /dev/null +++ b/test/t/area/test_area_id.cpp @@ -0,0 +1,25 @@ +#include "catch.hpp" + +#include + +TEST_CASE("area_id") { + +SECTION("object_id_to_area_id_conversion") { + REQUIRE( 46 == osmium::object_id_to_area_id( 23, osmium::item_type::way)); + REQUIRE( 47 == osmium::object_id_to_area_id( 23, osmium::item_type::relation)); + REQUIRE( 0 == osmium::object_id_to_area_id( 0, osmium::item_type::way)); + REQUIRE( 1 == osmium::object_id_to_area_id( 0, osmium::item_type::relation)); + REQUIRE(-24 == osmium::object_id_to_area_id(-12, osmium::item_type::way)); + REQUIRE(-25 == osmium::object_id_to_area_id(-12, osmium::item_type::relation)); +} + +SECTION("area_id_to_object_id_conversion") { + REQUIRE( 23 == osmium::area_id_to_object_id( 46)); + REQUIRE( 23 == osmium::area_id_to_object_id( 47)); + REQUIRE( 0 == osmium::area_id_to_object_id( 0)); + REQUIRE( 0 == osmium::area_id_to_object_id( 1)); + REQUIRE(-12 == osmium::area_id_to_object_id(-24)); + REQUIRE(-12 == osmium::area_id_to_object_id(-25)); +} + +} diff --git a/test/t/area/test_node_ref_segment.cpp b/test/t/area/test_node_ref_segment.cpp new file mode 100644 index 000000000..fd67e6c49 --- /dev/null +++ b/test/t/area/test_node_ref_segment.cpp @@ -0,0 +1,115 @@ +#include "catch.hpp" + +#include + +using osmium::area::detail::NodeRefSegment; + +TEST_CASE("NodeRefSegmentClass") { + +SECTION("instantiation_with_default_parameters") { + NodeRefSegment s; + REQUIRE(s.first().ref() == 0); + REQUIRE(s.first().location() == osmium::Location()); + REQUIRE(s.second().ref() == 0); + REQUIRE(s.second().location() == osmium::Location()); +} + +SECTION("instantiation") { + osmium::NodeRef nr1(1, { 1.2, 3.4 }); + osmium::NodeRef nr2(2, { 1.4, 3.1 }); + osmium::NodeRef nr3(3, { 1.2, 3.6 }); + osmium::NodeRef nr4(4, { 1.2, 3.7 }); + + NodeRefSegment s1(nr1, nr2, nullptr, nullptr); + REQUIRE(s1.first().ref() == 1); + REQUIRE(s1.second().ref() == 2); + + NodeRefSegment s2(nr2, nr3, nullptr, nullptr); + REQUIRE(s2.first().ref() == 3); + REQUIRE(s2.second().ref() == 2); + + NodeRefSegment s3(nr3, nr4, nullptr, nullptr); + REQUIRE(s3.first().ref() == 3); + REQUIRE(s3.second().ref() == 4); +} + +SECTION("intersection") { + NodeRefSegment s1({ 1, {0.0, 0.0}}, { 2, {2.0, 2.0}}, nullptr, nullptr); + NodeRefSegment s2({ 3, {0.0, 2.0}}, { 4, {2.0, 0.0}}, nullptr, nullptr); + NodeRefSegment s3({ 5, {2.0, 0.0}}, { 6, {4.0, 2.0}}, nullptr, nullptr); + NodeRefSegment s4({ 7, {1.0, 0.0}}, { 8, {3.0, 2.0}}, nullptr, nullptr); + NodeRefSegment s5({ 9, {0.0, 4.0}}, {10, {4.0, 0.0}}, nullptr, nullptr); + NodeRefSegment s6({11, {0.0, 0.0}}, {12, {1.0, 1.0}}, nullptr, nullptr); + NodeRefSegment s7({13, {1.0, 1.0}}, {14, {3.0, 3.0}}, nullptr, nullptr); + + REQUIRE(calculate_intersection(s1, s2) == osmium::Location(1.0, 1.0)); + REQUIRE(calculate_intersection(s1, s3) == osmium::Location()); + REQUIRE(calculate_intersection(s2, s3) == osmium::Location()); + REQUIRE(calculate_intersection(s1, s4) == osmium::Location()); + REQUIRE(calculate_intersection(s1, s5) == osmium::Location(2.0, 2.0)); + REQUIRE(calculate_intersection(s1, s1) == osmium::Location()); + REQUIRE(calculate_intersection(s1, s6) == osmium::Location()); + REQUIRE(calculate_intersection(s1, s7) == osmium::Location()); +} + +SECTION("to_left_of") { + osmium::Location loc { 2.0, 2.0 }; + + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {0.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {4.0, 0.0}}, {1, {4.0, 4.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {1.0, 0.0}}, {1, {1.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); + + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {1.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {2.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {3.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {4.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {4.0, 3.0}}, nullptr, nullptr).to_left_of(loc) == false); + + REQUIRE(NodeRefSegment({0, {1.0, 3.0}}, {1, {2.0, 0.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {1.0, 3.0}}, {1, {3.0, 1.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {1.0, 3.0}}, {1, {3.0, 2.0}}, nullptr, nullptr).to_left_of(loc) == false); + + REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {2.0, 2.0}}, nullptr, nullptr).to_left_of(loc) == false); + + REQUIRE(NodeRefSegment({0, {2.0, 0.0}}, {1, {2.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {2.0, 0.0}}, {1, {2.0, 2.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {2.0, 2.0}}, {1, {2.0, 4.0}}, nullptr, nullptr).to_left_of(loc) == false); + + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {0.0, 1.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {1.0, 0.0}}, {1, {0.0, 1.0}}, nullptr, nullptr).to_left_of(loc) == false); + + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {1.0, 3.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {2.0, 0.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {3.0, 4.0}}, nullptr, nullptr).to_left_of(loc) == false); + + REQUIRE(NodeRefSegment({0, {1.0, 0.0}}, {1, {1.0, 2.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {1.0, 2.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {1.0, 4.0}}, nullptr, nullptr).to_left_of(loc) == false); + + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {0.0, 2.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {4.0, 4.0}}, nullptr, nullptr).to_left_of(loc) == false); + + REQUIRE(NodeRefSegment({0, {0.0, 1.0}}, {1, {2.0, 2.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {2.0, 2.0}}, {1, {4.0, 0.0}}, nullptr, nullptr).to_left_of(loc) == false); +} + +SECTION("ordering") { + osmium::NodeRef node_ref1(1, { 1.0, 3.0 }); + osmium::NodeRef node_ref2(2, { 1.4, 2.9 }); + osmium::NodeRef node_ref3(3, { 1.2, 3.0 }); + osmium::NodeRef node_ref4(4, { 1.2, 3.3 }); + + REQUIRE(node_ref1 < node_ref2); + REQUIRE(node_ref2 < node_ref3); + REQUIRE(node_ref1 < node_ref3); + REQUIRE(node_ref1 >= node_ref1); + + REQUIRE( osmium::location_less()(node_ref1, node_ref2)); + REQUIRE(!osmium::location_less()(node_ref2, node_ref3)); + REQUIRE( osmium::location_less()(node_ref1, node_ref3)); + REQUIRE( osmium::location_less()(node_ref3, node_ref4)); + REQUIRE(!osmium::location_less()(node_ref1, node_ref1)); +} + +} + diff --git a/test/t/basic/helper.hpp b/test/t/basic/helper.hpp new file mode 100644 index 000000000..61e076934 --- /dev/null +++ b/test/t/basic/helper.hpp @@ -0,0 +1,97 @@ +#ifndef TEST_BASIC_HELPER_HPP +#define TEST_BASIC_HELPER_HPP + +#include +#include +#include + +#include + +inline void add_tags(osmium::memory::Buffer& buffer, osmium::builder::Builder& builder, const std::vector>& tags) { + osmium::builder::TagListBuilder tl_builder(buffer, &builder); + for (auto& tag : tags) { + tl_builder.add_tag(tag.first, tag.second); + } +} + +inline osmium::Node& buffer_add_node(osmium::memory::Buffer& buffer, const char* user, const std::vector>& tags, const osmium::Location& location) { + osmium::builder::NodeBuilder builder(buffer); + builder.add_user(user); + add_tags(buffer, builder, tags); + buffer.commit(); + return builder.object().set_location(location); +} + +inline osmium::Way& buffer_add_way(osmium::memory::Buffer& buffer, const char* user, const std::vector>& tags, const std::vector& nodes) { + osmium::builder::WayBuilder builder(buffer); + builder.add_user(user); + add_tags(buffer, builder, tags); + osmium::builder::WayNodeListBuilder wnl_builder(buffer, &builder); + for (const osmium::object_id_type ref : nodes) { + wnl_builder.add_node_ref(ref); + } + buffer.commit(); + return builder.object(); +} + +inline osmium::Way& buffer_add_way(osmium::memory::Buffer& buffer, const char* user, const std::vector>& tags, const std::vector>& nodes) { + osmium::builder::WayBuilder builder(buffer); + builder.add_user(user); + add_tags(buffer, builder, tags); + osmium::builder::WayNodeListBuilder wnl_builder(buffer, &builder); + for (auto& p : nodes) { + wnl_builder.add_node_ref(p.first, p.second); + } + buffer.commit(); + return builder.object(); +} + +inline osmium::Relation& buffer_add_relation( + osmium::memory::Buffer& buffer, + const char* user, + const std::vector>& tags, const std::vector>& members) { + osmium::builder::RelationBuilder builder(buffer); + builder.add_user(user); + add_tags(buffer, builder, tags); + osmium::builder::RelationMemberListBuilder rml_builder(buffer, &builder); + for (const auto& member : members) { + rml_builder.add_member(osmium::char_to_item_type(std::get<0>(member)), std::get<1>(member), std::get<2>(member)); + } + buffer.commit(); + return builder.object(); +} + +inline osmium::Area& buffer_add_area(osmium::memory::Buffer& buffer, const char* user, + const std::vector>& tags, + const std::vector>>>& rings) { + osmium::builder::AreaBuilder builder(buffer); + builder.add_user(user); + add_tags(buffer, builder, tags); + + for (auto& ring : rings) { + if (ring.first) { + osmium::builder::OuterRingBuilder ring_builder(buffer, &builder); + for (auto& p : ring.second) { + ring_builder.add_node_ref(p.first, p.second); + } + } else { + osmium::builder::InnerRingBuilder ring_builder(buffer, &builder); + for (auto& p : ring.second) { + ring_builder.add_node_ref(p.first, p.second); + } + } + } + buffer.commit(); + return builder.object(); +} + +inline osmium::Changeset& buffer_add_changeset(osmium::memory::Buffer& buffer, const char* user, const std::vector>& tags) { + osmium::builder::ChangesetBuilder builder(buffer); + builder.add_user(user); + add_tags(buffer, builder, tags); + buffer.commit(); + return builder.object(); +} + +#endif // TEST_BASIC_HELPER_HPP diff --git a/test/t/basic/test_box.cpp b/test/t/basic/test_box.cpp new file mode 100644 index 000000000..34789e815 --- /dev/null +++ b/test/t/basic/test_box.cpp @@ -0,0 +1,81 @@ +#include "catch.hpp" + +#include + +#include +#include + +TEST_CASE("Box") { + +SECTION("instantiation") { + osmium::Box b; + REQUIRE(!b); + REQUIRE(!b.bottom_left()); + REQUIRE(!b.top_right()); + REQUIRE_THROWS_AS(b.size(), osmium::invalid_location); +} + +SECTION("instantiation_and_extend_with_undefined") { + osmium::Box b; + REQUIRE(!b); + b.extend(osmium::Location()); + REQUIRE(!b.bottom_left()); + REQUIRE(!b.top_right()); +} + +SECTION("instantiation_and_extend") { + osmium::Box b; + b.extend(osmium::Location(1.2, 3.4)); + REQUIRE(!!b); + REQUIRE(!!b.bottom_left()); + REQUIRE(!!b.top_right()); + b.extend(osmium::Location(3.4, 4.5)); + b.extend(osmium::Location(5.6, 7.8)); + REQUIRE(b.bottom_left() == osmium::Location(1.2, 3.4)); + REQUIRE(b.top_right() == osmium::Location(5.6, 7.8)); + + // extend with undefined doesn't change anything + b.extend(osmium::Location()); + REQUIRE(b.bottom_left() == osmium::Location(1.2, 3.4)); + REQUIRE(b.top_right() == osmium::Location(5.6, 7.8)); +} + +SECTION("output_defined") { + osmium::Box b; + b.extend(osmium::Location(1.2, 3.4)); + b.extend(osmium::Location(5.6, 7.8)); + std::stringstream out; + out << b; + REQUIRE(out.str() == "(1.2,3.4,5.6,7.8)"); + REQUIRE((19.36 - b.size()) < 0.000001); +} + +SECTION("output_undefined") { + osmium::Box b; + std::stringstream out; + out << b; + REQUIRE(out.str() == "(undefined)"); +} + +SECTION("box_inside_box") { + osmium::Box outer; + outer.extend(osmium::Location(1, 1)); + outer.extend(osmium::Location(10, 10)); + + osmium::Box inner; + inner.extend(osmium::Location(2, 2)); + inner.extend(osmium::Location(4, 4)); + + osmium::Box overlap; + overlap.extend(osmium::Location(3, 3)); + overlap.extend(osmium::Location(5, 5)); + + REQUIRE( osmium::geom::contains(inner, outer)); + REQUIRE(!osmium::geom::contains(outer, inner)); + + REQUIRE(!osmium::geom::contains(overlap, inner)); + REQUIRE(!osmium::geom::contains(inner, overlap)); +} + +} + diff --git a/test/t/basic/test_changeset.cpp b/test/t/basic/test_changeset.cpp new file mode 100644 index 000000000..2549c1e67 --- /dev/null +++ b/test/t/basic/test_changeset.cpp @@ -0,0 +1,57 @@ +#include "catch.hpp" + +#include + +#include "helper.hpp" + +TEST_CASE("Basic_Changeset") { + +SECTION("changeset_builder") { + osmium::memory::Buffer buffer(10 * 1000); + + osmium::Changeset& cs1 = buffer_add_changeset(buffer, + "user", + {{"comment", "foo"}}); + + cs1.set_id(42) + .set_created_at(100) + .set_closed_at(200) + .set_num_changes(7) + .set_uid(9); + + REQUIRE(42 == cs1.id()); + REQUIRE(9 == cs1.uid()); + REQUIRE(7 == cs1.num_changes()); + REQUIRE(true == cs1.closed()); + REQUIRE(osmium::Timestamp(100) == cs1.created_at()); + REQUIRE(osmium::Timestamp(200) == cs1.closed_at()); + REQUIRE(1 == cs1.tags().size()); + REQUIRE(std::string("user") == cs1.user()); + + osmium::Changeset& cs2 = buffer_add_changeset(buffer, + "user", + {{"comment", "foo"}, {"foo", "bar"}}); + + cs2.set_id(43) + .set_created_at(120) + .set_num_changes(21) + .set_uid(9); + + REQUIRE(43 == cs2.id()); + REQUIRE(9 == cs2.uid()); + REQUIRE(21 == cs2.num_changes()); + REQUIRE(false == cs2.closed()); + REQUIRE(osmium::Timestamp(120) == cs2.created_at()); + REQUIRE(osmium::Timestamp() == cs2.closed_at()); + REQUIRE(2 == cs2.tags().size()); + REQUIRE(std::string("user") == cs2.user()); + + REQUIRE(cs1 != cs2); + + REQUIRE(cs1 < cs2); + REQUIRE(cs1 <= cs2); + REQUIRE(false == (cs1 > cs2)); + REQUIRE(false == (cs1 >= cs2)); +} + +} diff --git a/test/t/basic/test_entity_bits.cpp b/test/t/basic/test_entity_bits.cpp new file mode 100644 index 000000000..b3f3e66af --- /dev/null +++ b/test/t/basic/test_entity_bits.cpp @@ -0,0 +1,25 @@ +#include "catch.hpp" + +#include + +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); +} + +} diff --git a/test/t/basic/test_location.cpp b/test/t/basic/test_location.cpp new file mode 100644 index 000000000..25545a4ba --- /dev/null +++ b/test/t/basic/test_location.cpp @@ -0,0 +1,154 @@ +#include "catch.hpp" + +#include +#include + +#include + +TEST_CASE("Location") { + +// fails on MSVC and doesn't really matter +// static_assert(std::is_literal_type::value, "osmium::Location not literal type"); + +SECTION("instantiation_with_default_parameters") { + osmium::Location loc; + REQUIRE(!loc); + REQUIRE_THROWS_AS(loc.lon(), osmium::invalid_location); + REQUIRE_THROWS_AS(loc.lat(), osmium::invalid_location); +} + +SECTION("instantiation_with_double_parameters") { + osmium::Location loc1(1.2, 4.5); + REQUIRE(!!loc1); + REQUIRE(12000000 == loc1.x()); + REQUIRE(45000000 == loc1.y()); + REQUIRE(1.2 == loc1.lon()); + REQUIRE(4.5 == loc1.lat()); + + osmium::Location loc2(loc1); + REQUIRE(4.5 == loc2.lat()); + + osmium::Location loc3 = loc1; + REQUIRE(4.5 == loc3.lat()); +} + +SECTION("instantiation_with_double_parameters_constructor_with_universal_initializer") { + osmium::Location loc { 2.2, 3.3 }; + REQUIRE(2.2 == loc.lon()); + REQUIRE(3.3 == loc.lat()); +} + +SECTION("instantiation_with_double_parameters_constructor_with_initializer_list") { + osmium::Location loc({ 4.4, 5.5 }); + REQUIRE(4.4 == loc.lon()); + REQUIRE(5.5 == loc.lat()); +} + +SECTION("instantiation_with_double_parameters_operator_equal") { + osmium::Location loc = { 5.5, 6.6 }; + REQUIRE(5.5 == loc.lon()); + REQUIRE(6.6 == loc.lat()); +} + +SECTION("equality") { + osmium::Location loc1(1.2, 4.5); + osmium::Location loc2(1.2, 4.5); + osmium::Location loc3(1.5, 1.5); + REQUIRE(loc1 == loc2); + REQUIRE(loc1 != loc3); +} + +SECTION("order") { + REQUIRE(osmium::Location(-1.2, 10.0) < osmium::Location(1.2, 10.0)); + REQUIRE(osmium::Location(1.2, 10.0) > osmium::Location(-1.2, 10.0)); + + REQUIRE(osmium::Location(10.2, 20.0) < osmium::Location(11.2, 20.2)); + REQUIRE(osmium::Location(10.2, 20.2) < osmium::Location(11.2, 20.0)); + REQUIRE(osmium::Location(11.2, 20.2) > osmium::Location(10.2, 20.0)); +} + +SECTION("validity") { + REQUIRE(osmium::Location(0.0, 0.0).valid()); + REQUIRE(osmium::Location(1.2, 4.5).valid()); + REQUIRE(osmium::Location(-1.2, 4.5).valid()); + REQUIRE(osmium::Location(-180.0, -90.0).valid()); + REQUIRE(osmium::Location(180.0, -90.0).valid()); + REQUIRE(osmium::Location(-180.0, 90.0).valid()); + REQUIRE(osmium::Location(180.0, 90.0).valid()); + + REQUIRE(!osmium::Location(200.0, 4.5).valid()); + REQUIRE(!osmium::Location(-1.2, -100.0).valid()); + REQUIRE(!osmium::Location(-180.0, 90.005).valid()); +} + + +SECTION("output_to_iterator_comma_separator") { + char buffer[100]; + osmium::Location loc(-3.2, 47.3); + *loc.as_string(buffer, ',') = 0; + REQUIRE(std::string("-3.2,47.3") == buffer); +} + +SECTION("output_to_iterator_space_separator") { + char buffer[100]; + osmium::Location loc(0.0, 7.0); + *loc.as_string(buffer, ' ') = 0; + REQUIRE(std::string("0 7") == buffer); +} + +SECTION("output_to_iterator_check_precision") { + char buffer[100]; + osmium::Location loc(-179.9999999, -90.0); + *loc.as_string(buffer, ' ') = 0; + REQUIRE(std::string("-179.9999999 -90") == buffer); +} + +SECTION("output_to_iterator_undefined_location") { + char buffer[100]; + osmium::Location loc; + REQUIRE_THROWS_AS(loc.as_string(buffer, ','), osmium::invalid_location); +} + +SECTION("output_to_string_comman_separator") { + std::string s; + osmium::Location loc(-3.2, 47.3); + loc.as_string(std::back_inserter(s), ','); + REQUIRE(s == "-3.2,47.3"); +} + +SECTION("output_to_string_space_separator") { + std::string s; + osmium::Location loc(0.0, 7.0); + loc.as_string(std::back_inserter(s), ' '); + REQUIRE(s == "0 7"); +} + +SECTION("output_to_string_check_precision") { + std::string s; + osmium::Location loc(-179.9999999, -90.0); + loc.as_string(std::back_inserter(s), ' '); + REQUIRE(s == "-179.9999999 -90"); +} + +SECTION("output_to_string_undefined_location") { + std::string s; + osmium::Location loc; + REQUIRE_THROWS_AS(loc.as_string(std::back_inserter(s), ','), osmium::invalid_location); +} + +SECTION("output_defined") { + osmium::Location p(-3.2, 47.3); + std::stringstream out; + out << p; + REQUIRE(out.str() == "(-3.2,47.3)"); +} + +SECTION("output_undefined") { + osmium::Location p; + std::stringstream out; + out << p; + REQUIRE(out.str() == "(undefined,undefined)"); +} + +} + diff --git a/test/t/basic/test_node.cpp b/test/t/basic/test_node.cpp new file mode 100644 index 000000000..d5351d96f --- /dev/null +++ b/test/t/basic/test_node.cpp @@ -0,0 +1,114 @@ +#include "catch.hpp" + +#include + +#include "helper.hpp" + +TEST_CASE("Basic_Node") { + +SECTION("node_builder") { + osmium::memory::Buffer buffer(10000); + + osmium::Node& node = buffer_add_node(buffer, + "foo", + {{"amenity", "pub"}, {"name", "OSM BAR"}}, + {3.5, 4.7}); + + node.set_id(17) + .set_version(3) + .set_visible(true) + .set_changeset(333) + .set_uid(21) + .set_timestamp(123); + + REQUIRE(17l == node.id()); + REQUIRE(17ul == node.positive_id()); + REQUIRE(3 == node.version()); + REQUIRE(true == node.visible()); + REQUIRE(false == node.deleted()); + REQUIRE(333 == node.changeset()); + REQUIRE(21 == node.uid()); + REQUIRE(std::string("foo") == node.user()); + REQUIRE(123 == node.timestamp()); + REQUIRE(osmium::Location(3.5, 4.7) == node.location()); + REQUIRE(2 == node.tags().size()); + + node.set_visible(false); + REQUIRE(false == node.visible()); + REQUIRE(true == node.deleted()); +} + +SECTION("node_default_attributes") { + osmium::memory::Buffer buffer(10000); + + osmium::Node& node = buffer_add_node(buffer, "", {}, osmium::Location{}); + + REQUIRE(0l == node.id()); + REQUIRE(0ul == node.positive_id()); + REQUIRE(0 == node.version()); + REQUIRE(true == node.visible()); + REQUIRE(0 == node.changeset()); + REQUIRE(0 == node.uid()); + REQUIRE(std::string("") == node.user()); + REQUIRE(0 == node.timestamp()); + REQUIRE(osmium::Location() == node.location()); + REQUIRE(0 == node.tags().size()); +} + +SECTION("set_node_attributes_from_string") { + osmium::memory::Buffer buffer(10000); + + osmium::Node& node = buffer_add_node(buffer, + "foo", + {{"amenity", "pub"}, {"name", "OSM BAR"}}, + {3.5, 4.7}); + + node.set_id("-17") + .set_version("3") + .set_visible(true) + .set_changeset("333") + .set_uid("21"); + + REQUIRE(-17l == node.id()); + REQUIRE(17ul == node.positive_id()); + REQUIRE(3 == node.version()); + REQUIRE(true == node.visible()); + REQUIRE(333 == node.changeset()); + REQUIRE(21 == node.uid()); +} + +SECTION("large_id") { + osmium::memory::Buffer buffer(10000); + + osmium::Node& node = buffer_add_node(buffer, "", {}, osmium::Location{}); + + int64_t id = 3000000000l; + node.set_id(id); + + REQUIRE(id == node.id()); + REQUIRE(static_cast(id) == node.positive_id()); + + node.set_id(-id); + REQUIRE(-id == node.id()); + REQUIRE(static_cast(id) == node.positive_id()); +} + +SECTION("tags") { + osmium::memory::Buffer buffer(10000); + + osmium::Node& node = buffer_add_node(buffer, + "foo", + {{"amenity", "pub"}, {"name", "OSM BAR"}}, + {3.5, 4.7}); + + REQUIRE(nullptr == node.tags().get_value_by_key("fail")); + REQUIRE(std::string("pub") == node.tags().get_value_by_key("amenity")); + REQUIRE(std::string("pub") == node.get_value_by_key("amenity")); + + REQUIRE(std::string("default") == node.tags().get_value_by_key("fail", "default")); + REQUIRE(std::string("pub") == node.tags().get_value_by_key("amenity", "default")); + REQUIRE(std::string("pub") == node.get_value_by_key("amenity", "default")); +} + + +} diff --git a/test/t/basic/test_node_ref.cpp b/test/t/basic/test_node_ref.cpp new file mode 100644 index 000000000..5c7b670f1 --- /dev/null +++ b/test/t/basic/test_node_ref.cpp @@ -0,0 +1,57 @@ +#include "catch.hpp" + +#include + +TEST_CASE("NodeRef") { + +SECTION("instantiation_with_default_parameters") { + osmium::NodeRef node_ref; + REQUIRE(node_ref.ref() == 0); +// REQUIRE(!node_ref.has_location()); +} + +SECTION("instantiation_with_id") { + osmium::NodeRef node_ref(7); + REQUIRE(node_ref.ref() == 7); +} + +SECTION("equality") { + osmium::NodeRef node_ref1(7, { 1.2, 3.4 }); + osmium::NodeRef node_ref2(7, { 1.4, 3.1 }); + osmium::NodeRef node_ref3(9, { 1.2, 3.4 }); + REQUIRE(node_ref1 == node_ref2); + REQUIRE(node_ref1 != node_ref3); + REQUIRE(!osmium::location_equal()(node_ref1, node_ref2)); + REQUIRE(!osmium::location_equal()(node_ref2, node_ref3)); + REQUIRE(osmium::location_equal()(node_ref1, node_ref3)); +} + +SECTION("set_location") { + osmium::NodeRef node_ref(7); + REQUIRE(!node_ref.location().valid()); + REQUIRE(node_ref.location() == osmium::Location()); + node_ref.set_location(osmium::Location(13.5, -7.2)); + REQUIRE(node_ref.location().lon() == 13.5); + REQUIRE(node_ref.location().valid()); +} + +SECTION("ordering") { + osmium::NodeRef node_ref1(1, { 1.0, 3.0 }); + osmium::NodeRef node_ref2(2, { 1.4, 2.9 }); + osmium::NodeRef node_ref3(3, { 1.2, 3.0 }); + osmium::NodeRef node_ref4(4, { 1.2, 3.3 }); + + REQUIRE(node_ref1 < node_ref2); + REQUIRE(node_ref2 < node_ref3); + REQUIRE(node_ref1 < node_ref3); + REQUIRE(node_ref1 >= node_ref1); + + REQUIRE(osmium::location_less()(node_ref1, node_ref2)); + REQUIRE(!osmium::location_less()(node_ref2, node_ref3)); + REQUIRE(osmium::location_less()(node_ref1, node_ref3)); + REQUIRE(osmium::location_less()(node_ref3, node_ref4)); + REQUIRE(!osmium::location_less()(node_ref1, node_ref1)); +} + +} + diff --git a/test/t/basic/test_object_comparisons.cpp b/test/t/basic/test_object_comparisons.cpp new file mode 100644 index 000000000..49733ce30 --- /dev/null +++ b/test/t/basic/test_object_comparisons.cpp @@ -0,0 +1,147 @@ +#include "catch.hpp" + +#include +#include +#include + +TEST_CASE("Object_Comparisons") { + +SECTION("order") { + osmium::memory::Buffer buffer(10 * 1000); + + { + // add node 1 + osmium::builder::NodeBuilder node_builder(buffer); + node_builder.add_user("testuser"); + buffer.commit(); + } + + { + // add node 2 + osmium::builder::NodeBuilder node_builder(buffer); + node_builder.add_user("testuser"); + buffer.commit(); + } + + auto it = buffer.begin(); + osmium::Node& node1 = static_cast(*it); + osmium::Node& node2 = static_cast(*(++it)); + + node1.set_id(10); + node1.set_version(1); + node2.set_id(15); + node2.set_version(2); + REQUIRE(true == node1 < node2); + REQUIRE(false == node1 > node2); + node1.set_id(20); + node1.set_version(1); + node2.set_id(20); + node2.set_version(2); + REQUIRE(true == node1 < node2); + REQUIRE(false == node1 > node2); + node1.set_id(-10); + node1.set_version(2); + node2.set_id(-15); + node2.set_version(1); + REQUIRE(true == node1 < node2); + REQUIRE(false == node1 > node2); +} + +SECTION("order_types") { + osmium::memory::Buffer buffer(10 * 1000); + + { + // add node 1 + osmium::builder::NodeBuilder node_builder(buffer); + osmium::Node& node = node_builder.object(); + REQUIRE(osmium::item_type::node == node.type()); + + node.set_id(3); + node.set_version(3); + node_builder.add_user("testuser"); + + buffer.commit(); + } + + { + // add node 2 + osmium::builder::NodeBuilder node_builder(buffer); + osmium::Node& node = node_builder.object(); + REQUIRE(osmium::item_type::node == node.type()); + + node.set_id(3); + node.set_version(4); + node_builder.add_user("testuser"); + + buffer.commit(); + } + + { + // add node 3 + osmium::builder::NodeBuilder node_builder(buffer); + osmium::Node& node = node_builder.object(); + REQUIRE(osmium::item_type::node == node.type()); + + node.set_id(3); + node.set_version(4); + node_builder.add_user("testuser"); + + buffer.commit(); + } + + { + // add way + osmium::builder::WayBuilder way_builder(buffer); + osmium::Way& way = way_builder.object(); + REQUIRE(osmium::item_type::way == way.type()); + + way.set_id(2); + way.set_version(2); + way_builder.add_user("testuser"); + + buffer.commit(); + } + + { + // add relation + osmium::builder::RelationBuilder relation_builder(buffer); + osmium::Relation& relation = relation_builder.object(); + REQUIRE(osmium::item_type::relation == relation.type()); + + relation.set_id(1); + relation.set_version(1); + relation_builder.add_user("testuser"); + + buffer.commit(); + } + + auto it = buffer.begin(); + const osmium::Node& node1 = static_cast(*it); + const osmium::Node& node2 = static_cast(*(++it)); + const osmium::Node& node3 = static_cast(*(++it)); + const osmium::Way& way = static_cast(*(++it)); + const osmium::Relation& relation = static_cast(*(++it)); + + REQUIRE(true == node1 < node2); + REQUIRE(true == node2 < way); + REQUIRE(false == node2 > way); + REQUIRE(true == way < relation); + REQUIRE(true == node1 < relation); + + REQUIRE(true == osmium::object_order_type_id_version()(node1, node2)); + REQUIRE(true == osmium::object_order_type_id_reverse_version()(node2, node1)); + REQUIRE(true == osmium::object_order_type_id_version()(node1, way)); + REQUIRE(true == osmium::object_order_type_id_reverse_version()(node1, way)); + + REQUIRE(false == osmium::object_equal_type_id_version()(node1, node2)); + REQUIRE(true == osmium::object_equal_type_id_version()(node2, node3)); + + REQUIRE(true == osmium::object_equal_type_id()(node1, node2)); + REQUIRE(true == osmium::object_equal_type_id()(node2, node3)); + + REQUIRE(false == osmium::object_equal_type_id_version()(node1, way)); + REQUIRE(false == osmium::object_equal_type_id_version()(node1, relation)); + REQUIRE(false == osmium::object_equal_type_id()(node1, relation)); +} + +} diff --git a/test/t/basic/test_relation.cpp b/test/t/basic/test_relation.cpp new file mode 100644 index 000000000..4c62a4189 --- /dev/null +++ b/test/t/basic/test_relation.cpp @@ -0,0 +1,60 @@ +#include "catch.hpp" + +#include + +#include "helper.hpp" + +TEST_CASE("Basic_Relation") { + +SECTION("relation_builder") { + osmium::memory::Buffer buffer(10000); + + osmium::Relation& relation = buffer_add_relation(buffer, + "foo", { + {"type", "multipolygon"}, + {"name", "Sherwood Forest"} + }, { + std::make_tuple('w', 1, "inner"), + std::make_tuple('w', 2, ""), + std::make_tuple('w', 3, "outer") + }); + + relation.set_id(17) + .set_version(3) + .set_visible(true) + .set_changeset(333) + .set_uid(21) + .set_timestamp(123); + + REQUIRE(17 == relation.id()); + REQUIRE(3 == relation.version()); + REQUIRE(true == relation.visible()); + REQUIRE(333 == relation.changeset()); + REQUIRE(21 == relation.uid()); + REQUIRE(std::string("foo") == relation.user()); + REQUIRE(123 == relation.timestamp()); + REQUIRE(2 == relation.tags().size()); + REQUIRE(3 == relation.members().size()); + + int n=1; + for (auto& member : relation.members()) { + REQUIRE(osmium::item_type::way == member.type()); + REQUIRE(n == member.ref()); + switch (n) { + case 1: + REQUIRE(std::string("inner") == member.role()); + break; + case 2: + REQUIRE(std::string("") == member.role()); + break; + case 3: + REQUIRE(std::string("outer") == member.role()); + break; + default: + REQUIRE(false); + } + ++n; + } +} + +} diff --git a/test/t/basic/test_timestamp.cpp b/test/t/basic/test_timestamp.cpp new file mode 100644 index 000000000..453b94b2e --- /dev/null +++ b/test/t/basic/test_timestamp.cpp @@ -0,0 +1,45 @@ +#include "catch.hpp" + +#include + +#include + +TEST_CASE("Timestamp") { + +SECTION("can be default initialized to invalid value") { + osmium::Timestamp t; + REQUIRE(0 == t); + REQUIRE("" == t.to_iso()); +} + +SECTION("invalid value is zero") { + osmium::Timestamp t(static_cast(0)); + REQUIRE(0 == t); + REQUIRE("" == t.to_iso()); +} + +SECTION("can be initialized from time_t") { + osmium::Timestamp t(static_cast(1)); + REQUIRE(1 == t); + REQUIRE("1970-01-01T00:00:01Z" == t.to_iso()); +} + +SECTION("can be initialized from string") { + osmium::Timestamp t("2000-01-01T00:00:00Z"); + REQUIRE("2000-01-01T00:00:00Z" == t.to_iso()); +} + +SECTION("can be compared") { + osmium::Timestamp t1(10); + osmium::Timestamp t2(50); + REQUIRE(t1 < t2); +} + +SECTION("can be written to stream") { + std::stringstream ss; + osmium::Timestamp t(1); + ss << t; + REQUIRE("1970-01-01T00:00:01Z" == ss.str()); +} + +} diff --git a/test/t/basic/test_way.cpp b/test/t/basic/test_way.cpp new file mode 100644 index 000000000..6d510ab3e --- /dev/null +++ b/test/t/basic/test_way.cpp @@ -0,0 +1,79 @@ +#include "catch.hpp" + +#include +#include + +#include "helper.hpp" + +TEST_CASE("Basic_Way") { + +SECTION("way_builder") { + osmium::memory::Buffer buffer(10000); + + osmium::Way& way = buffer_add_way(buffer, + "foo", + {{"highway", "residential"}, {"name", "High Street"}}, + {1, 3, 2}); + + way.set_id(17) + .set_version(3) + .set_visible(true) + .set_changeset(333) + .set_uid(21) + .set_timestamp(123); + + REQUIRE(17 == way.id()); + REQUIRE(3 == way.version()); + REQUIRE(true == way.visible()); + REQUIRE(333 == way.changeset()); + REQUIRE(21 == way.uid()); + REQUIRE(std::string("foo") == way.user()); + REQUIRE(123 == way.timestamp()); + REQUIRE(2 == way.tags().size()); + REQUIRE(3 == way.nodes().size()); + REQUIRE(1 == way.nodes()[0].ref()); + REQUIRE(3 == way.nodes()[1].ref()); + REQUIRE(2 == way.nodes()[2].ref()); + REQUIRE(! way.is_closed()); +} + +SECTION("closed_way") { + osmium::memory::Buffer buffer(10000); + + osmium::Way& way = buffer_add_way(buffer, + "foo", + {{"highway", "residential"}, {"name", "High Street"}}, + {1, 3, 1}); + + REQUIRE(way.is_closed()); +} + +SECTION("way_builder_with_helpers") { + osmium::memory::Buffer buffer(10000); + { + osmium::builder::WayBuilder builder(buffer); + builder.add_user("username"); + builder.add_tags({ + {"amenity", "restaurant"}, + {"name", "Zum goldenen Schwanen"} + }); + builder.add_node_refs({ + {22, {3.5, 4.7}}, + {67, {4.1, 2.2}} + }); + } + buffer.commit(); + osmium::Way& way = buffer.get(0); + + REQUIRE(std::string("username") == way.user()); + + REQUIRE(2 == way.tags().size()); + REQUIRE(std::string("amenity") == way.tags().begin()->key()); + REQUIRE(std::string("Zum goldenen Schwanen") == way.tags()["name"]); + + REQUIRE(2 == way.nodes().size()); + REQUIRE(22 == way.nodes()[0].ref()); + REQUIRE(4.1 == way.nodes()[1].location().lon()); +} + +} diff --git a/test/t/buffer/test_buffer_node.cpp b/test/t/buffer/test_buffer_node.cpp new file mode 100644 index 000000000..aabe6cbea --- /dev/null +++ b/test/t/buffer/test_buffer_node.cpp @@ -0,0 +1,135 @@ +#include "catch.hpp" + +#include +#include + +void check_node_1(osmium::Node& node) { + REQUIRE(1 == node.id()); + REQUIRE(3 == node.version()); + REQUIRE(true == node.visible()); + REQUIRE(333 == node.changeset()); + REQUIRE(21 == node.uid()); + REQUIRE(123 == node.timestamp()); + REQUIRE(osmium::Location(3.5, 4.7) == node.location()); + REQUIRE(std::string("testuser") == node.user()); + + for (osmium::memory::Item& item : node) { + REQUIRE(osmium::item_type::tag_list == item.type()); + } + + REQUIRE(node.tags().begin() == node.tags().end()); + REQUIRE(node.tags().empty()); + REQUIRE(0 == std::distance(node.tags().begin(), node.tags().end())); +} + +void check_node_2(osmium::Node& node) { + REQUIRE(2 == node.id()); + REQUIRE(3 == node.version()); + REQUIRE(true == node.visible()); + REQUIRE(333 == node.changeset()); + REQUIRE(21 == node.uid()); + REQUIRE(123 == node.timestamp()); + REQUIRE(osmium::Location(3.5, 4.7) == node.location()); + REQUIRE(std::string("testuser") == node.user()); + + for (osmium::memory::Item& item : node) { + REQUIRE(osmium::item_type::tag_list == item.type()); + } + + REQUIRE(!node.tags().empty()); + REQUIRE(2 == std::distance(node.tags().begin(), node.tags().end())); + + int n = 0; + for (const osmium::Tag& tag : node.tags()) { + switch (n) { + case 0: + REQUIRE(std::string("amenity") == tag.key()); + REQUIRE(std::string("bank") == tag.value()); + break; + case 1: + REQUIRE(std::string("name") == tag.key()); + REQUIRE(std::string("OSM Savings") == tag.value()); + break; + } + ++n; + } + REQUIRE(2 == n); +} + +TEST_CASE("Buffer_Node") { + +SECTION("buffer_node") { + constexpr size_t buffer_size = 10000; + unsigned char data[buffer_size]; + + osmium::memory::Buffer buffer(data, buffer_size, 0); + + { + // add node 1 + osmium::builder::NodeBuilder node_builder(buffer); + osmium::Node& node = node_builder.object(); + REQUIRE(osmium::item_type::node == node.type()); + + node.set_id(1); + node.set_version(3); + node.set_visible(true); + node.set_changeset(333); + node.set_uid(21); + node.set_timestamp(123); + node.set_location(osmium::Location(3.5, 4.7)); + + node_builder.add_user("testuser"); + + buffer.commit(); + } + + { + // add node 2 + osmium::builder::NodeBuilder node_builder(buffer); + osmium::Node& node = node_builder.object(); + REQUIRE(osmium::item_type::node == node.type()); + + node.set_id(2); + node.set_version(3); + node.set_visible(true); + node.set_changeset(333); + node.set_uid(21); + node.set_timestamp(123); + node.set_location(osmium::Location(3.5, 4.7)); + + node_builder.add_user("testuser"); + + { + osmium::builder::TagListBuilder tag_builder(buffer, &node_builder); + tag_builder.add_tag("amenity", "bank"); + tag_builder.add_tag("name", "OSM Savings"); + } + + buffer.commit(); + } + + REQUIRE(2 == std::distance(buffer.begin(), buffer.end())); + int item_no = 0; + for (osmium::memory::Item& item : buffer) { + REQUIRE(osmium::item_type::node == item.type()); + + osmium::Node& node = static_cast(item); + + switch (item_no) { + case 0: + check_node_1(node); + break; + case 1: + check_node_2(node); + break; + default: + break; + } + + ++item_no; + + } + +} + +} diff --git a/test/t/buffer/test_buffer_purge.cpp b/test/t/buffer/test_buffer_purge.cpp new file mode 100644 index 000000000..10cdfe72c --- /dev/null +++ b/test/t/buffer/test_buffer_purge.cpp @@ -0,0 +1,186 @@ +#include "catch.hpp" + +#include +#include + +struct CallbackClass { + + int count = 0; + + void moving_in_buffer(size_t old_offset, size_t new_offset) { + REQUIRE(old_offset > new_offset); + ++count; + } + +}; // struct CallbackClass + +TEST_CASE("Purge data from buffer") { + + constexpr size_t buffer_size = 10000; + + SECTION("purge empty buffer") { + osmium::memory::Buffer buffer(buffer_size); + REQUIRE(std::distance(buffer.begin(), buffer.end()) == 0); + + CallbackClass callback; + buffer.purge_removed(&callback); + + REQUIRE(callback.count == 0); + REQUIRE(buffer.committed() == 0); + } + + SECTION("purge buffer with one object but nothing to delete") { + osmium::memory::Buffer buffer(buffer_size); + + { + osmium::builder::NodeBuilder node_builder(buffer); + node_builder.add_user("testuser"); + } + buffer.commit(); + REQUIRE(std::distance(buffer.begin(), buffer.end()) == 1); + size_t committed = buffer.committed(); + + CallbackClass callback; + buffer.purge_removed(&callback); + + REQUIRE(callback.count == 0); + REQUIRE(committed == buffer.committed()); + REQUIRE(std::distance(buffer.begin(), buffer.end()) == 1); + } + + SECTION("purge buffer with one object which gets deleted") { + osmium::memory::Buffer buffer(buffer_size); + + { + osmium::builder::NodeBuilder node_builder(buffer); + node_builder.add_user("testuser"); + node_builder.object().set_removed(true); + } + buffer.commit(); + REQUIRE(std::distance(buffer.begin(), buffer.end()) == 1); + + CallbackClass callback; + buffer.purge_removed(&callback); + + REQUIRE(callback.count == 0); + REQUIRE(buffer.committed() == 0); + REQUIRE(std::distance(buffer.begin(), buffer.end()) == 0); + } + + SECTION("purge buffer with two objects, first gets deleted") { + osmium::memory::Buffer buffer(buffer_size); + + { + osmium::builder::NodeBuilder node_builder(buffer); + node_builder.add_user("testuser"); + node_builder.object().set_removed(true); + } + buffer.commit(); + size_t size1 = buffer.committed(); + { + osmium::builder::NodeBuilder node_builder(buffer); + node_builder.add_user("testuser"); + } + buffer.commit(); + size_t size2 = buffer.committed() - size1; + REQUIRE(std::distance(buffer.begin(), buffer.end()) == 2); + + CallbackClass callback; + buffer.purge_removed(&callback); + + REQUIRE(callback.count == 1); + REQUIRE(std::distance(buffer.begin(), buffer.end()) == 1); + REQUIRE(buffer.committed() == size2); + } + + SECTION("purge buffer with two objects, second gets deleted") { + osmium::memory::Buffer buffer(buffer_size); + + { + osmium::builder::NodeBuilder node_builder(buffer); + node_builder.add_user("testuser_longer_name"); + } + buffer.commit(); + size_t size1 = buffer.committed(); + { + osmium::builder::NodeBuilder node_builder(buffer); + node_builder.add_user("testuser"); + node_builder.object().set_removed(true); + } + buffer.commit(); + size_t size2 = buffer.committed() - size1; + REQUIRE(std::distance(buffer.begin(), buffer.end()) == 2); + + CallbackClass callback; + buffer.purge_removed(&callback); + + REQUIRE(callback.count == 0); + REQUIRE(std::distance(buffer.begin(), buffer.end()) == 1); + REQUIRE(buffer.committed() == size1); + } + + SECTION("purge buffer with three objects, middle one gets deleted") { + osmium::memory::Buffer buffer(buffer_size); + + { + osmium::builder::NodeBuilder node_builder(buffer); + node_builder.add_user("testuser_longer_name"); + } + buffer.commit(); + size_t size1 = buffer.committed(); + { + osmium::builder::NodeBuilder node_builder(buffer); + node_builder.add_user("testuser"); + node_builder.object().set_removed(true); + } + buffer.commit(); + size_t size2 = buffer.committed() - size1; + { + osmium::builder::NodeBuilder node_builder(buffer); + node_builder.add_user("sn"); + } + buffer.commit(); + size_t size3 = buffer.committed() - (size1 + size2); + REQUIRE(std::distance(buffer.begin(), buffer.end()) == 3); + + CallbackClass callback; + buffer.purge_removed(&callback); + + REQUIRE(callback.count == 1); + REQUIRE(std::distance(buffer.begin(), buffer.end()) == 2); + } + + SECTION("purge buffer with three objects, all get deleted") { + osmium::memory::Buffer buffer(buffer_size); + + { + osmium::builder::NodeBuilder node_builder(buffer); + node_builder.add_user("testuser_longer_name"); + node_builder.object().set_removed(true); + } + buffer.commit(); + size_t size1 = buffer.committed(); + { + osmium::builder::NodeBuilder node_builder(buffer); + node_builder.add_user("testuser"); + node_builder.object().set_removed(true); + } + buffer.commit(); + size_t size2 = buffer.committed() - size1; + { + osmium::builder::NodeBuilder node_builder(buffer); + node_builder.add_user("sn"); + node_builder.object().set_removed(true); + } + buffer.commit(); + size_t size3 = buffer.committed() - (size1 + size2); + REQUIRE(std::distance(buffer.begin(), buffer.end()) == 3); + + CallbackClass callback; + buffer.purge_removed(&callback); + + REQUIRE(callback.count == 0); + REQUIRE(std::distance(buffer.begin(), buffer.end()) == 0); + } + +} diff --git a/test/t/geom/helper.hpp b/test/t/geom/helper.hpp new file mode 100644 index 000000000..e0cefe6d1 --- /dev/null +++ b/test/t/geom/helper.hpp @@ -0,0 +1,15 @@ +#ifndef TEST_GEOM_HELPER_HPP +#define TEST_GEOM_HELPER_HPP + +#include + +#include + +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 diff --git a/test/t/geom/test_factory_with_projection.cpp b/test/t/geom/test_factory_with_projection.cpp new file mode 100644 index 000000000..9bc8c0681 --- /dev/null +++ b/test/t/geom/test_factory_with_projection.cpp @@ -0,0 +1,41 @@ +#include "catch.hpp" + +#include +#include +#include +#include +#include + +#include "helper.hpp" + +TEST_CASE("Projection") { + +SECTION("point_mercator") { + osmium::geom::WKTFactory 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 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 wkb_factory(osmium::geom::Projection(3857), osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex); + osmium::geom::GEOSFactory geos_factory(osmium::geom::Projection(3857)); + + std::string wkb = wkb_factory.create_point(osmium::Location(3.2, 4.2)); + std::unique_ptr 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(); +} + +} diff --git a/test/t/geom/test_geojson.cpp b/test/t/geom/test_geojson.cpp new file mode 100644 index 000000000..8d7df3521 --- /dev/null +++ b/test/t/geom/test_geojson.cpp @@ -0,0 +1,236 @@ +#include "catch.hpp" + +#include +#include + +#include "../basic/helper.hpp" + +TEST_CASE("GeoJSON_Geometry") { + +SECTION("point") { + osmium::geom::GeoJSONFactory<> factory; + + 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") { + osmium::geom::GeoJSONFactory<> factory; + + REQUIRE_THROWS_AS(factory.create_point(osmium::Location()), osmium::invalid_location); +} + +SECTION("linestring") { + osmium::geom::GeoJSONFactory<> factory; + + osmium::memory::Buffer buffer(10000); + auto& wnl = osmium::builder::build_way_node_list(buffer, { + {1, {3.2, 4.2}}, + {3, {3.5, 4.7}}, + {4, {3.5, 4.7}}, + {2, {3.6, 4.9}} + }); + + { + 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); + } + + { + 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); + } + + { + 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); + } + + { + 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); + } +} + +SECTION("empty_linestring") { + osmium::geom::GeoJSONFactory<> factory; + + osmium::memory::Buffer buffer(10000); + auto& wnl = osmium::builder::build_way_node_list(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); + 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(10000); + auto& wnl = osmium::builder::build_way_node_list(buffer, { + {1, {3.5, 4.7}}, + {2, {3.5, 4.7}} + }); + + 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); + } + + { + 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") { + osmium::geom::GeoJSONFactory<> factory; + + osmium::memory::Buffer buffer(10000); + auto& wnl = osmium::builder::build_way_node_list(buffer, { + {1, {3.5, 4.7}}, + {2, osmium::Location()} + }); + + REQUIRE_THROWS_AS(factory.create_linestring(wnl), osmium::invalid_location); +} + +SECTION("area_1outer_0inner") { + osmium::geom::GeoJSONFactory<> factory; + + osmium::memory::Buffer buffer(10000); + osmium::Area& area = buffer_add_area(buffer, + "foo", + {}, + { + { true, { + {1, {3.2, 4.2}}, + {2, {3.5, 4.7}}, + {3, {3.6, 4.9}}, + {1, {3.2, 4.2}} + }} + }); + + REQUIRE(!area.is_multipolygon()); + REQUIRE(std::distance(area.cbegin(), area.cend()) == 2); + REQUIRE(std::distance(area.cbegin(), area.cend()) == 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); + } +} + +SECTION("area_1outer_1inner") { + osmium::geom::GeoJSONFactory<> factory; + + osmium::memory::Buffer buffer(10000); + osmium::Area& area = buffer_add_area(buffer, + "foo", + {}, + { + { true, { + {1, {0.1, 0.1}}, + {2, {9.1, 0.1}}, + {3, {9.1, 9.1}}, + {4, {0.1, 9.1}}, + {1, {0.1, 0.1}} + }}, + { false, { + {5, {1.0, 1.0}}, + {6, {8.0, 1.0}}, + {7, {8.0, 8.0}}, + {8, {1.0, 8.0}}, + {5, {1.0, 1.0}} + }} + }); + + REQUIRE(!area.is_multipolygon()); + REQUIRE(std::distance(area.cbegin(), area.cend()) == 3); + REQUIRE(std::distance(area.cbegin(), area.cend()) == area.num_rings().first); + REQUIRE(std::distance(area.cbegin(), area.cend()) == 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); + } +} + +SECTION("area_2outer_2inner") { + osmium::geom::GeoJSONFactory<> factory; + + osmium::memory::Buffer buffer(10000); + osmium::Area& area = buffer_add_area(buffer, + "foo", + {}, + { + { true, { + {1, {0.1, 0.1}}, + {2, {9.1, 0.1}}, + {3, {9.1, 9.1}}, + {4, {0.1, 9.1}}, + {1, {0.1, 0.1}} + }}, + { false, { + {5, {1.0, 1.0}}, + {6, {4.0, 1.0}}, + {7, {4.0, 4.0}}, + {8, {1.0, 4.0}}, + {5, {1.0, 1.0}} + }}, + { false, { + {10, {5.0, 5.0}}, + {11, {5.0, 7.0}}, + {12, {7.0, 7.0}}, + {10, {5.0, 5.0}} + }}, + { true, { + {100, {10.0, 10.0}}, + {101, {11.0, 10.0}}, + {102, {11.0, 11.0}}, + {103, {10.0, 11.0}}, + {100, {10.0, 10.0}} + }} + }); + + REQUIRE(area.is_multipolygon()); + REQUIRE(std::distance(area.cbegin(), area.cend()) == 5); + REQUIRE(std::distance(area.cbegin(), area.cend()) == area.num_rings().first); + REQUIRE(std::distance(area.cbegin(), area.cend()) == area.num_rings().second); + + int outer_ring=0; + int inner_ring=0; + for (auto it_outer = area.cbegin(); it_outer != area.cend(); ++it_outer) { + if (outer_ring == 0) { + REQUIRE(it_outer->front().ref() == 1); + } else if (outer_ring == 1) { + REQUIRE(it_outer->front().ref() == 100); + } else { + REQUIRE(false); + } + for (auto it_inner = area.inner_ring_cbegin(it_outer); it_inner != area.inner_ring_cend(it_outer); ++it_inner) { + if (outer_ring == 0 && inner_ring == 0) { + REQUIRE(it_inner->front().ref() == 5); + } else if (outer_ring == 0 && inner_ring == 1) { + REQUIRE(it_inner->front().ref() == 10); + } else { + REQUIRE(false); + } + ++inner_ring; + } + inner_ring = 0; + ++outer_ring; + } + + { + 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); + } +} + +} + diff --git a/test/t/geom/test_geos.cpp b/test/t/geom/test_geos.cpp new file mode 100644 index 000000000..e93228b4c --- /dev/null +++ b/test/t/geom/test_geos.cpp @@ -0,0 +1,198 @@ +#include "catch.hpp" + +#include +#include + +#include "../basic/helper.hpp" + +TEST_CASE("GEOS_Geometry") { + +SECTION("point") { + osmium::geom::GEOSFactory<> factory; + + std::unique_ptr point {factory.create_point(osmium::Location(3.2, 4.2))}; + REQUIRE(3.2 == point->getX()); + REQUIRE(4.2 == point->getY()); + REQUIRE(-1 == point->getSRID()); +} + +SECTION("non_default_srid") { + osmium::geom::GEOSFactory<> factory(4326); + + std::unique_ptr point {factory.create_point(osmium::Location(3.2, 4.2))}; + REQUIRE(3.2 == point->getX()); + REQUIRE(4.2 == point->getY()); + REQUIRE(4326 == point->getSRID()); +} + +SECTION("empty_point") { + osmium::geom::GEOSFactory<> factory; + + REQUIRE_THROWS_AS(factory.create_point(osmium::Location()), osmium::invalid_location); +} + +SECTION("linestring") { + osmium::geom::GEOSFactory<> factory; + + osmium::memory::Buffer buffer(10000); + auto& wnl = osmium::builder::build_way_node_list(buffer, { + {1, {3.2, 4.2}}, + {3, {3.5, 4.7}}, + {4, {3.5, 4.7}}, + {2, {3.6, 4.9}} + }); + + { + std::unique_ptr linestring {factory.create_linestring(wnl)}; + REQUIRE(3 == linestring->getNumPoints()); + + std::unique_ptr p0 = std::unique_ptr(linestring->getPointN(0)); + REQUIRE(3.2 == p0->getX()); + std::unique_ptr p2 = std::unique_ptr(linestring->getPointN(2)); + REQUIRE(3.6 == p2->getX()); + } + + { + std::unique_ptr linestring {factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward)}; + REQUIRE(3 == linestring->getNumPoints()); + std::unique_ptr p0 = std::unique_ptr(linestring->getPointN(0)); + REQUIRE(3.6 == p0->getX()); + std::unique_ptr p2 = std::unique_ptr(linestring->getPointN(2)); + REQUIRE(3.2 == p2->getX()); + } + + { + std::unique_ptr linestring {factory.create_linestring(wnl, osmium::geom::use_nodes::all)}; + REQUIRE(4 == linestring->getNumPoints()); + std::unique_ptr p0 = std::unique_ptr(linestring->getPointN(0)); + REQUIRE(3.2 == p0->getX()); + } + + { + std::unique_ptr linestring {factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward)}; + REQUIRE(4 == linestring->getNumPoints()); + std::unique_ptr p0 = std::unique_ptr(linestring->getPointN(0)); + REQUIRE(3.6 == p0->getX()); + } +} + +SECTION("area_1outer_0inner") { + osmium::geom::GEOSFactory<> factory; + + osmium::memory::Buffer buffer(10000); + osmium::Area& area = buffer_add_area(buffer, + "foo", + {}, + { + { true, { + {1, {3.2, 4.2}}, + {2, {3.5, 4.7}}, + {3, {3.6, 4.9}}, + {1, {3.2, 4.2}} + }} + }); + + std::unique_ptr mp {factory.create_multipolygon(area)}; + REQUIRE(1 == mp->getNumGeometries()); + + const geos::geom::Polygon* p0 = dynamic_cast(mp->getGeometryN(0)); + REQUIRE(0 == p0->getNumInteriorRing()); + + const geos::geom::LineString* l0e = p0->getExteriorRing(); + REQUIRE(4 == l0e->getNumPoints()); + + std::unique_ptr l0e_p0 = std::unique_ptr(l0e->getPointN(1)); + REQUIRE(3.5 == l0e_p0->getX()); +} + +SECTION("area_1outer_1inner") { + osmium::geom::GEOSFactory<> factory; + + osmium::memory::Buffer buffer(10000); + osmium::Area& area = buffer_add_area(buffer, + "foo", + {}, + { + { true, { + {1, {0.1, 0.1}}, + {2, {9.1, 0.1}}, + {3, {9.1, 9.1}}, + {4, {0.1, 9.1}}, + {1, {0.1, 0.1}} + }}, + { false, { + {5, {1.0, 1.0}}, + {6, {8.0, 1.0}}, + {7, {8.0, 8.0}}, + {8, {1.0, 8.0}}, + {5, {1.0, 1.0}} + }} + }); + + std::unique_ptr mp {factory.create_multipolygon(area)}; + REQUIRE(1 == mp->getNumGeometries()); + + const geos::geom::Polygon* p0 = dynamic_cast(mp->getGeometryN(0)); + REQUIRE(1 == p0->getNumInteriorRing()); + + const geos::geom::LineString* l0e = p0->getExteriorRing(); + REQUIRE(5 == l0e->getNumPoints()); + + const geos::geom::LineString* l0i0 = p0->getInteriorRingN(0); + REQUIRE(5 == l0i0->getNumPoints()); +} + +SECTION("area_2outer_2inner") { + osmium::geom::GEOSFactory<> factory; + + osmium::memory::Buffer buffer(10000); + osmium::Area& area = buffer_add_area(buffer, + "foo", + {}, + { + { true, { + {1, {0.1, 0.1}}, + {2, {9.1, 0.1}}, + {3, {9.1, 9.1}}, + {4, {0.1, 9.1}}, + {1, {0.1, 0.1}} + }}, + { false, { + {5, {1.0, 1.0}}, + {6, {4.0, 1.0}}, + {7, {4.0, 4.0}}, + {8, {1.0, 4.0}}, + {5, {1.0, 1.0}} + }}, + { false, { + {10, {5.0, 5.0}}, + {11, {5.0, 7.0}}, + {12, {7.0, 7.0}}, + {10, {5.0, 5.0}} + }}, + { true, { + {100, {10.0, 10.0}}, + {101, {11.0, 10.0}}, + {102, {11.0, 11.0}}, + {103, {10.0, 11.0}}, + {100, {10.0, 10.0}} + }} + }); + + std::unique_ptr mp {factory.create_multipolygon(area)}; + REQUIRE(2 == mp->getNumGeometries()); + + const geos::geom::Polygon* p0 = dynamic_cast(mp->getGeometryN(0)); + REQUIRE(2 == p0->getNumInteriorRing()); + + const geos::geom::LineString* l0e = p0->getExteriorRing(); + REQUIRE(5 == l0e->getNumPoints()); + + const geos::geom::Polygon* p1 = dynamic_cast(mp->getGeometryN(1)); + REQUIRE(0 == p1->getNumInteriorRing()); + + const geos::geom::LineString* l1e = p1->getExteriorRing(); + REQUIRE(5 == l1e->getNumPoints()); +} + +} diff --git a/test/t/geom/test_geos_wkb.cpp b/test/t/geom/test_geos_wkb.cpp new file mode 100644 index 000000000..0f54427e5 --- /dev/null +++ b/test/t/geom/test_geos_wkb.cpp @@ -0,0 +1,156 @@ +#include "catch.hpp" + +#include +#include +#include + +#include "../basic/helper.hpp" +#include "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_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 = osmium::builder::build_way_node_list(buffer, { + {1, {3.2, 4.2}}, + {3, {3.5, 4.7}}, + {4, {3.5, 4.7}}, + {2, {3.6, 4.9}} + }); + + { + std::string wkb = wkb_factory.create_linestring(wnl); + std::unique_ptr 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 = 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 = 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 = 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); + osmium::Area& area = buffer_add_area(buffer, + "foo", + {}, + { + { true, { + {1, {3.2, 4.2}}, + {2, {3.5, 4.7}}, + {3, {3.6, 4.9}}, + {1, {3.2, 4.2}} + }} + }); + + std::string wkb = wkb_factory.create_multipolygon(area); + std::unique_ptr 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); + osmium::Area& area = buffer_add_area(buffer, + "foo", + {}, + { + { true, { + {1, {0.1, 0.1}}, + {2, {9.1, 0.1}}, + {3, {9.1, 9.1}}, + {4, {0.1, 9.1}}, + {1, {0.1, 0.1}} + }}, + { false, { + {5, {1.0, 1.0}}, + {6, {8.0, 1.0}}, + {7, {8.0, 8.0}}, + {8, {1.0, 8.0}}, + {5, {1.0, 1.0}} + }} + }); + + std::string wkb = wkb_factory.create_multipolygon(area); + std::unique_ptr 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); + osmium::Area& area = buffer_add_area(buffer, + "foo", + {}, + { + { true, { + {1, {0.1, 0.1}}, + {2, {9.1, 0.1}}, + {3, {9.1, 9.1}}, + {4, {0.1, 9.1}}, + {1, {0.1, 0.1}} + }}, + { false, { + {5, {1.0, 1.0}}, + {6, {4.0, 1.0}}, + {7, {4.0, 4.0}}, + {8, {1.0, 4.0}}, + {5, {1.0, 1.0}} + }}, + { false, { + {10, {5.0, 5.0}}, + {11, {5.0, 7.0}}, + {12, {7.0, 7.0}}, + {10, {5.0, 5.0}} + }}, + { true, { + {100, {10.0, 10.0}}, + {101, {11.0, 10.0}}, + {102, {11.0, 11.0}}, + {103, {10.0, 11.0}}, + {100, {10.0, 10.0}} + }} + }); + + std::string wkb = wkb_factory.create_multipolygon(area); + std::unique_ptr geos = geos_factory.create_multipolygon(area); + REQUIRE(geos_to_wkb(geos.get()) == wkb); +} + +} + diff --git a/test/t/geom/test_mercator.cpp b/test/t/geom/test_mercator.cpp new file mode 100644 index 000000000..c5c663700 --- /dev/null +++ b/test/t/geom/test_mercator.cpp @@ -0,0 +1,37 @@ +#include "catch.hpp" + +#include + +TEST_CASE("Mercator") { + +SECTION("mercator_projection") { + osmium::geom::MercatorProjection projection; + REQUIRE(3857 == projection.epsg()); + REQUIRE("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs" == projection.proj_string()); +} + +SECTION("low_level_mercator_functions") { + osmium::geom::Coordinates c1(17.839, -3.249); + osmium::geom::Coordinates r1 = osmium::geom::mercator_to_lonlat(osmium::geom::lonlat_to_mercator(c1)); + REQUIRE(std::abs(c1.x - r1.x) < 0.000001); + REQUIRE(std::abs(c1.y - r1.y) < 0.000001); + + osmium::geom::Coordinates c2(-89.2, 15.915); + osmium::geom::Coordinates r2 = osmium::geom::mercator_to_lonlat(osmium::geom::lonlat_to_mercator(c2)); + REQUIRE(std::abs(c2.x - r2.x) < 0.000001); + REQUIRE(std::abs(c2.y - r2.y) < 0.000001); + + osmium::geom::Coordinates c3(180.0, 85.0); + osmium::geom::Coordinates r3 = osmium::geom::mercator_to_lonlat(osmium::geom::lonlat_to_mercator(c3)); + REQUIRE(std::abs(c3.x - r3.x) < 0.000001); + REQUIRE(std::abs(c3.y - r3.y) < 0.000001); +} + +SECTION("mercator_bounds") { + osmium::Location mmax(180.0, osmium::geom::MERCATOR_MAX_LAT); + osmium::geom::Coordinates c = osmium::geom::lonlat_to_mercator(mmax); + REQUIRE((c.x - c.y) < 0.001); + REQUIRE((osmium::geom::MERCATOR_MAX_LAT - osmium::geom::detail::y_to_lat(osmium::geom::detail::lon_to_x(180.0))) < 0.0000001); +} + +} diff --git a/test/t/geom/test_ogr.cpp b/test/t/geom/test_ogr.cpp new file mode 100644 index 000000000..28a10717d --- /dev/null +++ b/test/t/geom/test_ogr.cpp @@ -0,0 +1,185 @@ +#include "catch.hpp" + +#include +#include + +#include "../basic/helper.hpp" + +TEST_CASE("OGR_Geometry") { + +SECTION("point") { + osmium::geom::OGRFactory<> factory; + + std::unique_ptr point {factory.create_point(osmium::Location(3.2, 4.2))}; + REQUIRE(3.2 == point->getX()); + REQUIRE(4.2 == point->getY()); +} + +SECTION("empty_point") { + osmium::geom::OGRFactory<> factory; + + REQUIRE_THROWS_AS(factory.create_point(osmium::Location()), osmium::invalid_location); +} + +SECTION("linestring") { + osmium::geom::OGRFactory<> factory; + + osmium::memory::Buffer buffer(10000); + auto& wnl = osmium::builder::build_way_node_list(buffer, { + {1, {3.2, 4.2}}, + {3, {3.5, 4.7}}, + {4, {3.5, 4.7}}, + {2, {3.6, 4.9}} + }); + + { + std::unique_ptr linestring {factory.create_linestring(wnl)}; + REQUIRE(3 == linestring->getNumPoints()); + + REQUIRE(3.2 == linestring->getX(0)); + REQUIRE(3.6 == linestring->getX(2)); + } + + { + std::unique_ptr linestring {factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward)}; + REQUIRE(3 == linestring->getNumPoints()); + + REQUIRE(3.6 == linestring->getX(0)); + REQUIRE(3.2 == linestring->getX(2)); + } + + { + std::unique_ptr linestring {factory.create_linestring(wnl, osmium::geom::use_nodes::all)}; + REQUIRE(4 == linestring->getNumPoints()); + + REQUIRE(3.2 == linestring->getX(0)); + } + + { + std::unique_ptr linestring {factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward)}; + REQUIRE(4 == linestring->getNumPoints()); + + REQUIRE(3.6 == linestring->getX(0)); + } +} + +SECTION("area_1outer_0inner") { + osmium::geom::OGRFactory<> factory; + + osmium::memory::Buffer buffer(10000); + osmium::Area& area = buffer_add_area(buffer, + "foo", + {}, + { + { true, { + {1, {3.2, 4.2}}, + {2, {3.5, 4.7}}, + {3, {3.6, 4.9}}, + {1, {3.2, 4.2}} + }} + }); + + std::unique_ptr mp {factory.create_multipolygon(area)}; + REQUIRE(1 == mp->getNumGeometries()); + + const OGRPolygon* p0 = dynamic_cast(mp->getGeometryRef(0)); + REQUIRE(0 == p0->getNumInteriorRings()); + + const OGRLineString* l0e = p0->getExteriorRing(); + REQUIRE(4 == l0e->getNumPoints()); + + REQUIRE(3.5 == l0e->getX(1)); +} + +SECTION("area_1outer_1inner") { + osmium::geom::OGRFactory<> factory; + + osmium::memory::Buffer buffer(10000); + osmium::Area& area = buffer_add_area(buffer, + "foo", + {}, + { + { true, { + {1, {0.1, 0.1}}, + {2, {9.1, 0.1}}, + {3, {9.1, 9.1}}, + {4, {0.1, 9.1}}, + {1, {0.1, 0.1}} + }}, + { false, { + {5, {1.0, 1.0}}, + {6, {8.0, 1.0}}, + {7, {8.0, 8.0}}, + {8, {1.0, 8.0}}, + {5, {1.0, 1.0}} + }} + }); + + std::unique_ptr mp {factory.create_multipolygon(area)}; + REQUIRE(1 == mp->getNumGeometries()); + + const OGRPolygon* p0 = dynamic_cast(mp->getGeometryRef(0)); + REQUIRE(1 == p0->getNumInteriorRings()); + + const OGRLineString* l0e = p0->getExteriorRing(); + REQUIRE(5 == l0e->getNumPoints()); + + const OGRLineString* l0i0 = p0->getInteriorRing(0); + REQUIRE(5 == l0i0->getNumPoints()); +} + +SECTION("area_2outer_2inner") { + osmium::geom::OGRFactory<> factory; + + osmium::memory::Buffer buffer(10000); + osmium::Area& area = buffer_add_area(buffer, + "foo", + {}, + { + { true, { + {1, {0.1, 0.1}}, + {2, {9.1, 0.1}}, + {3, {9.1, 9.1}}, + {4, {0.1, 9.1}}, + {1, {0.1, 0.1}} + }}, + { false, { + {5, {1.0, 1.0}}, + {6, {4.0, 1.0}}, + {7, {4.0, 4.0}}, + {8, {1.0, 4.0}}, + {5, {1.0, 1.0}} + }}, + { false, { + {10, {5.0, 5.0}}, + {11, {5.0, 7.0}}, + {12, {7.0, 7.0}}, + {10, {5.0, 5.0}} + }}, + { true, { + {100, {10.0, 10.0}}, + {101, {11.0, 10.0}}, + {102, {11.0, 11.0}}, + {103, {10.0, 11.0}}, + {100, {10.0, 10.0}} + }} + }); + + std::unique_ptr mp {factory.create_multipolygon(area)}; + REQUIRE(2 == mp->getNumGeometries()); + + const OGRPolygon* p0 = dynamic_cast(mp->getGeometryRef(0)); + REQUIRE(2 == p0->getNumInteriorRings()); + + const OGRLineString* l0e = p0->getExteriorRing(); + REQUIRE(5 == l0e->getNumPoints()); + + const OGRPolygon* p1 = dynamic_cast(mp->getGeometryRef(1)); + REQUIRE(0 == p1->getNumInteriorRings()); + + const OGRLineString* l1e = p1->getExteriorRing(); + REQUIRE(5 == l1e->getNumPoints()); +} + +} + diff --git a/test/t/geom/test_projection.cpp b/test/t/geom/test_projection.cpp new file mode 100644 index 000000000..8d14ec598 --- /dev/null +++ b/test/t/geom/test_projection.cpp @@ -0,0 +1,131 @@ +#include "catch.hpp" + +#include +#include +#include + +TEST_CASE("Projection") { + +SECTION("identity_projection") { + osmium::geom::IdentityProjection projection; + REQUIRE(4326 == projection.epsg()); + REQUIRE("+proj=longlat +datum=WGS84 +no_defs" == projection.proj_string()); +} + +SECTION("project_location_4326") { + osmium::geom::Projection projection(4326); + REQUIRE(4326 == projection.epsg()); + REQUIRE("+init=epsg:4326" == projection.proj_string()); + + const osmium::Location loc(1.0, 2.0); + const osmium::geom::Coordinates c {1.0, 2.0}; + REQUIRE(c == projection(loc)); +} + +SECTION("project_location_4326_string") { + osmium::geom::Projection projection("+init=epsg:4326"); + REQUIRE(-1 == projection.epsg()); + REQUIRE("+init=epsg:4326" == projection.proj_string()); + + const osmium::Location loc(1.0, 2.0); + const osmium::geom::Coordinates c {1.0, 2.0}; + REQUIRE(c == projection(loc)); +} + +SECTION("unknown_projection_string") { + REQUIRE_THROWS_AS(osmium::geom::Projection projection("abc"), osmium::projection_error); +} + +SECTION("unknown_epsg_code") { + REQUIRE_THROWS_AS(osmium::geom::Projection projection(9999999), osmium::projection_error); +} + +SECTION("project_location_3857") { + osmium::geom::Projection projection(3857); + REQUIRE(3857 == projection.epsg()); + REQUIRE("+init=epsg:3857" == projection.proj_string()); + + { + const osmium::Location loc(0.0, 0.0); + const osmium::geom::Coordinates c {0.0, 0.0}; + REQUIRE(std::abs(projection(loc).x - c.x) < 0.1); + REQUIRE(std::abs(projection(loc).y - c.y) < 0.1); + } + { + const osmium::Location loc(180.0, 0.0); + const osmium::geom::Coordinates c {20037508.34, 0.0}; + REQUIRE(std::abs(projection(loc).x - c.x) < 0.1); + REQUIRE(std::abs(projection(loc).y - c.y) < 0.1); + } + { + const osmium::Location loc(180.0, 0.0); + const osmium::geom::Coordinates c {20037508.34, 0.0}; + REQUIRE(std::abs(projection(loc).x - c.x) < 0.1); + REQUIRE(std::abs(projection(loc).y - c.y) < 0.1); + } + { + const osmium::Location loc(0.0, 85.0511288); + const osmium::geom::Coordinates c {0.0, 20037508.34}; + REQUIRE(std::abs(projection(loc).x - c.x) < 0.1); + REQUIRE(std::abs(projection(loc).y - c.y) < 0.1); + } +} + +SECTION("project_location_mercator") { + osmium::geom::MercatorProjection projection; + + { + const osmium::Location loc(0.0, 0.0); + const osmium::geom::Coordinates c {0.0, 0.0}; + REQUIRE(std::abs(projection(loc).x - c.x) < 0.1); + REQUIRE(std::abs(projection(loc).y - c.y) < 0.1); + } + { + const osmium::Location loc(180.0, 0.0); + const osmium::geom::Coordinates c {20037508.34, 0.0}; + REQUIRE(std::abs(projection(loc).x - c.x) < 0.1); + REQUIRE(std::abs(projection(loc).y - c.y) < 0.1); + } + { + const osmium::Location loc(180.0, 0.0); + const osmium::geom::Coordinates c {20037508.34, 0.0}; + REQUIRE(std::abs(projection(loc).x - c.x) < 0.1); + REQUIRE(std::abs(projection(loc).y - c.y) < 0.1); + } + { + const osmium::Location loc(0.0, 85.0511288); + const osmium::geom::Coordinates c {0.0, 20037508.34}; + REQUIRE(std::abs(projection(loc).x - c.x) < 0.1); + REQUIRE(std::abs(projection(loc).y - c.y) < 0.1); + } +} + +SECTION("compare_mercators") { + osmium::geom::MercatorProjection projection_merc; + osmium::geom::Projection projection_3857(3857); + REQUIRE(3857 == projection_3857.epsg()); + REQUIRE("+init=epsg:3857" == projection_3857.proj_string()); + + { + const osmium::Location loc(4.2, 27.3); + REQUIRE(std::abs(projection_merc(loc).x - projection_3857(loc).x) < 0.1); + REQUIRE(std::abs(projection_merc(loc).y - projection_3857(loc).y) < 0.1); + } + { + const osmium::Location loc(160.789, -42.42); + REQUIRE(std::abs(projection_merc(loc).x - projection_3857(loc).x) < 0.1); + REQUIRE(std::abs(projection_merc(loc).y - projection_3857(loc).y) < 0.1); + } + { + const osmium::Location loc(-0.001, 0.001); + REQUIRE(std::abs(projection_merc(loc).x - projection_3857(loc).x) < 0.1); + REQUIRE(std::abs(projection_merc(loc).y - projection_3857(loc).y) < 0.1); + } + { + const osmium::Location loc(-85.2, -85.2); + REQUIRE(std::abs(projection_merc(loc).x - projection_3857(loc).x) < 0.1); + REQUIRE(std::abs(projection_merc(loc).y - projection_3857(loc).y) < 0.1); + } +} + +} diff --git a/test/t/geom/test_wkb.cpp b/test/t/geom/test_wkb.cpp new file mode 100644 index 000000000..730ee75ad --- /dev/null +++ b/test/t/geom/test_wkb.cpp @@ -0,0 +1,133 @@ +#include "catch.hpp" + +#include +#include + +#include "../basic/helper.hpp" + +#if __BYTE_ORDER == __LITTLE_ENDIAN + +TEST_CASE("WKB_Geometry_byte_order_dependent") { + +SECTION("point") { + osmium::geom::WKBFactory<> factory(osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex); + + std::string wkb {factory.create_point(osmium::Location(3.2, 4.2))}; + REQUIRE(std::string{"01010000009A99999999990940CDCCCCCCCCCC1040"} == wkb); +} + +SECTION("point_ewkb") { + osmium::geom::WKBFactory<> factory(osmium::geom::wkb_type::ewkb, osmium::geom::out_type::hex); + + std::string wkb {factory.create_point(osmium::Location(3.2, 4.2))}; + REQUIRE(std::string{"0101000020E61000009A99999999990940CDCCCCCCCCCC1040"} == wkb); +} + +SECTION("linestring") { + osmium::geom::WKBFactory<> factory(osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex); + + osmium::memory::Buffer buffer(10000); + auto& wnl = osmium::builder::build_way_node_list(buffer, { + {1, {3.2, 4.2}}, + {3, {3.5, 4.7}}, + {4, {3.5, 4.7}}, + {2, {3.6, 4.9}} + }); + + { + std::string wkb {factory.create_linestring(wnl)}; + REQUIRE(std::string{"0102000000030000009A99999999990940CDCCCCCCCCCC10400000000000000C40CDCCCCCCCCCC1240CDCCCCCCCCCC0C409A99999999991340"} == wkb); + } + + { + std::string wkb {factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward)}; + REQUIRE(std::string{"010200000003000000CDCCCCCCCCCC0C409A999999999913400000000000000C40CDCCCCCCCCCC12409A99999999990940CDCCCCCCCCCC1040"} == wkb); + } + + { + std::string wkb {factory.create_linestring(wnl, osmium::geom::use_nodes::all)}; + REQUIRE(std::string{"0102000000040000009A99999999990940CDCCCCCCCCCC10400000000000000C40CDCCCCCCCCCC12400000000000000C40CDCCCCCCCCCC1240CDCCCCCCCCCC0C409A99999999991340"} == wkb); + } + + { + std::string wkb {factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward)}; + REQUIRE(std::string{"010200000004000000CDCCCCCCCCCC0C409A999999999913400000000000000C40CDCCCCCCCCCC12400000000000000C40CDCCCCCCCCCC12409A99999999990940CDCCCCCCCCCC1040"} == wkb); + } +} + +SECTION("linestring_ewkb") { + osmium::geom::WKBFactory<> factory(osmium::geom::wkb_type::ewkb, osmium::geom::out_type::hex); + + osmium::memory::Buffer buffer(10000); + auto& wnl = osmium::builder::build_way_node_list(buffer, { + {1, {3.2, 4.2}}, + {3, {3.5, 4.7}}, + {4, {3.5, 4.7}}, + {2, {3.6, 4.9}} + }); + + std::string ewkb {factory.create_linestring(wnl)}; + REQUIRE(std::string{"0102000020E6100000030000009A99999999990940CDCCCCCCCCCC10400000000000000C40CDCCCCCCCCCC1240CDCCCCCCCCCC0C409A99999999991340"} == ewkb); +} + +SECTION("linestring_with_two_same_locations") { + osmium::geom::WKBFactory<> factory(osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex); + + osmium::memory::Buffer buffer(10000); + auto& wnl = osmium::builder::build_way_node_list(buffer, { + {1, {3.5, 4.7}}, + {2, {3.5, 4.7}} + }); + + 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 wkb {factory.create_linestring(wnl, osmium::geom::use_nodes::all)}; + REQUIRE(std::string{"0102000000020000000000000000000C40CDCCCCCCCCCC12400000000000000C40CDCCCCCCCCCC1240"} == wkb); + } + + { + std::string wkb {factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward)}; + REQUIRE(std::string{"0102000000020000000000000000000C40CDCCCCCCCCCC12400000000000000C40CDCCCCCCCCCC1240"} == wkb); + } +} + +SECTION("linestring_with_undefined_location") { + osmium::geom::WKBFactory<> factory(osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex); + + osmium::memory::Buffer buffer(10000); + auto& wnl = osmium::builder::build_way_node_list(buffer, { + {1, {3.5, 4.7}}, + {2, osmium::Location()} + }); + + REQUIRE_THROWS_AS(factory.create_linestring(wnl), osmium::invalid_location); +} + +} + +#endif + +TEST_CASE("WKB_Geometry_byte_order_independent") { + +SECTION("empty_point") { + osmium::geom::WKBFactory<> factory(osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex); + + REQUIRE_THROWS_AS(factory.create_point(osmium::Location()), osmium::invalid_location); +} + +SECTION("empty_linestring") { + osmium::geom::WKBFactory<> factory(osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex); + + osmium::memory::Buffer buffer(10000); + auto& wnl = osmium::builder::build_way_node_list(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); + 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); +} + +} + diff --git a/test/t/geom/test_wkt.cpp b/test/t/geom/test_wkt.cpp new file mode 100644 index 000000000..ff1417c72 --- /dev/null +++ b/test/t/geom/test_wkt.cpp @@ -0,0 +1,198 @@ +#include "catch.hpp" + +#include +#include + +#include "../basic/helper.hpp" + +TEST_CASE("WKT_Geometry") { + +SECTION("point") { + osmium::geom::WKTFactory<> factory; + + std::string wkt {factory.create_point(osmium::Location(3.2, 4.2))}; + REQUIRE(std::string{"POINT(3.2 4.2)"} == wkt); +} + +SECTION("empty_point") { + osmium::geom::WKTFactory<> factory; + + REQUIRE_THROWS_AS(factory.create_point(osmium::Location()), osmium::invalid_location); +} + +SECTION("linestring") { + osmium::geom::WKTFactory<> factory; + + osmium::memory::Buffer buffer(10000); + auto& wnl = osmium::builder::build_way_node_list(buffer, { + {1, {3.2, 4.2}}, + {3, {3.5, 4.7}}, + {4, {3.5, 4.7}}, + {2, {3.6, 4.9}} + }); + + { + std::string wkt {factory.create_linestring(wnl)}; + REQUIRE(std::string{"LINESTRING(3.2 4.2,3.5 4.7,3.6 4.9)"} == wkt); + } + + { + std::string wkt {factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward)}; + REQUIRE(std::string{"LINESTRING(3.6 4.9,3.5 4.7,3.2 4.2)"} == wkt); + } + + { + std::string wkt {factory.create_linestring(wnl, osmium::geom::use_nodes::all)}; + REQUIRE(std::string{"LINESTRING(3.2 4.2,3.5 4.7,3.5 4.7,3.6 4.9)"} == wkt); + } + + { + std::string wkt {factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward)}; + REQUIRE(std::string{"LINESTRING(3.6 4.9,3.5 4.7,3.5 4.7,3.2 4.2)"} == wkt); + } +} + +SECTION("empty_linestring") { + osmium::geom::WKTFactory<> factory; + + osmium::memory::Buffer buffer(10000); + auto& wnl = osmium::builder::build_way_node_list(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); + 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::WKTFactory<> factory; + + osmium::memory::Buffer buffer(10000); + auto& wnl = osmium::builder::build_way_node_list(buffer, { + {1, {3.5, 4.7}}, + {2, {3.5, 4.7}} + }); + + 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 wkt {factory.create_linestring(wnl, osmium::geom::use_nodes::all)}; + REQUIRE(std::string{"LINESTRING(3.5 4.7,3.5 4.7)"} == wkt); + } + + { + std::string wkt {factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward)}; + REQUIRE(std::string{"LINESTRING(3.5 4.7,3.5 4.7)"} == wkt); + } +} + +SECTION("linestring_with_undefined_location") { + osmium::geom::WKTFactory<> factory; + + osmium::memory::Buffer buffer(10000); + auto& wnl = osmium::builder::build_way_node_list(buffer, { + {1, {3.5, 4.7}}, + {2, osmium::Location()} + }); + + REQUIRE_THROWS_AS(factory.create_linestring(wnl), osmium::invalid_location); +} + +SECTION("area_1outer_0inner") { + osmium::geom::WKTFactory<> factory; + + osmium::memory::Buffer buffer(10000); + osmium::Area& area = buffer_add_area(buffer, + "foo", + {}, + { + { true, { + {1, {3.2, 4.2}}, + {2, {3.5, 4.7}}, + {3, {3.6, 4.9}}, + {1, {3.2, 4.2}} + }} + }); + + { + std::string wkt {factory.create_multipolygon(area)}; + REQUIRE(std::string{"MULTIPOLYGON(((3.2 4.2,3.5 4.7,3.6 4.9,3.2 4.2)))"} == wkt); + } +} + +SECTION("area_1outer_1inner") { + osmium::geom::WKTFactory<> factory; + + osmium::memory::Buffer buffer(10000); + osmium::Area& area = buffer_add_area(buffer, + "foo", + {}, + { + { true, { + {1, {0.1, 0.1}}, + {2, {9.1, 0.1}}, + {3, {9.1, 9.1}}, + {4, {0.1, 9.1}}, + {1, {0.1, 0.1}} + }}, + { false, { + {5, {1.0, 1.0}}, + {6, {8.0, 1.0}}, + {7, {8.0, 8.0}}, + {8, {1.0, 8.0}}, + {5, {1.0, 1.0}} + }} + }); + + { + std::string wkt {factory.create_multipolygon(area)}; + REQUIRE(std::string{"MULTIPOLYGON(((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)))"} == wkt); + } +} + +SECTION("area_2outer_2inner") { + osmium::geom::WKTFactory<> factory; + + osmium::memory::Buffer buffer(10000); + osmium::Area& area = buffer_add_area(buffer, + "foo", + {}, + { + { true, { + {1, {0.1, 0.1}}, + {2, {9.1, 0.1}}, + {3, {9.1, 9.1}}, + {4, {0.1, 9.1}}, + {1, {0.1, 0.1}} + }}, + { false, { + {5, {1.0, 1.0}}, + {6, {4.0, 1.0}}, + {7, {4.0, 4.0}}, + {8, {1.0, 4.0}}, + {5, {1.0, 1.0}} + }}, + { false, { + {10, {5.0, 5.0}}, + {11, {5.0, 7.0}}, + {12, {7.0, 7.0}}, + {10, {5.0, 5.0}} + }}, + { true, { + {100, {10.0, 10.0}}, + {101, {11.0, 10.0}}, + {102, {11.0, 11.0}}, + {103, {10.0, 11.0}}, + {100, {10.0, 10.0}} + }} + }); + + { + std::string wkt {factory.create_multipolygon(area)}; + REQUIRE(std::string{"MULTIPOLYGON(((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)))"} == wkt); + } +} + +} + diff --git a/test/t/index/test_id_to_location.cpp b/test/t/index/test_id_to_location.cpp new file mode 100644 index 000000000..4f873e1a0 --- /dev/null +++ b/test/t/index/test_id_to_location.cpp @@ -0,0 +1,143 @@ +#include "catch.hpp" + +#include +#include + +#include +#include +#include +#include +#include +#include + +template +void test_func_all(TIndex& index) { + osmium::unsigned_object_id_type id1 = 12; + osmium::unsigned_object_id_type id2 = 3; + osmium::Location loc1(1.2, 4.5); + osmium::Location loc2(3.5, -7.2); + + REQUIRE_THROWS_AS(index.get(id1), osmium::not_found); + + index.set(id1, loc1); + index.set(id2, loc2); + + index.sort(); + + REQUIRE_THROWS_AS(index.get(5), osmium::not_found); + REQUIRE_THROWS_AS(index.get(100), osmium::not_found); +} + +template +void test_func_real(TIndex& index) { + osmium::unsigned_object_id_type id1 = 12; + osmium::unsigned_object_id_type id2 = 3; + osmium::Location loc1(1.2, 4.5); + osmium::Location loc2(3.5, -7.2); + + index.set(id1, loc1); + index.set(id2, loc2); + + index.sort(); + + REQUIRE(loc1 == index.get(id1)); + REQUIRE(loc2 == index.get(id2)); + + REQUIRE_THROWS_AS(index.get(5), osmium::not_found); + REQUIRE_THROWS_AS(index.get(100), osmium::not_found); + + index.clear(); + + REQUIRE_THROWS_AS(index.get(id1), osmium::not_found); +} + +TEST_CASE("IdToLocation") { + +SECTION("Dummy") { + typedef osmium::index::map::Dummy index_type; + + index_type index1; + + REQUIRE(0 == index1.size()); + REQUIRE(0 == index1.used_memory()); + + test_func_all(index1); + + REQUIRE(0 == index1.size()); + REQUIRE(0 == index1.used_memory()); +} + +SECTION("DenseMapMem") { + typedef osmium::index::map::DenseMapMem index_type; + + index_type index1; + index1.reserve(1000); + test_func_all(index1); + + index_type index2; + index2.reserve(1000); + test_func_real(index2); +} + +#ifdef __linux__ +SECTION("DenseMapMmap") { + typedef osmium::index::map::DenseMapMmap index_type; + + index_type index1; + test_func_all(index1); + + index_type index2; + test_func_real(index2); +} +#else +# pragma message "not running 'DenseMapMmap' test case on this machine" +#endif + +SECTION("DenseMapFile") { + typedef osmium::index::map::DenseMapFile index_type; + + index_type index1; + test_func_all(index1); + + index_type index2; + test_func_real(index2); +} + +SECTION("SparseTable") { + typedef osmium::index::map::SparseTable index_type; + + index_type index1; + test_func_all(index1); + + index_type index2; + test_func_real(index2); +} + +SECTION("StlMap") { + typedef osmium::index::map::StlMap index_type; + + index_type index1; + test_func_all(index1); + + index_type index2; + test_func_real(index2); +} + +SECTION("SparseMapMem") { + typedef osmium::index::map::SparseMapMem index_type; + + index_type index1; + + REQUIRE(0 == index1.size()); + REQUIRE(0 == index1.used_memory()); + + test_func_all(index1); + + REQUIRE(2 == index1.size()); + + index_type index2; + test_func_real(index2); +} + +} + diff --git a/test/t/index/test_typed_mmap.cpp b/test/t/index/test_typed_mmap.cpp new file mode 100644 index 000000000..90f8f6242 --- /dev/null +++ b/test/t/index/test_typed_mmap.cpp @@ -0,0 +1,95 @@ +#include "catch.hpp" + +#include + +#if defined(_MSC_VER) || (defined(__GNUC__) && defined(_WIN32)) + #include "win_mkstemp.hpp" +#endif + +TEST_CASE("TypedMmap") { + +SECTION("Mmap") { + uint64_t* data = osmium::detail::typed_mmap::map(10); + + data[0] = 4ul; + data[3] = 9ul; + data[9] = 25ul; + + REQUIRE(4ul == data[0]); + REQUIRE(9ul == data[3]); + REQUIRE(25ul == data[9]); + + osmium::detail::typed_mmap::unmap(data, 10); +} + +SECTION("MmapSizeZero") { + REQUIRE_THROWS_AS(osmium::detail::typed_mmap::map(0), std::system_error); +} + +SECTION("MmapHugeSize") { + // this is a horrible hack to only run the test on 64bit machines. + if (sizeof(size_t) >= 8) { + REQUIRE_THROWS_AS(osmium::detail::typed_mmap::map(1ULL << (sizeof(size_t) * 6)), std::system_error); + } +} + +#ifdef __linux__ +SECTION("Remap") { + uint64_t* data = osmium::detail::typed_mmap::map(10); + + data[0] = 4ul; + data[3] = 9ul; + data[9] = 25ul; + + uint64_t* new_data = osmium::detail::typed_mmap::remap(data, 10, 1000); + + REQUIRE(4ul == new_data[0]); + REQUIRE(9ul == new_data[3]); + REQUIRE(25ul == new_data[9]); +} +#else +# pragma message "not running 'Remap' test case on this machine" +#endif + +SECTION("FileSize") { + const int size = 100; + char filename[] = "/tmp/osmium_unit_test_XXXXXX"; + const int fd = mkstemp(filename); + REQUIRE(fd > 0); + REQUIRE(0 == unlink(filename)); + REQUIRE(0 == osmium::detail::typed_mmap::file_size(fd)); + REQUIRE(0 == ftruncate(fd, size * sizeof(uint64_t))); + REQUIRE(size == osmium::detail::typed_mmap::file_size(fd)); + + osmium::detail::typed_mmap::grow_file(size / 2, fd); + REQUIRE(size == osmium::detail::typed_mmap::file_size(fd)); + + osmium::detail::typed_mmap::grow_file(size, fd); + REQUIRE(size == osmium::detail::typed_mmap::file_size(fd)); + + osmium::detail::typed_mmap::grow_file(size * 2, fd); + REQUIRE((size * 2) == osmium::detail::typed_mmap::file_size(fd)); +} + +SECTION("GrowAndMap") { + const int size = 100; + char filename[] = "/tmp/osmium_unit_test_XXXXXX"; + const int fd = mkstemp(filename); + REQUIRE(fd > 0); + REQUIRE(0 == unlink(filename)); + + uint64_t* data = osmium::detail::typed_mmap::grow_and_map(size, fd); + REQUIRE(size == osmium::detail::typed_mmap::file_size(fd)); + + data[0] = 1ul; + data[1] = 8ul; + data[99] = 27ul; + + REQUIRE(1ul == data[0]); + REQUIRE(8ul == data[1]); + REQUIRE(27ul == data[99]); + + osmium::detail::typed_mmap::unmap(data, size); +} + +} diff --git a/test/t/io/data.osm b/test/t/io/data.osm new file mode 100644 index 000000000..fffb77ad3 --- /dev/null +++ b/test/t/io/data.osm @@ -0,0 +1,4 @@ + + + + diff --git a/test/t/io/data.osm.bz2 b/test/t/io/data.osm.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..0f38797ebc6219cc4cfab63da1e4c7532007742a GIT binary patch literal 200 zcmV;(05|_aT4*^jL0KkKS>1wN)Bpf1-+(|6P=obXfdB>&FX!JtFaWu%VWE>CWMT|V zni^n)A)^`@MrvuMni>VP0*vRGkeVGfwh$BQp}GJmDS45V7?gcj zb6MgrsJw1U05MRY9u9kih6h<3!Cy`6J6>7k-Vu%3CaNFN`*T~(ZwD=aUKPh&41%;` zy+l623Sk*($Yw}S`K$wA=AHIf@W!|0Tq)u}-pdqlRIJn#Tp+|IQx|eYI8cz?f?d>a C4O0~W literal 0 HcmV?d00001 diff --git a/test/t/io/data.osm.gz b/test/t/io/data.osm.gz new file mode 100644 index 0000000000000000000000000000000000000000..07edb9095b9ce78d51666d221ad9faba309ff5d5 GIT binary patch literal 187 zcmV;s07U;EiwFoAN*GiE17u-zVJ>fTZ2(11%?g7s48HpmC6}JmR>l~^>TOTpF1rPr zxq@xQ*0IN55ZS_a_(<~owEf4=;!SIEF&L>UB?W~sS{EiG@58OU$i6GunEdYxRCNY1 zQJ@ubTn%JO*y8Jz p9ilDKkpg0TVVEdU-Y@fRRjGz4=7ZMUx8}lK@deEa=a1e1003pbRv`cY literal 0 HcmV?d00001 diff --git a/test/t/io/data_bzip2.txt b/test/t/io/data_bzip2.txt new file mode 100644 index 000000000..755d6af45 --- /dev/null +++ b/test/t/io/data_bzip2.txt @@ -0,0 +1 @@ +TESTDATA diff --git a/test/t/io/data_bzip2.txt.bz2 b/test/t/io/data_bzip2.txt.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..f0ee7e7d65cf069345fad9f6e75d03c6e88e0941 GIT binary patch literal 45 ycmZ>Y%CIzaj8qGb6yfW&V_;x$V_*U{I3CFko@L#wK3mY7sC2Bn<$~dI>%N literal 0 HcmV?d00001 diff --git a/test/t/io/test_bzip2.cpp b/test/t/io/test_bzip2.cpp new file mode 100644 index 000000000..143f70d36 --- /dev/null +++ b/test/t/io/test_bzip2.cpp @@ -0,0 +1,30 @@ +#include "catch.hpp" + +#include +#include +#include + +#include + +TEST_CASE("Bzip2") { + +SECTION("read_compressed_file") { + int fd = ::open("t/io/data_bzip2.txt.bz2", O_RDONLY); + REQUIRE(fd > 0); + + size_t size = 0; + std::string all; + { + osmium::io::Bzip2Decompressor decomp(fd); + for (std::string data = decomp.read(); !data.empty(); data = decomp.read()) { + size += data.size(); + all += data; + } + } + + REQUIRE(9 == size); + REQUIRE("TESTDATA\n" == all); +} + +} + diff --git a/test/t/io/test_file_formats.cpp b/test/t/io/test_file_formats.cpp new file mode 100644 index 000000000..03f95784c --- /dev/null +++ b/test/t/io/test_file_formats.cpp @@ -0,0 +1,251 @@ +#include "catch.hpp" + +#include + +#include + +TEST_CASE("FileFormats") { + +SECTION("default_file_format") { + osmium::io::File f; + REQUIRE(osmium::io::file_format::unknown == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + REQUIRE_THROWS_AS(f.check(), std::runtime_error); +} + +SECTION("stdin_stdout_empty") { + osmium::io::File f {""}; + REQUIRE(osmium::io::file_format::unknown == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + REQUIRE_THROWS_AS(f.check(), std::runtime_error); +} + +SECTION("stdin_stdout_dash") { + osmium::io::File f {"-"}; + REQUIRE(osmium::io::file_format::unknown == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + REQUIRE_THROWS_AS(f.check(), std::runtime_error); +} + +SECTION("stdin_stdout_bz2") { + osmium::io::File f {"-", "osm.bz2"}; + REQUIRE("" == f.filename()); + REQUIRE(osmium::io::file_format::xml == f.format()); + REQUIRE(osmium::io::file_compression::bzip2 == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("detect_file_format_by_suffix_osm") { + osmium::io::File f {"test.osm"}; + REQUIRE(osmium::io::file_format::xml == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("detect_file_format_by_suffix_pbf") { + osmium::io::File f {"test.pbf"}; + REQUIRE(osmium::io::file_format::pbf == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("detect_file_format_by_suffix_osm_pbf") { + osmium::io::File f {"test.osm.pbf"}; + REQUIRE(osmium::io::file_format::pbf == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("detect_file_format_by_suffix_opl") { + osmium::io::File f {"test.opl"}; + REQUIRE(osmium::io::file_format::opl == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("detect_file_format_by_suffix_osm_opl") { + osmium::io::File f {"test.osm.opl"}; + REQUIRE(osmium::io::file_format::opl == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("detect_file_format_by_suffix_osm_gz") { + osmium::io::File f {"test.osm.gz"}; + REQUIRE(osmium::io::file_format::xml == f.format()); + REQUIRE(osmium::io::file_compression::gzip == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("detect_file_format_by_suffix_opl_bz2") { + osmium::io::File f {"test.osm.opl.bz2"}; + REQUIRE(osmium::io::file_format::opl == f.format()); + REQUIRE(osmium::io::file_compression::bzip2 == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("detect_file_format_by_suffix_osc_gz") { + osmium::io::File f {"test.osc.gz"}; + REQUIRE(osmium::io::file_format::xml == f.format()); + REQUIRE(osmium::io::file_compression::gzip == f.compression()); + REQUIRE(true == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("detect_file_format_by_suffix_opl_gz") { + osmium::io::File f {"test.osh.opl.gz"}; + REQUIRE(osmium::io::file_format::opl == f.format()); + REQUIRE(osmium::io::file_compression::gzip == f.compression()); + REQUIRE(true == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("detect_file_format_by_suffix_osh_pbf") { + osmium::io::File f {"test.osh.pbf"}; + REQUIRE(osmium::io::file_format::pbf == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(true == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("override_file_format_by_suffix_osm") { + osmium::io::File f {"test", "osm"}; + REQUIRE(osmium::io::file_format::xml == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("override_file_format_by_suffix_pbf") { + osmium::io::File f {"test", "pbf"}; + REQUIRE(osmium::io::file_format::pbf == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("override_file_format_by_suffix_osm_pbf") { + osmium::io::File f {"test", "osm.pbf"}; + REQUIRE(osmium::io::file_format::pbf == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("override_file_format_by_suffix_opl") { + osmium::io::File f {"test", "opl"}; + REQUIRE(osmium::io::file_format::opl == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("override_file_format_by_suffix_osm_opl") { + osmium::io::File f {"test", "osm.opl"}; + REQUIRE(osmium::io::file_format::opl == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("override_file_format_by_suffix_osm_gz") { + osmium::io::File f {"test", "osm.gz"}; + REQUIRE(osmium::io::file_format::xml == f.format()); + REQUIRE(osmium::io::file_compression::gzip == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("override_file_format_by_suffix_osm_opl_bz2") { + osmium::io::File f {"test", "osm.opl.bz2"}; + REQUIRE(osmium::io::file_format::opl == f.format()); + REQUIRE(osmium::io::file_compression::bzip2 == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("override_file_format_by_suffix_osc_gz") { + osmium::io::File f {"test", "osc.gz"}; + REQUIRE(osmium::io::file_format::xml == f.format()); + REQUIRE(osmium::io::file_compression::gzip == f.compression()); + REQUIRE(true == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("override_file_format_by_suffix_osh_opl_gz") { + osmium::io::File f {"test", "osh.opl.gz"}; + REQUIRE(osmium::io::file_format::opl == f.format()); + REQUIRE(osmium::io::file_compression::gzip == f.compression()); + REQUIRE(true == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("override_file_format_by_suffix_osh_pbf") { + osmium::io::File f {"test", "osh.pbf"}; + REQUIRE(osmium::io::file_format::pbf == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(true == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("format_options_pbf_history") { + osmium::io::File f {"test", "pbf,history=true"}; + REQUIRE(osmium::io::file_format::pbf == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(true == f.has_multiple_object_versions()); + f.check(); +} + +SECTION("format_options_pbf_foo") { + osmium::io::File f {"test.osm", "pbf,foo=bar"}; + REQUIRE(osmium::io::file_format::pbf == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE("bar" == f.get("foo")); + f.check(); +} + +SECTION("format_options_xml_abc_something") { + osmium::io::File f {"test.bla", "xml,abc,some=thing"}; + REQUIRE(osmium::io::file_format::xml == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE("true" == f.get("abc")); + REQUIRE("thing" == f.get("some")); + REQUIRE(2 == std::distance(f.begin(), f.end())); + f.check(); +} + +SECTION("unknown_format_foo_bar") { + osmium::io::File f {"test.foo.bar"}; + REQUIRE(osmium::io::file_format::unknown == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE_THROWS_AS(f.check(), std::runtime_error); +} + +SECTION("unknown_format_foo") { + osmium::io::File f {"test", "foo"}; + REQUIRE_THROWS_AS(f.check(), std::runtime_error); +} + +SECTION("unknown_format_osm_foo") { + osmium::io::File f {"test", "osm.foo"}; + REQUIRE_THROWS_AS(f.check(), std::runtime_error); +} + +SECTION("unknown_format_bla_equals_foo") { + osmium::io::File f {"test", "bla=foo"}; + REQUIRE_THROWS_AS(f.check(), std::runtime_error); +} + +} + diff --git a/test/t/io/test_reader.cpp b/test/t/io/test_reader.cpp new file mode 100644 index 000000000..3be842b86 --- /dev/null +++ b/test/t/io/test_reader.cpp @@ -0,0 +1,116 @@ +#include "catch.hpp" + +#include +#include +#include +#include +#include + +struct CountHandler : public osmium::handler::Handler { + + int count = 0; + + void node(osmium::Node&) { + ++count; + } + +}; // class CountHandler + +TEST_CASE("Reader") { + + SECTION("reader can be initialized with file") { + osmium::io::File file("t/io/data.osm"); + osmium::io::Reader reader(file); + osmium::handler::Handler handler; + + osmium::apply(reader, handler); + } + + SECTION("reader can be initialized with string") { + osmium::io::Reader reader("t/io/data.osm"); + osmium::handler::Handler handler; + + osmium::apply(reader, handler); + } + + SECTION("should return invalid buffer after eof") { + osmium::io::File file("t/io/data.osm"); + osmium::io::Reader reader(file); + + REQUIRE(!reader.eof()); + + while (osmium::memory::Buffer buffer = reader.read()) { + } + + REQUIRE(reader.eof()); + + // extra read always returns invalid buffer + osmium::memory::Buffer buffer = reader.read(); + REQUIRE(!buffer); + } + + SECTION("should not hang when apply() is called twice on reader") { + osmium::io::File file("t/io/data.osm"); + osmium::io::Reader reader(file); + osmium::handler::Handler handler; + + osmium::apply(reader, handler); + osmium::apply(reader, handler); + } + + SECTION("should work with a buffer with uncompressed data") { + int fd = osmium::io::detail::open_for_reading("t/io/data.osm"); + REQUIRE(fd >= 0); + + const size_t buffer_size = 1000; + char buffer[buffer_size]; + ssize_t length = ::read(fd, buffer, buffer_size); + REQUIRE(length > 0); + + osmium::io::File file(buffer, static_cast(length), "osm"); + osmium::io::Reader reader(file); + CountHandler handler; + + REQUIRE(handler.count == 0); + osmium::apply(reader, handler); + REQUIRE(handler.count == 1); + } + + SECTION("should work with a buffer with gzip-compressed data") { + int fd = osmium::io::detail::open_for_reading("t/io/data.osm.gz"); + REQUIRE(fd >= 0); + + const size_t buffer_size = 1000; + char buffer[buffer_size]; + ssize_t length = ::read(fd, buffer, buffer_size); + REQUIRE(length > 0); + + osmium::io::File file(buffer, static_cast(length), "osm.gz"); + osmium::io::Reader reader(file); + CountHandler handler; + + REQUIRE(handler.count == 0); + osmium::apply(reader, handler); + REQUIRE(handler.count == 1); + } + + SECTION("should work with a buffer with bzip2-compressed data") { + int fd = osmium::io::detail::open_for_reading("t/io/data.osm.bz2"); + REQUIRE(fd >= 0); + + const size_t buffer_size = 1000; + char buffer[buffer_size]; + ssize_t length = ::read(fd, buffer, buffer_size); + REQUIRE(length > 0); + + osmium::io::File file(buffer, static_cast(length), "osm.bz2"); + osmium::io::Reader reader(file); + CountHandler handler; + + REQUIRE(handler.count == 0); + osmium::apply(reader, handler); + REQUIRE(handler.count == 1); + } + +} + diff --git a/test/t/tags/test_filter.cpp b/test/t/tags/test_filter.cpp new file mode 100644 index 000000000..e65f63d3b --- /dev/null +++ b/test/t/tags/test_filter.cpp @@ -0,0 +1,216 @@ +#include "catch.hpp" + +#include + +#include +#include +#include +#include +#include +#include + +template +void check_filter(const osmium::TagList& tag_list, const TFilter filter, const std::vector& reference) { + REQUIRE(tag_list.size() == reference.size()); + auto t_it = tag_list.begin(); + for (auto it = reference.begin(); it != reference.end(); ++t_it, ++it) { + REQUIRE(filter(*t_it) == *it); + } + + typename TFilter::iterator fi_begin(filter, tag_list.begin(), tag_list.end()); + typename TFilter::iterator fi_end(filter, tag_list.end(), tag_list.end()); + + REQUIRE(std::distance(fi_begin, fi_end) == std::count(reference.begin(), reference.end(), true)); +} + +TEST_CASE("Filter") { + +SECTION("KeyFilter_matches_some_tags") { + osmium::tags::KeyFilter filter(false); + filter.add(true, "highway").add(true, "railway"); + + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, // match + { "name", "Main Street" }, // no match + { "source", "GPS" } // no match + }); + + std::vector results = { true, false, false }; + + check_filter(tag_list, filter, results); +} + +SECTION("KeyFilter_iterator_filters_tags") { + osmium::tags::KeyFilter filter(false); + filter.add(true, "highway").add(true, "source"); + + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tl = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, // match + { "name", "Main Street" }, // no match + { "source", "GPS" } // no match + }); + + osmium::tags::KeyFilter::iterator it(filter, tl.begin(), tl.end()); + const osmium::tags::KeyFilter::iterator end(filter, tl.end(), tl.end()); + + REQUIRE(2 == std::distance(it, end)); + + REQUIRE(it != end); + REQUIRE(std::string("highway") == it->key()); + REQUIRE(std::string("primary") == it->value()); + ++it; + REQUIRE(std::string("source") == it->key()); + REQUIRE(std::string("GPS") == it->value()); + REQUIRE(++it == end); +} + +SECTION("KeyValueFilter_matches_some_tags") { + osmium::tags::KeyValueFilter filter(false); + + filter.add(true, "highway", "residential").add(true, "highway", "primary").add(true, "railway"); + + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "railway", "tram" }, + { "source", "GPS" } + }); + + std::vector results = {true, true, false}; + + check_filter(tag_list, filter, results); +} + +SECTION("KeyValueFilter_ordering_matters") { + osmium::tags::KeyValueFilter filter1(false); + filter1.add(true, "highway").add(false, "highway", "road"); + + osmium::tags::KeyValueFilter filter2(false); + filter2.add(false, "highway", "road").add(true, "highway"); + + osmium::memory::Buffer buffer(10240); + + const osmium::TagList& tag_list1 = osmium::builder::build_tag_list(buffer, { + { "highway", "road" }, + { "name", "Main Street" } + }); + + const osmium::TagList& tag_list2 = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "name", "Main Street" } + }); + + check_filter(tag_list1, filter1, {true, false}); + check_filter(tag_list1, filter2, {false, false}); + check_filter(tag_list2, filter2, {true, false}); +} + +SECTION("KeyValueFilter_matches_against_taglist_with_any") { + osmium::tags::KeyValueFilter filter(false); + + filter.add(true, "highway", "primary").add(true, "name"); + + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "railway", "tram" }, + { "source", "GPS" } + }); + + REQUIRE( osmium::tags::match_any_of(tag_list, filter)); + REQUIRE(!osmium::tags::match_all_of(tag_list, filter)); + REQUIRE(!osmium::tags::match_none_of(tag_list, filter)); +} + +SECTION("KeyValueFilter_matches_against_taglist_with_all") { + osmium::tags::KeyValueFilter filter(false); + + filter.add(true, "highway", "primary").add(true, "name"); + + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "name", "Main Street" } + }); + + REQUIRE( osmium::tags::match_any_of(tag_list, filter)); + REQUIRE( osmium::tags::match_all_of(tag_list, filter)); + REQUIRE(!osmium::tags::match_none_of(tag_list, filter)); +} + +SECTION("KeyValueFilter_matches_against_taglist_with_none") { + osmium::tags::KeyValueFilter filter(false); + + filter.add(true, "highway", "road").add(true, "source"); + + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "name", "Main Street" } + }); + + REQUIRE(!osmium::tags::match_any_of(tag_list, filter)); + REQUIRE(!osmium::tags::match_all_of(tag_list, filter)); + REQUIRE( osmium::tags::match_none_of(tag_list, filter)); +} + +SECTION("KeyValueFilter_matches_against_taglist_with_any_called_with_rvalue") { + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "railway", "tram" }, + { "source", "GPS" } + }); + + REQUIRE(osmium::tags::match_any_of(tag_list, + osmium::tags::KeyValueFilter().add(true, "highway", "primary").add(true, "name"))); +} + +SECTION("RegexFilter_matches_some_tags") { + osmium::tags::RegexFilter filter(false); + filter.add(true, "highway", std::regex(".*_link")); + + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list1 = osmium::builder::build_tag_list(buffer, { + { "highway", "primary_link" }, + { "source", "GPS" } + }); + const osmium::TagList& tag_list2 = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "source", "GPS" } + }); + + check_filter(tag_list1, filter, {true, false}); + check_filter(tag_list2, filter, {false, false}); +} + +SECTION("RegexFilter_matches_some_tags_with_lvalue_regex") { + osmium::tags::RegexFilter filter(false); + std::regex r(".*straße"); + filter.add(true, "name", r); + + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "name", "Hauptstraße" } + }); + + check_filter(tag_list, filter, {false, true}); +} + +SECTION("KeyPrefixFilter_matches_some_tags") { + osmium::tags::KeyPrefixFilter filter(false); + filter.add(true, "name:"); + + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "name:de", "Hauptstraße" } + }); + + check_filter(tag_list, filter, {false, true}); +} + +} diff --git a/test/t/tags/test_operators.cpp b/test/t/tags/test_operators.cpp new file mode 100644 index 000000000..e2c22a405 --- /dev/null +++ b/test/t/tags/test_operators.cpp @@ -0,0 +1,61 @@ +#include "catch.hpp" + +#include + +#include +#include +#include + +TEST_CASE("Operators") { + +SECTION("Equal") { + osmium::memory::Buffer buffer1(10240); + { + osmium::builder::TagListBuilder tl_builder(buffer1); + tl_builder.add_tag("highway", "primary"); + tl_builder.add_tag("name", "Main Street"); + tl_builder.add_tag("source", "GPS"); + } + buffer1.commit(); + + osmium::memory::Buffer buffer2(10240); + { + osmium::builder::TagListBuilder tl_builder(buffer2); + tl_builder.add_tag("highway", "primary"); + } + buffer2.commit(); + + const osmium::TagList& tl1 = buffer1.get(0); + const osmium::TagList& tl2 = buffer2.get(0); + + auto tagit1 = tl1.begin(); + auto tagit2 = tl2.begin(); + REQUIRE(*tagit1 == *tagit2); + ++tagit1; + REQUIRE(!(*tagit1 == *tagit2)); +} + +SECTION("Order") { + osmium::memory::Buffer buffer(10240); + { + osmium::builder::TagListBuilder tl_builder(buffer); + tl_builder.add_tag("highway", "residential"); + tl_builder.add_tag("highway", "primary"); + tl_builder.add_tag("name", "Main Street"); + tl_builder.add_tag("amenity", "post_box"); + } + buffer.commit(); + + const osmium::TagList& tl = buffer.get(0); + const osmium::Tag& t1 = *(tl.begin()); + const osmium::Tag& t2 = *(std::next(tl.begin(), 1)); + const osmium::Tag& t3 = *(std::next(tl.begin(), 2)); + const osmium::Tag& t4 = *(std::next(tl.begin(), 3)); + + REQUIRE(t2 < t1); + REQUIRE(t1 < t3); + REQUIRE(t2 < t3); + REQUIRE(t4 < t1); +} + +} diff --git a/test/t/tags/test_tag_list.cpp b/test/t/tags/test_tag_list.cpp new file mode 100644 index 000000000..b25d8cac7 --- /dev/null +++ b/test/t/tags/test_tag_list.cpp @@ -0,0 +1,76 @@ +#include "catch.hpp" + +#include +#include +#include + +TEST_CASE("tag_list") { + +SECTION("can_be_created_from_initializer_list") { + osmium::memory::Buffer buffer(10240); + + const osmium::TagList& tl = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "name", "Main Street" }, + { "source", "GPS" } + }); + + REQUIRE(osmium::item_type::tag_list == tl.type()); + REQUIRE(3 == tl.size()); + REQUIRE(std::string("highway") == tl.begin()->key()); + REQUIRE(std::string("primary") == tl.begin()->value()); +} + +SECTION("can_be_created_from_map") { + osmium::memory::Buffer buffer(10240); + + const osmium::TagList& tl = osmium::builder::build_tag_list_from_map(buffer, std::map({ + { "highway", "primary" }, + { "name", "Main Street" } + })); + + REQUIRE(osmium::item_type::tag_list == tl.type()); + REQUIRE(2 == tl.size()); + + if (std::string("highway") == tl.begin()->key()) { + REQUIRE(std::string("primary") == tl.begin()->value()); + REQUIRE(std::string("name") == std::next(tl.begin(), 1)->key()); + REQUIRE(std::string("Main Street") == std::next(tl.begin(), 1)->value()); + } else { + REQUIRE(std::string("highway") == std::next(tl.begin(), 1)->key()); + REQUIRE(std::string("primary") == std::next(tl.begin(), 1)->value()); + REQUIRE(std::string("name") == tl.begin()->key()); + REQUIRE(std::string("Main Street") == tl.begin()->value()); + } +} + +SECTION("can_be_created_with_callback") { + osmium::memory::Buffer buffer(10240); + + const osmium::TagList& tl = osmium::builder::build_tag_list_from_func(buffer, [](osmium::builder::TagListBuilder& tlb) { + tlb.add_tag("highway", "primary"); + tlb.add_tag("bridge", "true"); + }); + + REQUIRE(osmium::item_type::tag_list == tl.type()); + REQUIRE(2 == tl.size()); + REQUIRE(std::string("bridge") == std::next(tl.begin(), 1)->key()); + REQUIRE(std::string("true") == std::next(tl.begin(), 1)->value()); +} + +SECTION("returns_value_by_key") { + osmium::memory::Buffer buffer(10240); + + const osmium::TagList& tl = osmium::builder::build_tag_list_from_func(buffer, [](osmium::builder::TagListBuilder& tlb) { + tlb.add_tag("highway", "primary"); + tlb.add_tag("bridge", "true"); + }); + + REQUIRE(std::string("primary") == tl.get_value_by_key("highway")); + REQUIRE(nullptr == tl.get_value_by_key("name")); + REQUIRE(std::string("foo") == tl.get_value_by_key("name", "foo")); + + REQUIRE(std::string("true") == tl["bridge"]); +} + +} diff --git a/test/t/util/test_double.cpp b/test/t/util/test_double.cpp new file mode 100644 index 000000000..79e8509b0 --- /dev/null +++ b/test/t/util/test_double.cpp @@ -0,0 +1,33 @@ +#include "catch.hpp" + +#include + +TEST_CASE("Double") { + +SECTION("double2string") { + std::string s1; + osmium::util::double2string(s1, 1.123, 7); + REQUIRE(s1 == "1.123"); + + std::string s2; + osmium::util::double2string(s2, 1.000, 7); + REQUIRE(s2 == "1"); + + std::string s3; + osmium::util::double2string(s3, 0.0, 7); + REQUIRE(s3 == "0"); + + std::string s4; + osmium::util::double2string(s4, 0.020, 7); + REQUIRE(s4 == "0.02"); + + std::string s5; + osmium::util::double2string(s5, -0.020, 7); + REQUIRE(s5 == "-0.02"); + + std::string s6; + osmium::util::double2string(s6, -0.0, 7); + REQUIRE(s6 == "-0"); +} +} + diff --git a/test/t/util/test_options.cpp b/test/t/util/test_options.cpp new file mode 100644 index 000000000..203b9db48 --- /dev/null +++ b/test/t/util/test_options.cpp @@ -0,0 +1,48 @@ +#include "catch.hpp" + +#include + +#include + +TEST_CASE("Options") { + +SECTION("set_simple") { + osmium::util::Options o; + o.set("foo", "bar"); + REQUIRE("bar" == o.get("foo")); + REQUIRE("" == o.get("empty")); + REQUIRE("default" == o.get("empty", "default")); + REQUIRE(!o.is_true("foo")); + REQUIRE(!o.is_true("empty")); + REQUIRE(1 == o.size()); +} + +SECTION("set_from_bool") { + osmium::util::Options o; + o.set("t", true); + o.set("f", false); + REQUIRE("true" == o.get("t")); + REQUIRE("false" == o.get("f")); + REQUIRE("" == o.get("empty")); + REQUIRE(o.is_true("t")); + REQUIRE(!o.is_true("f")); + REQUIRE(2 == o.size()); +} + +SECTION("set_from_single_string_with_equals") { + osmium::util::Options o; + o.set("foo=bar"); + REQUIRE("bar" == o.get("foo")); + REQUIRE(1 == o.size()); +} + +SECTION("set_from_single_string_without_equals") { + osmium::util::Options o; + o.set("foo"); + REQUIRE("true" == o.get("foo")); + REQUIRE(o.is_true("foo")); + REQUIRE(1 == o.size()); +} + +} + diff --git a/test/t/util/test_string.cpp b/test/t/util/test_string.cpp new file mode 100644 index 000000000..c7b75cf24 --- /dev/null +++ b/test/t/util/test_string.cpp @@ -0,0 +1,57 @@ +#include "catch.hpp" + +#include + +TEST_CASE("split_string") { + +SECTION("split_string string") { + std::string str { "foo,baramba,baz" }; + std::vector result = {"foo", "baramba", "baz"}; + + REQUIRE(result == osmium::split_string(str, ',')); +} + +SECTION("split_string string without sep") { + std::string str { "foo" }; + std::vector result = {"foo"}; + + REQUIRE(result == osmium::split_string(str, ',')); +} + +SECTION("split_string string with empty at end") { + std::string str { "foo,bar," }; + std::vector result = {"foo", "bar", ""}; + + REQUIRE(result == osmium::split_string(str, ',')); +} + +SECTION("split_string string with empty in middle") { + std::string str { "foo,,bar" }; + std::vector result = {"foo", "", "bar"}; + + REQUIRE(result == osmium::split_string(str, ',')); +} + +SECTION("split_string string with empty at start") { + std::string str { ",bar,baz" }; + std::vector result = {"", "bar", "baz"}; + + REQUIRE(result == osmium::split_string(str, ',')); +} + +SECTION("split_string sep") { + std::string str { "," }; + std::vector result = {"", ""}; + + REQUIRE(result == osmium::split_string(str, ',')); +} + +SECTION("split_string empty string") { + std::string str { "" }; + std::vector result; + + REQUIRE(result == osmium::split_string(str, ',')); +} + +} + diff --git a/test/test_main.cpp b/test/test_main.cpp new file mode 100644 index 000000000..0c7c351f4 --- /dev/null +++ b/test/test_main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include "catch.hpp" diff --git a/test/valgrind.supp b/test/valgrind.supp new file mode 100644 index 000000000..aa5024a82 --- /dev/null +++ b/test/valgrind.supp @@ -0,0 +1,38 @@ +{ + dl_error1 + Memcheck:Cond + fun:index + fun:expand_dynamic_string_token + fun:fillin_rpath + fun:_dl_init_paths + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start +} +{ + dl_error2 + Memcheck:Cond + fun:index + fun:expand_dynamic_string_token + fun:_dl_map_object + fun:map_doit + fun:_dl_catch_error + fun:do_preload + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start +} +{ + libpoppler_leak + Memcheck:Leak + fun:malloc + fun:gmalloc + fun:copyString +} +{ + tmpfile + Memcheck:Leak + fun:malloc + fun:fdopen@@GLIBC_* + fun:tmpfile@@GLIBC_* +} From f5caf96d2e46fed48a4a3b8191fcaf8ca9dc3a14 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 13 Jan 2015 17:14:54 +0100 Subject: [PATCH 044/360] add new include dir of libosmium --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b5bd1779e..c643dc9e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,7 @@ OPTION(WITH_TOOLS "Build OSRM tools" OFF) OPTION(BUILD_TOOLS "Build OSRM tools" OFF) include_directories(${CMAKE_SOURCE_DIR}/Include/) -include_directories(${CMAKE_SOURCE_DIR}/third_party/) +include_directories(${CMAKE_SOURCE_DIR}/third_party/libosmium/include/) add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/fingerprint.cpp fingerprint.cpp.alwaysbuild COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR} From 201afbbeec5ac20182d8074eaa3505c86d6d0939 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 14 Jan 2015 09:32:43 +0100 Subject: [PATCH 045/360] rm hard copy of variant. --- Include/variant/optional.hpp | 69 --- Include/variant/recursive_wrapper.hpp | 127 ----- Include/variant/variant.hpp | 740 -------------------------- 3 files changed, 936 deletions(-) delete mode 100644 Include/variant/optional.hpp delete mode 100644 Include/variant/recursive_wrapper.hpp delete mode 100644 Include/variant/variant.hpp diff --git a/Include/variant/optional.hpp b/Include/variant/optional.hpp deleted file mode 100644 index 133e2c8f9..000000000 --- a/Include/variant/optional.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef MAPBOX_UTIL_OPTIONAL_HPP -#define MAPBOX_UTIL_OPTIONAL_HPP - -#include - -#include "variant.hpp" - -namespace mapbox -{ -namespace util -{ - -template class optional -{ - static_assert(!std::is_reference::value, "optional doesn't support references"); - - struct none_type - { - }; - - variant variant_; - - public: - optional() = default; - - optional(optional const &rhs) - { - if (this != &rhs) - { // protect against invalid self-assignment - variant_ = rhs.variant_; - } - } - - optional(T const &v) { variant_ = v; } - - explicit operator bool() const noexcept { return variant_.template is(); } - - T const &get() const { return variant_.template get(); } - T &get() { return variant_.template get(); } - - T const &operator*() const { return this->get(); } - T operator*() { return this->get(); } - - optional &operator=(T const &v) - { - variant_ = v; - return *this; - } - - optional &operator=(optional const &rhs) - { - if (this != &rhs) - { - variant_ = rhs.variant_; - } - return *this; - } - - template void emplace(Args &&... args) - { - variant_ = T{std::forward(args)...}; - } - - void reset() { variant_ = none_type{}; } -}; -} -} - -#endif diff --git a/Include/variant/recursive_wrapper.hpp b/Include/variant/recursive_wrapper.hpp deleted file mode 100644 index 54b27634a..000000000 --- a/Include/variant/recursive_wrapper.hpp +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP -#define MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP - -#include - -namespace mapbox { namespace util { - -template -class recursive_wrapper -{ -public: - using type = T; -private: - - T* p_; - -public: - - ~recursive_wrapper(); - recursive_wrapper(); - - recursive_wrapper(recursive_wrapper const& operand); - recursive_wrapper(T const& operand); - recursive_wrapper(recursive_wrapper&& operand); - recursive_wrapper(T&& operand); - -private: - - void assign(const T& rhs); - -public: - - inline recursive_wrapper& operator=(recursive_wrapper const& rhs) - { - assign( rhs.get() ); - return *this; - } - - inline recursive_wrapper& operator=(T const& rhs) - { - assign( rhs ); - return *this; - } - - inline void swap(recursive_wrapper& operand) noexcept - { - T* temp = operand.p_; - operand.p_ = p_; - p_ = temp; - } - - - recursive_wrapper& operator=(recursive_wrapper&& rhs) noexcept - { - swap(rhs); - return *this; - } - - recursive_wrapper& operator=(T&& rhs) - { - get() = std::move(rhs); - return *this; - } - - -public: - - T& get() { return *get_pointer(); } - const T& get() const { return *get_pointer(); } - T* get_pointer() { return p_; } - const T* get_pointer() const { return p_; } - operator T const&() const { return this->get(); } - operator T&() { return this->get(); } -}; - -template -recursive_wrapper::~recursive_wrapper() -{ - delete p_; -} - -template -recursive_wrapper::recursive_wrapper() - : p_(new T) -{ -} - -template -recursive_wrapper::recursive_wrapper(recursive_wrapper const& operand) - : p_(new T( operand.get() )) -{ -} - -template -recursive_wrapper::recursive_wrapper(T const& operand) - : p_(new T(operand)) -{ -} - -template -recursive_wrapper::recursive_wrapper(recursive_wrapper&& operand) - : p_(operand.p_) -{ - operand.p_ = nullptr; -} - -template -recursive_wrapper::recursive_wrapper(T&& operand) - : p_(new T( std::move(operand) )) -{ -} - -template -void recursive_wrapper::assign(const T& rhs) -{ - this->get() = rhs; -} - -template -inline void swap(recursive_wrapper& lhs, recursive_wrapper& rhs) noexcept -{ - lhs.swap(rhs); -} - -}} - -#endif // MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP diff --git a/Include/variant/variant.hpp b/Include/variant/variant.hpp deleted file mode 100644 index 3b5659425..000000000 --- a/Include/variant/variant.hpp +++ /dev/null @@ -1,740 +0,0 @@ -#ifndef MAPBOX_UTIL_VARIANT_HPP -#define MAPBOX_UTIL_VARIANT_HPP - -#include -#include -#include -#include // runtime_error -#include // operator new -#include // size_t -#include -#include - -#include "recursive_wrapper.hpp" - -#ifdef _MSC_VER - // http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx - #ifdef NDEBUG - #define VARIANT_INLINE __forceinline - #else - #define VARIANT_INLINE __declspec(noinline) - #endif -#else - #ifdef NDEBUG - #define VARIANT_INLINE inline __attribute__((always_inline)) - #else - #define VARIANT_INLINE __attribute__((noinline)) - #endif -#endif - -#define VARIANT_MAJOR_VERSION 0 -#define VARIANT_MINOR_VERSION 1 -#define VARIANT_PATCH_VERSION 0 - -// translates to 100 -#define VARIANT_VERSION (VARIANT_MAJOR_VERSION*100000) + (VARIANT_MINOR_VERSION*100) + (VARIANT_PATCH_VERSION) - -namespace mapbox { namespace util { namespace detail { - -static constexpr std::size_t invalid_value = std::size_t(-1); - -template -struct direct_type; - -template -struct direct_type -{ - static constexpr std::size_t index = std::is_same::value - ? sizeof...(Types) : direct_type::index; -}; - -template -struct direct_type -{ - static constexpr std::size_t index = invalid_value; -}; - -template -struct convertible_type; - -template -struct convertible_type -{ - static constexpr std::size_t index = std::is_convertible::value - ? sizeof...(Types) : convertible_type::index; -}; - -template -struct convertible_type -{ - static constexpr std::size_t index = invalid_value; -}; - -template -struct value_traits -{ - static constexpr std::size_t direct_index = direct_type::index; - static constexpr std::size_t index = - (direct_index == invalid_value) ? convertible_type::index : direct_index; -}; - -template -struct is_valid_type; - -template -struct is_valid_type -{ - static constexpr bool value = std::is_convertible::value - || is_valid_type::value; -}; - -template -struct is_valid_type : std::false_type {}; - -template -struct select_type -{ - static_assert(N < sizeof...(Types), "index out of bounds"); -}; - -template -struct select_type -{ - using type = typename select_type::type; -}; - -template -struct select_type<0, T, Types...> -{ - using type = T; -}; - -} // namespace detail - -// static visitor -template -struct static_visitor -{ - using result_type = R; -protected: - static_visitor() {} - ~static_visitor() {} -}; - - -template -struct static_max; - -template -struct static_max -{ - static const std::size_t value = arg; -}; - -template -struct static_max -{ - static const std::size_t value = arg1 >= arg2 ? static_max::value : - static_max::value; -}; - -template -struct variant_helper; - -template -struct variant_helper -{ - VARIANT_INLINE static void destroy(const std::size_t id, void * data) - { - if (id == sizeof...(Types)) - { - reinterpret_cast(data)->~T(); - } - else - { - variant_helper::destroy(id, data); - } - } - - VARIANT_INLINE static void move(const std::size_t old_id, void * old_value, void * new_value) - { - if (old_id == sizeof...(Types)) - { - new (new_value) T(std::move(*reinterpret_cast(old_value))); - //std::memcpy(new_value, old_value, sizeof(T)); - // ^^ DANGER: this should only be considered for relocatable types e.g built-in types - // Also, I don't see any measurable performance benefit just yet - } - else - { - variant_helper::move(old_id, old_value, new_value); - } - } - - VARIANT_INLINE static void copy(const std::size_t old_id, const void * old_value, void * new_value) - { - if (old_id == sizeof...(Types)) - { - new (new_value) T(*reinterpret_cast(old_value)); - } - else - { - variant_helper::copy(old_id, old_value, new_value); - } - } -}; - -template<> struct variant_helper<> -{ - VARIANT_INLINE static void destroy(const std::size_t, void *) {} - VARIANT_INLINE static void move(const std::size_t, void *, void *) {} - VARIANT_INLINE static void copy(const std::size_t, const void *, void *) {} -}; - -namespace detail { - -template -struct unwrapper -{ - T const& operator() (T const& obj) const - { - return obj; - } - - T& operator() (T & obj) const - { - return obj; - } -}; - - -template -struct unwrapper> -{ - auto operator() (recursive_wrapper const& obj) const - -> typename recursive_wrapper::type const& - { - return obj.get(); - } -}; - - -template -struct dispatcher; - -template -struct dispatcher -{ - using result_type = typename F::result_type; - VARIANT_INLINE static result_type apply_const(V const& v, F f) - { - if (v.get_type_index() == sizeof...(Types)) - { - return f(unwrapper()(v. template get())); - } - else - { - return dispatcher::apply_const(v, f); - } - } - - VARIANT_INLINE static result_type apply(V & v, F f) - { - if (v.get_type_index() == sizeof...(Types)) - { - return f(unwrapper()(v. template get())); - } - else - { - return dispatcher::apply(v, f); - } - } -}; - -template -struct dispatcher -{ - using result_type = typename F::result_type; - VARIANT_INLINE static result_type apply_const(V const&, F) - { - throw std::runtime_error(std::string("unary dispatch: FAIL ") + typeid(V).name()); - } - - VARIANT_INLINE static result_type apply(V &, F) - { - throw std::runtime_error(std::string("unary dispatch: FAIL ") + typeid(V).name()); - } -}; - - -template -struct binary_dispatcher_rhs; - -template -struct binary_dispatcher_rhs -{ - using result_type = typename F::result_type; - VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f) - { - if (rhs.get_type_index() == sizeof...(Types)) // call binary functor - { - return f(unwrapper()(lhs. template get()), - unwrapper()(rhs. template get())); - } - else - { - return binary_dispatcher_rhs::apply_const(lhs, rhs, f); - } - } - - VARIANT_INLINE static result_type apply(V & lhs, V & rhs, F f) - { - if (rhs.get_type_index() == sizeof...(Types)) // call binary functor - { - return f(unwrapper()(lhs. template get()), - unwrapper()(rhs. template get())); - } - else - { - return binary_dispatcher_rhs::apply(lhs, rhs, f); - } - } - -}; - -template -struct binary_dispatcher_rhs -{ - using result_type = typename F::result_type; - VARIANT_INLINE static result_type apply_const(V const&, V const&, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } - VARIANT_INLINE static result_type apply(V &, V &, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } -}; - - -template -struct binary_dispatcher_lhs; - -template -struct binary_dispatcher_lhs -{ - using result_type = typename F::result_type; - VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f) - { - if (lhs.get_type_index() == sizeof...(Types)) // call binary functor - { - return f(lhs. template get(), rhs. template get()); - } - else - { - return binary_dispatcher_lhs::apply_const(lhs, rhs, f); - } - } - - VARIANT_INLINE static result_type apply(V & lhs, V & rhs, F f) - { - if (lhs.get_type_index() == sizeof...(Types)) // call binary functor - { - return f(lhs. template get(), rhs. template get()); - } - else - { - return binary_dispatcher_lhs::apply(lhs, rhs, f); - } - } - -}; - -template -struct binary_dispatcher_lhs -{ - using result_type = typename F::result_type; - VARIANT_INLINE static result_type apply_const(V const&, V const&, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } - - VARIANT_INLINE static result_type apply(V &, V &, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } -}; - -template -struct binary_dispatcher; - -template -struct binary_dispatcher -{ - using result_type = typename F::result_type; - VARIANT_INLINE static result_type apply_const(V const& v0, V const& v1, F f) - { - if (v0.get_type_index() == sizeof...(Types)) - { - if (v0.get_type_index() == v1.get_type_index()) - { - return f(v0. template get(), v1. template get()); // call binary functor - } - else - { - return binary_dispatcher_rhs::apply_const(v0, v1, f); - } - } - else if (v1.get_type_index() == sizeof...(Types)) - { - return binary_dispatcher_lhs::apply_const(v0, v1, f); - } - return binary_dispatcher::apply_const(v0, v1, f); - } - - VARIANT_INLINE static result_type apply(V & v0, V & v1, F f) - { - if (v0.get_type_index() == sizeof...(Types)) - { - if (v0.get_type_index() == v1.get_type_index()) - { - return f(v0. template get(), v1. template get()); // call binary functor - } - else - { - return binary_dispatcher_rhs::apply(v0, v1, f); - } - } - else if (v1.get_type_index() == sizeof...(Types)) - { - return binary_dispatcher_lhs::apply(v0, v1, f); - } - return binary_dispatcher::apply(v0, v1, f); - } -}; - -template -struct binary_dispatcher -{ - using result_type = typename F::result_type; - VARIANT_INLINE static result_type apply_const(V const&, V const&, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } - - VARIANT_INLINE static result_type apply(V &, V &, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } -}; - -// comparator functors -struct equal_comp -{ - template - bool operator()(T const& lhs, T const& rhs) const - { - return lhs == rhs; - } -}; - -struct less_comp -{ - template - bool operator()(T const& lhs, T const& rhs) const - { - return lhs < rhs; - } -}; - -template -class comparer : public static_visitor -{ -public: - explicit comparer(Variant const& lhs) noexcept - : lhs_(lhs) {} - comparer& operator=(comparer const&) = delete; - // visitor - template - bool operator()(T const& rhs_content) const - { - T const& lhs_content = lhs_.template get(); - return Comp()(lhs_content, rhs_content); - } -private: - Variant const& lhs_; -}; - -// operator<< helper -template -class printer : public static_visitor<> -{ -public: - explicit printer(Out & out) - : out_(out) {} - printer& operator=(printer const&) = delete; - -// visitor - template - void operator()(T const& operand) const - { - out_ << operand; - } -private: - Out & out_; -}; - -} // namespace detail - -struct no_init {}; - -template -class variant -{ -private: - - static const std::size_t data_size = static_max::value; - static const std::size_t data_align = static_max::value; - - using data_type = typename std::aligned_storage::type; - using helper_type = variant_helper; - - std::size_t type_index; - data_type data; - -public: - - - VARIANT_INLINE variant() - : type_index(sizeof...(Types) - 1) - { - new (&data) typename detail::select_type<0, Types...>::type(); - } - - VARIANT_INLINE variant(no_init) - : type_index(detail::invalid_value) {} - - // http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers - template ::type, Types...>::value>::type> - VARIANT_INLINE variant(T && val) noexcept - : type_index(detail::value_traits::type, Types...>::index) - { - constexpr std::size_t index = sizeof...(Types) - detail::value_traits::type, Types...>::index - 1; - using target_type = typename detail::select_type::type; - new (&data) target_type(std::forward(val)); // nothrow - } - - VARIANT_INLINE variant(variant const& old) - : type_index(old.type_index) - { - helper_type::copy(old.type_index, &old.data, &data); - } - - VARIANT_INLINE variant(variant&& old) noexcept - : type_index(old.type_index) - { - helper_type::move(old.type_index, &old.data, &data); - } - - friend void swap(variant & first, variant & second) - { - using std::swap; //enable ADL - swap(first.type_index, second.type_index); - swap(first.data, second.data); - } - - VARIANT_INLINE variant& operator=(variant other) - { - swap(*this, other); - return *this; - } - - // conversions - // move-assign - template - VARIANT_INLINE variant& operator=(T && rhs) noexcept - { - variant temp(std::forward(rhs)); - swap(*this, temp); - return *this; - } - - // copy-assign - template - VARIANT_INLINE variant& operator=(T const& rhs) - { - variant temp(rhs); - swap(*this, temp); - return *this; - } - - template - VARIANT_INLINE bool is() const - { - return (type_index == detail::direct_type::index); - } - - VARIANT_INLINE bool valid() const - { - return (type_index != detail::invalid_value); - } - - template - VARIANT_INLINE void set(Args&&... args) - { - helper_type::destroy(type_index, &data); - new (&data) T(std::forward(args)...); - type_index = detail::direct_type::index; - } - - template - VARIANT_INLINE T& get() - { - if (type_index == detail::direct_type::index) - { - return *reinterpret_cast(&data); - } - else - { - throw std::runtime_error("in get()"); - } - } - - template - VARIANT_INLINE T const& get() const - { - if (type_index == detail::direct_type::index) - { - return *reinterpret_cast(&data); - } - else - { - throw std::runtime_error("in get()"); - } - } - - VARIANT_INLINE std::size_t get_type_index() const - { - return type_index; - } - - // visitor - // unary - template - auto VARIANT_INLINE - static visit(V const& v, F f) - -> decltype(detail::dispatcher::apply_const(v, f)) - { - return detail::dispatcher::apply_const(v, f); - } - // non-const - template - auto VARIANT_INLINE - static visit(V & v, F f) - -> decltype(detail::dispatcher::apply(v, f)) - { - return detail::dispatcher::apply(v, f); - } - - // binary - // const - template - auto VARIANT_INLINE - static binary_visit(V const& v0, V const& v1, F f) - -> decltype(detail::binary_dispatcher::apply_const(v0, v1, f)) - { - return detail::binary_dispatcher::apply_const(v0, v1, f); - } - // non-const - template - auto VARIANT_INLINE - static binary_visit(V& v0, V& v1, F f) - -> decltype(detail::binary_dispatcher::apply(v0, v1, f)) - { - return detail::binary_dispatcher::apply(v0, v1, f); - } - - ~variant() noexcept - { - helper_type::destroy(type_index, &data); - } - - // comparison operators - // equality - VARIANT_INLINE bool operator==(variant const& rhs) const - { - if (this->get_type_index() != rhs.get_type_index()) - return false; - detail::comparer visitor(*this); - return visit(rhs, visitor); - } - // less than - VARIANT_INLINE bool operator<(variant const& rhs) const - { - if (this->get_type_index() != rhs.get_type_index()) - { - return this->get_type_index() < rhs.get_type_index(); - // ^^ borrowed from boost::variant - } - detail::comparer visitor(*this); - return visit(rhs, visitor); - } -}; - -// unary visitor interface - -// const -template -auto VARIANT_INLINE static apply_visitor(F f, V const& v) -> decltype(V::visit(v, f)) -{ - return V::visit(v, f); -} -// non-const -template -auto VARIANT_INLINE static apply_visitor(F f, V & v) -> decltype(V::visit(v, f)) -{ - return V::visit(v, f); -} - -// binary visitor interface -// const -template -auto VARIANT_INLINE static apply_visitor(F f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, f)) -{ - return V::binary_visit(v0, v1, f); -} -// non-const -template -auto VARIANT_INLINE static apply_visitor(F f, V & v0, V & v1) -> decltype(V::binary_visit(v0, v1, f)) -{ - return V::binary_visit(v0, v1, f); -} - -// getter interface -template -ResultType & get(T & var) -{ - return var.template get(); -} - -template -ResultType const& get(T const& var) -{ - return var.template get(); -} - - -// operator<< -template -VARIANT_INLINE std::basic_ostream& -operator<< (std::basic_ostream& out, variant const& rhs) -{ - detail::printer> visitor(out); - apply_visitor(visitor, rhs); - return out; -} - -}} - -#endif // MAPBOX_UTIL_VARIANT_HPP From b65f1d7df0b997eac085da7f5a3344a86b812916 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 14 Jan 2015 09:36:20 +0100 Subject: [PATCH 046/360] Squashed 'Include/variant/' content from commit 00ab881 git-subtree-dir: Include/variant git-subtree-split: 00ab88117ed25f78cdca2faa00beea0061271e85 --- .gitignore | 3 + .travis.yml | 22 + Jamroot | 61 + LICENSE | 25 + Makefile | 92 + README.md | 66 + appveyor.yml | 27 + common.gypi | 143 + optional.hpp | 69 + recursive_wrapper.hpp | 127 + scripts/linux.sh | 40 + scripts/osx.sh | 20 + test/bench_variant.cpp | 204 + test/binary_visitor_test.cpp | 135 + test/boost_variant_hello_world.cpp | 19 + test/catch.hpp | 8683 ++++++++++++++++++++++++++++ test/optional_unit.cpp | 82 + test/recursive_wrapper_test.cpp | 132 + test/unique_ptr_test.cpp | 128 + test/unit.cpp | 306 + test/variant_hello_world.cpp | 22 + variant.gyp | 21 + variant.hpp | 783 +++ vcbuild.bat | 8 + 24 files changed, 11218 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 Jamroot create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 appveyor.yml create mode 100644 common.gypi create mode 100644 optional.hpp create mode 100644 recursive_wrapper.hpp create mode 100644 scripts/linux.sh create mode 100644 scripts/osx.sh create mode 100644 test/bench_variant.cpp create mode 100644 test/binary_visitor_test.cpp create mode 100644 test/boost_variant_hello_world.cpp create mode 100644 test/catch.hpp create mode 100644 test/optional_unit.cpp create mode 100644 test/recursive_wrapper_test.cpp create mode 100644 test/unique_ptr_test.cpp create mode 100644 test/unit.cpp create mode 100644 test/variant_hello_world.cpp create mode 100644 variant.gyp create mode 100644 variant.hpp create mode 100644 vcbuild.bat diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..5620e5dd1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +out +profiling \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..cd1e65578 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,22 @@ +language: cpp + +# http://docs.travis-ci.com/user/multi-os/ +os: + - linux + - osx + +compiler: + - clang + - gcc + +before_install: + - true + +install: + - true + +before_script: + - true + +script: + - source "scripts/${TRAVIS_OS_NAME}.sh" diff --git a/Jamroot b/Jamroot new file mode 100644 index 000000000..abf312b9c --- /dev/null +++ b/Jamroot @@ -0,0 +1,61 @@ +local BOOST_DIR = "/opt/boost" ; + +#using clang : : ; + +lib system : : boost_system $(BOOST_DIR)/lib ; +lib timer : chrono : boost_timer $(BOOST_DIR)/lib ; +lib chrono : system : boost_chrono $(BOOST_DIR)/lib ; + +exe variant-test + : + test/bench_variant.cpp + .//system + .//timer + .//chrono + : + $(BOOST_DIR)/include + ./ + -std=c++11 + #SINGLE_THREADED + release:-march=native + ; + + +exe binary-visitor-test + : + test/binary_visitor_test.cpp + .//system + .//timer + .//chrono + : + $(BOOST_DIR)/include + ./ + -std=c++11 + release:-march=native + ; + +exe recursive-wrapper-test + : + test/recursive_wrapper_test.cpp + .//system + .//timer + .//chrono + : + $(BOOST_DIR)/include + ./ + -std=c++11 + release:-march=native + ; + +exe unique-ptr-test + : + test/unique_ptr_test.cpp + .//system + .//timer + .//chrono + : + $(BOOST_DIR)/include + ./ + -std=c++11 + release:-march=native + ; diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..6c4ce40d5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) MapBox +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. +- Neither the name "MapBox" nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..0eb20b628 --- /dev/null +++ b/Makefile @@ -0,0 +1,92 @@ +CXX := $(CXX) +BOOST_LIBS = -lboost_timer -lboost_system -lboost_chrono +RELEASE_FLAGS = -O3 -DNDEBUG -finline-functions -march=native -DSINGLE_THREADED +DEBUG_FLAGS = -O0 -g -DDEBUG -fno-inline-functions +COMMON_FLAGS = -Wall -Wsign-compare -Wsign-conversion -Wshadow -Wunused-parameter -pedantic -fvisibility-inlines-hidden -std=c++11 +CXXFLAGS := $(CXXFLAGS) +LDFLAGS := $(LDFLAGS) + +OS:=$(shell uname -s) +ifeq ($(OS),Darwin) + CXXFLAGS += -stdlib=libc++ + LDFLAGS += -stdlib=libc++ -F/ -framework CoreFoundation +else + BOOST_LIBS += -lrt +endif + +ifeq (sizes,$(firstword $(MAKECMDGOALS))) + RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) + $(eval $(RUN_ARGS):;@:) + ifndef RUN_ARGS + $(error sizes target requires you pass full path to boost variant.hpp) + endif + .PHONY: $(RUN_ARGS) +endif + +all: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test + +./deps/gyp: + git clone --depth 1 https://chromium.googlesource.com/external/gyp.git ./deps/gyp + +gyp: ./deps/gyp + deps/gyp/gyp --depth=. -Goutput_dir=./ --generator-output=./out -f make + make V=1 -C ./out tests + ./out/Release/tests + +out/bench-variant-debug: Makefile test/bench_variant.cpp variant.hpp + mkdir -p ./out + $(CXX) -o out/bench-variant-debug test/bench_variant.cpp -I./ $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) + +out/bench-variant: Makefile test/bench_variant.cpp variant.hpp + mkdir -p ./out + $(CXX) -o out/bench-variant test/bench_variant.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) + +out/unique_ptr_test: Makefile test/unique_ptr_test.cpp variant.hpp + mkdir -p ./out + $(CXX) -o out/unique_ptr_test test/unique_ptr_test.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) + +out/recursive_wrapper_test: Makefile test/recursive_wrapper_test.cpp variant.hpp + mkdir -p ./out + $(CXX) -o out/recursive_wrapper_test test/recursive_wrapper_test.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) + +out/binary_visitor_test: Makefile test/binary_visitor_test.cpp variant.hpp + mkdir -p ./out + $(CXX) -o out/binary_visitor_test test/binary_visitor_test.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) + +bench: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test + ./out/bench-variant 100000 + ./out/unique_ptr_test 100000 + ./out/recursive_wrapper_test 100000 + ./out/binary_visitor_test 100000 + +out/unit: Makefile test/unit.cpp test/optional_unit.cpp optional.hpp variant.hpp + mkdir -p ./out + $(CXX) -o out/unit test/unit.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) + $(CXX) -o out/optional_unit test/optional_unit.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) + +test: out/unit + ./out/unit + ./out/optional_unit + +sizes: Makefile variant.hpp + mkdir -p ./out + @$(CXX) -o ./out/variant_hello_world.out variant.hpp $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/variant_hello_world.out + @$(CXX) -o ./out/boost_variant_hello_world.out $(RUN_ARGS) $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/boost_variant_hello_world.out + @$(CXX) -o ./out/variant_hello_world ./test/variant_hello_world.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/variant_hello_world + @$(CXX) -o ./out/boost_variant_hello_world ./test/boost_variant_hello_world.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/boost_variant_hello_world + +profile: out/bench-variant-debug + mkdir -p profiling/ + rm -rf profiling/* + iprofiler -timeprofiler -d profiling/ ./out/bench-variant-debug 500000 + +clean: + rm -rf ./out + rm -rf *.dSYM + +pgo: out Makefile variant.hpp + $(CXX) -o out/bench-variant test/bench_variant.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) -pg -fprofile-generate + ./test-variant 500000 >/dev/null 2>/dev/null + $(CXX) -o out/bench-variant test/bench_variant.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) -fprofile-use + +.PHONY: sizes test diff --git a/README.md b/README.md new file mode 100644 index 000000000..018163c1c --- /dev/null +++ b/README.md @@ -0,0 +1,66 @@ +# Mapbox Variant + +An alternative to `boost::variant` for C++11. + +[![Build Status](https://secure.travis-ci.org/mapbox/variant.svg)](https://travis-ci.org/mapbox/variant) +[![Build status](https://ci.appveyor.com/api/projects/status/v9tatx21j1k0fcgy)](https://ci.appveyor.com/project/Mapbox/variant) + +# Why use Mapbox Variant? + +Mapbox variant has the same speedy performance of `boost::variant` but is faster to compile, results in smaller binaries, and has no dependencies. + +For example on OS X 10.9 with clang++ and libc++: + +Test | Mapbox Variant | Boost Variant +---- | -------------- | ------------- +Size of pre-compiled header (release / debug) | 2.8/2.8 MB | 12/15 MB +Size of simple program linking variant (release / debug) | 8/24 K | 12/40 K +Time to compile header | 185 ms | 675 ms + + +# Depends + + - Compiler supporting `-std=c++11` + +Tested with + + - g++-4.7 + - g++-4.8 + - clang++-3.4 + - clang++-3.5 + - Visual C++ Compiler November 2013 CTP + - Visual C++ Compiler 2014 CTP 4 + +Note: get the "2013 Nov CTP" release at http://www.microsoft.com/en-us/download/details.aspx?id=41151 and the 2014 CTP at http://www.visualstudio.com/en-us/downloads/visual-studio-14-ctp-vs.aspx + +# Usage + +There is nothing to build, just include `variant.hpp` and `recursive_wrapper.hpp` in your project. + +# Tests + +The tests depend on: + + - Boost headers (for benchmarking against `boost::variant`) + - Boost built with `--with-timer` (used for benchmark timing) + +On Unix systems set your boost includes and libs locations and run `make test`: + + export LDFLAGS='-L/opt/boost/lib' + export CXXFLAGS='-I/opt/boost/include' + make test + +On windows do: + + vcbuild + +## Benchmark + +On Unix systems run the benchmark like: + + make bench + +## Check object sizes + + make sizes /path/to/boost/variant.hpp + diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..9d7c59984 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,27 @@ + +platform: + - x64 + - x86 + +configuration: + - Debug + - Release + +install: + - SET PATH=c:\python27;%PATH% + - SET PATH=C:\Program Files (x86)\MSBuild\12.0\bin\;%PATH% + - git clone --quiet --depth 1 https://chromium.googlesource.com/external/gyp.git deps/gyp + # note windows requires --generator-output to be absolute + - python deps/gyp/gyp_main.py variant.gyp --depth=. -f msvs -G msvs_version=2013 + - set MSBUILD_PLATFORM=%platform% + - if "%MSBUILD_PLATFORM%" == "x86" set MSBUILD_PLATFORM=Win32 + - msbuild variant.sln /nologo /p:Configuration=%configuration%;Platform=%MSBUILD_PLATFORM% + - .\"%configuration%"\tests.exe + +build: OFF + +test: OFF + +test_script: OFF + +deploy: OFF diff --git a/common.gypi b/common.gypi new file mode 100644 index 000000000..67e333b7e --- /dev/null +++ b/common.gypi @@ -0,0 +1,143 @@ +{ + "conditions": [ + ["OS=='win'", { + "target_defaults": { + "default_configuration": "Release_x64", + "msbuild_toolset":"CTP_Nov2013", + "msvs_settings": { + "VCCLCompilerTool": { + "ExceptionHandling": 1, # /EHsc + "RuntimeTypeInfo": "true" # /GR + } + }, + "configurations": { + "Debug_Win32": { + "msvs_configuration_platform": "Win32", + "defines": [ "DEBUG","_DEBUG"], + "msvs_settings": { + "VCCLCompilerTool": { + "RuntimeLibrary": "1", # static debug /MTd + "Optimization": 0, # /Od, no optimization + "MinimalRebuild": "false", + "OmitFramePointers": "false", + "BasicRuntimeChecks": 3 # /RTC1 + } + } + }, + "Debug_x64": { + "msvs_configuration_platform": "x64", + "defines": [ "DEBUG","_DEBUG"], + "msvs_settings": { + "VCCLCompilerTool": { + "RuntimeLibrary": "1", # static debug /MTd + "Optimization": 0, # /Od, no optimization + "MinimalRebuild": "false", + "OmitFramePointers": "false", + "BasicRuntimeChecks": 3 # /RTC1 + } + } + }, + "Release_Win32": { + "msvs_configuration_platform": "Win32", + "defines": [ "NDEBUG"], + "msvs_settings": { + "VCCLCompilerTool": { + "RuntimeLibrary": 0, # static release + "Optimization": 3, # /Ox, full optimization + "FavorSizeOrSpeed": 1, # /Ot, favour speed over size + "InlineFunctionExpansion": 2, # /Ob2, inline anything eligible + "WholeProgramOptimization": "true", # /GL, whole program optimization, needed for LTCG + "OmitFramePointers": "true", + "EnableFunctionLevelLinking": "true", + "EnableIntrinsicFunctions": "true", + "AdditionalOptions": [ + "/MP", # compile across multiple CPUs + ], + "DebugInformationFormat": "0" + }, + "VCLibrarianTool": { + "AdditionalOptions": [ + "/LTCG" # link time code generation + ], + }, + "VCLinkerTool": { + "LinkTimeCodeGeneration": 1, # link-time code generation + "OptimizeReferences": 2, # /OPT:REF + "EnableCOMDATFolding": 2, # /OPT:ICF + "LinkIncremental": 1, # disable incremental linking + "GenerateDebugInformation": "false" + } + } + }, + "Release_x64": { + "msvs_configuration_platform": "x64", + "defines": [ "NDEBUG"], + "msvs_settings": { + "VCCLCompilerTool": { + "RuntimeLibrary": 0, # static release + "Optimization": 3, # /Ox, full optimization + "FavorSizeOrSpeed": 1, # /Ot, favour speed over size + "InlineFunctionExpansion": 2, # /Ob2, inline anything eligible + "WholeProgramOptimization": "true", # /GL, whole program optimization, needed for LTCG + "OmitFramePointers": "true", + "EnableFunctionLevelLinking": "true", + "EnableIntrinsicFunctions": "true", + "AdditionalOptions": [ + "/MP", # compile across multiple CPUs + ], + "DebugInformationFormat": "0" + }, + "VCLibrarianTool": { + "AdditionalOptions": [ + "/LTCG" # link time code generation + ], + }, + "VCLinkerTool": { + "LinkTimeCodeGeneration": 1, # link-time code generation + "OptimizeReferences": 2, # /OPT:REF + "EnableCOMDATFolding": 2, # /OPT:ICF + "LinkIncremental": 1, # disable incremental linking + "GenerateDebugInformation": "false" + } + } + } + } + } + }, { + "target_defaults": { + "default_configuration": "Release", + "xcode_settings": { + "CLANG_CXX_LIBRARY": "libc++", + "CLANG_CXX_LANGUAGE_STANDARD":"c++11", + "GCC_VERSION": "com.apple.compilers.llvm.clang.1_0", + }, + "cflags_cc": ["-std=c++11"], + "configurations": { + "Debug": { + "defines": [ + "DEBUG" + ], + "xcode_settings": { + "GCC_OPTIMIZATION_LEVEL": "0", + "GCC_GENERATE_DEBUGGING_SYMBOLS": "YES", + "OTHER_CPLUSPLUSFLAGS": [ "-Wall", "-Wextra", "-pedantic", "-g", "-O0" ] + } + }, + "Release": { + "defines": [ + "NDEBUG" + ], + "xcode_settings": { + "GCC_OPTIMIZATION_LEVEL": "3", + "GCC_GENERATE_DEBUGGING_SYMBOLS": "NO", + "DEAD_CODE_STRIPPING": "YES", + "GCC_INLINES_ARE_PRIVATE_EXTERN": "YES", + "OTHER_CPLUSPLUSFLAGS": [ "-Wall", "-Wextra", "-pedantic", "-O3" ] + } + } + } + } + }] + ] +} + diff --git a/optional.hpp b/optional.hpp new file mode 100644 index 000000000..133e2c8f9 --- /dev/null +++ b/optional.hpp @@ -0,0 +1,69 @@ +#ifndef MAPBOX_UTIL_OPTIONAL_HPP +#define MAPBOX_UTIL_OPTIONAL_HPP + +#include + +#include "variant.hpp" + +namespace mapbox +{ +namespace util +{ + +template class optional +{ + static_assert(!std::is_reference::value, "optional doesn't support references"); + + struct none_type + { + }; + + variant variant_; + + public: + optional() = default; + + optional(optional const &rhs) + { + if (this != &rhs) + { // protect against invalid self-assignment + variant_ = rhs.variant_; + } + } + + optional(T const &v) { variant_ = v; } + + explicit operator bool() const noexcept { return variant_.template is(); } + + T const &get() const { return variant_.template get(); } + T &get() { return variant_.template get(); } + + T const &operator*() const { return this->get(); } + T operator*() { return this->get(); } + + optional &operator=(T const &v) + { + variant_ = v; + return *this; + } + + optional &operator=(optional const &rhs) + { + if (this != &rhs) + { + variant_ = rhs.variant_; + } + return *this; + } + + template void emplace(Args &&... args) + { + variant_ = T{std::forward(args)...}; + } + + void reset() { variant_ = none_type{}; } +}; +} +} + +#endif diff --git a/recursive_wrapper.hpp b/recursive_wrapper.hpp new file mode 100644 index 000000000..54b27634a --- /dev/null +++ b/recursive_wrapper.hpp @@ -0,0 +1,127 @@ +#ifndef MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP +#define MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP + +#include + +namespace mapbox { namespace util { + +template +class recursive_wrapper +{ +public: + using type = T; +private: + + T* p_; + +public: + + ~recursive_wrapper(); + recursive_wrapper(); + + recursive_wrapper(recursive_wrapper const& operand); + recursive_wrapper(T const& operand); + recursive_wrapper(recursive_wrapper&& operand); + recursive_wrapper(T&& operand); + +private: + + void assign(const T& rhs); + +public: + + inline recursive_wrapper& operator=(recursive_wrapper const& rhs) + { + assign( rhs.get() ); + return *this; + } + + inline recursive_wrapper& operator=(T const& rhs) + { + assign( rhs ); + return *this; + } + + inline void swap(recursive_wrapper& operand) noexcept + { + T* temp = operand.p_; + operand.p_ = p_; + p_ = temp; + } + + + recursive_wrapper& operator=(recursive_wrapper&& rhs) noexcept + { + swap(rhs); + return *this; + } + + recursive_wrapper& operator=(T&& rhs) + { + get() = std::move(rhs); + return *this; + } + + +public: + + T& get() { return *get_pointer(); } + const T& get() const { return *get_pointer(); } + T* get_pointer() { return p_; } + const T* get_pointer() const { return p_; } + operator T const&() const { return this->get(); } + operator T&() { return this->get(); } +}; + +template +recursive_wrapper::~recursive_wrapper() +{ + delete p_; +} + +template +recursive_wrapper::recursive_wrapper() + : p_(new T) +{ +} + +template +recursive_wrapper::recursive_wrapper(recursive_wrapper const& operand) + : p_(new T( operand.get() )) +{ +} + +template +recursive_wrapper::recursive_wrapper(T const& operand) + : p_(new T(operand)) +{ +} + +template +recursive_wrapper::recursive_wrapper(recursive_wrapper&& operand) + : p_(operand.p_) +{ + operand.p_ = nullptr; +} + +template +recursive_wrapper::recursive_wrapper(T&& operand) + : p_(new T( std::move(operand) )) +{ +} + +template +void recursive_wrapper::assign(const T& rhs) +{ + this->get() = rhs; +} + +template +inline void swap(recursive_wrapper& lhs, recursive_wrapper& rhs) noexcept +{ + lhs.swap(rhs); +} + +}} + +#endif // MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP diff --git a/scripts/linux.sh b/scripts/linux.sh new file mode 100644 index 000000000..54215d934 --- /dev/null +++ b/scripts/linux.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +set -e -u +set -o pipefail + +# ppa for latest boost +sudo add-apt-repository -y ppa:boost-latest/ppa +# ppa for g++ 4.7 and 4.8 +sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test +sudo apt-get update -y + +# install boost headers and g++ upgrades +sudo apt-get -y -qq install boost1.55 gcc-4.8 g++-4.8 gcc-4.7 g++-4.7 + +# run tests against g++ 4.7 +export CXX="g++-4.7"; export CC="gcc-4.7" +echo 'running tests against g++ 4.7' +make test +make bench +make clean + +# run tests against g++ 4.8 +export CXX="g++-4.8"; export CC="gcc-4.8" +echo 'running tests against g++ 4.8' +make test +make bench +make clean + +# compare object sizes against boost::variant +echo 'comparing object sizes to boost::variant' +make sizes /usr/include/boost/variant.hpp +make clean + +# test building with gyp +echo 'testing build with gyp' +make gyp + +# set strictness back to normal +# to avoid tripping up travis +set +e +u diff --git a/scripts/osx.sh b/scripts/osx.sh new file mode 100644 index 000000000..14149ca04 --- /dev/null +++ b/scripts/osx.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +set -e -u +set -o pipefail + +# install boost headers +brew unlink boost +brew install boost + +# run tests +make test +make bench +make clean + +# compare object sizes against boost::variant +make sizes `brew --prefix`/include/boost/variant.hpp +make clean + +# test building with gyp +make gyp \ No newline at end of file diff --git a/test/bench_variant.cpp b/test/bench_variant.cpp new file mode 100644 index 000000000..f27124593 --- /dev/null +++ b/test/bench_variant.cpp @@ -0,0 +1,204 @@ +#include +#include +#include +#include +#include +#include +#include +#include "variant.hpp" + +#define TEXT "Testing various variant implementations with a longish string ........................................." +//#define BOOST_VARIANT_MINIMIZE_SIZE + +using namespace mapbox; + +namespace test { + +template +struct Holder +{ + typedef V value_type; + std::vector data; + + template + void append_move(T && obj) + { + data.emplace_back(std::forward(obj)); + } + + template + void append(T const& obj) + { + data.push_back(obj); + } +}; + +} // namespace test + +struct print : util::static_visitor<> +{ + template + void operator() (T const& val) const + { + std::cerr << val << ":" << typeid(T).name() << std::endl; + } +}; + + +template +struct dummy : boost::static_visitor<> +{ + dummy(V & v) + : v_(v) {} + + template + void operator() (T const& val) const + { + v_ = val; + } + V & v_; +}; + +template +struct dummy2 : util::static_visitor<> +{ + dummy2(V & v) + : v_(v) {} + + template + void operator() (T const& val) const + { + v_.template set(val); + } + V & v_; +}; + +void run_boost_test(std::size_t runs) +{ + test::Holder> h; + h.data.reserve(runs); + for (std::size_t i=0; i< runs; ++i) + { + h.append_move(std::string(TEXT)); + h.append_move(123); + h.append_move(3.14159); + } + + boost::variant v; + for (auto const& v2 : h.data) + { + dummy> d(v); + boost::apply_visitor(d, v2); + } +} + +void run_variant_test(std::size_t runs) +{ + test::Holder> h; + h.data.reserve(runs); + for (std::size_t i=0; i< runs; ++i) + { + h.append_move(std::string(TEXT)); + h.append_move(123); + h.append_move(3.14159); + } + + util::variant v; + for (auto const& v2 : h.data) + { + dummy2> d(v); + util::apply_visitor (d, v2); + } +} + +int main (int argc, char** argv) +{ + if (argc!=2) + { + std::cerr << "Usage:" << argv[0] << " " << std::endl; + return 1; + } + +#ifndef SINGLE_THREADED + const std::size_t THREADS = 4; +#endif + const std::size_t NUM_RUNS = static_cast(std::stol(argv[1])); + +#ifdef SINGLE_THREADED + { + std::cerr << "custom variant: "; + boost::timer::auto_cpu_timer t; + run_variant_test(NUM_RUNS); + } + { + std::cerr << "boost variant: "; + boost::timer::auto_cpu_timer t; + run_boost_test(NUM_RUNS); + } + { + std::cerr << "custom variant: "; + boost::timer::auto_cpu_timer t; + run_variant_test(NUM_RUNS); + } + { + std::cerr << "boost variant: "; + boost::timer::auto_cpu_timer t; + run_boost_test(NUM_RUNS); + } +#else + { + typedef std::vector> thread_group; + typedef thread_group::value_type value_type; + thread_group tg; + std::cerr << "custom variant: "; + boost::timer::auto_cpu_timer timer; + for (std::size_t i=0; ijoinable()) t->join();}); + } + + { + typedef std::vector> thread_group; + typedef thread_group::value_type value_type; + thread_group tg; + std::cerr << "boost variant: "; + boost::timer::auto_cpu_timer timer; + for (std::size_t i=0; ijoinable()) t->join();}); + } + + { + typedef std::vector> thread_group; + typedef thread_group::value_type value_type; + thread_group tg; + std::cerr << "custom variant: "; + boost::timer::auto_cpu_timer timer; + for (std::size_t i=0; ijoinable()) t->join();}); + } + + { + typedef std::vector> thread_group; + typedef thread_group::value_type value_type; + thread_group tg; + std::cerr << "boost variant: "; + boost::timer::auto_cpu_timer timer; + for (std::size_t i=0; ijoinable()) t->join();}); + } +#endif + + + return EXIT_SUCCESS; +} diff --git a/test/binary_visitor_test.cpp b/test/binary_visitor_test.cpp new file mode 100644 index 000000000..b1d3ab9f8 --- /dev/null +++ b/test/binary_visitor_test.cpp @@ -0,0 +1,135 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "variant.hpp" + +using namespace mapbox; + +namespace test { + +template +struct string_to_number {}; + +template <> +struct string_to_number +{ + double operator() (std::string const& str) const + { + return std::stod(str); + } +}; + +template <> +struct string_to_number +{ + std::int64_t operator() (std::string const& str) const + { + return std::stoll(str); + } +}; + +template <> +struct string_to_number +{ + std::uint64_t operator() (std::string const& str) const + { + return std::stoull(str); + } +}; + +template <> +struct string_to_number +{ + bool operator() (std::string const& str) const + { + bool result; + std::istringstream(str) >> std::boolalpha >> result; + return result; + } +}; + +struct javascript_equal_visitor : util::static_visitor +{ + template + bool operator() (T lhs, T rhs) const + { + return lhs == rhs; + } + + template ::value>::type> + bool operator() (T lhs, std::string const& rhs) const + { + return lhs == string_to_number()(rhs); + } + + template ::value>::type> + bool operator() (std::string const& lhs, T rhs) const + { + return string_to_number()(lhs) == rhs; + } + + template + bool operator() (T0 lhs, T1 rhs) const + { + return lhs == static_cast(rhs); + } +}; + +template +struct javascript_equal +{ + javascript_equal(T const& lhs) + : lhs_(lhs) {} + + bool operator() (T const& rhs) const + { + return util::apply_visitor(test::javascript_equal_visitor(), lhs_, rhs); + } + T const& lhs_; +}; + +} // namespace test + +int main (/*int argc, char** argv*/) +{ + typedef util::variant variant_type; + variant_type v0(3.14159); + variant_type v1(std::string("3.14159")); + variant_type v2(std::uint64_t(1)); + + std::cerr << v0 << " == " << v1 << " -> " + << std::boolalpha << util::apply_visitor(test::javascript_equal_visitor(), v0, v1) << std::endl; + + + std::vector vec; + + vec.emplace_back(std::string("1")); + vec.push_back(variant_type(std::uint64_t(2))); + vec.push_back(variant_type(std::uint64_t(3))); + vec.push_back(std::string("3.14159")); + vec.emplace_back(3.14159); + + //auto itr = std::find_if(vec.begin(), vec.end(), [&v0](variant_type const& val) { + // return util::apply_visitor(test::javascript_equal_visitor(), v0, val); + // }); + + auto itr = std::find_if(vec.begin(), vec.end(), test::javascript_equal(v2)); + + if (itr != std::end(vec)) + { + std::cout << "found " << *itr << std::endl; + } + else + { + std::cout << "can't find " << v2 << '\n'; + } + + return EXIT_SUCCESS; +} diff --git a/test/boost_variant_hello_world.cpp b/test/boost_variant_hello_world.cpp new file mode 100644 index 000000000..0d0925a7e --- /dev/null +++ b/test/boost_variant_hello_world.cpp @@ -0,0 +1,19 @@ +#include +#include +#include + +struct check : boost::static_visitor<> +{ + template + void operator() (T const& val) const + { + if (val != 0) throw std::runtime_error("invalid"); + } +}; + +int main() { + typedef boost::variant variant_type; + variant_type v(0); + boost::apply_visitor(check(), v); + return 0; +} diff --git a/test/catch.hpp b/test/catch.hpp new file mode 100644 index 000000000..057c82ee0 --- /dev/null +++ b/test/catch.hpp @@ -0,0 +1,8683 @@ +/* + * CATCH v1.0 build 45 (master branch) + * Generated: 2014-05-19 18:22:42.461908 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + +#define TWOBLUECUBES_CATCH_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wglobal-constructors" +#pragma clang diagnostic ignored "-Wvariadic-macros" +#pragma clang diagnostic ignored "-Wc99-extensions" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#pragma clang diagnostic ignored "-Wc++98-compat" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + +#ifdef CATCH_CONFIG_MAIN +# define CATCH_CONFIG_RUNNER +#endif + +#ifdef CATCH_CONFIG_RUNNER +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// #included from: internal/catch_notimplemented_exception.h +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED + +// #included from: catch_common.h +#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED + +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) + +#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr +#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) + +#include +#include +#include + +// #included from: catch_compiler_capabilities.h +#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + +// Much of the following code is based on Boost (1.53) + +#ifdef __clang__ + +# if __has_feature(cxx_nullptr) +# define CATCH_CONFIG_CPP11_NULLPTR +# endif + +# if __has_feature(cxx_noexcept) +# define CATCH_CONFIG_CPP11_NOEXCEPT +# endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Borland +#ifdef __BORLANDC__ + +#if (__BORLANDC__ > 0x582 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __BORLANDC__ + +//////////////////////////////////////////////////////////////////////////////// +// EDG +#ifdef __EDG_VERSION__ + +#if (__EDG_VERSION__ > 238 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __EDG_VERSION__ + +//////////////////////////////////////////////////////////////////////////////// +// Digital Mars +#ifdef __DMC__ + +#if (__DMC__ > 0x840 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __DMC__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +#if __GNUC__ < 3 + +#if (__GNUC_MINOR__ >= 96 ) +//#define CATCH_CONFIG_SFINAE +#endif + +#elif __GNUC__ >= 3 + +// #define CATCH_CONFIG_SFINAE // Taking this out completely for now + +#endif // __GNUC__ < 3 + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) ) + +#define CATCH_CONFIG_CPP11_NULLPTR +#endif + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1310 ) // (VC++ 7.0+) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // _MSC_VER + +// Use variadic macros if the compiler supports them +#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ + ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ + ( defined __GNUC__ && __GNUC__ >= 3 ) || \ + ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) + +#ifndef CATCH_CONFIG_NO_VARIADIC_MACROS +#define CATCH_CONFIG_VARIADIC_MACROS +#endif + +#endif + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// detect language version: +#if (__cplusplus == 201103L) +# define CATCH_CPP11 +# define CATCH_CPP11_OR_GREATER +#elif (__cplusplus >= 201103L) +# define CATCH_CPP11_OR_GREATER +#endif + +// noexcept support: +#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) +# define CATCH_NOEXCEPT noexcept +# define CATCH_NOEXCEPT_IS(x) noexcept(x) +#else +# define CATCH_NOEXCEPT throw() +# define CATCH_NOEXCEPT_IS(x) +#endif + +namespace Catch { + + class NonCopyable { + NonCopyable( NonCopyable const& ); + void operator = ( NonCopyable const& ); + protected: + NonCopyable() {} + virtual ~NonCopyable(); + }; + + class SafeBool { + public: + typedef void (SafeBool::*type)() const; + + static type makeSafe( bool value ) { + return value ? &SafeBool::trueValue : 0; + } + private: + void trueValue() const {} + }; + + template + inline void deleteAll( ContainerT& container ) { + typename ContainerT::const_iterator it = container.begin(); + typename ContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete *it; + } + template + inline void deleteAllValues( AssociativeContainerT& container ) { + typename AssociativeContainerT::const_iterator it = container.begin(); + typename AssociativeContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete it->second; + } + + bool startsWith( std::string const& s, std::string const& prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; + + struct SourceLineInfo { + + SourceLineInfo(); + SourceLineInfo( char const* _file, std::size_t _line ); + SourceLineInfo( SourceLineInfo const& other ); +# ifdef CATCH_CPP11_OR_GREATER + SourceLineInfo( SourceLineInfo && ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo& operator = ( SourceLineInfo && ) = default; +# endif + bool empty() const; + bool operator == ( SourceLineInfo const& other ) const; + + std::string file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // This is just here to avoid compiler warnings with macro constants and boolean literals + inline bool isTrue( bool value ){ return value; } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() { + return std::string(); + } + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); + +#include + +namespace Catch { + + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + + virtual ~NotImplementedException() CATCH_NOEXCEPT {} + + virtual const char* what() const CATCH_NOEXCEPT; + + private: + std::string m_what; + SourceLineInfo m_lineInfo; + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + +// #included from: internal/catch_context.h +#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED + +// #included from: catch_interfaces_generators.h +#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED + +#include + +namespace Catch { + + struct IGeneratorInfo { + virtual ~IGeneratorInfo(); + virtual bool moveNext() = 0; + virtual std::size_t getCurrentIndex() const = 0; + }; + + struct IGeneratorsForTest { + virtual ~IGeneratorsForTest(); + + virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; + virtual bool moveNext() = 0; + }; + + IGeneratorsForTest* createGeneratorsForTest(); + +} // end namespace Catch + +// #included from: catch_ptr.hpp +#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + // An intrusive reference counting smart pointer. + // T must implement addRef() and release() methods + // typically implementing the IShared interface + template + class Ptr { + public: + Ptr() : m_p( NULL ){} + Ptr( T* p ) : m_p( p ){ + if( m_p ) + m_p->addRef(); + } + Ptr( Ptr const& other ) : m_p( other.m_p ){ + if( m_p ) + m_p->addRef(); + } + ~Ptr(){ + if( m_p ) + m_p->release(); + } + void reset() { + if( m_p ) + m_p->release(); + m_p = NULL; + } + Ptr& operator = ( T* p ){ + Ptr temp( p ); + swap( temp ); + return *this; + } + Ptr& operator = ( Ptr const& other ){ + Ptr temp( other ); + swap( temp ); + return *this; + } + void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } + T* get() { return m_p; } + const T* get() const{ return m_p; } + T& operator*() const { return *m_p; } + T* operator->() const { return m_p; } + bool operator !() const { return m_p == NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); } + + private: + T* m_p; + }; + + struct IShared : NonCopyable { + virtual ~IShared(); + virtual void addRef() const = 0; + virtual void release() const = 0; + }; + + template + struct SharedImpl : T { + + SharedImpl() : m_rc( 0 ){} + + virtual void addRef() const { + ++m_rc; + } + virtual void release() const { + if( --m_rc == 0 ) + delete this; + } + + mutable unsigned int m_rc; + }; + +} // end namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#include +#include +#include + +namespace Catch { + + class TestCase; + class Stream; + struct IResultCapture; + struct IRunner; + struct IGeneratorsForTest; + struct IConfig; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture& getResultCapture() = 0; + virtual IRunner& getRunner() = 0; + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; + virtual bool advanceGeneratorsForCurrentTest() = 0; + virtual Ptr getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( Ptr const& config ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); + Stream createStream( std::string const& streamName ); + +} + +// #included from: internal/catch_test_registry.hpp +#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED + +// #included from: catch_interfaces_testcase.h +#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED + +#include + +namespace Catch { + + class TestSpec; + + struct ITestCase : IShared { + virtual void invoke () const = 0; + protected: + virtual ~ITestCase(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases ) const = 0; + + }; +} + +namespace Catch { + +template +class MethodTestCase : public SharedImpl { + +public: + MethodTestCase( void (C::*method)() ) : m_method( method ) {} + + virtual void invoke() const { + C obj; + (obj.*m_method)(); + } + +private: + virtual ~MethodTestCase() {} + + void (C::*m_method)(); +}; + +typedef void(*TestFunction)(); + +struct NameAndDesc { + NameAndDesc( const char* _name = "", const char* _description= "" ) + : name( _name ), description( _description ) + {} + + const char* name; + const char* description; +}; + +struct AutoReg { + + AutoReg( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + + template + AutoReg( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + registerTestCase( new MethodTestCase( method ), + className, + nameAndDesc, + lineInfo ); + } + + void registerTestCase( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + + ~AutoReg(); + +private: + AutoReg( AutoReg const& ); + void operator= ( AutoReg const& ); +}; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( ... ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + +#else + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + +#endif + +// #included from: internal/catch_capture.hpp +#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED + +// #included from: catch_expression_decomposer.hpp +#define TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED + +// #included from: catch_expression_lhs.hpp +#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED + +// #included from: catch_expressionresult_builder.h +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_BUILDER_H_INCLUDED + +// #included from: catch_tostring.h +#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED + +// #included from: catch_sfinae.hpp +#define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED + +// Try to detect if the current compiler supports SFINAE + +namespace Catch { + + struct TrueType { + static const bool value = true; + typedef void Enable; + char sizer[1]; + }; + struct FalseType { + static const bool value = false; + typedef void Disable; + char sizer[2]; + }; + +#ifdef CATCH_CONFIG_SFINAE + + template struct NotABooleanExpression; + + template struct If : NotABooleanExpression {}; + template<> struct If : TrueType {}; + template<> struct If : FalseType {}; + + template struct SizedIf; + template<> struct SizedIf : TrueType {}; + template<> struct SizedIf : FalseType {}; + +#endif // CATCH_CONFIG_SFINAE + +} // end namespace Catch + +#include +#include +#include +#include +#include + +#ifdef __OBJC__ +// #included from: catch_objc_arc.hpp +#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED + +#import + +#ifdef __has_feature +#define CATCH_ARC_ENABLED __has_feature(objc_arc) +#else +#define CATCH_ARC_ENABLED 0 +#endif + +void arcSafeRelease( NSObject* obj ); +id performOptionalSelector( id obj, SEL sel ); + +#if !CATCH_ARC_ENABLED +inline void arcSafeRelease( NSObject* obj ) { + [obj release]; +} +inline id performOptionalSelector( id obj, SEL sel ) { + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; + return nil; +} +#define CATCH_UNSAFE_UNRETAINED +#define CATCH_ARC_STRONG +#else +inline void arcSafeRelease( NSObject* ){} +inline id performOptionalSelector( id obj, SEL sel ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#endif + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + return nil; +} +#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained +#define CATCH_ARC_STRONG __strong +#endif + +#endif + +namespace Catch { +namespace Detail { + +// SFINAE is currently disabled by default for all compilers. +// If the non SFINAE version of IsStreamInsertable is ambiguous for you +// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE +#ifdef CATCH_CONFIG_SFINAE + + template + class IsStreamInsertableHelper { + template struct TrueIfSizeable : TrueType {}; + + template + static TrueIfSizeable dummy(T2*); + static FalseType dummy(...); + + public: + typedef SizedIf type; + }; + + template + struct IsStreamInsertable : IsStreamInsertableHelper::type {}; + +#else + + struct BorgType { + template BorgType( T const& ); + }; + + TrueType& testStreamable( std::ostream& ); + FalseType testStreamable( FalseType ); + + FalseType operator<<( std::ostream const&, BorgType const& ); + + template + struct IsStreamInsertable { + static std::ostream &s; + static T const&t; + enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; + }; + +#endif + + template + struct StringMakerBase { + template + static std::string convert( T const& ) { return "{?}"; } + }; + + template<> + struct StringMakerBase { + template + static std::string convert( T const& _value ) { + std::ostringstream oss; + oss << _value; + return oss.str(); + } + }; + + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + + // Writes the raw memory into a string, considering endianness + template + std::string rawMemoryToString( T value ) { + union _ { + T typedValue; + unsigned char bytes[sizeof(T)]; + } u; + + u.typedValue = value; + + std::ostringstream oss; + oss << "0x"; + + int i = 0, end = sizeof(T), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + for( ; i != end; i += inc ) + oss << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)u.bytes[i]; + return oss.str(); + } + +} // end namespace Detail + +template +std::string toString( T const& value ); + +template +struct StringMaker : + Detail::StringMakerBase::value> {}; + +template +struct StringMaker { + template + static std::string convert( U* p ) { + if( !p ) + return INTERNAL_CATCH_STRINGIFY( NULL ); + else + return Detail::rawMemoryToString( p ); + } +}; + +template +struct StringMaker { + static std::string convert( R C::* p ) { + if( !p ) + return INTERNAL_CATCH_STRINGIFY( NULL ); + else + return Detail::rawMemoryToString( p ); + } +}; + +namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ); +} + +template +struct StringMaker > { + static std::string convert( std::vector const& v ) { + return Detail::rangeToString( v.begin(), v.end() ); + } +}; + +namespace Detail { + template + std::string makeString( T const& value ) { + return StringMaker::convert( value ); + } +} // end namespace Detail + +/// \brief converts any type to a string +/// +/// The default template forwards on to ostringstream - except when an +/// ostringstream overload does not exist - in which case it attempts to detect +/// that and writes {?}. +/// Overload (not specialise) this template for custom typs that you don't want +/// to provide an ostream overload for. +template +std::string toString( T const& value ) { + return StringMaker::convert( value ); +} + +// Built in overloads + +std::string toString( std::string const& value ); +std::string toString( std::wstring const& value ); +std::string toString( const char* const value ); +std::string toString( char* const value ); +std::string toString( int value ); +std::string toString( unsigned long value ); +std::string toString( unsigned int value ); +std::string toString( const double value ); +std::string toString( bool value ); +std::string toString( char value ); +std::string toString( signed char value ); +std::string toString( unsigned char value ); + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ); +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); + std::string toString( NSObject* const& nsObject ); +#endif + + namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ) { + std::ostringstream oss; + oss << "{ "; + if( first != last ) { + oss << toString( *first ); + for( ++first ; first != last ; ++first ) { + oss << ", " << toString( *first ); + } + } + oss << " }"; + return oss.str(); + } +} + +} // end namespace Catch + +// #included from: catch_assertionresult.h +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED + +#include +// #included from: catch_result_type.h +#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2 + + }; }; + + inline bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + inline bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + // ResultAction::Value enum + struct ResultAction { enum Value { + None, + Failed = 1, // Failure - but no debug break if Debug bit not set + Debug = 2, // If this bit is set, invoke the debugger + Abort = 4 // Test run should abort + }; }; + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x00, + + ContinueOnFailure = 0x01, // Failures fail test, but execution continues + NegateResult = 0x02, // Prefix expressiom with ! + SuppressFail = 0x04 // Failures are reported but do not fail the test + }; }; + + inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( static_cast( lhs ) | static_cast( rhs ) ); + } + + inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } + inline bool shouldNegate( int flags ) { return ( flags & ResultDisposition::NegateResult ) != 0; } + inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + +} // end namespace Catch + + +namespace Catch { + + struct AssertionInfo + { + AssertionInfo() {} + AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ); + + std::string macroName; + SourceLineInfo lineInfo; + std::string capturedExpression; + ResultDisposition::Flags resultDisposition; + }; + + struct AssertionResultData + { + AssertionResultData() : resultType( ResultWas::Unknown ) {} + + std::string reconstructedExpression; + std::string message; + ResultWas::OfType resultType; + }; + + class AssertionResult { + public: + AssertionResult(); + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); + ~AssertionResult(); +# ifdef CATCH_CPP11_OR_GREATER + AssertionResult( AssertionResult const& ) = default; + AssertionResult( AssertionResult && ) = default; + AssertionResult& operator = ( AssertionResult const& ) = default; + AssertionResult& operator = ( AssertionResult && ) = default; +# endif + + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + std::string getMessage() const; + SourceLineInfo getSourceInfo() const; + std::string getTestMacroName() const; + + protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + +} // end namespace Catch + +// #included from: catch_evaluate.hpp +#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#endif + +#include + +namespace Catch { +namespace Internal { + + enum Operator { + IsEqualTo, + IsNotEqualTo, + IsLessThan, + IsGreaterThan, + IsLessThanOrEqualTo, + IsGreaterThanOrEqualTo + }; + + template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; + template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; + template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; + + template + inline T& opCast(T const& t) { return const_cast(t); } + +// nullptr_t support based on pull request #154 from Konstantin Baumann +#ifdef CATCH_CONFIG_CPP11_NULLPTR + inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } +#endif // CATCH_CONFIG_CPP11_NULLPTR + + // So the compare overloads can be operator agnostic we convey the operator as a template + // enum, which is used to specialise an Evaluator for doing the comparison. + template + class Evaluator{}; + + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs) { + return opCast( lhs ) == opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) != opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) < opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) > opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) >= opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) <= opCast( rhs ); + } + }; + + template + bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // This level of indirection allows us to specialise for integer types + // to avoid signed/ unsigned warnings + + // "base" overload + template + bool compare( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // unsigned X to int + template bool compare( unsigned int lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // unsigned X to long + template bool compare( unsigned int lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // int to unsigned X + template bool compare( int lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // long to unsigned X + template bool compare( long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long (when comparing against NULL) + template bool compare( long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + + // pointer to int (when comparing against NULL) + template bool compare( int lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, int rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + +#ifdef CATCH_CONFIG_CPP11_NULLPTR + // pointer to nullptr_t (when comparing against nullptr) + template bool compare( std::nullptr_t, T* rhs ) { + return Evaluator::evaluate( NULL, rhs ); + } + template bool compare( T* lhs, std::nullptr_t ) { + return Evaluator::evaluate( lhs, NULL ); + } +#endif // CATCH_CONFIG_CPP11_NULLPTR + +} // end of namespace Internal +} // end of namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +namespace Catch { + +struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; + +// Wraps the (stringised versions of) the lhs, operator and rhs of an expression - as well as +// the result of evaluating it. This is used to build an AssertionResult object +class ExpressionResultBuilder { +public: + + ExpressionResultBuilder( ResultWas::OfType resultType = ResultWas::Unknown ); + ExpressionResultBuilder( ExpressionResultBuilder const& other ); + ExpressionResultBuilder& operator=(ExpressionResultBuilder const& other ); + + ExpressionResultBuilder& setResultType( ResultWas::OfType result ); + ExpressionResultBuilder& setResultType( bool result ); + ExpressionResultBuilder& setLhs( std::string const& lhs ); + ExpressionResultBuilder& setRhs( std::string const& rhs ); + ExpressionResultBuilder& setOp( std::string const& op ); + + ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition ); + + template + ExpressionResultBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + std::string reconstructExpression( AssertionInfo const& info ) const; + + AssertionResult buildResult( AssertionInfo const& info ) const; + + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + +private: + AssertionResultData m_data; + struct ExprComponents { + ExprComponents() : shouldNegate( false ) {} + bool shouldNegate; + std::string lhs, rhs, op; + } m_exprComponents; + std::ostringstream m_stream; +}; + +} // end namespace Catch + +namespace Catch { + +// Wraps the LHS of an expression and captures the operator and RHS (if any) - +// wrapping them all in an ExpressionResultBuilder object +template +class ExpressionLhs { + ExpressionLhs& operator = ( ExpressionLhs const& ); +# ifdef CATCH_CPP11_OR_GREATER + ExpressionLhs& operator = ( ExpressionLhs && ) = delete; +# endif + +public: + ExpressionLhs( T lhs ) : m_lhs( lhs ) {} +# ifdef CATCH_CPP11_OR_GREATER + ExpressionLhs( ExpressionLhs const& ) = default; + ExpressionLhs( ExpressionLhs && ) = default; +# endif + + template + ExpressionResultBuilder& operator == ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ExpressionResultBuilder& operator != ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ExpressionResultBuilder& operator < ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ExpressionResultBuilder& operator > ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ExpressionResultBuilder& operator <= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ExpressionResultBuilder& operator >= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + ExpressionResultBuilder& operator == ( bool rhs ) { + return captureExpression( rhs ); + } + + ExpressionResultBuilder& operator != ( bool rhs ) { + return captureExpression( rhs ); + } + + ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition ) { + bool value = m_lhs ? true : false; + return m_result + .setLhs( Catch::toString( value ) ) + .setResultType( value ) + .endExpression( resultDisposition ); + } + + // Only simple binary expressions are allowed on the LHS. + // If more complex compositions are required then place the sub expression in parentheses + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + +private: + template + ExpressionResultBuilder& captureExpression( RhsT const& rhs ) { + return m_result + .setResultType( Internal::compare( m_lhs, rhs ) ) + .setLhs( Catch::toString( m_lhs ) ) + .setRhs( Catch::toString( rhs ) ) + .setOp( Internal::OperatorTraits::getName() ); + } + +private: + ExpressionResultBuilder m_result; + T m_lhs; +}; + +} // end namespace Catch + +namespace Catch { + +// Captures the LHS of the expression and wraps it in an Expression Lhs object +class ExpressionDecomposer { +public: + + template + ExpressionLhs operator->* ( T const& operand ) { + return ExpressionLhs( operand ); + } + + ExpressionLhs operator->* ( bool value ) { + return ExpressionLhs( value ); + } +}; + +} // end namespace Catch + +// #included from: catch_message.h +#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED + +#include + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + SourceLineInfo lineInfo; + ResultWas::OfType type; + std::string message; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const { + return sequence == other.sequence; + } + bool operator < ( MessageInfo const& other ) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + + struct MessageBuilder { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + : m_info( macroName, lineInfo, type ) + {} + + template + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + MessageInfo m_info; + std::ostringstream m_stream; + }; + + class ScopedMessage { + public: + ScopedMessage( MessageBuilder const& builder ); + ~ScopedMessage(); + + MessageInfo m_info; + }; + +} // end namespace Catch + +// #included from: catch_interfaces_capture.h +#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + class ExpressionResultBuilder; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct MessageInfo; + class ScopedMessageBuilder; + struct Counts; + + struct IResultCapture { + + virtual ~IResultCapture(); + + virtual void assertionEnded( AssertionResult const& result ) = 0; + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0; + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual bool shouldDebugBreak() const = 0; + + virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) = 0; + + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + }; +} + +// #included from: catch_debugger.h +#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED + +// #included from: catch_platform.h +#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED + +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_IPHONE +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CATCH_PLATFORM_WINDOWS +#endif + +#include + +namespace Catch{ + + bool isDebuggerActive(); + void writeToDebugConsole( std::string const& text ); +} + +#ifdef CATCH_PLATFORM_MAC + + // The following code snippet based on: + // http://cocoawithlove.com/2008/03/break-into-debugger.html + #ifdef DEBUG + #if defined(__ppc64__) || defined(__ppc__) + #define CATCH_BREAK_INTO_DEBUGGER() \ + if( Catch::isDebuggerActive() ) { \ + __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ + : : : "memory","r0","r3","r4" ); \ + } + #else + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} + #endif + #endif + +#elif defined(_MSC_VER) + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } +#endif + +#ifndef CATCH_BREAK_INTO_DEBUGGER +#define CATCH_BREAK_INTO_DEBUGGER() Catch::isTrue( true ); +#endif + +// #included from: catch_interfaces_registry_hub.h +#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; + + struct IRegistryHub { + virtual ~IRegistryHub(); + + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + }; + + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0; + virtual void registerTest( TestCase const& testInfo ) = 0; + virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + }; + + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + +// #included from: catch_interfaces_config.h +#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct Verbosity { enum Level { + NoOutput = 0, + Quiet, + Normal + }; }; + + struct WarnAbout { enum What { + Nothing = 0x00, + NoAssertions = 0x01 + }; }; + + struct ShowDurations { enum OrNot { + DefaultForReporter, + Always, + Never + }; }; + + class TestSpec; + + struct IConfig : IShared { + + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + }; +} + +#include + +namespace Catch { + + inline IResultCapture& getResultCapture() { + return getCurrentContext().getResultCapture(); + } + + template + ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher, + std::string const& matcherCallAsString ) { + std::string matcherAsString = matcher.toString(); + if( matcherAsString == "{?}" ) + matcherAsString = matcherCallAsString; + return ExpressionResultBuilder() + .setRhs( matcherAsString ) + .setOp( "matches" ); + } + + template + ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher, + ArgT const& arg, + std::string const& matcherCallAsString ) { + return expressionResultBuilderFromMatcher( matcher, matcherCallAsString ) + .setLhs( Catch::toString( arg ) ) + .setResultType( matcher.match( arg ) ); + } + + template + ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher, + ArgT* arg, + std::string const& matcherCallAsString ) { + return expressionResultBuilderFromMatcher( matcher, matcherCallAsString ) + .setLhs( Catch::toString( arg ) ) + .setResultType( matcher.match( arg ) ); + } + +struct TestFailureException{}; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \ + if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, __assertionInfo ) ) { \ + if( internal_catch_action & Catch::ResultAction::Debug ) CATCH_BREAK_INTO_DEBUGGER(); \ + if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \ + if( !Catch::shouldContinueOnFailure( resultDisposition ) ) throw Catch::TestFailureException(); \ + Catch::isTrue( false && originalExpr ); \ + } + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ + do { \ + Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \ + } catch( Catch::TestFailureException& ) { \ + throw; \ + } catch( ... ) { \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \ + Catch::ResultDisposition::Normal, expr ); \ + } \ + } while( Catch::isTrue( false ) ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( !Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ + do { \ + Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + expr; \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \ + } \ + catch( ... ) { \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), resultDisposition, false ); \ + } \ +} while( Catch::isTrue( false ) ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ + try { \ + if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \ + expr; \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \ + } \ + } \ + catch( Catch::TestFailureException& ) { \ + throw; \ + } \ + catch( exceptionType ) { \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \ + } + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \ + do { \ + Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ + } while( Catch::isTrue( false ) ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ + do { \ + Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ + catch( ... ) { \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \ + resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \ + } \ + } while( Catch::isTrue( false ) ) + +/////////////////////////////////////////////////////////////////////////////// +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ + do { \ + Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << __VA_ARGS__ +::Catch::StreamEndStop(), resultDisposition, true ) \ + } while( Catch::isTrue( false ) ) +#else + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ + do { \ + Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << log, resultDisposition, true ) \ + } while( Catch::isTrue( false ) ) +#endif + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( log, macroName ) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ + do { \ + Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \ + try { \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \ + } catch( Catch::TestFailureException& ) { \ + throw; \ + } catch( ... ) { \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \ + resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \ + } \ + } while( Catch::isTrue( false ) ) + +// #included from: internal/catch_section.h +#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED + +// #included from: catch_section_info.h +#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED + +namespace Catch { + + struct SectionInfo { + SectionInfo( std::string const& _name, + std::string const& _description, + SourceLineInfo const& _lineInfo ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + +} // end namespace Catch + +// #included from: catch_totals.hpp +#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED + +#include + +namespace Catch { + + struct Counts { + Counts() : passed( 0 ), failed( 0 ) {} + + Counts operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + return diff; + } + Counts& operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + return *this; + } + + std::size_t total() const { + return passed + failed; + } + + std::size_t passed; + std::size_t failed; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else + ++diff.testCases.passed; + return diff; + } + + Totals& operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Counts assertions; + Counts testCases; + }; +} + +// #included from: catch_timer.h +#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED + +#ifdef CATCH_PLATFORM_WINDOWS +typedef unsigned long long uint64_t; +#else +#include +#endif + +namespace Catch { + + class Timer { + public: + Timer() : m_ticks( 0 ) {} + void start(); + unsigned int getElapsedNanoseconds() const; + unsigned int getElapsedMilliseconds() const; + double getElapsedSeconds() const; + + private: + uint64_t m_ticks; + }; + +} // namespace Catch + +#include + +namespace Catch { + + class Section { + public: + Section( SourceLineInfo const& lineInfo, + std::string const& name, + std::string const& description = "" ); + ~Section(); +# ifdef CATCH_CPP11_OR_GREATER + Section( Section const& ) = default; + Section( Section && ) = default; + Section& operator = ( Section const& ) = default; + Section& operator = ( Section && ) = default; +# endif + + // This indicates whether the section should be executed or not + operator bool(); + + private: + + SectionInfo m_info; + + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_SECTION( ... ) \ + if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) +#else + #define INTERNAL_CATCH_SECTION( name, desc ) \ + if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, name, desc ) ) +#endif + +// #included from: internal/catch_generators.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + +template +struct IGenerator { + virtual ~IGenerator() {} + virtual T getValue( std::size_t index ) const = 0; + virtual std::size_t size () const = 0; +}; + +template +class BetweenGenerator : public IGenerator { +public: + BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} + + virtual T getValue( std::size_t index ) const { + return m_from+static_cast( index ); + } + + virtual std::size_t size() const { + return static_cast( 1+m_to-m_from ); + } + +private: + + T m_from; + T m_to; +}; + +template +class ValuesGenerator : public IGenerator { +public: + ValuesGenerator(){} + + void add( T value ) { + m_values.push_back( value ); + } + + virtual T getValue( std::size_t index ) const { + return m_values[index]; + } + + virtual std::size_t size() const { + return m_values.size(); + } + +private: + std::vector m_values; +}; + +template +class CompositeGenerator { +public: + CompositeGenerator() : m_totalSize( 0 ) {} + + // *** Move semantics, similar to auto_ptr *** + CompositeGenerator( CompositeGenerator& other ) + : m_fileInfo( other.m_fileInfo ), + m_totalSize( 0 ) + { + move( other ); + } + + CompositeGenerator& setFileInfo( const char* fileInfo ) { + m_fileInfo = fileInfo; + return *this; + } + + ~CompositeGenerator() { + deleteAll( m_composed ); + } + + operator T () const { + size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); + + typename std::vector*>::const_iterator it = m_composed.begin(); + typename std::vector*>::const_iterator itEnd = m_composed.end(); + for( size_t index = 0; it != itEnd; ++it ) + { + const IGenerator* generator = *it; + if( overallIndex >= index && overallIndex < index + generator->size() ) + { + return generator->getValue( overallIndex-index ); + } + index += generator->size(); + } + CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); + return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so + } + + void add( const IGenerator* generator ) { + m_totalSize += generator->size(); + m_composed.push_back( generator ); + } + + CompositeGenerator& then( CompositeGenerator& other ) { + move( other ); + return *this; + } + + CompositeGenerator& then( T value ) { + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( value ); + add( valuesGen ); + return *this; + } + +private: + + void move( CompositeGenerator& other ) { + std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); + m_totalSize += other.m_totalSize; + other.m_composed.clear(); + } + + std::vector*> m_composed; + std::string m_fileInfo; + size_t m_totalSize; +}; + +namespace Generators +{ + template + CompositeGenerator between( T from, T to ) { + CompositeGenerator generators; + generators.add( new BetweenGenerator( from, to ) ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3 ){ + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3, T val4 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + valuesGen->add( val4 ); + generators.add( valuesGen ); + return generators; + } + +} // end namespace Generators + +using namespace Generators; + +} // end namespace Catch + +#define INTERNAL_CATCH_LINESTR2( line ) #line +#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) + +#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) + +// #included from: internal/catch_interfaces_exception.h +#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED + +#include + +namespace Catch { + + typedef std::string(*exceptionTranslateFunction)(); + + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate() const = 0; + }; + + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + virtual std::string translate() const { + try { + throw; + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator( translateFunction ) ); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) + +// #included from: internal/catch_approx.hpp +#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED + +#include +#include + +namespace Catch { +namespace Detail { + + class Approx { + public: + explicit Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx( Approx const& other ) + : m_epsilon( other.m_epsilon ), + m_scale( other.m_scale ), + m_value( other.m_value ) + {} + + static Approx custom() { + return Approx( 0 ); + } + + Approx operator()( double value ) { + Approx approx( value ); + approx.epsilon( m_epsilon ); + approx.scale( m_scale ); + return approx; + } + + friend bool operator == ( double lhs, Approx const& rhs ) { + // Thanks to Richard Harris for his help refining this formula + return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); + } + + friend bool operator == ( Approx const& lhs, double rhs ) { + return operator==( rhs, lhs ); + } + + friend bool operator != ( double lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + friend bool operator != ( Approx const& lhs, double rhs ) { + return !operator==( rhs, lhs ); + } + + Approx& epsilon( double newEpsilon ) { + m_epsilon = newEpsilon; + return *this; + } + + Approx& scale( double newScale ) { + m_scale = newScale; + return *this; + } + + std::string toString() const { + std::ostringstream oss; + oss << "Approx( " << Catch::toString( m_value ) << " )"; + return oss.str(); + } + + private: + double m_epsilon; + double m_scale; + double m_value; + }; +} + +template<> +inline std::string toString( Detail::Approx const& value ) { + return value.toString(); +} + +} // end namespace Catch + +// #included from: internal/catch_matchers.hpp +#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED + +namespace Catch { +namespace Matchers { + namespace Impl { + + template + struct Matcher : SharedImpl + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + }; + + template + struct MatcherImpl : Matcher { + + virtual Ptr > clone() const { + return Ptr >( new DerivedT( static_cast( *this ) ) ); + } + }; + + namespace Generic { + + template + class AllOf : public MatcherImpl, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + private: + std::vector > > m_matchers; + }; + + template + class AnyOf : public MatcherImpl, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + private: + std::vector > > m_matchers; + }; + + } + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct Equals : MatcherImpl { + Equals( std::string const& str ) : m_str( str ){} + Equals( Equals const& other ) : m_str( other.m_str ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_str == expr; + } + virtual std::string toString() const { + return "equals: \"" + m_str + "\""; + } + + std::string m_str; + }; + + struct Contains : MatcherImpl { + Contains( std::string const& substr ) : m_substr( substr ){} + Contains( Contains const& other ) : m_substr( other.m_substr ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + + struct StartsWith : MatcherImpl { + StartsWith( std::string const& substr ) : m_substr( substr ){} + StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) == 0; + } + virtual std::string toString() const { + return "starts with: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + + struct EndsWith : MatcherImpl { + EndsWith( std::string const& substr ) : m_substr( substr ){} + EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) == expr.size() - m_substr.size(); + } + virtual std::string toString() const { + return "ends with: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str ) { + return Impl::StdString::Equals( str ); + } + inline Impl::StdString::Equals Equals( const char* str ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ) ); + } + inline Impl::StdString::Contains Contains( std::string const& substr ) { + return Impl::StdString::Contains( substr ); + } + inline Impl::StdString::Contains Contains( const char* substr ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + +// These files are included here so the single_include script doesn't put them +// in the conditionally compiled sections +// #included from: internal/catch_test_case_info.h +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED + +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + struct ITestCase; + + struct TestCaseInfo { + TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + bool _isHidden, + SourceLineInfo const& _lineInfo ); + + TestCaseInfo( TestCaseInfo const& other ); + + std::string name; + std::string className; + std::string description; + std::set tags; + std::string tagsAsString; + SourceLineInfo lineInfo; + bool isHidden; + bool throws; + }; + + class TestCase : public TestCaseInfo { + public: + + TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( TestCase const& other ); + + TestCase withName( std::string const& _newName ) const; + + void invoke() const; + + TestCaseInfo const& getTestCaseInfo() const; + + bool isHidden() const; + bool throws() const; + + void swap( TestCase& other ); + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + TestCase& operator = ( TestCase const& other ); + + private: + Ptr test; + }; + + TestCase makeTestCase( ITestCase* testCase, + std::string const& className, + std::string const& name, + std::string const& description, + SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// #included from: internal/catch_interfaces_runner.h +#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED + +namespace Catch { + class TestCase; + + struct IRunner { + virtual ~IRunner(); + }; +} + + +#ifdef __OBJC__ +// #included from: internal/catch_objc.hpp +#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED + +#import + +#include + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage + +/////////////////////////////////////////////////////////////////////////////// +// This protocol is really only here for (self) documenting purposes, since +// all its methods are optional. +@protocol OcFixture + +@optional + +-(void) setUp; +-(void) tearDown; + +@end + +namespace Catch { + + class OcMethod : public SharedImpl { + + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + + virtual void invoke() const { + id obj = [[m_cls alloc] init]; + + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); + + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; + }; + + namespace Detail{ + + inline std::string getAnnotation( Class cls, + std::string const& annotationName, + std::string const& testCaseName ) { + NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; + SEL sel = NSSelectorFromString( selStr ); + arcSafeRelease( selStr ); + id value = performOptionalSelector( cls, sel ); + if( value ) + return [(NSString*)value UTF8String]; + return ""; + } + } + + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( NULL, 0 ); + + Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); + objc_getClassList( classes, noClasses ); + + for( int c = 0; c < noClasses; c++ ) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList( cls, &count ); + for( u_int m = 0; m < count ; m++ ) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if( startsWith( methodName, "Catch_TestCase_" ) ) { + std::string testCaseName = methodName.substr( 15 ); + std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); + std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); + const char* className = class_getName( cls ); + + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + noTestMethods++; + } + } + free(methods); + } + } + return noTestMethods; + } + + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { + + template + struct StringHolder : MatcherImpl{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } + + NSString* m_substr; + }; + + struct Equals : StringHolder { + Equals( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_substr]; + } + + virtual std::string toString() const { + return "equals string: \"" + Catch::toString( m_substr ) + "\""; + } + }; + + struct Contains : StringHolder { + Contains( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } + + virtual std::string toString() const { + return "contains string: \"" + Catch::toString( m_substr ) + "\""; + } + }; + + struct StartsWith : StringHolder { + StartsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } + + virtual std::string toString() const { + return "starts with: \"" + Catch::toString( m_substr ) + "\""; + } + }; + struct EndsWith : StringHolder { + EndsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } + + virtual std::string toString() const { + return "ends with: \"" + Catch::toString( m_substr ) + "\""; + } + }; + + } // namespace NSStringMatchers + } // namespace Impl + + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } + + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } + + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } + + inline Impl::NSStringMatchers::EndsWith + EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } + + } // namespace Matchers + + using namespace Matchers; + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define OC_TEST_CASE( name, desc )\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ +{\ +return @ name; \ +}\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +{ \ +return @ desc; \ +} \ +-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) + +#endif + +#ifdef CATCH_CONFIG_RUNNER +// #included from: internal/catch_impl.hpp +#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED + +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// #included from: catch_runner.hpp +#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED + +// #included from: internal/catch_commandline.hpp +#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED + +// #included from: catch_config.hpp +#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED + +// #included from: catch_test_spec_parser.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_test_spec.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +#include +#include + +namespace Catch { + + class TestSpec { + struct Pattern : SharedImpl<> { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + class NamePattern : public Pattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) { + if( startsWith( m_name, "*" ) ) { + m_name = m_name.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_name, "*" ) ) { + m_name = m_name.substr( 0, m_name.size()-1 ); + m_wildcard = (WildcardPosition)( m_wildcard | WildcardAtEnd ); + } + } + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_name == toLower( testCase.name ); + case WildcardAtStart: + return endsWith( toLower( testCase.name ), m_name ); + case WildcardAtEnd: + return startsWith( toLower( testCase.name ), m_name ); + case WildcardAtBothEnds: + return contains( toLower( testCase.name ), m_name ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string m_name; + WildcardPosition m_wildcard; + }; + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + virtual ~TagPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return testCase.tags.find( m_tag ) != testCase.tags.end(); + } + private: + std::string m_tag; + }; + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr m_underlyingPattern; + }; + + struct Filter { + std::vector > m_patterns; + + bool matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) + if( !(*it)->matches( testCase ) ) + return false; + return true; + } + }; + + public: + bool hasFilters() const { + return !m_filters.empty(); + } + bool matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } + + private: + std::vector m_filters; + + friend class TestSpecParser; + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +namespace Catch { + + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag }; + Mode m_mode; + bool m_exclusion; + std::size_t m_start, m_pos; + std::string m_arg; + TestSpec::Filter m_currentFilter; + TestSpec m_testSpec; + + public: + TestSpecParser parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = arg; + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern(); + addFilter(); + return *this; + } + TestSpec testSpec() { + return m_testSpec; + } + private: + void visitChar( char c ) { + if( m_mode == None ) { + switch( c ) { + case ' ': return; + case '~': m_exclusion = true; return; + case '[': return startNewMode( Tag, ++m_pos ); + case '"': return startNewMode( QuotedName, ++m_pos ); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + startNewMode( Tag, ++m_pos ); + } + } + else if( m_mode == QuotedName && c == '"' ) + addPattern(); + else if( m_mode == Tag && c == ']' ) + addPattern(); + } + void startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + template + void addPattern() { + std::string token = subString(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr pattern = new T( token ); + if( m_exclusion ) + pattern = new TestSpec::ExcludedPattern( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + void addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + }; + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser().parse( arg ).testSpec(); + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// #included from: catch_stream.h +#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED + +#include + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + class Stream { + public: + Stream(); + Stream( std::streambuf* _streamBuf, bool _isOwned ); + void release(); + + std::streambuf* streamBuf; + + private: + bool isOwned; + }; +} + +#include +#include +#include +#include + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + + struct ConfigData { + + ConfigData() + : listTests( false ), + listTags( false ), + listReporters( false ), + listTestNamesOnly( false ), + showSuccessfulTests( false ), + shouldDebugBreak( false ), + noThrow( false ), + showHelp( false ), + showInvisibles( false ), + abortAfter( -1 ), + verbosity( Verbosity::Normal ), + warnings( WarnAbout::Nothing ), + showDurations( ShowDurations::DefaultForReporter ) + {} + + bool listTests; + bool listTags; + bool listReporters; + bool listTestNamesOnly; + + bool showSuccessfulTests; + bool shouldDebugBreak; + bool noThrow; + bool showHelp; + bool showInvisibles; + + int abortAfter; + + Verbosity::Level verbosity; + WarnAbout::What warnings; + ShowDurations::OrNot showDurations; + + std::string reporterName; + std::string outputFilename; + std::string name; + std::string processName; + + std::vector testsOrTags; + }; + + class Config : public SharedImpl { + private: + Config( Config const& other ); + Config& operator = ( Config const& other ); + virtual void dummy(); + public: + + Config() + : m_os( std::cout.rdbuf() ) + {} + + Config( ConfigData const& data ) + : m_data( data ), + m_os( std::cout.rdbuf() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser; + for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) + parser.parse( data.testsOrTags[i] ); + m_testSpec = parser.testSpec(); + } + } + + virtual ~Config() { + m_os.rdbuf( std::cout.rdbuf() ); + m_stream.release(); + } + + void setFilename( std::string const& filename ) { + m_data.outputFilename = filename; + } + + std::string const& getFilename() const { + return m_data.outputFilename ; + } + + bool listTests() const { return m_data.listTests; } + bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool listTags() const { return m_data.listTags; } + bool listReporters() const { return m_data.listReporters; } + + std::string getProcessName() const { return m_data.processName; } + + bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } + + void setStreamBuf( std::streambuf* buf ) { + m_os.rdbuf( buf ? buf : std::cout.rdbuf() ); + } + + void useStream( std::string const& streamName ) { + Stream stream = createStream( streamName ); + setStreamBuf( stream.streamBuf ); + m_stream.release(); + m_stream = stream; + } + + std::string getReporterName() const { return m_data.reporterName; } + + int abortAfter() const { return m_data.abortAfter; } + + TestSpec const& testSpec() const { return m_testSpec; } + + bool showHelp() const { return m_data.showHelp; } + bool showInvisibles() const { return m_data.showInvisibles; } + + // IConfig interface + virtual bool allowThrows() const { return !m_data.noThrow; } + virtual std::ostream& stream() const { return m_os; } + virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } + virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } + + private: + ConfigData m_data; + + Stream m_stream; + mutable std::ostream m_os; + TestSpec m_testSpec; + }; + +} // end namespace Catch + +// #included from: catch_clara.h +#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#undef CLARA_CONFIG_CONSOLE_WIDTH +#endif +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +// Declare Clara inside the Catch namespace +#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { +// #included from: ../external/clara.h + +// Only use header guard if we are not using an outer namespace +#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) + +#ifndef STITCH_CLARA_OPEN_NAMESPACE +#define TWOBLUECUBES_CLARA_H_INCLUDED +#define STITCH_CLARA_OPEN_NAMESPACE +#define STITCH_CLARA_CLOSE_NAMESPACE +#else +#define STITCH_CLARA_CLOSE_NAMESPACE } +#endif + +#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE + +// ----------- #included from tbc_text_format.h ----------- + +// Only use header guard if we are not using an outer namespace +#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) +#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +#define TBC_TEXT_FORMAT_H_INCLUDED +#endif + +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TBC_TEXT_FORMAT_H_INCLUDED + +// ----------- end of #include from tbc_text_format.h ----------- +// ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h + +#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE + +#include +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_CLARA_OPEN_NAMESPACE +STITCH_CLARA_OPEN_NAMESPACE +#endif + +namespace Clara { + + struct UnpositionalTag {}; + + extern UnpositionalTag _; + +#ifdef CLARA_CONFIG_MAIN + UnpositionalTag _; +#endif + + namespace Detail { + +#ifdef CLARA_CONSOLE_WIDTH + const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + using namespace Tbc; + + inline bool startsWith( std::string const& str, std::string const& prefix ) { + return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; + } + + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + + template struct IsBool { static const bool value = false; }; + template<> struct IsBool { static const bool value = true; }; + + template + void convertInto( std::string const& _source, T& _dest ) { + std::stringstream ss; + ss << _source; + ss >> _dest; + if( ss.fail() ) + throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); + } + inline void convertInto( std::string const& _source, std::string& _dest ) { + _dest = _source; + } + inline void convertInto( std::string const& _source, bool& _dest ) { + std::string sourceLC = _source; + std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower ); + if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) + _dest = true; + else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) + _dest = false; + else + throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); + } + inline void convertInto( bool _source, bool& _dest ) { + _dest = _source; + } + template + inline void convertInto( bool, T& ) { + throw std::runtime_error( "Invalid conversion" ); + } + + template + struct IArgFunction { + virtual ~IArgFunction() {} +# ifdef CATCH_CPP11_OR_GREATER + IArgFunction() = default; + IArgFunction( IArgFunction const& ) = default; +# endif + virtual void set( ConfigT& config, std::string const& value ) const = 0; + virtual void setFlag( ConfigT& config ) const = 0; + virtual bool takesArg() const = 0; + virtual IArgFunction* clone() const = 0; + }; + + template + class BoundArgFunction { + public: + BoundArgFunction() : functionObj( NULL ) {} + BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {} + BoundArgFunction& operator = ( BoundArgFunction const& other ) { + IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL; + delete functionObj; + functionObj = newFunctionObj; + return *this; + } + ~BoundArgFunction() { delete functionObj; } + + void set( ConfigT& config, std::string const& value ) const { + functionObj->set( config, value ); + } + void setFlag( ConfigT& config ) const { + functionObj->setFlag( config ); + } + bool takesArg() const { return functionObj->takesArg(); } + + bool isSet() const { + return functionObj != NULL; + } + private: + IArgFunction* functionObj; + }; + + template + struct NullBinder : IArgFunction{ + virtual void set( C&, std::string const& ) const {} + virtual void setFlag( C& ) const {} + virtual bool takesArg() const { return true; } + virtual IArgFunction* clone() const { return new NullBinder( *this ); } + }; + + template + struct BoundDataMember : IArgFunction{ + BoundDataMember( M C::* _member ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + convertInto( stringValue, p.*member ); + } + virtual void setFlag( C& p ) const { + convertInto( true, p.*member ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } + M C::* member; + }; + template + struct BoundUnaryMethod : IArgFunction{ + BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + (p.*member)( value ); + } + virtual void setFlag( C& p ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + (p.*member)( value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } + void (C::*member)( M ); + }; + template + struct BoundNullaryMethod : IArgFunction{ + BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + (p.*member)(); + } + virtual void setFlag( C& p ) const { + (p.*member)(); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } + void (C::*member)(); + }; + + template + struct BoundUnaryFunction : IArgFunction{ + BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + function( obj ); + } + virtual void setFlag( C& p ) const { + function( p ); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } + void (*function)( C& ); + }; + + template + struct BoundBinaryFunction : IArgFunction{ + BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + function( obj, value ); + } + virtual void setFlag( C& obj ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + function( obj, value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } + void (*function)( C&, T ); + }; + + } // namespace Detail + + struct Parser { + Parser() : separators( " \t=:" ) {} + + struct Token { + enum Type { Positional, ShortOpt, LongOpt }; + Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} + Type type; + std::string data; + }; + + void parseIntoTokens( int argc, char const * const * argv, std::vector& tokens ) const { + const std::string doubleDash = "--"; + for( int i = 1; i < argc && argv[i] != doubleDash; ++i ) + parseIntoTokens( argv[i] , tokens); + } + void parseIntoTokens( std::string arg, std::vector& tokens ) const { + while( !arg.empty() ) { + Parser::Token token( Parser::Token::Positional, arg ); + arg = ""; + if( token.data[0] == '-' ) { + if( token.data.size() > 1 && token.data[1] == '-' ) { + token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) ); + } + else { + token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) ); + if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) { + arg = "-" + token.data.substr( 1 ); + token.data = token.data.substr( 0, 1 ); + } + } + } + if( token.type != Parser::Token::Positional ) { + std::size_t pos = token.data.find_first_of( separators ); + if( pos != std::string::npos ) { + arg = token.data.substr( pos+1 ); + token.data = token.data.substr( 0, pos ); + } + } + tokens.push_back( token ); + } + } + std::string separators; + }; + + template + struct CommonArgProperties { + CommonArgProperties() {} + CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} + + Detail::BoundArgFunction boundField; + std::string description; + std::string detail; + std::string placeholder; // Only value if boundField takes an arg + + bool takesArg() const { + return !placeholder.empty(); + } + void validate() const { + if( !boundField.isSet() ) + throw std::logic_error( "option not bound" ); + } + }; + struct OptionArgProperties { + std::vector shortNames; + std::string longName; + + bool hasShortName( std::string const& shortName ) const { + return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); + } + bool hasLongName( std::string const& _longName ) const { + return _longName == longName; + } + }; + struct PositionalArgProperties { + PositionalArgProperties() : position( -1 ) {} + int position; // -1 means non-positional (floating) + + bool isFixedPositional() const { + return position != -1; + } + }; + + template + class CommandLine { + + struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { + Arg() {} + Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} + + using CommonArgProperties::placeholder; // !TBD + + std::string dbgName() const { + if( !longName.empty() ) + return "--" + longName; + if( !shortNames.empty() ) + return "-" + shortNames[0]; + return "positional args"; + } + std::string commands() const { + std::ostringstream oss; + bool first = true; + std::vector::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); + for(; it != itEnd; ++it ) { + if( first ) + first = false; + else + oss << ", "; + oss << "-" << *it; + } + if( !longName.empty() ) { + if( !first ) + oss << ", "; + oss << "--" << longName; + } + if( !placeholder.empty() ) + oss << " <" << placeholder << ">"; + return oss.str(); + } + }; + + // NOTE: std::auto_ptr is deprecated in c++11/c++0x +#if defined(__cplusplus) && __cplusplus > 199711L + typedef std::unique_ptr ArgAutoPtr; +#else + typedef std::auto_ptr ArgAutoPtr; +#endif + + friend void addOptName( Arg& arg, std::string const& optName ) + { + if( optName.empty() ) + return; + if( Detail::startsWith( optName, "--" ) ) { + if( !arg.longName.empty() ) + throw std::logic_error( "Only one long opt may be specified. '" + + arg.longName + + "' already specified, now attempting to add '" + + optName + "'" ); + arg.longName = optName.substr( 2 ); + } + else if( Detail::startsWith( optName, "-" ) ) + arg.shortNames.push_back( optName.substr( 1 ) ); + else + throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); + } + friend void setPositionalArg( Arg& arg, int position ) + { + arg.position = position; + } + + class ArgBuilder { + public: + ArgBuilder( Arg* arg ) : m_arg( arg ) {} + + // Bind a non-boolean data member (requires placeholder string) + template + void bind( M C::* field, std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + m_arg->placeholder = placeholder; + } + // Bind a boolean data member (no placeholder required) + template + void bind( bool C::* field ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + } + + // Bind a method taking a single, non-boolean argument (requires a placeholder string) + template + void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + m_arg->placeholder = placeholder; + } + + // Bind a method taking a single, boolean argument (no placeholder string required) + template + void bind( void (C::* unaryMethod)( bool ) ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + } + + // Bind a method that takes no arguments (will be called if opt is present) + template + void bind( void (C::* nullaryMethod)() ) { + m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); + } + + // Bind a free function taking a single argument - the object to operate on (no placeholder string required) + template + void bind( void (* unaryFunction)( C& ) ) { + m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); + } + + // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) + template + void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); + m_arg->placeholder = placeholder; + } + + ArgBuilder& describe( std::string const& description ) { + m_arg->description = description; + return *this; + } + ArgBuilder& detail( std::string const& detail ) { + m_arg->detail = detail; + return *this; + } + + protected: + Arg* m_arg; + }; + + class OptBuilder : public ArgBuilder { + public: + OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} + OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} + + OptBuilder& operator[]( std::string const& optName ) { + addOptName( *ArgBuilder::m_arg, optName ); + return *this; + } + }; + + public: + + CommandLine() + : m_boundProcessName( new Detail::NullBinder() ), + m_highestSpecifiedArgPosition( 0 ), + m_throwOnUnrecognisedTokens( false ) + {} + CommandLine( CommandLine const& other ) + : m_boundProcessName( other.m_boundProcessName ), + m_options ( other.m_options ), + m_positionalArgs( other.m_positionalArgs ), + m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), + m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) + { + if( other.m_floatingArg.get() ) + m_floatingArg = ArgAutoPtr( new Arg( *other.m_floatingArg ) ); + } + + CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { + m_throwOnUnrecognisedTokens = shouldThrow; + return *this; + } + + OptBuilder operator[]( std::string const& optName ) { + m_options.push_back( Arg() ); + addOptName( m_options.back(), optName ); + OptBuilder builder( &m_options.back() ); + return builder; + } + + ArgBuilder operator[]( int position ) { + m_positionalArgs.insert( std::make_pair( position, Arg() ) ); + if( position > m_highestSpecifiedArgPosition ) + m_highestSpecifiedArgPosition = position; + setPositionalArg( m_positionalArgs[position], position ); + ArgBuilder builder( &m_positionalArgs[position] ); + return builder; + } + + // Invoke this with the _ instance + ArgBuilder operator[]( UnpositionalTag ) { + if( m_floatingArg.get() ) + throw std::logic_error( "Only one unpositional argument can be added" ); + m_floatingArg = ArgAutoPtr( new Arg() ); + ArgBuilder builder( m_floatingArg.get() ); + return builder; + } + + template + void bindProcessName( M C::* field ) { + m_boundProcessName = new Detail::BoundDataMember( field ); + } + template + void bindProcessName( void (C::*_unaryMethod)( M ) ) { + m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); + } + + void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { + typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; + std::size_t maxWidth = 0; + for( it = itBegin; it != itEnd; ++it ) + maxWidth = (std::max)( maxWidth, it->commands().size() ); + + for( it = itBegin; it != itEnd; ++it ) { + Detail::Text usage( it->commands(), Detail::TextAttributes() + .setWidth( maxWidth+indent ) + .setIndent( indent ) ); + Detail::Text desc( it->description, Detail::TextAttributes() + .setWidth( width - maxWidth - 3 ) ); + + for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { + std::string usageCol = i < usage.size() ? usage[i] : ""; + os << usageCol; + + if( i < desc.size() && !desc[i].empty() ) + os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) + << desc[i]; + os << "\n"; + } + } + } + std::string optUsage() const { + std::ostringstream oss; + optUsage( oss ); + return oss.str(); + } + + void argSynopsis( std::ostream& os ) const { + for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { + if( i > 1 ) + os << " "; + typename std::map::const_iterator it = m_positionalArgs.find( i ); + if( it != m_positionalArgs.end() ) + os << "<" << it->second.placeholder << ">"; + else if( m_floatingArg.get() ) + os << "<" << m_floatingArg->placeholder << ">"; + else + throw std::logic_error( "non consecutive positional arguments with no floating args" ); + } + // !TBD No indication of mandatory args + if( m_floatingArg.get() ) { + if( m_highestSpecifiedArgPosition > 1 ) + os << " "; + os << "[<" << m_floatingArg->placeholder << "> ...]"; + } + } + std::string argSynopsis() const { + std::ostringstream oss; + argSynopsis( oss ); + return oss.str(); + } + + void usage( std::ostream& os, std::string const& procName ) const { + validate(); + os << "usage:\n " << procName << " "; + argSynopsis( os ); + if( !m_options.empty() ) { + os << " [options]\n\nwhere options are: \n"; + optUsage( os, 2 ); + } + os << "\n"; + } + std::string usage( std::string const& procName ) const { + std::ostringstream oss; + usage( oss, procName ); + return oss.str(); + } + + ConfigT parse( int argc, char const * const * argv ) const { + ConfigT config; + parseInto( argc, argv, config ); + return config; + } + + std::vector parseInto( int argc, char const * const * argv, ConfigT& config ) const { + std::string processName = argv[0]; + std::size_t lastSlash = processName.find_last_of( "/\\" ); + if( lastSlash != std::string::npos ) + processName = processName.substr( lastSlash+1 ); + m_boundProcessName.set( config, processName ); + std::vector tokens; + Parser parser; + parser.parseIntoTokens( argc, argv, tokens ); + return populate( tokens, config ); + } + + std::vector populate( std::vector const& tokens, ConfigT& config ) const { + validate(); + std::vector unusedTokens = populateOptions( tokens, config ); + unusedTokens = populateFixedArgs( unusedTokens, config ); + unusedTokens = populateFloatingArgs( unusedTokens, config ); + return unusedTokens; + } + + std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + std::vector errors; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); + for(; it != itEnd; ++it ) { + Arg const& arg = *it; + + try { + if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || + ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { + if( arg.takesArg() ) { + if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) + errors.push_back( "Expected argument to option: " + token.data ); + else + arg.boundField.set( config, tokens[++i].data ); + } + else { + arg.boundField.setFlag( config ); + } + break; + } + } + catch( std::exception& ex ) { + errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); + } + } + if( it == itEnd ) { + if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) + unusedTokens.push_back( token ); + else if( m_throwOnUnrecognisedTokens ) + errors.push_back( "unrecognised option: " + token.data ); + } + } + if( !errors.empty() ) { + std::ostringstream oss; + for( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); + it != itEnd; + ++it ) { + if( it != errors.begin() ) + oss << "\n"; + oss << *it; + } + throw std::runtime_error( oss.str() ); + } + return unusedTokens; + } + std::vector populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + int position = 1; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::map::const_iterator it = m_positionalArgs.find( position ); + if( it != m_positionalArgs.end() ) + it->second.boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + if( token.type == Parser::Token::Positional ) + position++; + } + return unusedTokens; + } + std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { + if( !m_floatingArg.get() ) + return tokens; + std::vector unusedTokens; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + if( token.type == Parser::Token::Positional ) + m_floatingArg->boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + } + return unusedTokens; + } + + void validate() const + { + if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) + throw std::logic_error( "No options or arguments specified" ); + + for( typename std::vector::const_iterator it = m_options.begin(), + itEnd = m_options.end(); + it != itEnd; ++it ) + it->validate(); + } + + private: + Detail::BoundArgFunction m_boundProcessName; + std::vector m_options; + std::map m_positionalArgs; + ArgAutoPtr m_floatingArg; + int m_highestSpecifiedArgPosition; + bool m_throwOnUnrecognisedTokens; + }; + +} // end namespace Clara + +STITCH_CLARA_CLOSE_NAMESPACE +#undef STITCH_CLARA_OPEN_NAMESPACE +#undef STITCH_CLARA_CLOSE_NAMESPACE + +#endif // TWOBLUECUBES_CLARA_H_INCLUDED +#undef STITCH_CLARA_OPEN_NAMESPACE + +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +#include + +namespace Catch { + + inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } + inline void abortAfterX( ConfigData& config, int x ) { + if( x < 1 ) + throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); + config.abortAfter = x; + } + inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + + inline void addWarning( ConfigData& config, std::string const& _warning ) { + if( _warning == "NoAssertions" ) + config.warnings = (WarnAbout::What)( config.warnings | WarnAbout::NoAssertions ); + else + throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); + + } + inline void setVerbosity( ConfigData& config, int level ) { + // !TBD: accept strings? + config.verbosity = (Verbosity::Level)level; + } + inline void setShowDurations( ConfigData& config, bool _showDurations ) { + config.showDurations = _showDurations + ? ShowDurations::Always + : ShowDurations::Never; + } + inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { + std::ifstream f( _filename.c_str() ); + if( !f.is_open() ) + throw std::domain_error( "Unable to load input file: " + _filename ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, "#" ) ) + addTestOrTags( config, "\"" + line + "\"" ); + } + } + + inline Clara::CommandLine makeCommandLineParser() { + + using namespace Clara; + CommandLine cli; + + cli.bindProcessName( &ConfigData::processName ); + + cli["-?"]["-h"]["--help"] + .describe( "display usage information" ) + .bind( &ConfigData::showHelp ); + + cli["-l"]["--list-tests"] + .describe( "list all/matching test cases" ) + .bind( &ConfigData::listTests ); + + cli["-t"]["--list-tags"] + .describe( "list all/matching tags" ) + .bind( &ConfigData::listTags ); + + cli["-s"]["--success"] + .describe( "include successful tests in output" ) + .bind( &ConfigData::showSuccessfulTests ); + + cli["-b"]["--break"] + .describe( "break into debugger on failure" ) + .bind( &ConfigData::shouldDebugBreak ); + + cli["-e"]["--nothrow"] + .describe( "skip exception tests" ) + .bind( &ConfigData::noThrow ); + + cli["-i"]["--invisibles"] + .describe( "show invisibles (tabs, newlines)" ) + .bind( &ConfigData::showInvisibles ); + + cli["-o"]["--out"] + .describe( "output filename" ) + .bind( &ConfigData::outputFilename, "filename" ); + + cli["-r"]["--reporter"] +// .placeholder( "name[:filename]" ) + .describe( "reporter to use (defaults to console)" ) + .bind( &ConfigData::reporterName, "name" ); + + cli["-n"]["--name"] + .describe( "suite name" ) + .bind( &ConfigData::name, "name" ); + + cli["-a"]["--abort"] + .describe( "abort at first failure" ) + .bind( &abortAfterFirst ); + + cli["-x"]["--abortx"] + .describe( "abort after x failures" ) + .bind( &abortAfterX, "no. failures" ); + + cli["-w"]["--warn"] + .describe( "enable warnings" ) + .bind( &addWarning, "warning name" ); + +// - needs updating if reinstated +// cli.into( &setVerbosity ) +// .describe( "level of verbosity (0=no output)" ) +// .shortOpt( "v") +// .longOpt( "verbosity" ) +// .placeholder( "level" ); + + cli[_] + .describe( "which test or tests to use" ) + .bind( &addTestOrTags, "test name, pattern or tags" ); + + cli["-d"]["--durations"] + .describe( "show test durations" ) + .bind( &setShowDurations, "yes/no" ); + + cli["-f"]["--input-file"] + .describe( "load test names to run from a file" ) + .bind( &loadTestNamesFromFile, "filename" ); + + // Less common commands which don't have a short form + cli["--list-test-names-only"] + .describe( "list all/matching test cases names only" ) + .bind( &ConfigData::listTestNamesOnly ); + + cli["--list-reporters"] + .describe( "list all reporters" ) + .bind( &ConfigData::listReporters ); + + return cli; + } + +} // end namespace Catch + +// #included from: internal/catch_list.hpp +#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED + +// #included from: catch_text.h +#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED + +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +// #included from: ../external/tbc_text_format.h +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# endif +# else +# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include +#include +#include + +// Use optional outer namespace +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE + +namespace Catch { + using Tbc::Text; + using Tbc::TextAttributes; +} + +// #included from: catch_console_colour.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED + +namespace Catch { + + namespace Detail { + struct IColourImpl; + } + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + + // By intention + FileName = LightGrey, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + static Detail::IColourImpl* impl(); + }; + +} // end namespace Catch + +// #included from: catch_interfaces_reporter.h +#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED + +// #included from: catch_option.hpp +#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED + +namespace Catch { + + // An optional type + template + class Option { + public: + Option() : nullableValue( NULL ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : NULL ) + {} + + ~Option() { + reset(); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = NULL; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != NULL; } + bool none() const { return nullableValue == NULL; } + + bool operator !() const { return nullableValue == NULL; } + operator SafeBool::type() const { + return SafeBool::makeSafe( some() ); + } + + private: + T* nullableValue; + char storage[sizeof(T)]; + }; + +} // end namespace Catch + +#include +#include +#include +#include + +namespace Catch +{ + struct ReporterConfig { + explicit ReporterConfig( Ptr const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) + : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + + std::ostream& stream() const { return *m_stream; } + Ptr fullConfig() const { return m_fullConfig; } + + private: + std::ostream* m_stream; + Ptr m_fullConfig; + }; + + struct ReporterPreferences { + ReporterPreferences() + : shouldRedirectStdOut( false ) + {} + + bool shouldRedirectStdOut; + }; + + template + struct LazyStat : Option { + LazyStat() : used( false ) {} + LazyStat& operator=( T const& _value ) { + Option::operator=( _value ); + used = false; + return *this; + } + void reset() { + Option::reset(); + used = false; + } + bool used; + }; + + struct TestRunInfo { + TestRunInfo( std::string const& _name ) : name( _name ) {} + std::string name; + }; + struct GroupInfo { + GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) + {} + + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; + + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) + { + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); + + infoMessages.push_back( builder.m_info ); + } + } + virtual ~AssertionStats(); + +# ifdef CATCH_CPP11_OR_GREATER + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; +# endif + + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; + }; + + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + virtual ~SectionStats(); +# ifdef CATCH_CPP11_OR_GREATER + SectionStats( SectionStats const& ) = default; + SectionStats( SectionStats && ) = default; + SectionStats& operator = ( SectionStats const& ) = default; + SectionStats& operator = ( SectionStats && ) = default; +# endif + + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; + }; + + struct TestCaseStats { + TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ) + : testInfo( _testInfo ), + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + virtual ~TestCaseStats(); + +# ifdef CATCH_CPP11_OR_GREATER + TestCaseStats( TestCaseStats const& ) = default; + TestCaseStats( TestCaseStats && ) = default; + TestCaseStats& operator = ( TestCaseStats const& ) = default; + TestCaseStats& operator = ( TestCaseStats && ) = default; +# endif + + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; + + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + virtual ~TestGroupStats(); + +# ifdef CATCH_CPP11_OR_GREATER + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; +# endif + + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; + + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + virtual ~TestRunStats(); + +# ifndef CATCH_CPP11_OR_GREATER + TestRunStats( TestRunStats const& _other ) + : runInfo( _other.runInfo ), + totals( _other.totals ), + aborting( _other.aborting ) + {} +# else + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; +# endif + + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; + + struct IStreamingReporter : IShared { + virtual ~IStreamingReporter(); + + // Implementing class must also provide the following static method: + // static std::string getDescription(); + + virtual ReporterPreferences getPreferences() const = 0; + + virtual void noMatchingTestCases( std::string const& spec ) = 0; + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; + virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + + virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; + virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + }; + + struct IReporterFactory { + virtual ~IReporterFactory(); + virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; + + struct IReporterRegistry { + typedef std::map FactoryMap; + + virtual ~IReporterRegistry(); + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + }; + +} + +#include +#include + +namespace Catch { + + inline std::size_t listTests( Config const& config ) { + + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + std::cout << "Matching test cases:\n"; + else { + std::cout << "All available test cases:\n"; + testSpec = TestSpecParser().parse( "*" ).testSpec(); + } + + std::size_t matchedTests = 0; + TextAttributes nameAttr, tagsAttr; + nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + tagsAttr.setIndent( 6 ); + + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Colour::Code colour = testCaseInfo.isHidden + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard( colour ); + + std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl; + if( !testCaseInfo.tags.empty() ) + std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; + } + + if( !config.testSpec().hasFilters() ) + std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl; + else + std::cout << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; + return matchedTests; + } + + inline std::size_t listTestsNamesOnly( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( !config.testSpec().hasFilters() ) + testSpec = TestSpecParser().parse( "*" ).testSpec(); + std::size_t matchedTests = 0; + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + std::cout << testCaseInfo.name << std::endl; + } + return matchedTests; + } + + inline std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + std::cout << "Tags for matching test cases:\n"; + else { + std::cout << "All available tags:\n"; + testSpec = TestSpecParser().parse( "*" ).testSpec(); + } + + std::map tagCounts; + + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + for( std::set::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), + tagItEnd = it->getTestCaseInfo().tags.end(); + tagIt != tagItEnd; + ++tagIt ) { + std::string tagName = *tagIt; + std::map::iterator countIt = tagCounts.find( tagName ); + if( countIt == tagCounts.end() ) + tagCounts.insert( std::make_pair( tagName, 1 ) ); + else + countIt->second++; + } + } + + for( std::map::const_iterator countIt = tagCounts.begin(), + countItEnd = tagCounts.end(); + countIt != countItEnd; + ++countIt ) { + std::ostringstream oss; + oss << " " << countIt->second << " "; + Text wrapper( "[" + countIt->first + "]", TextAttributes() + .setInitialIndent( 0 ) + .setIndent( oss.str().size() ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); + std::cout << oss.str() << wrapper << "\n"; + } + std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; + return tagCounts.size(); + } + + inline std::size_t listReporters( Config const& /*config*/ ) { + std::cout << "Available reports:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; + std::size_t maxNameLen = 0; + for(it = itBegin; it != itEnd; ++it ) + maxNameLen = (std::max)( maxNameLen, it->first.size() ); + + for(it = itBegin; it != itEnd; ++it ) { + Text wrapper( it->second->getDescription(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( 7+maxNameLen ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); + std::cout << " " + << it->first + << ":" + << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << wrapper << "\n"; + } + std::cout << std::endl; + return factories.size(); + } + + inline Option list( Config const& config ) { + Option listedCount; + if( config.listTests() ) + listedCount = listedCount.valueOr(0) + listTests( config ); + if( config.listTestNamesOnly() ) + listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); + if( config.listTags() ) + listedCount = listedCount.valueOr(0) + listTags( config ); + if( config.listReporters() ) + listedCount = listedCount.valueOr(0) + listReporters( config ); + return listedCount; + } + +} // end namespace Catch + +// #included from: internal/catch_runner_impl.hpp +#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED + +// #included from: catch_test_case_tracker.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { +namespace SectionTracking { + + class TrackedSection { + + typedef std::map TrackedSections; + + public: + enum RunState { + NotStarted, + Executing, + ExecutingChildren, + Completed + }; + + TrackedSection( std::string const& name, TrackedSection* parent ) + : m_name( name ), m_runState( NotStarted ), m_parent( parent ) + {} + + RunState runState() const { return m_runState; } + + TrackedSection* findChild( std::string const& childName ) { + TrackedSections::iterator it = m_children.find( childName ); + return it != m_children.end() + ? &it->second + : NULL; + } + TrackedSection* acquireChild( std::string const& childName ) { + if( TrackedSection* child = findChild( childName ) ) + return child; + m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) ); + return findChild( childName ); + } + void enter() { + if( m_runState == NotStarted ) + m_runState = Executing; + } + void leave() { + for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end(); + it != itEnd; + ++it ) + if( it->second.runState() != Completed ) { + m_runState = ExecutingChildren; + return; + } + m_runState = Completed; + } + TrackedSection* getParent() { + return m_parent; + } + bool hasChildren() const { + return !m_children.empty(); + } + + private: + std::string m_name; + RunState m_runState; + TrackedSections m_children; + TrackedSection* m_parent; + + }; + + class TestCaseTracker { + public: + TestCaseTracker( std::string const& testCaseName ) + : m_testCase( testCaseName, NULL ), + m_currentSection( &m_testCase ), + m_completedASectionThisRun( false ) + {} + + bool enterSection( std::string const& name ) { + TrackedSection* child = m_currentSection->acquireChild( name ); + if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed ) + return false; + + m_currentSection = child; + m_currentSection->enter(); + return true; + } + void leaveSection() { + m_currentSection->leave(); + m_currentSection = m_currentSection->getParent(); + assert( m_currentSection != NULL ); + m_completedASectionThisRun = true; + } + + bool currentSectionHasChildren() const { + return m_currentSection->hasChildren(); + } + bool isCompleted() const { + return m_testCase.runState() == TrackedSection::Completed; + } + + class Guard { + public: + Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) { + m_tracker.enterTestCase(); + } + ~Guard() { + m_tracker.leaveTestCase(); + } + private: + Guard( Guard const& ); + void operator = ( Guard const& ); + TestCaseTracker& m_tracker; + }; + + private: + void enterTestCase() { + m_currentSection = &m_testCase; + m_completedASectionThisRun = false; + m_testCase.enter(); + } + void leaveTestCase() { + m_testCase.leave(); + } + + TrackedSection m_testCase; + TrackedSection* m_currentSection; + bool m_completedASectionThisRun; + }; + +} // namespace SectionTracking + +using SectionTracking::TestCaseTracker; + +} // namespace Catch + +#include +#include + +namespace Catch { + + class StreamRedirect { + + public: + StreamRedirect( std::ostream& stream, std::string& targetString ) + : m_stream( stream ), + m_prevBuf( stream.rdbuf() ), + m_targetString( targetString ) + { + stream.rdbuf( m_oss.rdbuf() ); + } + + ~StreamRedirect() { + m_targetString += m_oss.str(); + m_stream.rdbuf( m_prevBuf ); + } + + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + RunContext( RunContext const& ); + void operator =( RunContext const& ); + + public: + + explicit RunContext( Ptr const& config, Ptr const& reporter ) + : m_runInfo( config->name() ), + m_context( getCurrentMutableContext() ), + m_activeTestCase( NULL ), + m_config( config ), + m_reporter( reporter ), + m_prevRunner( &m_context.getRunner() ), + m_prevResultCapture( &m_context.getResultCapture() ), + m_prevConfig( m_context.getConfig() ) + { + m_context.setRunner( this ); + m_context.setConfig( m_config ); + m_context.setResultCapture( this ); + m_reporter->testRunStarting( m_runInfo ); + } + + virtual ~RunContext() { + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); + m_context.setRunner( m_prevRunner ); + m_context.setConfig( NULL ); + m_context.setResultCapture( m_prevResultCapture ); + m_context.setConfig( m_prevConfig ); + } + + void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); + } + void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); + } + + Totals runTest( TestCase const& testCase ) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + TestCaseInfo testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting( testInfo ); + + m_activeTestCase = &testCase; + m_testCaseTracker = TestCaseTracker( testInfo.name ); + + do { + do { + runCurrentTest( redirectedCout, redirectedCerr ); + } + while( !m_testCaseTracker->isCompleted() && !aborting() ); + } + while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); + + Totals deltaTotals = m_totals.delta( prevTotals ); + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting() ) ); + + m_activeTestCase = NULL; + m_testCaseTracker.reset(); + + return deltaTotals; + } + + Ptr config() const { + return m_config; + } + + private: // IResultCapture + + virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) { + m_lastAssertionInfo = assertionInfo; + return actOnCurrentResult( assertionResult.buildResult( assertionInfo ) ); + } + + virtual void assertionEnded( AssertionResult const& result ) { + if( result.getResultType() == ResultWas::Ok ) { + m_totals.assertions.passed++; + } + else if( !result.isOk() ) { + m_totals.assertions.failed++; + } + + if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) + m_messages.clear(); + + // Reset working state + m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + } + + virtual bool sectionStarted ( + SectionInfo const& sectionInfo, + Counts& assertions + ) + { + std::ostringstream oss; + oss << sectionInfo.name << "@" << sectionInfo.lineInfo; + + if( !m_testCaseTracker->enterSection( oss.str() ) ) + return false; + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting( sectionInfo ); + + assertions = m_totals.assertions; + + return true; + } + bool testForMissingAssertions( Counts& assertions ) { + if( assertions.total() != 0 || + !m_config->warnAboutMissingAssertions() || + m_testCaseTracker->currentSectionHasChildren() ) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) { + if( std::uncaught_exception() ) { + m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) ); + return; + } + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + m_testCaseTracker->leaveSection(); + + m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) ); + m_messages.clear(); + } + + virtual void pushScopedMessage( MessageInfo const& message ) { + m_messages.push_back( message ); + } + + virtual void popScopedMessage( MessageInfo const& message ) { + m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); + } + + virtual bool shouldDebugBreak() const { + return m_config->shouldDebugBreak(); + } + + virtual std::string getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : ""; + } + + virtual const AssertionResult* getLastResult() const { + return &m_lastResult; + } + + public: + // !TBD We need to do this another way! + bool aborting() const { + return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); + } + + private: + + ResultAction::Value actOnCurrentResult( AssertionResult const& result ) { + m_lastResult = result; + assertionEnded( m_lastResult ); + + ResultAction::Value action = ResultAction::None; + + if( !m_lastResult.isOk() ) { + action = ResultAction::Failed; + if( shouldDebugBreak() ) + action = (ResultAction::Value)( action | ResultAction::Debug ); + if( aborting() ) + action = (ResultAction::Value)( action | ResultAction::Abort ); + } + return action; + } + + void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo ); + m_reporter->sectionStarting( testCaseSection ); + Counts prevAssertions = m_totals.assertions; + double duration = 0; + try { + m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); + TestCaseTracker::Guard guard( *m_testCaseTracker ); + + Timer timer; + timer.start(); + if( m_reporter->getPreferences().shouldRedirectStdOut ) { + StreamRedirect coutRedir( std::cout, redirectedCout ); + StreamRedirect cerrRedir( std::cerr, redirectedCerr ); + m_activeTestCase->invoke(); + } + else { + m_activeTestCase->invoke(); + } + duration = timer.getElapsedSeconds(); + } + catch( TestFailureException& ) { + // This just means the test was aborted due to failure + } + catch(...) { + ExpressionResultBuilder exResult( ResultWas::ThrewException ); + exResult << translateActiveException(); + actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo ) ); + } + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it ) + sectionEnded( it->info, it->prevAssertions, it->durationInSeconds ); + m_unfinishedSections.clear(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); + m_reporter->sectionEnded( testCaseSectionStats ); + } + + private: + struct UnfinishedSections { + UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds ) + : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo info; + Counts prevAssertions; + double durationInSeconds; + }; + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase; + Option m_testCaseTracker; + AssertionResult m_lastResult; + + Ptr m_config; + Totals m_totals; + Ptr m_reporter; + std::vector m_messages; + IRunner* m_prevRunner; + IResultCapture* m_prevResultCapture; + Ptr m_prevConfig; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + }; + +} // end namespace Catch + +// #included from: internal/catch_version.h +#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED + +namespace Catch { + + // Versioning information + struct Version { + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _buildNumber, + char const* const _branchName ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + buildNumber( _buildNumber ), + branchName( _branchName ) + {} + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const buildNumber; + char const* const branchName; + + private: + void operator=( Version const& ); + }; + + extern Version libraryVersion; +} + +#include +#include +#include + +namespace Catch { + + class Runner { + + public: + Runner( Ptr const& config ) + : m_config( config ) + { + openStream(); + makeReporter(); + } + + Totals runTests() { + + RunContext context( m_config.get(), m_reporter ); + + Totals totals; + + context.testGroupStarting( "", 1, 1 ); // deprecated? + + TestSpec testSpec = m_config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser().parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector testCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases ); + + int testsRunForGroup = 0; + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) { + testsRunForGroup++; + if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) { + + if( context.aborting() ) + break; + + totals += context.runTest( *it ); + m_testsAlreadyRun.insert( *it ); + } + } + context.testGroupEnded( "", totals, 1, 1 ); + return totals; + } + + private: + void openStream() { + // Open output file, if specified + if( !m_config->getFilename().empty() ) { + m_ofs.open( m_config->getFilename().c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << m_config->getFilename() << "'"; + throw std::domain_error( oss.str() ); + } + m_config->setStreamBuf( m_ofs.rdbuf() ); + } + } + void makeReporter() { + std::string reporterName = m_config->getReporterName().empty() + ? "console" + : m_config->getReporterName(); + + m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() ); + if( !m_reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); + } + } + + private: + Ptr m_config; + std::ofstream m_ofs; + Ptr m_reporter; + std::set m_testsAlreadyRun; + }; + + class Session { + static bool alreadyInstantiated; + + public: + + struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; + + Session() + : m_cli( makeCommandLineParser() ) { + if( alreadyInstantiated ) { + std::string msg = "Only one instance of Catch::Session can ever be used"; + std::cerr << msg << std::endl; + throw std::logic_error( msg ); + } + alreadyInstantiated = true; + } + ~Session() { + Catch::cleanUp(); + } + + void showHelp( std::string const& processName ) { + std::cout << "\nCatch v" << libraryVersion.majorVersion << "." + << libraryVersion.minorVersion << " build " + << libraryVersion.buildNumber; + if( libraryVersion.branchName != std::string( "master" ) ) + std::cout << " (" << libraryVersion.branchName << " branch)"; + std::cout << "\n"; + + m_cli.usage( std::cout, processName ); + std::cout << "For more detail usage please see the project docs\n" << std::endl; + } + + int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + try { + m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); + m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); + if( m_configData.showHelp ) + showHelp( m_configData.processName ); + m_config.reset(); + } + catch( std::exception& ex ) { + { + Colour colourGuard( Colour::Red ); + std::cerr << "\nError(s) in input:\n" + << Text( ex.what(), TextAttributes().setIndent(2) ) + << "\n\n"; + } + m_cli.usage( std::cout, m_configData.processName ); + return (std::numeric_limits::max)(); + } + return 0; + } + + void useConfigData( ConfigData const& _configData ) { + m_configData = _configData; + m_config.reset(); + } + + int run( int argc, char* const argv[] ) { + + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + + int run() { + if( m_configData.showHelp ) + return 0; + + try + { + config(); // Force config to be constructed + Runner runner( m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + return static_cast( runner.runTests().assertions.failed ); + } + catch( std::exception& ex ) { + std::cerr << ex.what() << std::endl; + return (std::numeric_limits::max)(); + } + } + + Clara::CommandLine const& cli() const { + return m_cli; + } + std::vector const& unusedTokens() const { + return m_unusedTokens; + } + ConfigData& configData() { + return m_configData; + } + Config& config() { + if( !m_config ) + m_config = new Config( m_configData ); + return *m_config; + } + + private: + Clara::CommandLine m_cli; + std::vector m_unusedTokens; + ConfigData m_configData; + Ptr m_config; + }; + + bool Session::alreadyInstantiated = false; + +} // end namespace Catch + +// #included from: catch_registry_hub.hpp +#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED + +// #included from: catch_test_case_registry_impl.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + class TestRegistry : public ITestCaseRegistry { + public: + TestRegistry() : m_unnamedCount( 0 ) {} + virtual ~TestRegistry(); + + virtual void registerTest( TestCase const& testCase ) { + std::string name = testCase.getTestCaseInfo().name; + if( name == "" ) { + std::ostringstream oss; + oss << "Anonymous test case " << ++m_unnamedCount; + return registerTest( testCase.withName( oss.str() ) ); + } + + if( m_functions.find( testCase ) == m_functions.end() ) { + m_functions.insert( testCase ); + m_functionsInOrder.push_back( testCase ); + if( !testCase.isHidden() ) + m_nonHiddenFunctions.push_back( testCase ); + } + else { + TestCase const& prev = *m_functions.find( testCase ); + { + Colour colourGuard( Colour::Red ); + std::cerr << "error: TEST_CASE( \"" << name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl; + } + exit(1); + } + } + + virtual std::vector const& getAllTests() const { + return m_functionsInOrder; + } + + virtual std::vector const& getAllNonHiddenTests() const { + return m_nonHiddenFunctions; + } + + virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases ) const { + for( std::vector::const_iterator it = m_functionsInOrder.begin(), + itEnd = m_functionsInOrder.end(); + it != itEnd; + ++it ) { + if( testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ) ) + matchingTestCases.push_back( *it ); + } + } + + private: + + std::set m_functions; + std::vector m_functionsInOrder; + std::vector m_nonHiddenFunctions; + size_t m_unnamedCount; + }; + + /////////////////////////////////////////////////////////////////////////// + + class FreeFunctionTestCase : public SharedImpl { + public: + + FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} + + virtual void invoke() const { + m_fun(); + } + + private: + virtual ~FreeFunctionTestCase(); + + TestFunction m_fun; + }; + + inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { + std::string className = classOrQualifiedMethodName; + if( startsWith( className, "&" ) ) + { + std::size_t lastColons = className.rfind( "::" ); + std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); + if( penultimateColons == std::string::npos ) + penultimateColons = 1; + className = className.substr( penultimateColons, lastColons-penultimateColons ); + } + return className; + } + + /////////////////////////////////////////////////////////////////////////// + + AutoReg::AutoReg( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + } + + AutoReg::~AutoReg() {} + + void AutoReg::registerTestCase( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + getMutableRegistryHub().registerTest + ( makeTestCase( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + +} // end namespace Catch + +// #included from: catch_reporter_registry.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED + +#include + +namespace Catch { + + class ReporterRegistry : public IReporterRegistry { + + public: + + virtual ~ReporterRegistry() { + deleteAllValues( m_factories ); + } + + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const { + FactoryMap::const_iterator it = m_factories.find( name ); + if( it == m_factories.end() ) + return NULL; + return it->second->create( ReporterConfig( config ) ); + } + + void registerReporter( std::string const& name, IReporterFactory* factory ) { + m_factories.insert( std::make_pair( name, factory ) ); + } + + FactoryMap const& getFactories() const { + return m_factories; + } + + private: + FactoryMap m_factories; + }; +} + +// #included from: catch_exception_translator_registry.hpp +#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED + +#ifdef __OBJC__ +#import "Foundation/Foundation.h" +#endif + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry() { + deleteAll( m_translators ); + } + + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( translator ); + } + + virtual std::string translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + throw; + } + @catch (NSException *exception) { + return toString( [exception description] ); + } +#else + throw; +#endif + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return tryTranslators( m_translators.begin() ); + } + } + + std::string tryTranslators( std::vector::const_iterator it ) const { + if( it == m_translators.end() ) + return "Unknown exception"; + + try { + return (*it)->translate(); + } + catch(...) { + return tryTranslators( it+1 ); + } + } + + private: + std::vector m_translators; + }; +} + +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub { + + RegistryHub( RegistryHub const& ); + void operator=( RegistryHub const& ); + + public: // IRegistryHub + RegistryHub() { + } + virtual IReporterRegistry const& getReporterRegistry() const { + return m_reporterRegistry; + } + virtual ITestCaseRegistry const& getTestCaseRegistry() const { + return m_testCaseRegistry; + } + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() { + return m_exceptionTranslatorRegistry; + } + + public: // IMutableRegistryHub + virtual void registerReporter( std::string const& name, IReporterFactory* factory ) { + m_reporterRegistry.registerReporter( name, factory ); + } + virtual void registerTest( TestCase const& testInfo ) { + m_testCaseRegistry.registerTest( testInfo ); + } + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + }; + + // Single, global, instance + inline RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = NULL; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = NULL; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + +} // end namespace Catch + +// #included from: catch_notimplemented_exception.hpp +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED + +#include + +namespace Catch { + + NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) + : m_lineInfo( lineInfo ) { + std::ostringstream oss; + oss << lineInfo << ": function "; + oss << "not implemented"; + m_what = oss.str(); + } + + const char* NotImplementedException::what() const CATCH_NOEXCEPT { + return m_what.c_str(); + } + +} // end namespace Catch + +// #included from: catch_context_impl.hpp +#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED + +// #included from: catch_stream.hpp +#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED + +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED + +#include + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() CATCH_NOEXCEPT; + }; +} + +#include +#include + +namespace Catch { + + template + class StreamBufImpl : public StreamBufBase { + char data[bufferSize]; + WriterF m_writer; + + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); + } + + ~StreamBufImpl() CATCH_NOEXCEPT { + sync(); + } + + private: + int overflow( int c ) { + sync(); + + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast( c ) ) ); + else + sputc( static_cast( c ) ); + } + return 0; + } + + int sync() { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + Stream::Stream() + : streamBuf( NULL ), isOwned( false ) + {} + + Stream::Stream( std::streambuf* _streamBuf, bool _isOwned ) + : streamBuf( _streamBuf ), isOwned( _isOwned ) + {} + + void Stream::release() { + if( isOwned ) { + delete streamBuf; + streamBuf = NULL; + isOwned = false; + } + } +} + +namespace Catch { + + class Context : public IMutableContext { + + Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {} + Context( Context const& ); + void operator=( Context const& ); + + public: // IContext + virtual IResultCapture& getResultCapture() { + return *m_resultCapture; + } + virtual IRunner& getRunner() { + return *m_runner; + } + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { + return getGeneratorsForCurrentTest() + .getGeneratorInfo( fileInfo, totalSize ) + .getCurrentIndex(); + } + virtual bool advanceGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + return generators && generators->moveNext(); + } + + virtual Ptr getConfig() const { + return m_config; + } + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ) { + m_resultCapture = resultCapture; + } + virtual void setRunner( IRunner* runner ) { + m_runner = runner; + } + virtual void setConfig( Ptr const& config ) { + m_config = config; + } + + friend IMutableContext& getCurrentMutableContext(); + + private: + IGeneratorsForTest* findGeneratorsForCurrentTest() { + std::string testName = getResultCapture().getCurrentTestName(); + + std::map::const_iterator it = + m_generatorsByTestName.find( testName ); + return it != m_generatorsByTestName.end() + ? it->second + : NULL; + } + + IGeneratorsForTest& getGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + if( !generators ) { + std::string testName = getResultCapture().getCurrentTestName(); + generators = createGeneratorsForTest(); + m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); + } + return *generators; + } + + private: + Ptr m_config; + IRunner* m_runner; + IResultCapture* m_resultCapture; + std::map m_generatorsByTestName; + }; + + namespace { + Context* currentContext = NULL; + } + IMutableContext& getCurrentMutableContext() { + if( !currentContext ) + currentContext = new Context(); + return *currentContext; + } + IContext& getCurrentContext() { + return getCurrentMutableContext(); + } + + Stream createStream( std::string const& streamName ) { + if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false ); + if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false ); + if( streamName == "debug" ) return Stream( new StreamBufImpl, true ); + + throw std::domain_error( "Unknown stream: " + streamName ); + } + + void cleanUpContext() { + delete currentContext; + currentContext = NULL; + } +} + +// #included from: catch_console_colour_impl.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED + +namespace Catch { namespace Detail { + struct IColourImpl { + virtual ~IColourImpl() {} + virtual void use( Colour::Code _colourCode ) = 0; + }; +}} + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +namespace Catch { +namespace { + + class Win32ColourImpl : public Detail::IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalAttributes = csbiInfo.wAttributes; + } + + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalAttributes ); + case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::Red: return setTextAttribute( FOREGROUND_RED ); + case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); + case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); + case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); + case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::Grey: return setTextAttribute( 0 ); + + case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); + case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); + case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); + case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + + private: + void setTextAttribute( WORD _textAttribute ) { + SetConsoleTextAttribute( stdoutHandle, _textAttribute ); + } + HANDLE stdoutHandle; + WORD originalAttributes; + }; + + inline bool shouldUseColourForPlatform() { + return true; + } + + static Detail::IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + return &s_instance; + } + +} // end anon namespace +} // end namespace Catch + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +#include + +namespace Catch { +namespace { + + // use POSIX/ ANSI console terminal codes + // Thanks to Adam Strzelecki for original contribution + // (http://github.com/nanoant) + // https://github.com/philsquared/Catch/pull/131 + class PosixColourImpl : public Detail::IColourImpl { + public: + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: + case Colour::White: return setColour( "[0m" ); + case Colour::Red: return setColour( "[0;31m" ); + case Colour::Green: return setColour( "[0;32m" ); + case Colour::Blue: return setColour( "[0:34m" ); + case Colour::Cyan: return setColour( "[0;36m" ); + case Colour::Yellow: return setColour( "[0;33m" ); + case Colour::Grey: return setColour( "[1;30m" ); + + case Colour::LightGrey: return setColour( "[0;37m" ); + case Colour::BrightRed: return setColour( "[1;31m" ); + case Colour::BrightGreen: return setColour( "[1;32m" ); + case Colour::BrightWhite: return setColour( "[1;37m" ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + private: + void setColour( const char* _escapeCode ) { + std::cout << '\033' << _escapeCode; + } + }; + + inline bool shouldUseColourForPlatform() { + return isatty(STDOUT_FILENO); + } + + static Detail::IColourImpl* platformColourInstance() { + static PosixColourImpl s_instance; + return &s_instance; + } + +} // end anon namespace +} // end namespace Catch + +#endif // not Windows + +namespace Catch { + + namespace { + struct NoColourImpl : Detail::IColourImpl { + void use( Colour::Code ) {} + + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + static bool shouldUseColour() { + return shouldUseColourForPlatform() && !isDebuggerActive(); + } + } + + Colour::Colour( Code _colourCode ){ use( _colourCode ); } + Colour::~Colour(){ use( None ); } + void Colour::use( Code _colourCode ) { + impl()->use( _colourCode ); + } + + Detail::IColourImpl* Colour::impl() { + return shouldUseColour() + ? platformColourInstance() + : NoColourImpl::instance(); + } + +} // end namespace Catch + +// #included from: catch_generators_impl.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct GeneratorInfo : IGeneratorInfo { + + GeneratorInfo( std::size_t size ) + : m_size( size ), + m_currentIndex( 0 ) + {} + + bool moveNext() { + if( ++m_currentIndex == m_size ) { + m_currentIndex = 0; + return false; + } + return true; + } + + std::size_t getCurrentIndex() const { + return m_currentIndex; + } + + std::size_t m_size; + std::size_t m_currentIndex; + }; + + /////////////////////////////////////////////////////////////////////////// + + class GeneratorsForTest : public IGeneratorsForTest { + + public: + ~GeneratorsForTest() { + deleteAll( m_generatorsInOrder ); + } + + IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { + std::map::const_iterator it = m_generatorsByName.find( fileInfo ); + if( it == m_generatorsByName.end() ) { + IGeneratorInfo* info = new GeneratorInfo( size ); + m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); + m_generatorsInOrder.push_back( info ); + return *info; + } + return *it->second; + } + + bool moveNext() { + std::vector::const_iterator it = m_generatorsInOrder.begin(); + std::vector::const_iterator itEnd = m_generatorsInOrder.end(); + for(; it != itEnd; ++it ) { + if( (*it)->moveNext() ) + return true; + } + return false; + } + + private: + std::map m_generatorsByName; + std::vector m_generatorsInOrder; + }; + + IGeneratorsForTest* createGeneratorsForTest() + { + return new GeneratorsForTest(); + } + +} // end namespace Catch + +// #included from: catch_assertionresult.hpp +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED + +namespace Catch { + + AssertionInfo::AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + capturedExpression( _capturedExpression ), + resultDisposition( _resultDisposition ) + {} + + AssertionResult::AssertionResult() {} + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + AssertionResult::~AssertionResult() {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return !m_info.capturedExpression.empty(); + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if( shouldNegate( m_info.resultDisposition ) ) + return "!" + m_info.capturedExpression; + else + return m_info.capturedExpression; + } + std::string AssertionResult::getExpressionInMacro() const { + if( m_info.macroName.empty() ) + return m_info.capturedExpression; + else + return m_info.macroName + "( " + m_info.capturedExpression + " )"; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + return m_resultData.reconstructedExpression; + } + + std::string AssertionResult::getMessage() const { + return m_resultData.message; + } + SourceLineInfo AssertionResult::getSourceInfo() const { + return m_info.lineInfo; + } + + std::string AssertionResult::getTestMacroName() const { + return m_info.macroName; + } + +} // end namespace Catch + +// #included from: catch_expressionresult_builder.hpp +#define TWOBLUECUBES_CATCH_EXPRESSIONRESULT_BUILDER_HPP_INCLUDED + +#include + +namespace Catch { + + ExpressionResultBuilder::ExpressionResultBuilder( ResultWas::OfType resultType ) { + m_data.resultType = resultType; + } + ExpressionResultBuilder::ExpressionResultBuilder( ExpressionResultBuilder const& other ) + : m_data( other.m_data ), + m_exprComponents( other.m_exprComponents ) + { + m_stream << other.m_stream.str(); + } + ExpressionResultBuilder& ExpressionResultBuilder::operator=(ExpressionResultBuilder const& other ) { + m_data = other.m_data; + m_exprComponents = other.m_exprComponents; + m_stream.str(""); + m_stream << other.m_stream.str(); + return *this; + } + ExpressionResultBuilder& ExpressionResultBuilder::setResultType( ResultWas::OfType result ) { + m_data.resultType = result; + return *this; + } + ExpressionResultBuilder& ExpressionResultBuilder::setResultType( bool result ) { + m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; + return *this; + } + ExpressionResultBuilder& ExpressionResultBuilder::endExpression( ResultDisposition::Flags resultDisposition ) { + m_exprComponents.shouldNegate = shouldNegate( resultDisposition ); + return *this; + } + ExpressionResultBuilder& ExpressionResultBuilder::setLhs( std::string const& lhs ) { + m_exprComponents.lhs = lhs; + return *this; + } + ExpressionResultBuilder& ExpressionResultBuilder::setRhs( std::string const& rhs ) { + m_exprComponents.rhs = rhs; + return *this; + } + ExpressionResultBuilder& ExpressionResultBuilder::setOp( std::string const& op ) { + m_exprComponents.op = op; + return *this; + } + AssertionResult ExpressionResultBuilder::buildResult( AssertionInfo const& info ) const + { + assert( m_data.resultType != ResultWas::Unknown ); + + AssertionResultData data = m_data; + + // Flip bool results if shouldNegate is set + if( m_exprComponents.shouldNegate && data.resultType == ResultWas::Ok ) + data.resultType = ResultWas::ExpressionFailed; + else if( m_exprComponents.shouldNegate && data.resultType == ResultWas::ExpressionFailed ) + data.resultType = ResultWas::Ok; + + data.message = m_stream.str(); + data.reconstructedExpression = reconstructExpression( info ); + if( m_exprComponents.shouldNegate ) { + if( m_exprComponents.op == "" ) + data.reconstructedExpression = "!" + data.reconstructedExpression; + else + data.reconstructedExpression = "!(" + data.reconstructedExpression + ")"; + } + return AssertionResult( info, data ); + } + std::string ExpressionResultBuilder::reconstructExpression( AssertionInfo const& info ) const { + if( m_exprComponents.op == "" ) + return m_exprComponents.lhs.empty() ? info.capturedExpression : m_exprComponents.op + m_exprComponents.lhs; + else if( m_exprComponents.op == "matches" ) + return m_exprComponents.lhs + " " + m_exprComponents.rhs; + else if( m_exprComponents.op != "!" ) { + if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && + m_exprComponents.lhs.find("\n") == std::string::npos && + m_exprComponents.rhs.find("\n") == std::string::npos ) + return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; + else + return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; + } + else + return "{can't expand - use " + info.macroName + "_FALSE( " + info.capturedExpression.substr(1) + " ) instead of " + info.macroName + "( " + info.capturedExpression + " ) for better diagnostics}"; + } + +} // end namespace Catch + +// #included from: catch_test_case_info.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED + +namespace Catch { + + inline bool isSpecialTag( std::string const& tag ) { + return tag == "." || + tag == "hide" || + tag == "!hide" || + tag == "!throws"; + } + inline bool isReservedTag( std::string const& tag ) { + return !isSpecialTag( tag ) && tag.size() > 0 && !isalnum( tag[0] ); + } + inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + if( isReservedTag( tag ) ) { + { + Colour colourGuard( Colour::Red ); + std::cerr + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n"; + } + { + Colour colourGuard( Colour::FileName ); + std::cerr << _lineInfo << std::endl; + } + exit(1); + } + } + + TestCase makeTestCase( ITestCase* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden( startsWith( _name, "./" ) ); // Legacy support + + // Parse out tags + std::set tags; + std::string desc, tag; + bool inTag = false; + for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { + char c = _descOrTags[i]; + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; + } + else { + if( c == ']' ) { + enforceNotReservedTag( tag, _lineInfo ); + + inTag = false; + if( tag == "hide" || tag == "." ) { + tags.insert( "hide" ); + tags.insert( "." ); + isHidden = true; + } + else { + tags.insert( tag ); + } + tag.clear(); + } + else + tag += c; + } + } + TestCaseInfo info( _name, _className, desc, tags, isHidden, _lineInfo ); + return TestCase( _testCase, info ); + } + + TestCaseInfo::TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + bool _isHidden, + SourceLineInfo const& _lineInfo ) + : name( _name ), + className( _className ), + description( _description ), + tags( _tags ), + lineInfo( _lineInfo ), + isHidden( _isHidden ), + throws( false ) + { + std::ostringstream oss; + for( std::set::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + if( *it == "!throws" ) + throws = true; + } + tagsAsString = oss.str(); + } + + TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) + : name( other.name ), + className( other.className ), + description( other.description ), + tags( other.tags ), + tagsAsString( other.tagsAsString ), + lineInfo( other.lineInfo ), + isHidden( other.isHidden ), + throws( other.throws ) + {} + + TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + + TestCase::TestCase( TestCase const& other ) + : TestCaseInfo( other ), + test( other.test ) + {} + + TestCase TestCase::withName( std::string const& _newName ) const { + TestCase other( *this ); + other.name = _newName; + return other; + } + + void TestCase::invoke() const { + test->invoke(); + } + + bool TestCase::isHidden() const { + return TestCaseInfo::isHidden; + } + bool TestCase::throws() const { + return TestCaseInfo::throws; + } + + void TestCase::swap( TestCase& other ) { + test.swap( other.test ); + className.swap( other.className ); + name.swap( other.name ); + description.swap( other.description ); + std::swap( lineInfo, other.lineInfo ); + } + + bool TestCase::operator == ( TestCase const& other ) const { + return test.get() == other.test.get() && + name == other.name && + className == other.className; + } + + bool TestCase::operator < ( TestCase const& other ) const { + return name < other.name; + } + TestCase& TestCase::operator = ( TestCase const& other ) { + TestCase temp( other ); + swap( temp ); + return *this; + } + + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } + +} // end namespace Catch + +// #included from: catch_version.hpp +#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED + +namespace Catch { + + // These numbers are maintained by a script + Version libraryVersion( 1, 0, 45, "master" ); +} + +// #included from: catch_message.hpp +#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + ScopedMessage::~ScopedMessage() { + getResultCapture().popScopedMessage( m_info ); + } + +} // end namespace Catch + +// #included from: catch_legacy_reporter_adapter.hpp +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED + +// #included from: catch_legacy_reporter_adapter.h +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED + +namespace Catch +{ + // Deprecated + struct IReporter : IShared { + virtual ~IReporter(); + + virtual bool shouldRedirectStdout() const = 0; + + virtual void StartTesting() = 0; + virtual void EndTesting( Totals const& totals ) = 0; + virtual void StartGroup( std::string const& groupName ) = 0; + virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; + virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; + virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; + virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; + virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; + virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; + virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; + virtual void Aborted() = 0; + virtual void Result( AssertionResult const& result ) = 0; + }; + + class LegacyReporterAdapter : public SharedImpl + { + public: + LegacyReporterAdapter( Ptr const& legacyReporter ); + virtual ~LegacyReporterAdapter(); + + virtual ReporterPreferences getPreferences() const; + virtual void noMatchingTestCases( std::string const& ); + virtual void testRunStarting( TestRunInfo const& ); + virtual void testGroupStarting( GroupInfo const& groupInfo ); + virtual void testCaseStarting( TestCaseInfo const& testInfo ); + virtual void sectionStarting( SectionInfo const& sectionInfo ); + virtual void assertionStarting( AssertionInfo const& ); + virtual bool assertionEnded( AssertionStats const& assertionStats ); + virtual void sectionEnded( SectionStats const& sectionStats ); + virtual void testCaseEnded( TestCaseStats const& testCaseStats ); + virtual void testGroupEnded( TestGroupStats const& testGroupStats ); + virtual void testRunEnded( TestRunStats const& testRunStats ); + + private: + Ptr m_legacyReporter; + }; +} + +namespace Catch +{ + LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) + : m_legacyReporter( legacyReporter ) + {} + LegacyReporterAdapter::~LegacyReporterAdapter() {} + + ReporterPreferences LegacyReporterAdapter::getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); + return prefs; + } + + void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} + void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { + m_legacyReporter->StartTesting(); + } + void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { + m_legacyReporter->StartGroup( groupInfo.name ); + } + void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { + m_legacyReporter->StartTestCase( testInfo ); + } + void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { + m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); + } + void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { + // Not on legacy interface + } + + bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + ExpressionResultBuilder expressionBuilder( it->type ); + expressionBuilder << it->message; + AssertionInfo info( it->macroName, it->lineInfo, "", ResultDisposition::Normal ); + AssertionResult result = expressionBuilder.buildResult( info ); + m_legacyReporter->Result( result ); + } + } + } + m_legacyReporter->Result( assertionStats.assertionResult ); + return true; + } + void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { + if( sectionStats.missingAssertions ) + m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); + m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); + } + void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { + m_legacyReporter->EndTestCase + ( testCaseStats.testInfo, + testCaseStats.totals, + testCaseStats.stdOut, + testCaseStats.stdErr ); + } + void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { + if( testGroupStats.aborting ) + m_legacyReporter->Aborted(); + m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); + } + void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { + m_legacyReporter->EndTesting( testRunStats.totals ); + } +} + +// #included from: catch_timer.hpp + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-long-long" +#endif + +#ifdef CATCH_PLATFORM_WINDOWS +#include +#else +#include +#endif + +namespace Catch { + + namespace { +#ifdef CATCH_PLATFORM_WINDOWS + uint64_t getCurrentTicks() { + static uint64_t hz=0, hzo=0; + if (!hz) { + QueryPerformanceFrequency((LARGE_INTEGER*)&hz); + QueryPerformanceCounter((LARGE_INTEGER*)&hzo); + } + uint64_t t; + QueryPerformanceCounter((LARGE_INTEGER*)&t); + return ((t-hzo)*1000000)/hz; + } +#else + uint64_t getCurrentTicks() { + timeval t; + gettimeofday(&t,NULL); + return (uint64_t)t.tv_sec * 1000000ull + (uint64_t)t.tv_usec; + } +#endif + } + + void Timer::start() { + m_ticks = getCurrentTicks(); + } + unsigned int Timer::getElapsedNanoseconds() const { + return (unsigned int)(getCurrentTicks() - m_ticks); + } + unsigned int Timer::getElapsedMilliseconds() const { + return (unsigned int)((getCurrentTicks() - m_ticks)/1000); + } + double Timer::getElapsedSeconds() const { + return (getCurrentTicks() - m_ticks)/1000000.0; + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +// #included from: catch_common.hpp +#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), ::tolower ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << " " << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << "s"; + return os; + } + + SourceLineInfo::SourceLineInfo() : line( 0 ){} + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) + : file( _file ), + line( _line ) + {} + SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) + : file( other.file ), + line( other.line ) + {} + bool SourceLineInfo::empty() const { + return file.empty(); + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { + return line == other.line && file == other.file; + } + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { +#ifndef __GNUG__ + os << info.file << "(" << info.line << ")"; +#else + os << info.file << ":" << info.line; +#endif + return os; + } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { + std::ostringstream oss; + oss << locationInfo << ": Internal Catch error: '" << message << "'"; + if( isTrue( true )) + throw std::logic_error( oss.str() ); + } +} + +// #included from: catch_section.hpp +#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED + +namespace Catch { + + Section::Section( SourceLineInfo const& lineInfo, + std::string const& name, + std::string const& description ) + : m_info( name, description, lineInfo ), + m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( m_info, m_assertions ) ) + { + m_timer.start(); + } + + Section::~Section() { + if( m_sectionIncluded ) + getCurrentContext().getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); + } + + // This indicates whether the section should be executed or not + Section::operator bool() { + return m_sectionIncluded; + } + +} // end namespace Catch + +// #included from: catch_debugger.hpp +#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED + +#include + +#ifdef CATCH_PLATFORM_MAC + + #include + #include + #include + #include + #include + + namespace Catch{ + + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive(){ + + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) { + std::cerr << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; + return false; + } + + // We're being debugged if the P_TRACED flag is set. + + return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + } + } // namespace Catch + +#elif defined(_MSC_VER) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#else + namespace Catch { + inline bool isDebuggerActive() { return false; } + } +#endif // Platform + +#ifdef CATCH_PLATFORM_WINDOWS + extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + std::cout << text; + } + } +#endif // Platform + +// #included from: catch_tostring.hpp +#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED + +namespace Catch { + +std::string toString( std::string const& value ) { + std::string s = value; + if( getCurrentContext().getConfig()->showInvisibles() ) { + for(size_t i = 0; i < s.size(); ++i ) { + std::string subs; + switch( s[i] ) { + case '\n': subs = "\\n"; break; + case '\t': subs = "\\t"; break; + default: break; + } + if( !subs.empty() ) { + s = s.substr( 0, i ) + subs + s.substr( i+1 ); + ++i; + } + } + } + return "\"" + s + "\""; +} +std::string toString( std::wstring const& value ) { + + std::string s; + s.reserve( value.size() ); + for(size_t i = 0; i < value.size(); ++i ) + s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; + return toString( s ); +} + +std::string toString( const char* const value ) { + return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); +} + +std::string toString( char* const value ) { + return Catch::toString( static_cast( value ) ); +} + +std::string toString( int value ) { + std::ostringstream oss; + oss << value; + return oss.str(); +} + +std::string toString( unsigned long value ) { + std::ostringstream oss; + if( value > 8192 ) + oss << "0x" << std::hex << value; + else + oss << value; + return oss.str(); +} + +std::string toString( unsigned int value ) { + return toString( static_cast( value ) ); +} + +std::string toString( const double value ) { + std::ostringstream oss; + oss << std::setprecision( 10 ) + << std::fixed + << value; + std::string d = oss.str(); + std::size_t i = d.find_last_not_of( '0' ); + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) + i++; + d = d.substr( 0, i+1 ); + } + return d; +} + +std::string toString( bool value ) { + return value ? "true" : "false"; +} + +std::string toString( char value ) { + return value < ' ' + ? toString( static_cast( value ) ) + : Detail::makeString( value ); +} + +std::string toString( signed char value ) { + return toString( static_cast( value ) ); +} + +std::string toString( unsigned char value ) { + return toString( static_cast( value ) ); +} + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ) { + return "nullptr"; +} +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ) { + if( !nsstring ) + return "nil"; + return std::string( "@\"" ) + [nsstring UTF8String] + "\""; + } + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { + if( !nsstring ) + return "nil"; + return std::string( "@\"" ) + [nsstring UTF8String] + "\""; + } + std::string toString( NSObject* const& nsObject ) { + return toString( [nsObject description] ); + } +#endif + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_xml.hpp +#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED + +// #included from: catch_reporter_bases.hpp +#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED + +namespace Catch { + + struct StreamingReporterBase : SharedImpl { + + StreamingReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + {} + + virtual ~StreamingReporterBase(); + + virtual void noMatchingTestCases( std::string const& ) {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) { + currentTestRunInfo = _testRunInfo; + } + virtual void testGroupStarting( GroupInfo const& _groupInfo ) { + currentGroupInfo = _groupInfo; + } + + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) { + currentTestCaseInfo = _testInfo; + } + virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + m_sectionStack.push_back( _sectionInfo ); + } + + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) { + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) { + currentTestCaseInfo.reset(); + assert( m_sectionStack.empty() ); + } + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) { + currentGroupInfo.reset(); + } + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + Ptr m_config; + std::ostream& stream; + + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; + + std::vector m_sectionStack; + }; + + struct CumulativeReporterBase : SharedImpl { + template + struct Node : SharedImpl<> { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} + + typedef std::vector > ChildNodes; + T value; + ChildNodes children; + }; + struct SectionNode : SharedImpl<> { + explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} + virtual ~SectionNode(); + + bool operator == ( SectionNode const& other ) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + bool operator == ( Ptr const& other ) const { + return operator==( *other ); + } + + SectionStats stats; + typedef std::vector > ChildSections; + typedef std::vector Assertions; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + + struct BySectionInfo { + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + bool operator() ( Ptr const& node ) const { + return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + } + private: + BySectionInfo& operator=( BySectionInfo const& other ); // = delete; + + SectionInfo const& m_other; + }; + + typedef Node TestCaseNode; + typedef Node TestGroupNode; + typedef Node TestRunNode; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + {} + ~CumulativeReporterBase(); + + virtual void testRunStarting( TestRunInfo const& ) {} + virtual void testGroupStarting( GroupInfo const& ) {} + + virtual void testCaseStarting( TestCaseInfo const& ) {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + Ptr node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = new SectionNode( incompleteStats ); + node = m_rootSection; + } + else { + SectionNode& parentNode = *m_sectionStack.back(); + SectionNode::ChildSections::const_iterator it = + std::find_if( parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo( sectionInfo ) ); + if( it == parentNode.childSections.end() ) { + node = new SectionNode( incompleteStats ); + parentNode.childSections.push_back( node ); + } + else + node = *it; + } + m_sectionStack.push_back( node ); + m_deepestSection = node; + } + + virtual void assertionStarting( AssertionInfo const& ) {} + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back( assertionStats ); + return true; + } + virtual void sectionEnded( SectionStats const& sectionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + Ptr node = new TestCaseNode( testCaseStats ); + assert( m_sectionStack.size() == 0 ); + node->children.push_back( m_rootSection ); + m_testCases.push_back( node ); + m_rootSection.reset(); + + assert( m_deepestSection ); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + Ptr node = new TestGroupNode( testGroupStats ); + node->children.swap( m_testCases ); + m_testGroups.push_back( node ); + } + virtual void testRunEnded( TestRunStats const& testRunStats ) { + Ptr node = new TestRunNode( testRunStats ); + node->children.swap( m_testGroups ); + m_testRuns.push_back( node ); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + Ptr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector > > m_sections; + std::vector > m_testCases; + std::vector > m_testGroups; + + std::vector > m_testRuns; + + Ptr m_rootSection; + Ptr m_deepestSection; + std::vector > m_sectionStack; + + }; + +} // end namespace Catch + +// #included from: ../internal/catch_reporter_registrars.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED + +namespace Catch { + + template + class LegacyReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new LegacyReporterAdapter( new T( config ) ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + LegacyReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + class ReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + + // *** Please Note ***: + // - If you end up here looking at a compiler error because it's trying to register + // your custom reporter class be aware that the native reporter interface has changed + // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via + // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. + // However please consider updating to the new interface as the old one is now + // deprecated and will probably be removed quite soon! + // Please contact me via github if you have any questions at all about this. + // In fact, ideally, please contact me anyway to let me know you've hit this - as I have + // no idea who is actually using custom reporters at all (possibly no-one!). + // The new interface is designed to minimise exposure to interface changes in the future. + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; +} + +#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ + namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +// #included from: ../internal/catch_xmlwriter.hpp +#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = NULL; + } + + ~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + ScopedElement& writeText( std::string const& text, bool indent = true ) { + m_writer->writeText( text, indent ); + return *this; + } + + template + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer; + }; + + XmlWriter() + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &std::cout ) + {} + + XmlWriter( std::ostream& os ) + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &os ) + {} + + ~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + +# ifndef CATCH_CPP11_OR_GREATER + XmlWriter& operator = ( XmlWriter const& other ) { + XmlWriter temp( other ); + swap( temp ); + return *this; + } +# else + XmlWriter( XmlWriter const& ) = default; + XmlWriter( XmlWriter && ) = default; + XmlWriter& operator = ( XmlWriter const& ) = default; + XmlWriter& operator = ( XmlWriter && ) = default; +# endif + + void swap( XmlWriter& other ) { + std::swap( m_tagIsOpen, other.m_tagIsOpen ); + std::swap( m_needsNewline, other.m_needsNewline ); + std::swap( m_tags, other.m_tags ); + std::swap( m_indent, other.m_indent ); + std::swap( m_os, other.m_os ); + } + + XmlWriter& startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + stream() << m_indent << "<" << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + ScopedElement scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + stream() << "/>\n"; + m_tagIsOpen = false; + } + else { + stream() << m_indent << "\n"; + } + m_tags.pop_back(); + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) { + stream() << " " << name << "=\""; + writeEncodedText( attribute ); + stream() << "\""; + } + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, bool attribute ) { + stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; + return *this; + } + + template + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + if( !name.empty() ) + stream() << " " << name << "=\"" << attribute << "\""; + return *this; + } + + XmlWriter& writeText( std::string const& text, bool indent = true ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + stream() << m_indent; + writeEncodedText( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& writeComment( std::string const& text ) { + ensureTagClosed(); + stream() << m_indent << ""; + m_needsNewline = true; + return *this; + } + + XmlWriter& writeBlankLine() { + ensureTagClosed(); + stream() << "\n"; + return *this; + } + + private: + + std::ostream& stream() { + return *m_os; + } + + void ensureTagClosed() { + if( m_tagIsOpen ) { + stream() << ">\n"; + m_tagIsOpen = false; + } + } + + void newlineIfNecessary() { + if( m_needsNewline ) { + stream() << "\n"; + m_needsNewline = false; + } + } + + void writeEncodedText( std::string const& text ) { + static const char* charsToEncode = "<&\""; + std::string mtext = text; + std::string::size_type pos = mtext.find_first_of( charsToEncode ); + while( pos != std::string::npos ) { + stream() << mtext.substr( 0, pos ); + + switch( mtext[pos] ) { + case '<': + stream() << "<"; + break; + case '&': + stream() << "&"; + break; + case '\"': + stream() << """; + break; + } + mtext = mtext.substr( pos+1 ); + pos = mtext.find_first_of( charsToEncode ); + } + stream() << mtext; + } + + bool m_tagIsOpen; + bool m_needsNewline; + std::vector m_tags; + std::string m_indent; + std::ostream* m_os; + }; + +} +namespace Catch { + class XmlReporter : public SharedImpl { + public: + XmlReporter( ReporterConfig const& config ) : m_config( config ), m_sectionDepth( 0 ) {} + + static std::string getDescription() { + return "Reports test results as an XML document"; + } + virtual ~XmlReporter(); + + private: // IReporter + + virtual bool shouldRedirectStdout() const { + return true; + } + + virtual void StartTesting() { + m_xml = XmlWriter( m_config.stream() ); + m_xml.startElement( "Catch" ); + if( !m_config.fullConfig()->name().empty() ) + m_xml.writeAttribute( "name", m_config.fullConfig()->name() ); + } + + virtual void EndTesting( const Totals& totals ) { + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", totals.assertions.passed ) + .writeAttribute( "failures", totals.assertions.failed ); + m_xml.endElement(); + } + + virtual void StartGroup( const std::string& groupName ) { + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupName ); + } + + virtual void EndGroup( const std::string&, const Totals& totals ) { + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", totals.assertions.passed ) + .writeAttribute( "failures", totals.assertions.failed ); + m_xml.endElement(); + } + + virtual void StartSection( const std::string& sectionName, const std::string& description ) { + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionName ) ) + .writeAttribute( "description", description ); + } + } + virtual void NoAssertionsInSection( const std::string& ) {} + virtual void NoAssertionsInTestCase( const std::string& ) {} + + virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) { + if( --m_sectionDepth > 0 ) { + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", assertions.passed ) + .writeAttribute( "failures", assertions.failed ); + m_xml.endElement(); + } + } + + virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) { + m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); + m_currentTestSuccess = true; + } + + virtual void Result( const Catch::AssertionResult& assertionResult ) { + if( !m_config.fullConfig()->includeSuccessfulResults() && assertionResult.getResultType() == ResultWas::Ok ) + return; + + if( assertionResult.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", assertionResult.succeeded() ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ); + + m_xml.scopedElement( "Original" ) + .writeText( assertionResult.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( assertionResult.getExpandedExpression() ); + m_currentTestSuccess &= assertionResult.succeeded(); + } + + switch( assertionResult.getResultType() ) { + case ResultWas::ThrewException: + m_xml.scopedElement( "Exception" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + m_currentTestSuccess = false; + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Warning: + m_xml.scopedElement( "Warning" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::ExplicitFailure: + m_xml.scopedElement( "Failure" ) + .writeText( assertionResult.getMessage() ); + m_currentTestSuccess = false; + break; + case ResultWas::Unknown: + case ResultWas::Ok: + case ResultWas::FailureBit: + case ResultWas::ExpressionFailed: + case ResultWas::Exception: + case ResultWas::DidntThrowException: + break; + } + if( assertionResult.hasExpression() ) + m_xml.endElement(); + } + + virtual void Aborted() { + // !TBD + } + + virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) { + m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess ); + m_xml.endElement(); + } + + private: + ReporterConfig m_config; + bool m_currentTestSuccess; + XmlWriter m_xml; + int m_sectionDepth; + }; + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_junit.hpp +#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED + +#include + +namespace Catch { + + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter( ReporterConfig const& _config ) + : CumulativeReporterBase( _config ), + xml( _config.stream() ) + {} + + ~JunitReporter(); + + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + virtual void noMatchingTestCases( std::string const& /*spec*/ ) {} + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = true; + return prefs; + } + + virtual void testRunStarting( TestRunInfo const& runInfo ) { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + virtual void testRunEndedCumulative() { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", "tbd" ); // !TBD + + // Write test cases + for( TestGroupNode::ChildNodes::const_iterator + it = groupNode.children.begin(), itEnd = groupNode.children.end(); + it != itEnd; + ++it ) + writeTestCase( **it ); + + xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); + xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); + } + + void writeTestCase( TestCaseNode const& testCaseNode ) { + TestCaseStats const& stats = testCaseNode.value; + + // All test cases have exactly one section - which represents the + // test case itself. That section may have 0-n nested sections + assert( testCaseNode.children.size() == 1 ); + SectionNode const& rootSection = *testCaseNode.children.front(); + + std::string className = stats.testInfo.className; + + if( className.empty() ) { + if( rootSection.childSections.empty() ) + className = "global"; + } + writeSection( className, "", rootSection ); + } + + void writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode ) { + std::string name = trim( sectionNode.stats.sectionInfo.name ); + if( !rootName.empty() ) + name = rootName + "/" + name; + + if( !sectionNode.assertions.empty() || + !sectionNode.stdOut.empty() || + !sectionNode.stdErr.empty() ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); + if( className.empty() ) { + xml.writeAttribute( "classname", name ); + xml.writeAttribute( "name", "root" ); + } + else { + xml.writeAttribute( "classname", className ); + xml.writeAttribute( "name", name ); + } + xml.writeAttribute( "time", toString( sectionNode.stats.durationInSeconds ) ); + + writeAssertions( sectionNode ); + + if( !sectionNode.stdOut.empty() ) + xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); + if( !sectionNode.stdErr.empty() ) + xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); + } + for( SectionNode::ChildSections::const_iterator + it = sectionNode.childSections.begin(), + itEnd = sectionNode.childSections.end(); + it != itEnd; + ++it ) + if( className.empty() ) + writeSection( name, "", **it ); + else + writeSection( className, name, **it ); + } + + void writeAssertions( SectionNode const& sectionNode ) { + for( SectionNode::Assertions::const_iterator + it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); + it != itEnd; + ++it ) + writeAssertion( *it ); + } + void writeAssertion( AssertionStats const& stats ) { + AssertionResult const& result = stats.assertionResult; + if( !result.isOk() ) { + std::string elementName; + switch( result.getResultType() ) { + case ResultWas::ThrewException: + elementName = "error"; + break; + case ResultWas::ExplicitFailure: + elementName = "failure"; + break; + case ResultWas::ExpressionFailed: + elementName = "failure"; + break; + case ResultWas::DidntThrowException: + elementName = "failure"; + break; + + // We should never see these here: + case ResultWas::Info: + case ResultWas::Warning: + case ResultWas::Ok: + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + elementName = "internalError"; + break; + } + + XmlWriter::ScopedElement e = xml.scopedElement( elementName ); + + xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "type", result.getTestMacroName() ); + + std::ostringstream oss; + if( !result.getMessage().empty() ) + oss << result.getMessage() << "\n"; + for( std::vector::const_iterator + it = stats.infoMessages.begin(), + itEnd = stats.infoMessages.end(); + it != itEnd; + ++it ) + if( it->type == ResultWas::Info ) + oss << it->message << "\n"; + + oss << "at " << result.getSourceInfo(); + xml.writeText( oss.str(), false ); + } + } + + XmlWriter xml; + Timer suiteTimer; + std::ostringstream stdOutForSuite; + std::ostringstream stdErrForSuite; + unsigned int unexpectedExceptions; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_console.hpp +#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED + +#include + +namespace Catch { + + struct ConsoleReporter : StreamingReporterBase { + ConsoleReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_headerPrinted( false ), + m_atLeastOneTestCasePrinted( false ) + {} + + virtual ~ConsoleReporter(); + static std::string getDescription() { + return "Reports test results as plain lines of text"; + } + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + lazyPrint(); + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + stream << std::endl; + return true; + } + + virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting( _sectionInfo ); + } + virtual void sectionEnded( SectionStats const& _sectionStats ) { + if( _sectionStats.missingAssertions ) { + lazyPrint(); + Colour colour( Colour::ResultError ); + if( m_sectionStack.size() > 1 ) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if( m_headerPrinted ) { + if( m_config->showDurations() == ShowDurations::Always ) + stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + m_headerPrinted = false; + } + else { + if( m_config->showDurations() == ShowDurations::Always ) + stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + } + StreamingReporterBase::sectionEnded( _sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) { + StreamingReporterBase::testCaseEnded( _testCaseStats ); + m_headerPrinted = false; + } + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) { + if( currentGroupInfo.used ) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals( _testGroupStats.totals ); + stream << "\n" << std::endl; + } + StreamingReporterBase::testGroupEnded( _testGroupStats ); + } + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + if( m_atLeastOneTestCasePrinted ) + printTotalsDivider(); + printTotals( _testRunStats.totals ); + stream << "\n" << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ), + stats( _stats ), + result( _stats.assertionResult ), + colour( Colour::None ), + message( result.getMessage() ), + messages( _stats.infoMessages ), + printInfoMessages( _printInfoMessages ) + { + switch( result.getResultType() ) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + //if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; + } + else { + colour = Colour::Error; + passOrFail = "FAILED"; + } + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with message"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if( _stats.infoMessages.size() == 1 ) + messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; + } + } + + void print() const { + printSourceInfo(); + if( stats.totals.assertions.total() > 0 ) { + if( result.isOk() ) + stream << "\n"; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } + else { + stream << "\n"; + } + printMessage(); + } + + private: + void printResultType() const { + if( !passOrFail.empty() ) { + Colour colourGuard( colour ); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if( result.hasExpression() ) { + Colour colourGuard( Colour::OriginalExpression ); + stream << " "; + stream << result.getExpressionInMacro(); + stream << "\n"; + } + } + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + stream << "with expansion:\n"; + Colour colourGuard( Colour::ReconstructedExpression ); + stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n"; + } + } + void printMessage() const { + if( !messageLabel.empty() ) + stream << messageLabel << ":" << "\n"; + for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); + it != itEnd; + ++it ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || it->type != ResultWas::Info ) + stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n"; + } + } + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector messages; + bool printInfoMessages; + }; + + void lazyPrint() { + + if( !currentTestRunInfo.used ) + lazyPrintRunInfo(); + if( !currentGroupInfo.used ) + lazyPrintGroupInfo(); + + if( !m_headerPrinted ) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } + m_atLeastOneTestCasePrinted = true; + } + void lazyPrintRunInfo() { + stream << "\n" << getLineOfChars<'~'>() << "\n"; + Colour colour( Colour::SecondaryText ); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion.majorVersion << "." + << libraryVersion.minorVersion << " b" + << libraryVersion.buildNumber; + if( libraryVersion.branchName != std::string( "master" ) ) + stream << " (" << libraryVersion.branchName << ")"; + stream << " host application.\n" + << "Run with -? for options\n\n"; + + currentTestRunInfo.used = true; + } + void lazyPrintGroupInfo() { + if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { + printClosedHeader( "Group: " + currentGroupInfo->name ); + currentGroupInfo.used = true; + } + } + void printTestCaseAndSectionHeader() { + assert( !m_sectionStack.empty() ); + printOpenHeader( currentTestCaseInfo->name ); + + if( m_sectionStack.size() > 1 ) { + Colour colourGuard( Colour::Headers ); + + std::vector::const_iterator + it = m_sectionStack.begin()+1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for( ; it != itEnd; ++it ) + printHeaderString( it->name, 2 ); + } + + SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; + + if( !lineInfo.empty() ){ + stream << getLineOfChars<'-'>() << "\n"; + Colour colourGuard( Colour::FileName ); + stream << lineInfo << "\n"; + } + stream << getLineOfChars<'.'>() << "\n" << std::endl; + } + + void printClosedHeader( std::string const& _name ) { + printOpenHeader( _name ); + stream << getLineOfChars<'.'>() << "\n"; + } + void printOpenHeader( std::string const& _name ) { + stream << getLineOfChars<'-'>() << "\n"; + { + Colour colourGuard( Colour::Headers ); + printHeaderString( _name ); + } + } + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { + std::size_t i = _string.find( ": " ); + if( i != std::string::npos ) + i+=2; + else + i = 0; + stream << Text( _string, TextAttributes() + .setIndent( indent+i) + .setInitialIndent( indent ) ) << "\n"; + } + + void printTotals( const Totals& totals ) { + if( totals.testCases.total() == 0 ) { + stream << "No tests ran"; + } + else if( totals.assertions.total() == 0 ) { + Colour colour( Colour::Yellow ); + printCounts( "test case", totals.testCases ); + stream << " (no assertions)"; + } + else if( totals.assertions.failed ) { + Colour colour( Colour::ResultError ); + printCounts( "test case", totals.testCases ); + if( totals.testCases.failed > 0 ) { + stream << " ("; + printCounts( "assertion", totals.assertions ); + stream << ")"; + } + } + else { + Colour colour( Colour::ResultSuccess ); + stream << "All tests passed (" + << pluralise( totals.assertions.passed, "assertion" ) << " in " + << pluralise( totals.testCases.passed, "test case" ) << ")"; + } + } + void printCounts( std::string const& label, Counts const& counts ) { + if( counts.total() == 1 ) { + stream << "1 " << label << " - "; + if( counts.failed ) + stream << "failed"; + else + stream << "passed"; + } + else { + stream << counts.total() << " " << label << "s "; + if( counts.passed ) { + if( counts.failed ) + stream << "- " << counts.failed << " failed"; + else if( counts.passed == 2 ) + stream << "- both passed"; + else + stream << "- all passed"; + } + else { + if( counts.failed == 2 ) + stream << "- both failed"; + else + stream << "- all failed"; + } + } + } + + void printTotalsDivider() { + stream << getLineOfChars<'='>() << "\n"; + } + void printSummaryDivider() { + stream << getLineOfChars<'-'>() << "\n"; + } + template + static char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; + } + + private: + bool m_headerPrinted; + bool m_atLeastOneTestCasePrinted; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_compact.hpp +#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + CompactReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual ~CompactReporter(); + + static std::string getDescription() { + return "Reports test results on a single line, suitable for IDEs"; + } + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; + } + + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotals( _testRunStats.totals ); + stream << "\n" << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , stats( _stats ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + + switch( result.getResultType() ) { + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType( Colour::None, "warning" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType( Colour::Error, failedString() ); + printIssue( "explicitly" ); + printRemainingMessages( Colour::None ); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType( Colour::Error, "** internal error **" ); + break; + } + } + + private: + // Colour::LightGrey + + static Colour dimColour() { return Colour::FileName; } + +#ifdef CATCH_PLATFORM_MAC + static const char* failedString() { return "FAILED"; } + static const char* passedString() { return "PASSED"; } +#else + static const char* failedString() { return "failed"; } + static const char* passedString() { return "passed"; } +#endif + + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ":"; + } + + void printResultType( Colour colour, std::string passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << " " << passOrFail; + } + stream << ":"; + } + } + + void printIssue( std::string issue ) const { + stream << " " << issue; + } + + void printExpressionWas() { + if( result.hasExpression() ) { + stream << ";"; + { + Colour colour( dimColour() ); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if( result.hasExpression() ) { + stream << " " << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + { + Colour colour( dimColour() ); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if ( itMessage != messages.end() ) { + stream << " '" << itMessage->message << "'"; + ++itMessage; + } + } + + void printRemainingMessages( Colour colour = dimColour() ) { + if ( itMessage == messages.end() ) + return; + + // using messages.end() directly yields compilation error: + std::vector::const_iterator itEnd = messages.end(); + const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); + + { + Colour colourGuard( colour ); + stream << " with " << pluralise( N, "message" ) << ":"; + } + + for(; itMessage != itEnd; ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || itMessage->type != ResultWas::Info ) { + stream << " '" << itMessage->message << "'"; + if ( ++itMessage != itEnd ) { + Colour colourGuard( dimColour() ); + stream << " and"; + } + } + } + } + + private: + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + std::vector messages; + std::vector::const_iterator itMessage; + bool printInfoMessages; + }; + + // Colour, message variants: + // - white: No tests ran. + // - red: Failed [both/all] N test cases, failed [both/all] M assertions. + // - white: Passed [both/all] N test cases (no assertions). + // - red: Failed N tests cases, failed M assertions. + // - green: Passed [both/all] N tests cases with M assertions. + + std::string bothOrAll( std::size_t count ) const { + return count == 1 ? "" : count == 2 ? "both " : "all " ; + } + + void printTotals( const Totals& totals ) const { + if( totals.testCases.total() == 0 ) { + stream << "No tests ran."; + } + else if( totals.testCases.failed == totals.testCases.total() ) { + Colour colour( Colour::ResultError ); + const std::string qualify_assertions_failed = + totals.assertions.failed == totals.assertions.total() ? + bothOrAll( totals.assertions.failed ) : ""; + stream << + "Failed " << bothOrAll( totals.testCases.failed ) + << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << qualify_assertions_failed << + pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else if( totals.assertions.total() == 0 ) { + stream << + "Passed " << bothOrAll( totals.testCases.total() ) + << pluralise( totals.testCases.total(), "test case" ) + << " (no assertions)."; + } + else if( totals.assertions.failed ) { + Colour colour( Colour::ResultError ); + stream << + "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else { + Colour colour( Colour::ResultSuccess ); + stream << + "Passed " << bothOrAll( totals.testCases.passed ) + << pluralise( totals.testCases.passed, "test case" ) << + " with " << pluralise( totals.assertions.passed, "assertion" ) << "."; + } + } + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch + +namespace Catch { + NonCopyable::~NonCopyable() {} + IShared::~IShared() {} + StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} + IContext::~IContext() {} + IResultCapture::~IResultCapture() {} + ITestCase::~ITestCase() {} + ITestCaseRegistry::~ITestCaseRegistry() {} + IRegistryHub::~IRegistryHub() {} + IMutableRegistryHub::~IMutableRegistryHub() {} + IExceptionTranslator::~IExceptionTranslator() {} + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} + IReporter::~IReporter() {} + IReporterFactory::~IReporterFactory() {} + IReporterRegistry::~IReporterRegistry() {} + IStreamingReporter::~IStreamingReporter() {} + AssertionStats::~AssertionStats() {} + SectionStats::~SectionStats() {} + TestCaseStats::~TestCaseStats() {} + TestGroupStats::~TestGroupStats() {} + TestRunStats::~TestRunStats() {} + CumulativeReporterBase::SectionNode::~SectionNode() {} + CumulativeReporterBase::~CumulativeReporterBase() {} + + StreamingReporterBase::~StreamingReporterBase() {} + ConsoleReporter::~ConsoleReporter() {} + CompactReporter::~CompactReporter() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + XmlReporter::~XmlReporter() {} + JunitReporter::~JunitReporter() {} + TestRegistry::~TestRegistry() {} + FreeFunctionTestCase::~FreeFunctionTestCase() {} + IGeneratorInfo::~IGeneratorInfo() {} + IGeneratorsForTest::~IGeneratorsForTest() {} + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} + + Matchers::Impl::StdString::Equals::~Equals() {} + Matchers::Impl::StdString::Contains::~Contains() {} + Matchers::Impl::StdString::StartsWith::~StartsWith() {} + Matchers::Impl::StdString::EndsWith::~EndsWith() {} + + void Config::dummy() {} + + INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter ) +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif + +#ifdef CATCH_CONFIG_MAIN +// #included from: internal/catch_default_main.hpp +#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED + +#ifndef __OBJC__ + +// Standard C/C++ main entry point +int main (int argc, char * const argv[]) { + return Catch::Session().run( argc, argv ); +} + +#else // __OBJC__ + +// Objective-C entry point +int main (int argc, char * const argv[]) { +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int result = Catch::Session().run( argc, (char* const*)argv ); + +#if !CATCH_ARC_ENABLED + [pool drain]; +#endif + + return result; +} + +#endif // __OBJC__ + +#endif + +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +# undef CLARA_CONFIG_MAIN +#endif + +////// + +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) +#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "CATCH_REQUIRE_FALSE" ) + +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) + +#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) +#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CATCH_CHECK_FALSE" ) +#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) +#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) +#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) + +#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) + +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) +#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) +#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) + #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) +#else + #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) + #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) +#endif +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#else +#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#endif +#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) +#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "REQUIRE_FALSE" ) + +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "REQUIRE_THROWS" ) +#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) + +#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) +#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CHECK_FALSE" ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) +#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) + +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" ) +#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) + +#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) +#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) +#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) + #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) +#else + #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) + #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) +#endif +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#else +#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#endif +#define GIVEN( desc ) SECTION( " Given: " desc, "" ) +#define WHEN( desc ) SECTION( " When: " desc, "" ) +#define AND_WHEN( desc ) SECTION( "And when: " desc, "" ) +#define THEN( desc ) SECTION( " Then: " desc, "" ) +#define AND_THEN( desc ) SECTION( " And: " desc, "" ) + +using Catch::Detail::Approx; + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + diff --git a/test/optional_unit.cpp b/test/optional_unit.cpp new file mode 100644 index 000000000..a6573ca41 --- /dev/null +++ b/test/optional_unit.cpp @@ -0,0 +1,82 @@ +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" + +#include "optional.hpp" + +using namespace mapbox; + +struct dummy { + dummy(int _m_1, int _m_2) : m_1(_m_1), m_2(_m_2) {} + int m_1; + int m_2; + +}; + +int main (int argc, char* const argv[]) +{ + int result = Catch::Session().run(argc, argv); + if (!result) printf("\x1b[1;32m ✓ \x1b[0m\n"); + return result; +} + +TEST_CASE( "optional can be instantiated with a POD type", "[optiona]" ) { + mapbox::util::optional dbl_opt; + + REQUIRE(!dbl_opt); + dbl_opt = 3.1415; + REQUIRE(dbl_opt); + + REQUIRE(dbl_opt.get() == 3.1415); + REQUIRE(*dbl_opt == 3.1415); +} + +TEST_CASE( "copy c'tor", "[optiona]" ) { + mapbox::util::optional dbl_opt; + + REQUIRE(!dbl_opt); + dbl_opt = 3.1415; + REQUIRE(dbl_opt); + + mapbox::util::optional other = dbl_opt; + + REQUIRE(other.get() == 3.1415); + REQUIRE(*other == 3.1415); +} + +TEST_CASE( "const operator*, const get()", "[optiona]" ) { + mapbox::util::optional dbl_opt = 3.1415; + + REQUIRE(dbl_opt); + + const double pi1 = dbl_opt.get(); + const double pi2 = *dbl_opt; + + REQUIRE(pi1 == 3.1415); + REQUIRE(pi2 == 3.1415); +} + +TEST_CASE( "emplace initialization, reset", "[optional]" ) { + mapbox::util::optional dummy_opt; + REQUIRE(!dummy_opt); + + // rvalues, baby! + dummy_opt.emplace(1, 2); + REQUIRE(dummy_opt); + REQUIRE(dummy_opt.get().m_1 == 1); + REQUIRE((*dummy_opt).m_2 == 2); + + dummy_opt.reset(); + REQUIRE(!dummy_opt); +} + +TEST_CASE( "assignment", "[optional]") { + mapbox::util::optional a; + mapbox::util::optional b; + + a = 1; b = 3; + REQUIRE(a.get() == 1); + REQUIRE(b.get() == 3); + b = a; + REQUIRE(a.get() == b.get()); + REQUIRE(b.get() == 1); +} diff --git a/test/recursive_wrapper_test.cpp b/test/recursive_wrapper_test.cpp new file mode 100644 index 000000000..3cd79b5ce --- /dev/null +++ b/test/recursive_wrapper_test.cpp @@ -0,0 +1,132 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "variant.hpp" + +using namespace mapbox; + +namespace test { + +struct add; +struct sub; +template struct binary_op; + +typedef util::variant>, + util::recursive_wrapper> + > expression; + +template +struct binary_op +{ + expression left; // variant instantiated here... + expression right; + + binary_op(expression && lhs, expression && rhs) + : left(std::move(lhs)), right(std::move(rhs)) + { + } +}; + +struct print : util::static_visitor +{ + template + void operator() (T const& val) const + { + std::cerr << val << ":" << typeid(T).name() << std::endl; + } +}; + + +struct test : util::static_visitor +{ + template + std::string operator() (T const& obj) const + { + return std::string("TYPE_ID=") + typeid(obj).name(); + } +}; + +struct calculator : public util::static_visitor +{ +public: + + int operator()(int value) const + { + return value; + } + + int operator()(binary_op const& binary) const + { + return util::apply_visitor(calculator(), binary.left) + + util::apply_visitor(calculator(), binary.right); + } + + int operator()(binary_op const& binary) const + { + return util::apply_visitor(calculator(), binary.left) + - util::apply_visitor(calculator(), binary.right); + } +}; + +struct to_string : public util::static_visitor +{ +public: + + std::string operator()(int value) const + { + return std::to_string(value); + } + + std::string operator()(binary_op const& binary) const + { + return util::apply_visitor(to_string(), binary.left) + std::string("+") + + util::apply_visitor(to_string(), binary.right); + } + + std::string operator()(binary_op const& binary) const + { + return util::apply_visitor(to_string(), binary.left) + std::string("-") + + util::apply_visitor(to_string(), binary.right); + } + +}; + +} // namespace test + +int main (int argc, char** argv) +{ + + if (argc != 2) + { + std::cerr << "Usage" << argv[0] << " " << std::endl; + return EXIT_FAILURE; + } + + const std::size_t NUM_ITER = static_cast(std::stol(argv[1])); + + test::expression result( + test::binary_op( + test::binary_op(2, 3), 4)); + + std::cerr << "TYPE OF RESULT-> " << util::apply_visitor(test::test(), result) << std::endl; + + { + boost::timer::auto_cpu_timer t; + int total = 0; + for (std::size_t i = 0; i < NUM_ITER; ++i) + { + total += util::apply_visitor(test::calculator(), result); + } + std::cerr << "total=" << total << std::endl; + } + + std::cerr << util::apply_visitor(test::to_string(), result) << "=" << util::apply_visitor(test::calculator(), result) << std::endl; + + return EXIT_SUCCESS; +} diff --git a/test/unique_ptr_test.cpp b/test/unique_ptr_test.cpp new file mode 100644 index 000000000..2a51efef0 --- /dev/null +++ b/test/unique_ptr_test.cpp @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "variant.hpp" + +using namespace mapbox; + +namespace test { + +struct add; +struct sub; +template struct binary_op; + +typedef util::variant>, + std::unique_ptr> + > expression; + +template +struct binary_op +{ + expression left; // variant instantiated here... + expression right; + + binary_op(expression && lhs, expression && rhs) + : left(std::move(lhs)), right(std::move(rhs)) {} +}; + +struct print : util::static_visitor +{ + template + void operator() (T const& val) const + { + std::cerr << val << ":" << typeid(T).name() << std::endl; + } +}; + + +struct test : util::static_visitor +{ + template + std::string operator() (T const& obj) const + { + return std::string("TYPE_ID=") + typeid(obj).name(); + } +}; + +struct calculator : public util::static_visitor +{ +public: + + int operator()(int value) const + { + return value; + } + + int operator()(std::unique_ptr> const& binary) const + { + return util::apply_visitor(calculator(), binary->left) + + util::apply_visitor(calculator(), binary->right); + } + + int operator()(std::unique_ptr> const& binary) const + { + return util::apply_visitor(calculator(), binary->left) + - util::apply_visitor(calculator(), binary->right); + } +}; + +struct to_string : public util::static_visitor +{ +public: + + std::string operator()(int value) const + { + return std::to_string(value); + } + + std::string operator()(std::unique_ptr> const& binary) const + { + return util::apply_visitor(to_string(), binary->left) + std::string("+") + + util::apply_visitor(to_string(), binary->right); + } + + std::string operator()(std::unique_ptr> const& binary) const + { + return util::apply_visitor(to_string(), binary->left) + std::string("-") + + util::apply_visitor(to_string(), binary->right); + } + +}; + +} // namespace test + +int main (int argc, char** argv) +{ + if (argc != 2) + { + std::cerr << "Usage" << argv[0] << " " << std::endl; + return EXIT_FAILURE; + } + + const std::size_t NUM_ITER = static_cast(std::stol(argv[1])); + + test::expression sum(std::unique_ptr>(new test::binary_op(2, 3))); + test::expression result(std::unique_ptr>(new test::binary_op(std::move(sum), 4))); + std::cerr << "TYPE OF RESULT-> " << util::apply_visitor(test::test(), result) << std::endl; + + { + boost::timer::auto_cpu_timer t; + int total = 0; + for (std::size_t i = 0; i < NUM_ITER; ++i) + { + total += util::apply_visitor(test::calculator(), result); + } + std::cerr << "total=" << total << std::endl; + } + + std::cerr << util::apply_visitor(test::to_string(), result) << "=" << util::apply_visitor(test::calculator(), result) << std::endl; + + return EXIT_SUCCESS; +} diff --git a/test/unit.cpp b/test/unit.cpp new file mode 100644 index 000000000..53fd72423 --- /dev/null +++ b/test/unit.cpp @@ -0,0 +1,306 @@ +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" + +#include "variant.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace mapbox; + +template +struct mutating_visitor +{ + mutating_visitor(T & val) + : val_(val) {} + + void operator() (T & val) const + { + val = val_; + } + + template + void operator() (T1& ) const {} // no-op + + T & val_; +}; + + + +TEST_CASE( "variant version", "[variant]" ) { + unsigned int version = VARIANT_VERSION; + REQUIRE(version == 100); + #if VARIANT_VERSION == 100 + REQUIRE(true); + #else + REQUIRE(false); + #endif +} + +TEST_CASE( "variant can be moved into vector", "[variant]" ) { + typedef util::variant variant_type; + variant_type v(std::string("test")); + std::vector vec; + vec.emplace_back(std::move(v)); + REQUIRE(v.get() != std::string("test")); + REQUIRE(vec.at(0).get() == std::string("test")); +} + +TEST_CASE( "variant should support built-in types", "[variant]" ) { + SECTION( "bool" ) { + util::variant v(true); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(v.get() == true); + v.set(false); + REQUIRE(v.get() == false); + v = true; + REQUIRE(v == util::variant(true)); + } + SECTION( "nullptr" ) { + typedef std::nullptr_t value_type; + util::variant v(nullptr); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + // TODO: commented since it breaks on windows: 'operator << is ambiguous' + //REQUIRE(v.get() == nullptr); + // FIXME: does not compile: ./variant.hpp:340:14: error: use of overloaded operator '<<' is ambiguous (with operand types 'std::__1::basic_ostream' and 'const nullptr_t') + // https://github.com/mapbox/variant/issues/14 + //REQUIRE(v == util::variant(nullptr)); + } + SECTION( "unique_ptr" ) { + typedef std::unique_ptr value_type; + util::variant v(value_type(new std::string("hello"))); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(*v.get().get() == *value_type(new std::string("hello")).get()); + } + SECTION( "string" ) { + typedef std::string value_type; + util::variant v(value_type("hello")); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(v.get() == value_type("hello")); + v.set(value_type("there")); + REQUIRE(v.get() == value_type("there")); + v = value_type("variant"); + REQUIRE(v == util::variant(value_type("variant"))); + } + SECTION( "size_t" ) { + typedef std::size_t value_type; + util::variant v(std::numeric_limits::max()); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(v.get() == std::numeric_limits::max()); + v.set(value_type(0)); + REQUIRE(v.get() == value_type(0)); + v = value_type(1); + REQUIRE(v == util::variant(value_type(1))); + } + SECTION( "int8_t" ) { + typedef std::int8_t value_type; + util::variant v(std::numeric_limits::max()); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(v.get() == std::numeric_limits::max()); + v.set(0); + REQUIRE(v.get() == value_type(0)); + v = value_type(1); + REQUIRE(v == util::variant(value_type(1))); + } + SECTION( "int16_t" ) { + typedef std::int16_t value_type; + util::variant v(std::numeric_limits::max()); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(v.get() == std::numeric_limits::max()); + v.set(0); + REQUIRE(v.get() == value_type(0)); + v = value_type(1); + REQUIRE(v == util::variant(value_type(1))); + } + SECTION( "int32_t" ) { + typedef std::int32_t value_type; + util::variant v(std::numeric_limits::max()); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(v.get() == std::numeric_limits::max()); + v.set(0); + REQUIRE(v.get() == value_type(0)); + v = value_type(1); + REQUIRE(v == util::variant(value_type(1))); + } + SECTION( "int64_t" ) { + typedef std::int64_t value_type; + util::variant v(std::numeric_limits::max()); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(v.get() == std::numeric_limits::max()); + v.set(0); + REQUIRE(v.get() == value_type(0)); + v = value_type(1); + REQUIRE(v == util::variant(value_type(1))); + } +} + +struct MissionInteger +{ + typedef uint64_t value_type; + value_type val_; + public: + MissionInteger(uint64_t val) : + val_(val) {} + + bool operator==(MissionInteger const& rhs) const + { + return (val_ == rhs.get()); + } + + uint64_t get() const + { + return val_; + } +}; + +// TODO - remove after https://github.com/mapbox/variant/issues/14 +std::ostream& operator<<(std::ostream& os, MissionInteger const& rhs) +{ + os << rhs.get(); + return os; +} + +TEST_CASE( "variant should support custom types", "[variant]" ) { + // http://www.missionintegers.com/integer/34838300 + util::variant v(MissionInteger(34838300)); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(v.get() == MissionInteger(34838300)); + REQUIRE(v.get().get() == MissionInteger::value_type(34838300)); + // TODO: should both of the set usages below compile? + v.set(MissionInteger::value_type(0)); + v.set(MissionInteger(0)); + REQUIRE(v.get().get() == MissionInteger::value_type(0)); + v = MissionInteger(1); + REQUIRE(v == util::variant(MissionInteger(1))); +} + +// Test internal api +TEST_CASE( "variant should correctly index types", "[variant]" ) { + typedef util::variant variant_type; + // Index is in reverse order + REQUIRE(variant_type(true).get_type_index() == 5); + REQUIRE(variant_type(std::string("test")).get_type_index() == 4); + REQUIRE(variant_type(std::uint64_t(0)).get_type_index() == 3); + REQUIRE(variant_type(std::int64_t(0)).get_type_index() == 2); + REQUIRE(variant_type(double(0.0)).get_type_index() == 1); + REQUIRE(variant_type(float(0.0)).get_type_index() == 0); +} + +TEST_CASE( "get with type not in variant type list should throw", "[variant]" ) { + typedef util::variant variant_type; + variant_type var = 5; + REQUIRE(var.get() == 5); + REQUIRE_THROWS(var.get()); // XXX shouldn't this be a compile time error? See https://github.com/mapbox/variant/issues/24 +} + +TEST_CASE( "get with wrong type (here: double) should throw", "[variant]" ) { + typedef util::variant variant_type; + variant_type var = 5; + REQUIRE(var.get() == 5); + REQUIRE_THROWS(var.get()); +} + +TEST_CASE( "get with wrong type (here: int) should throw", "[variant]" ) { + typedef util::variant variant_type; + variant_type var = 5.0; + REQUIRE(var.get() == 5.0); + REQUIRE_THROWS(var.get()); +} + +TEST_CASE( "implicit conversion", "[variant][implicit conversion]" ) { + typedef util::variant variant_type; + variant_type var(5.0); // converted to int + REQUIRE(var.get() == 5); + REQUIRE_THROWS(var.get()); + var = 6.0; // works for operator=, too + REQUIRE(var.get() == 6); +} + +TEST_CASE( "implicit conversion to first type in variant type list", "[variant][implicit conversion]" ) { + typedef util::variant variant_type; + variant_type var = 5.0; // converted to long + REQUIRE(var.get() == 5); + REQUIRE_THROWS(var.get()); + REQUIRE_THROWS(var.get()); +} + +TEST_CASE( "implicit conversion to unsigned char", "[variant][implicit conversion]" ) { + typedef util::variant variant_type; + variant_type var = 100.0; + CHECK(var.get() == static_cast(100.0)); + CHECK(var.get() == static_cast(static_cast(100.0))); +} + +struct dummy {}; + +TEST_CASE( "variant value traits", "[variant::detail]" ) { + // Users should not create variants with duplicated types + // however our type indexing should still work + // Index is in reverse order + REQUIRE((util::detail::value_traits::index == 3)); + REQUIRE((util::detail::value_traits::index == 2)); + REQUIRE((util::detail::value_traits::index == 1)); + REQUIRE((util::detail::value_traits::index == 0)); + REQUIRE((util::detail::value_traits::index == util::detail::invalid_value)); + REQUIRE((util::detail::value_traits, bool, int, double, std::string>::index == util::detail::invalid_value)); +} + +TEST_CASE( "variant default constructor", "[variant][default constructor]" ) { + // By default variant is initialised with (default constructed) first type in template parameters pack + // As a result first type in Types... must be default constructable + // NOTE: index in reverse order -> index = N - 1 + REQUIRE((util::variant().get_type_index() == 2)); + REQUIRE((util::variant(util::no_init()).get_type_index() == util::detail::invalid_value)); +} + +TEST_CASE( "variant visitation", "[visitor][unary visitor]" ) { + util::variant var(123); + REQUIRE(var.get() == 123); + int val = 456; + mutating_visitor visitor(val); + util::apply_visitor(visitor, var); + REQUIRE(var.get() == 456); +} + +TEST_CASE( "variant printer", "[visitor][unary visitor][printer]" ) { + typedef util::variant variant_type; + std::vector var = {2.1, 123, "foo", 456}; + std::stringstream out; + std::copy(var.begin(), var.end(), std::ostream_iterator(out, ",")); + out << var[2]; + REQUIRE(out.str() == "2.1,123,foo,456,foo"); +} + + +int main (int argc, char* const argv[]) +{ + int result = Catch::Session().run(argc, argv); + if (!result) printf("\x1b[1;32m ✓ \x1b[0m\n"); + return result; +} diff --git a/test/variant_hello_world.cpp b/test/variant_hello_world.cpp new file mode 100644 index 000000000..b445fdbab --- /dev/null +++ b/test/variant_hello_world.cpp @@ -0,0 +1,22 @@ +#include "variant.hpp" +#include +#include + +using namespace mapbox; + +struct check : util::static_visitor<> +{ + template + void operator() (T const& val) const + { + if (val != 0) throw std::runtime_error("invalid"); + } +}; + + +int main() { + typedef util::variant variant_type; + variant_type v(0); + util::apply_visitor(check(), v); + return 0; +} diff --git a/variant.gyp b/variant.gyp new file mode 100644 index 000000000..712cafed1 --- /dev/null +++ b/variant.gyp @@ -0,0 +1,21 @@ +{ + "includes": [ + "common.gypi" + ], + "targets": [ + { + "target_name": "tests", + "type": "executable", + "sources": [ + "test/unit.cpp" + ], + "xcode_settings": { + "SDKROOT": "macosx", + "SUPPORTED_PLATFORMS":["macosx"] + }, + "include_dirs": [ + "./" + ] + } + ] +} \ No newline at end of file diff --git a/variant.hpp b/variant.hpp new file mode 100644 index 000000000..49d74d559 --- /dev/null +++ b/variant.hpp @@ -0,0 +1,783 @@ +#ifndef MAPBOX_UTIL_VARIANT_HPP +#define MAPBOX_UTIL_VARIANT_HPP + +#include +#include +#include +#include // runtime_error +#include // operator new +#include // size_t +#include +#include + +#include "recursive_wrapper.hpp" + +#ifdef _MSC_VER + // http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx + #ifdef NDEBUG + #define VARIANT_INLINE __forceinline + #else + #define VARIANT_INLINE __declspec(noinline) + #endif +#else + #ifdef NDEBUG + #define VARIANT_INLINE inline __attribute__((always_inline)) + #else + #define VARIANT_INLINE __attribute__((noinline)) + #endif +#endif + +#define VARIANT_MAJOR_VERSION 0 +#define VARIANT_MINOR_VERSION 1 +#define VARIANT_PATCH_VERSION 0 + +// translates to 100 +#define VARIANT_VERSION (VARIANT_MAJOR_VERSION*100000) + (VARIANT_MINOR_VERSION*100) + (VARIANT_PATCH_VERSION) + +namespace mapbox { namespace util { + +// static visitor +template +struct static_visitor +{ + using result_type = R; +protected: + static_visitor() {} + ~static_visitor() {} +}; + +namespace detail { + +static constexpr std::size_t invalid_value = std::size_t(-1); + +template +struct direct_type; + +template +struct direct_type +{ + static constexpr std::size_t index = std::is_same::value + ? sizeof...(Types) : direct_type::index; +}; + +template +struct direct_type +{ + static constexpr std::size_t index = invalid_value; +}; + +template +struct convertible_type; + +template +struct convertible_type +{ + static constexpr std::size_t index = std::is_convertible::value + ? sizeof...(Types) : convertible_type::index; +}; + +template +struct convertible_type +{ + static constexpr std::size_t index = invalid_value; +}; + +template +struct value_traits +{ + static constexpr std::size_t direct_index = direct_type::index; + static constexpr std::size_t index = + (direct_index == invalid_value) ? convertible_type::index : direct_index; +}; + +template +struct is_valid_type; + +template +struct is_valid_type +{ + static constexpr bool value = std::is_convertible::value + || is_valid_type::value; +}; + +template +struct is_valid_type : std::false_type {}; + +template +struct select_type +{ + static_assert(N < sizeof...(Types), "index out of bounds"); +}; + +template +struct select_type +{ + using type = typename select_type::type; +}; + +template +struct select_type<0, T, Types...> +{ + using type = T; +}; + + +template +struct enable_if_type { using type = R; }; + +template +struct result_of_unary_visit +{ + using type = typename std::result_of::type; +}; + +template +struct result_of_unary_visit::type > +{ + using type = typename F::result_type; +}; + +template +struct result_of_binary_visit +{ + using type = typename std::result_of::type; +}; + + +template +struct result_of_binary_visit::type > +{ + using type = typename F::result_type; +}; + + +} // namespace detail + + +template +struct static_max; + +template +struct static_max +{ + static const std::size_t value = arg; +}; + +template +struct static_max +{ + static const std::size_t value = arg1 >= arg2 ? static_max::value : + static_max::value; +}; + +template +struct variant_helper; + +template +struct variant_helper +{ + VARIANT_INLINE static void destroy(const std::size_t id, void * data) + { + if (id == sizeof...(Types)) + { + reinterpret_cast(data)->~T(); + } + else + { + variant_helper::destroy(id, data); + } + } + + VARIANT_INLINE static void move(const std::size_t old_id, void * old_value, void * new_value) + { + if (old_id == sizeof...(Types)) + { + new (new_value) T(std::move(*reinterpret_cast(old_value))); + //std::memcpy(new_value, old_value, sizeof(T)); + // ^^ DANGER: this should only be considered for relocatable types e.g built-in types + // Also, I don't see any measurable performance benefit just yet + } + else + { + variant_helper::move(old_id, old_value, new_value); + } + } + + VARIANT_INLINE static void copy(const std::size_t old_id, const void * old_value, void * new_value) + { + if (old_id == sizeof...(Types)) + { + new (new_value) T(*reinterpret_cast(old_value)); + } + else + { + variant_helper::copy(old_id, old_value, new_value); + } + } +}; + +template<> struct variant_helper<> +{ + VARIANT_INLINE static void destroy(const std::size_t, void *) {} + VARIANT_INLINE static void move(const std::size_t, void *, void *) {} + VARIANT_INLINE static void copy(const std::size_t, const void *, void *) {} +}; + +namespace detail { + +template +struct unwrapper +{ + T const& operator() (T const& obj) const + { + return obj; + } + + T& operator() (T & obj) const + { + return obj; + } +}; + + +template +struct unwrapper> +{ + auto operator() (recursive_wrapper const& obj) const + -> typename recursive_wrapper::type const& + { + return obj.get(); + } +}; + + +template +struct dispatcher; + +template +struct dispatcher +{ + using result_type = R; + VARIANT_INLINE static result_type apply_const(V const& v, F f) + { + if (v.get_type_index() == sizeof...(Types)) + { + return f(unwrapper()(v. template get())); + } + else + { + return dispatcher::apply_const(v, f); + } + } + + VARIANT_INLINE static result_type apply(V & v, F f) + { + if (v.get_type_index() == sizeof...(Types)) + { + return f(unwrapper()(v. template get())); + } + else + { + return dispatcher::apply(v, f); + } + } +}; + +template +struct dispatcher +{ + using result_type = R; + VARIANT_INLINE static result_type apply_const(V const&, F) + { + throw std::runtime_error(std::string("unary dispatch: FAIL ") + typeid(V).name()); + } + + VARIANT_INLINE static result_type apply(V &, F) + { + throw std::runtime_error(std::string("unary dispatch: FAIL ") + typeid(V).name()); + } +}; + + +template +struct binary_dispatcher_rhs; + +template +struct binary_dispatcher_rhs +{ + using result_type = R; + VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f) + { + if (rhs.get_type_index() == sizeof...(Types)) // call binary functor + { + return f(unwrapper()(lhs. template get()), + unwrapper()(rhs. template get())); + } + else + { + return binary_dispatcher_rhs::apply_const(lhs, rhs, f); + } + } + + VARIANT_INLINE static result_type apply(V & lhs, V & rhs, F f) + { + if (rhs.get_type_index() == sizeof...(Types)) // call binary functor + { + return f(unwrapper()(lhs. template get()), + unwrapper()(rhs. template get())); + } + else + { + return binary_dispatcher_rhs::apply(lhs, rhs, f); + } + } + +}; + +template +struct binary_dispatcher_rhs +{ + using result_type = R; + VARIANT_INLINE static result_type apply_const(V const&, V const&, F) + { + throw std::runtime_error("binary dispatch: FAIL"); + } + VARIANT_INLINE static result_type apply(V &, V &, F) + { + throw std::runtime_error("binary dispatch: FAIL"); + } +}; + + +template +struct binary_dispatcher_lhs; + +template +struct binary_dispatcher_lhs +{ + using result_type = R; + VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f) + { + if (lhs.get_type_index() == sizeof...(Types)) // call binary functor + { + return f(lhs. template get(), rhs. template get()); + } + else + { + return binary_dispatcher_lhs::apply_const(lhs, rhs, f); + } + } + + VARIANT_INLINE static result_type apply(V & lhs, V & rhs, F f) + { + if (lhs.get_type_index() == sizeof...(Types)) // call binary functor + { + return f(lhs. template get(), rhs. template get()); + } + else + { + return binary_dispatcher_lhs::apply(lhs, rhs, f); + } + } + +}; + +template +struct binary_dispatcher_lhs +{ + using result_type = R; + VARIANT_INLINE static result_type apply_const(V const&, V const&, F) + { + throw std::runtime_error("binary dispatch: FAIL"); + } + + VARIANT_INLINE static result_type apply(V &, V &, F) + { + throw std::runtime_error("binary dispatch: FAIL"); + } +}; + +template +struct binary_dispatcher; + +template +struct binary_dispatcher +{ + using result_type = R; + VARIANT_INLINE static result_type apply_const(V const& v0, V const& v1, F f) + { + if (v0.get_type_index() == sizeof...(Types)) + { + if (v0.get_type_index() == v1.get_type_index()) + { + return f(v0. template get(), v1. template get()); // call binary functor + } + else + { + return binary_dispatcher_rhs::apply_const(v0, v1, f); + } + } + else if (v1.get_type_index() == sizeof...(Types)) + { + return binary_dispatcher_lhs::apply_const(v0, v1, f); + } + return binary_dispatcher::apply_const(v0, v1, f); + } + + VARIANT_INLINE static result_type apply(V & v0, V & v1, F f) + { + if (v0.get_type_index() == sizeof...(Types)) + { + if (v0.get_type_index() == v1.get_type_index()) + { + return f(v0. template get(), v1. template get()); // call binary functor + } + else + { + return binary_dispatcher_rhs::apply(v0, v1, f); + } + } + else if (v1.get_type_index() == sizeof...(Types)) + { + return binary_dispatcher_lhs::apply(v0, v1, f); + } + return binary_dispatcher::apply(v0, v1, f); + } +}; + +template +struct binary_dispatcher +{ + using result_type = R; + VARIANT_INLINE static result_type apply_const(V const&, V const&, F) + { + throw std::runtime_error("binary dispatch: FAIL"); + } + + VARIANT_INLINE static result_type apply(V &, V &, F) + { + throw std::runtime_error("binary dispatch: FAIL"); + } +}; + +// comparator functors +struct equal_comp +{ + template + bool operator()(T const& lhs, T const& rhs) const + { + return lhs == rhs; + } +}; + +struct less_comp +{ + template + bool operator()(T const& lhs, T const& rhs) const + { + return lhs < rhs; + } +}; + +template +class comparer +{ +public: + explicit comparer(Variant const& lhs) noexcept + : lhs_(lhs) {} + comparer& operator=(comparer const&) = delete; + // visitor + template + bool operator()(T const& rhs_content) const + { + T const& lhs_content = lhs_.template get(); + return Comp()(lhs_content, rhs_content); + } +private: + Variant const& lhs_; +}; + +// operator<< helper +template +class printer +{ +public: + explicit printer(Out & out) + : out_(out) {} + printer& operator=(printer const&) = delete; + +// visitor + template + void operator()(T const& operand) const + { + out_ << operand; + } +private: + Out & out_; +}; + +} // namespace detail + +struct no_init {}; + +template +class variant +{ +private: + + static const std::size_t data_size = static_max::value; + static const std::size_t data_align = static_max::value; + + using data_type = typename std::aligned_storage::type; + using helper_type = variant_helper; + + std::size_t type_index; + data_type data; + +public: + + VARIANT_INLINE variant() + : type_index(sizeof...(Types) - 1) + { + new (&data) typename detail::select_type<0, Types...>::type(); + } + + VARIANT_INLINE variant(no_init) + : type_index(detail::invalid_value) {} + + // http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers + template ::type, Types...>::value>::type> + VARIANT_INLINE variant(T && val) noexcept + : type_index(detail::value_traits::type, Types...>::index) + { + constexpr std::size_t index = sizeof...(Types) - detail::value_traits::type, Types...>::index - 1; + using target_type = typename detail::select_type::type; + new (&data) target_type(std::forward(val)); // nothrow + } + + VARIANT_INLINE variant(variant const& old) + : type_index(old.type_index) + { + helper_type::copy(old.type_index, &old.data, &data); + } + + VARIANT_INLINE variant(variant&& old) noexcept + : type_index(old.type_index) + { + helper_type::move(old.type_index, &old.data, &data); + } + + friend void swap(variant & first, variant & second) + { + using std::swap; //enable ADL + swap(first.type_index, second.type_index); + swap(first.data, second.data); + } + + VARIANT_INLINE variant& operator=(variant other) + { + swap(*this, other); + return *this; + } + + // conversions + // move-assign + template + VARIANT_INLINE variant& operator=(T && rhs) noexcept + { + variant temp(std::forward(rhs)); + swap(*this, temp); + return *this; + } + + // copy-assign + template + VARIANT_INLINE variant& operator=(T const& rhs) + { + variant temp(rhs); + swap(*this, temp); + return *this; + } + + template + VARIANT_INLINE bool is() const + { + return (type_index == detail::direct_type::index); + } + + VARIANT_INLINE bool valid() const + { + return (type_index != detail::invalid_value); + } + + template + VARIANT_INLINE void set(Args&&... args) + { + helper_type::destroy(type_index, &data); + new (&data) T(std::forward(args)...); + type_index = detail::direct_type::index; + } + + template + VARIANT_INLINE T& get() + { + if (type_index == detail::direct_type::index) + { + return *reinterpret_cast(&data); + } + else + { + throw std::runtime_error("in get()"); + } + } + + template + VARIANT_INLINE T const& get() const + { + if (type_index == detail::direct_type::index) + { + return *reinterpret_cast(&data); + } + else + { + throw std::runtime_error("in get()"); + } + } + + VARIANT_INLINE std::size_t get_type_index() const + { + return type_index; + } + + // visitor + // unary + template + auto VARIANT_INLINE + static visit(V const& v, F f) + -> decltype(detail::dispatcher::type>::type, Types...>::apply_const(v, f)) + { + using R = typename detail::result_of_unary_visit::type>::type; + return detail::dispatcher::apply_const(v, f); + } + // non-const + template + auto VARIANT_INLINE + static visit(V & v, F f) + -> decltype(detail::dispatcher::type>::type, Types...>::apply(v, f)) + { + using R = typename detail::result_of_unary_visit::type>::type; + return detail::dispatcher::apply(v, f); + } + + // binary + // const + template + auto VARIANT_INLINE + static binary_visit(V const& v0, V const& v1, F f) + -> decltype(detail::binary_dispatcher::type>::type, Types...>::apply_const(v0, v1, f)) + { + using R = typename detail::result_of_binary_visit::type>::type; + return detail::binary_dispatcher::apply_const(v0, v1, f); + } + // non-const + template + auto VARIANT_INLINE + static binary_visit(V& v0, V& v1, F f) + -> decltype(detail::binary_dispatcher::type>::type, Types...>::apply(v0, v1, f)) + { + using R = typename detail::result_of_binary_visit::type>::type; + return detail::binary_dispatcher::apply(v0, v1, f); + } + + ~variant() noexcept + { + helper_type::destroy(type_index, &data); + } + + // comparison operators + // equality + VARIANT_INLINE bool operator==(variant const& rhs) const + { + if (this->get_type_index() != rhs.get_type_index()) + return false; + detail::comparer visitor(*this); + return visit(rhs, visitor); + } + // less than + VARIANT_INLINE bool operator<(variant const& rhs) const + { + if (this->get_type_index() != rhs.get_type_index()) + { + return this->get_type_index() < rhs.get_type_index(); + // ^^ borrowed from boost::variant + } + detail::comparer visitor(*this); + return visit(rhs, visitor); + } +}; + +// unary visitor interface + +// const +template +auto VARIANT_INLINE static apply_visitor(F f, V const& v) -> decltype(V::visit(v, f)) +{ + return V::visit(v, f); +} +// non-const +template +auto VARIANT_INLINE static apply_visitor(F f, V & v) -> decltype(V::visit(v, f)) +{ + return V::visit(v, f); +} + +// binary visitor interface +// const +template +auto VARIANT_INLINE static apply_visitor(F f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, f)) +{ + return V::binary_visit(v0, v1, f); +} +// non-const +template +auto VARIANT_INLINE static apply_visitor(F f, V & v0, V & v1) -> decltype(V::binary_visit(v0, v1, f)) +{ + return V::binary_visit(v0, v1, f); +} + +// getter interface +template +ResultType & get(T & var) +{ + return var.template get(); +} + +template +ResultType const& get(T const& var) +{ + return var.template get(); +} + + +// operator<< +template +VARIANT_INLINE std::basic_ostream& +operator<< (std::basic_ostream& out, variant const& rhs) +{ + detail::printer> visitor(out); + apply_visitor(visitor, rhs); + return out; +} + +}} + +#endif // MAPBOX_UTIL_VARIANT_HPP diff --git a/vcbuild.bat b/vcbuild.bat new file mode 100644 index 000000000..21489a134 --- /dev/null +++ b/vcbuild.bat @@ -0,0 +1,8 @@ +SET configuration=Debug +IF NOT EXIST deps\gyp\ git clone --depth 1 https://chromium.googlesource.com/external/gyp.git deps/gyp +IF EXIST %configuration% rd /s /q %configuration% +del variant.sln +del tests.vcxproj +C:\Python27\python.exe deps/gyp/gyp_main.py variant.gyp --depth=. -f msvs -G msvs_version=2013 +msbuild variant.sln /nologo /p:Configuration=%configuration%;Platform=Win32 +.\"%configuration%"\tests.exe \ No newline at end of file From 39edbcbabd47ff1eb93a2d8e7df2e409ca3be57e Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 14 Jan 2015 17:26:59 +0100 Subject: [PATCH 047/360] after profiling with intel vtune, mitigate some performance hotspots. may give a 10-20% performance boost during preprocessing --- data_structures/binary_heap.hpp | 27 ++++++++++++++++------- data_structures/xor_fast_hash_storage.hpp | 25 +++++++++++++++------ 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/data_structures/binary_heap.hpp b/data_structures/binary_heap.hpp index 049f12fca..48a989082 100644 --- a/data_structures/binary_heap.hpp +++ b/data_structures/binary_heap.hpp @@ -76,6 +76,16 @@ template class UnorderedMapStorage Key &operator[](const NodeID node) { return nodes[node]; } + Key peek_index(const NodeID node) const + { + const auto iter = nodes.find(node); + if (std::end(nodes) != iter) + { + return iter->second; + } + return Key(-1); + } + Key const &operator[](const NodeID node) const { auto iter = nodes.find(node); @@ -132,13 +142,13 @@ class BinaryHeap Data &GetData(NodeID node) { - const Key index = node_index[node]; + const Key index = node_index.peek_index(node); return inserted_nodes[index].data; } Data const &GetData(NodeID node) const { - const Key index = node_index[node]; + const Key index = node_index.peek_index(node); return inserted_nodes[index].data; } @@ -148,16 +158,16 @@ class BinaryHeap return inserted_nodes[index].weight; } - bool WasRemoved(const NodeID node) + bool WasRemoved(const NodeID node) const { BOOST_ASSERT(WasInserted(node)); - const Key index = node_index[node]; + const Key index = node_index.peek_index(node); return inserted_nodes[index].key == 0; } bool WasInserted(const NodeID node) { - const Key index = node_index[node]; + const Key index = node_index.peek_index(node); if (index >= static_cast(inserted_nodes.size())) { return false; @@ -200,7 +210,7 @@ class BinaryHeap void DecreaseKey(NodeID node, Weight weight) { BOOST_ASSERT(std::numeric_limits::max() != node); - const Key &index = node_index[node]; + const Key &index = node_index.peek_index(node); Key &key = inserted_nodes[index].key; BOOST_ASSERT(key >= 0); @@ -235,11 +245,12 @@ class BinaryHeap { const Key droppingIndex = heap[key].index; const Weight weight = heap[key].weight; + const Key heap_size = static_cast(heap.size()); Key nextKey = key << 1; - while (nextKey < static_cast(heap.size())) + while (nextKey < heap_size) { const Key nextKeyOther = nextKey + 1; - if ((nextKeyOther < static_cast(heap.size())) && + if ((nextKeyOther < heap_size) && (heap[nextKey].weight > heap[nextKeyOther].weight)) { nextKey = nextKeyOther; diff --git a/data_structures/xor_fast_hash_storage.hpp b/data_structures/xor_fast_hash_storage.hpp index 1d84260c2..c2ad6c13b 100644 --- a/data_structures/xor_fast_hash_storage.hpp +++ b/data_structures/xor_fast_hash_storage.hpp @@ -38,12 +38,12 @@ template class XORFastHashStorage public: struct HashCell { - Key key; - NodeID id; unsigned time; + NodeID id; + Key key; HashCell() - : key(std::numeric_limits::max()), id(std::numeric_limits::max()), - time(std::numeric_limits::max()) + : time(std::numeric_limits::max()), id(std::numeric_limits::max()), + key(std::numeric_limits::max()) { } @@ -51,7 +51,7 @@ template class XORFastHashStorage operator Key() const { return key; } - void operator=(const Key &key_to_insert) { key = key_to_insert; } + void operator=(const Key key_to_insert) { key = key_to_insert; } }; explicit XORFastHashStorage(size_t) : positions(2 << 16), current_timestamp(0) {} @@ -64,18 +64,29 @@ template class XORFastHashStorage ++position %= (2 << 16); } - positions[position].id = node; positions[position].time = current_timestamp; + positions[position].id = node; return positions[position]; } + // peek into table, get key for node, think of it as a read-only operator[] + Key peek_index(const NodeID node) const + { + unsigned short position = fast_hasher(node); + while ((positions[position].time == current_timestamp) && (positions[position].id != node)) + { + ++position %= (2 << 16); + } + return positions[position].key; + } + void Clear() { ++current_timestamp; if (std::numeric_limits::max() == current_timestamp) { positions.clear(); - positions.resize((2 << 16)); + // positions.resize((2 << 16)); } } From 527e6cbc727e57e33d9152c99def2d6df7c7c96e Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 14 Jan 2015 18:14:55 +0100 Subject: [PATCH 048/360] xor fast hash storage: reorder initialization of elements, delete default c'tor, resetting of table may be expensive as it is rare --- data_structures/xor_fast_hash_storage.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/data_structures/xor_fast_hash_storage.hpp b/data_structures/xor_fast_hash_storage.hpp index c2ad6c13b..3da95e7c2 100644 --- a/data_structures/xor_fast_hash_storage.hpp +++ b/data_structures/xor_fast_hash_storage.hpp @@ -47,13 +47,15 @@ template class XORFastHashStorage { } - HashCell(const HashCell &other) : key(other.key), id(other.id), time(other.time) {} + HashCell(const HashCell &other) : time(other.key), id(other.id), key(other.time) {} operator Key() const { return key; } void operator=(const Key key_to_insert) { key = key_to_insert; } }; + XORFastHashStorage() = delete; + explicit XORFastHashStorage(size_t) : positions(2 << 16), current_timestamp(0) {} HashCell &operator[](const NodeID node) @@ -86,12 +88,11 @@ template class XORFastHashStorage if (std::numeric_limits::max() == current_timestamp) { positions.clear(); - // positions.resize((2 << 16)); + positions.resize(2 << 16); } } private: - XORFastHashStorage() : positions(2 << 16), current_timestamp(0) {} std::vector positions; XORFastHash fast_hasher; unsigned current_timestamp; From 6dabf4507aa2fa5ea2cbfe98b0eea63addffd788 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 15 Jan 2015 11:15:48 +0100 Subject: [PATCH 049/360] implement peek_index() functions for all binary heap storage classes --- data_structures/binary_heap.hpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/data_structures/binary_heap.hpp b/data_structures/binary_heap.hpp index 48a989082..f5f75a6e2 100644 --- a/data_structures/binary_heap.hpp +++ b/data_structures/binary_heap.hpp @@ -50,6 +50,11 @@ template class ArrayStorage Key &operator[](NodeID node) { return positions[node]; } + Key peek_index(const NodeID node) const + { + return positions[node]; + } + void Clear() {} private: @@ -65,6 +70,15 @@ template class MapStorage void Clear() { nodes.clear(); } + Key peek_index(const NodeID node) const + { + const auto iter = nodes.find(node); + if (std::end(nodes) != iter) + { + return iter->second; + } + return Key(-1); + } private: std::map nodes; }; @@ -76,14 +90,14 @@ template class UnorderedMapStorage Key &operator[](const NodeID node) { return nodes[node]; } - Key peek_index(const NodeID node) const - { + Key peek_index(const NodeID node) const + { const auto iter = nodes.find(node); if (std::end(nodes) != iter) { return iter->second; } - return Key(-1); + return Key(-1); } Key const &operator[](const NodeID node) const From 6e138bbf543b6dbf4581d49930391ebd64ee783a Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 15 Jan 2015 12:59:08 +0100 Subject: [PATCH 050/360] fixes data structure tests: - MapStorage: fix returned index in peek_index() on fail - UnorderedMapStorage: fix returned index in peek_index() on fail - BinaryHeap: auto-deduce Index type - ArrayStorage: replace raw array with std::vector --- data_structures/binary_heap.hpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/data_structures/binary_heap.hpp b/data_structures/binary_heap.hpp index f5f75a6e2..87d145c6f 100644 --- a/data_structures/binary_heap.hpp +++ b/data_structures/binary_heap.hpp @@ -36,17 +36,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include template class ArrayStorage { public: - explicit ArrayStorage(size_t size) : positions(new Key[size]) + explicit ArrayStorage(size_t size) : positions(size, 0) { - memset(positions, 0, size * sizeof(Key)); } - ~ArrayStorage() { delete[] positions; } + ~ArrayStorage() { } Key &operator[](NodeID node) { return positions[node]; } @@ -58,7 +56,7 @@ template class ArrayStorage void Clear() {} private: - Key *positions; + std::vector positions; }; template class MapStorage @@ -73,11 +71,11 @@ template class MapStorage Key peek_index(const NodeID node) const { const auto iter = nodes.find(node); - if (std::end(nodes) != iter) + if (nodes.end() != iter) { return iter->second; } - return Key(-1); + return std::numeric_limits::max(); } private: std::map nodes; @@ -97,7 +95,7 @@ template class UnorderedMapStorage { return iter->second; } - return Key(-1); + return std::numeric_limits::max(); } Key const &operator[](const NodeID node) const @@ -179,9 +177,9 @@ class BinaryHeap return inserted_nodes[index].key == 0; } - bool WasInserted(const NodeID node) + bool WasInserted(const NodeID node) const { - const Key index = node_index.peek_index(node); + const auto index = node_index.peek_index(node); if (index >= static_cast(inserted_nodes.size())) { return false; From 6b1d672dc14a3fc32493afc3fb3cf2245cae3da1 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 15 Jan 2015 13:11:25 +0100 Subject: [PATCH 051/360] fix signed/unsigned comparison --- data_structures/binary_heap.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/binary_heap.hpp b/data_structures/binary_heap.hpp index 87d145c6f..4522460a2 100644 --- a/data_structures/binary_heap.hpp +++ b/data_structures/binary_heap.hpp @@ -180,7 +180,7 @@ class BinaryHeap bool WasInserted(const NodeID node) const { const auto index = node_index.peek_index(node); - if (index >= static_cast(inserted_nodes.size())) + if (index >= static_cast(inserted_nodes.size())) { return false; } From 800cb8c6dd62133b911468af51547d98a4f65fd1 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 15 Jan 2015 18:07:47 +0100 Subject: [PATCH 052/360] renamed: ../UnitTests/data_structures/BinaryHeapTest.cpp -> ../UnitTests/data_structures/binary_heap.cpp renamed: ../UnitTests/data_structures/RangeTableTest.cpp -> ../UnitTests/data_structures/range_table.cpp renamed: ../UnitTests/data_structures/StaticGraphTest.cpp -> ../UnitTests/data_structures/static_graph.cpp renamed: ../UnitTests/data_structures/StaticRTreeTest.cpp -> ../UnitTests/data_structures/static_rtree.cpp --- UnitTests/data_structures/{BinaryHeapTest.cpp => binary_heap.cpp} | 0 UnitTests/data_structures/{RangeTableTest.cpp => range_table.cpp} | 0 .../data_structures/{StaticGraphTest.cpp => static_graph.cpp} | 0 .../data_structures/{StaticRTreeTest.cpp => static_rtree.cpp} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename UnitTests/data_structures/{BinaryHeapTest.cpp => binary_heap.cpp} (100%) rename UnitTests/data_structures/{RangeTableTest.cpp => range_table.cpp} (100%) rename UnitTests/data_structures/{StaticGraphTest.cpp => static_graph.cpp} (100%) rename UnitTests/data_structures/{StaticRTreeTest.cpp => static_rtree.cpp} (100%) diff --git a/UnitTests/data_structures/BinaryHeapTest.cpp b/UnitTests/data_structures/binary_heap.cpp similarity index 100% rename from UnitTests/data_structures/BinaryHeapTest.cpp rename to UnitTests/data_structures/binary_heap.cpp diff --git a/UnitTests/data_structures/RangeTableTest.cpp b/UnitTests/data_structures/range_table.cpp similarity index 100% rename from UnitTests/data_structures/RangeTableTest.cpp rename to UnitTests/data_structures/range_table.cpp diff --git a/UnitTests/data_structures/StaticGraphTest.cpp b/UnitTests/data_structures/static_graph.cpp similarity index 100% rename from UnitTests/data_structures/StaticGraphTest.cpp rename to UnitTests/data_structures/static_graph.cpp diff --git a/UnitTests/data_structures/StaticRTreeTest.cpp b/UnitTests/data_structures/static_rtree.cpp similarity index 100% rename from UnitTests/data_structures/StaticRTreeTest.cpp rename to UnitTests/data_structures/static_rtree.cpp From 1bbfced61abce67b030c05ee3d8daa6c1c29eca8 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 15 Jan 2015 18:10:22 +0100 Subject: [PATCH 053/360] reorder includes --- extractor/extractor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extractor/extractor.cpp b/extractor/extractor.cpp index 880e9e47c..3533d291f 100644 --- a/extractor/extractor.cpp +++ b/extractor/extractor.cpp @@ -37,9 +37,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../Util/git_sha.hpp" #include "../Util/IniFileUtil.h" +#include "../Util/make_unique.hpp" #include "../Util/simple_logger.hpp" #include "../Util/timing_util.hpp" -#include "../Util/make_unique.hpp" #include "../typedefs.h" From f2b556adfdd6c7bbc9c437425e412d6f3311c50c Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 15 Jan 2015 18:39:26 +0100 Subject: [PATCH 054/360] umbenannt: UnitTests/* -> unit_tests/* --- CMakeLists.txt | 9 +++++---- {UnitTests => unit_tests}/algorithm_tests.cpp | 0 .../algorithms/douglas_peucker.cpp | 0 .../data_structures/binary_heap.cpp | 0 .../data_structures/range_table.cpp | 0 .../data_structures/static_graph.cpp | 0 .../data_structures/static_rtree.cpp | 0 {UnitTests => unit_tests}/datastructure_tests.cpp | 0 8 files changed, 5 insertions(+), 4 deletions(-) rename {UnitTests => unit_tests}/algorithm_tests.cpp (100%) rename UnitTests/Algorithms/DouglasPeuckerTest.cpp => unit_tests/algorithms/douglas_peucker.cpp (100%) rename {UnitTests => unit_tests}/data_structures/binary_heap.cpp (100%) rename {UnitTests => unit_tests}/data_structures/range_table.cpp (100%) rename {UnitTests => unit_tests}/data_structures/static_graph.cpp (100%) rename {UnitTests => unit_tests}/data_structures/static_rtree.cpp (100%) rename {UnitTests => unit_tests}/datastructure_tests.cpp (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index c643dc9e1..356908071 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,8 +76,8 @@ file(GLOB CoordinateGlob data_structures/coordinate.cpp) file(GLOB AlgorithmGlob algorithms/*.cpp) file(GLOB HttpGlob Server/Http/*.cpp) file(GLOB LibOSRMGlob Library/*.cpp) -file(GLOB DataStructureTestsGlob UnitTests/data_structures/*.cpp data_structures/hilbert_value.cpp) -file(GLOB AlgorithmTestsGlob UnitTests/Algorithms/*.cpp) +file(GLOB DataStructureTestsGlob unit_tests/data_structures/*.cpp data_structures/hilbert_value.cpp) +file(GLOB AlgorithmTestsGlob unit_tests/algorithms/*.cpp) set( OSRMSources @@ -99,8 +99,8 @@ add_executable(osrm-routed routed.cpp ${ServerGlob} $) add_executable(osrm-datastore datastore.cpp $ $ $ $ $ $) # Unit tests -add_executable(datastructure-tests EXCLUDE_FROM_ALL UnitTests/datastructure_tests.cpp ${DataStructureTestsGlob} $ $ $ $ $) -add_executable(algorithm-tests EXCLUDE_FROM_ALL UnitTests/algorithm_tests.cpp ${AlgorithmTestsGlob} $ $ $ $) +add_executable(datastructure-tests EXCLUDE_FROM_ALL unit_tests/datastructure_tests.cpp ${DataStructureTestsGlob} $ $ $ $ $) +add_executable(algorithm-tests EXCLUDE_FROM_ALL unit_tests/algorithm_tests.cpp ${AlgorithmTestsGlob} $ $ $ $) # Benchmarks add_executable(rtree-bench EXCLUDE_FROM_ALL benchmarks/static_rtree.cpp $ $ $ $ $) @@ -131,6 +131,7 @@ if(CMAKE_BUILD_TYPE MATCHES Release) message(STATUS "Using gcc specific binutils for LTO.") set(CMAKE_AR "/usr/bin/gcc-ar") set(CMAKE_RANLIB "/usr/bin/gcc-ranlib") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3") endif() endif (HAS_LTO_FLAG) endif() diff --git a/UnitTests/algorithm_tests.cpp b/unit_tests/algorithm_tests.cpp similarity index 100% rename from UnitTests/algorithm_tests.cpp rename to unit_tests/algorithm_tests.cpp diff --git a/UnitTests/Algorithms/DouglasPeuckerTest.cpp b/unit_tests/algorithms/douglas_peucker.cpp similarity index 100% rename from UnitTests/Algorithms/DouglasPeuckerTest.cpp rename to unit_tests/algorithms/douglas_peucker.cpp diff --git a/UnitTests/data_structures/binary_heap.cpp b/unit_tests/data_structures/binary_heap.cpp similarity index 100% rename from UnitTests/data_structures/binary_heap.cpp rename to unit_tests/data_structures/binary_heap.cpp diff --git a/UnitTests/data_structures/range_table.cpp b/unit_tests/data_structures/range_table.cpp similarity index 100% rename from UnitTests/data_structures/range_table.cpp rename to unit_tests/data_structures/range_table.cpp diff --git a/UnitTests/data_structures/static_graph.cpp b/unit_tests/data_structures/static_graph.cpp similarity index 100% rename from UnitTests/data_structures/static_graph.cpp rename to unit_tests/data_structures/static_graph.cpp diff --git a/UnitTests/data_structures/static_rtree.cpp b/unit_tests/data_structures/static_rtree.cpp similarity index 100% rename from UnitTests/data_structures/static_rtree.cpp rename to unit_tests/data_structures/static_rtree.cpp diff --git a/UnitTests/datastructure_tests.cpp b/unit_tests/datastructure_tests.cpp similarity index 100% rename from UnitTests/datastructure_tests.cpp rename to unit_tests/datastructure_tests.cpp From 356dfc806db0a04e46fd2fd9562e43424b2c57ff Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 16 Jan 2015 00:34:07 +0100 Subject: [PATCH 055/360] Fix ComputePerpendicularDistance convinience function This function is used by StaticRTree and returns wrong results. The other variation is correct. To reduce code duplication the correct version is used instead, as the implementation is nearly identical. --- data_structures/coordinate.cpp | 94 +++------------------------------- 1 file changed, 6 insertions(+), 88 deletions(-) diff --git a/data_structures/coordinate.cpp b/data_structures/coordinate.cpp index 2d045e195..61fa433da 100644 --- a/data_structures/coordinate.cpp +++ b/data_structures/coordinate.cpp @@ -157,98 +157,16 @@ float FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1, float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate, const FixedPointCoordinate &target_coordinate, - const FixedPointCoordinate &point) + const FixedPointCoordinate &query_location) { - // initialize values - const float x_value = static_cast(mercator::lat2y(point.lat / COORDINATE_PRECISION)); - const float y_value = point.lon / COORDINATE_PRECISION; - float a = static_cast(mercator::lat2y(source_coordinate.lat / COORDINATE_PRECISION)); - float b = source_coordinate.lon / COORDINATE_PRECISION; - float c = static_cast(mercator::lat2y(target_coordinate.lat / COORDINATE_PRECISION)); - float d = target_coordinate.lon / COORDINATE_PRECISION; - float p, q; - if (std::abs(a - c) > std::numeric_limits::epsilon()) - { - const float slope = (d - b) / (c - a); // slope - // Projection of (x,y) on line joining (a,b) and (c,d) - p = ((x_value + (slope * y_value)) + (slope * slope * a - slope * b)) / - (1.f + slope * slope); - q = b + slope * (p - a); - } - else - { - p = c; - q = y_value; - } - float ratio; - bool inverse_ratio = false; - - // straight line segment on equator - if (std::abs(c) < std::numeric_limits::epsilon() && - std::abs(a) < std::numeric_limits::epsilon()) - { - ratio = (q - b) / (d - b); - } - else - { - if (std::abs(c) < std::numeric_limits::epsilon()) - { - // swap start/end - std::swap(a, c); - std::swap(b, d); - inverse_ratio = true; - } - - float nY = (d * p - c * q) / (a * d - b * c); - // discretize the result to coordinate precision. it's a hack! - if (std::abs(nY) < (1.f / COORDINATE_PRECISION)) - { - nY = 0.f; - } - - // compute ratio - ratio = (p - nY * a) / c; - } - - if (std::isnan(ratio)) - { - ratio = (target_coordinate == point ? 1.f : 0.f); - } - else if (std::abs(ratio) <= std::numeric_limits::epsilon()) - { - ratio = 0.f; - } - else if (std::abs(ratio - 1.f) <= std::numeric_limits::epsilon()) - { - ratio = 1.f; - } - - // we need to do this, if we switched start/end coordinates - if (inverse_ratio) - { - ratio = 1.0f - ratio; - } - - // compute the nearest location FixedPointCoordinate nearest_location; - BOOST_ASSERT(!std::isnan(ratio)); - if (ratio <= 0.f) - { // point is "left" of edge - nearest_location = source_coordinate; - } - else if (ratio >= 1.f) - { // point is "right" of edge - nearest_location = target_coordinate; - } - else - { // point lies in between - nearest_location.lat = static_cast(mercator::y2lat(p) * COORDINATE_PRECISION); - nearest_location.lon = static_cast(q * COORDINATE_PRECISION); - } - BOOST_ASSERT(nearest_location.is_valid()); - return FixedPointCoordinate::ApproximateEuclideanDistance(point, nearest_location); + return ComputePerpendicularDistance(source_coordinate, + target_coordinate, + query_location, + nearest_location, + ratio); } float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &segment_source, From 1b5d332e9309f7fc83c5c779d5828199360dd184 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 16 Jan 2015 00:49:43 +0100 Subject: [PATCH 056/360] Add regression test for FixedpointCoordinate --- unit_tests/data_structures/coordinate.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 unit_tests/data_structures/coordinate.cpp diff --git a/unit_tests/data_structures/coordinate.cpp b/unit_tests/data_structures/coordinate.cpp new file mode 100644 index 000000000..bf28666cf --- /dev/null +++ b/unit_tests/data_structures/coordinate.cpp @@ -0,0 +1,20 @@ +#include + +#include + +// Regression test for bug captured in #1347 +BOOST_AUTO_TEST_CASE(regression_test_1347) +{ + FixedPointCoordinate u(10 * COORDINATE_PRECISION, -100 * COORDINATE_PRECISION); + FixedPointCoordinate v(10.001 * COORDINATE_PRECISION, -100.002 * COORDINATE_PRECISION); + FixedPointCoordinate q(10.002 * COORDINATE_PRECISION, -100.001 * COORDINATE_PRECISION); + + float d1 = FixedPointCoordinate::ComputePerpendicularDistance(u, v, q); + + float ratio; + FixedPointCoordinate nearest_location; + float d2 = FixedPointCoordinate::ComputePerpendicularDistance(u, v, q, nearest_location, ratio); + + BOOST_CHECK_LE(std::abs(d1 - d2), 0.01); +} + From 8d6d7d1f200bb8941b3e90ce3693bb5e3affc6f5 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 16 Jan 2015 11:27:46 +0100 Subject: [PATCH 057/360] remove superflous inline keywords --- data_structures/restriction.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/data_structures/restriction.hpp b/data_structures/restriction.hpp index 5f6e9b0f5..ed38dc639 100644 --- a/data_structures/restriction.hpp +++ b/data_structures/restriction.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -108,19 +108,19 @@ struct InputRestrictionContainer struct CmpRestrictionContainerByFrom { typedef InputRestrictionContainer value_type; - inline bool operator()(const InputRestrictionContainer &a, + bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b) const { return a.restriction.from.way < b.restriction.from.way; } - inline value_type max_value() const { return InputRestrictionContainer::max_value(); } - inline value_type min_value() const { return InputRestrictionContainer::min_value(); } + value_type max_value() const { return InputRestrictionContainer::max_value(); } + value_type min_value() const { return InputRestrictionContainer::min_value(); } }; struct CmpRestrictionContainerByTo { typedef InputRestrictionContainer value_type; - inline bool operator()(const InputRestrictionContainer &a, + bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b) const { return a.restriction.to.way < b.restriction.to.way; From 7cf34a6d6f52f566accf33aed0793d582886bf9d Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 16 Jan 2015 15:47:01 +0100 Subject: [PATCH 058/360] make debug output more verbose during renumbering of turn restriction members --- Util/graph_loader.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Util/graph_loader.hpp b/Util/graph_loader.hpp index bbf9d5fbb..6c40ee7c7 100644 --- a/Util/graph_loader.hpp +++ b/Util/graph_loader.hpp @@ -102,7 +102,7 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, auto internal_id_iter = ext_to_int_id_map.find(current_restriction.from.node); if (internal_id_iter == ext_to_int_id_map.end()) { - SimpleLogger().Write(logDEBUG) << "Unmapped from Node of restriction"; + SimpleLogger().Write(logDEBUG) << "Unmapped from node " << current_restriction.from.node << " of restriction"; continue; } current_restriction.from.node = internal_id_iter->second; @@ -110,15 +110,16 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, internal_id_iter = ext_to_int_id_map.find(current_restriction.via.node); if (internal_id_iter == ext_to_int_id_map.end()) { - SimpleLogger().Write(logDEBUG) << "Unmapped via node of restriction"; + SimpleLogger().Write(logDEBUG) << "Unmapped via node " << current_restriction.via.node << " of restriction"; continue; } + current_restriction.via.node = internal_id_iter->second; internal_id_iter = ext_to_int_id_map.find(current_restriction.to.node); if (internal_id_iter == ext_to_int_id_map.end()) { - SimpleLogger().Write(logDEBUG) << "Unmapped to node of restriction"; + SimpleLogger().Write(logDEBUG) << "Unmapped to node " << current_restriction.to.node << " of restriction"; continue; } current_restriction.to.node = internal_id_iter->second; From 959d9a3ad94ae5891597ca35cb912ec8d5f6b76f Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 16 Jan 2015 15:49:29 +0100 Subject: [PATCH 059/360] explicitly implement check if is_only turn is restricted --- data_structures/restriction_map.cpp | 13 +++++++++---- data_structures/restriction_map.hpp | 6 +++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/data_structures/restriction_map.cpp b/data_structures/restriction_map.cpp index 3c13d738a..b43be579c 100644 --- a/data_structures/restriction_map.cpp +++ b/data_structures/restriction_map.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -149,11 +149,16 @@ bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID node_u, { const unsigned index = restriction_iter->second; const auto &bucket = m_restriction_bucket_list.at(index); + for (const RestrictionTarget &restriction_target : bucket) { - if ((node_w == restriction_target.target_node) && // target found - (!restriction_target.is_only) // and not an only_-restr. - ) + if (node_w == restriction_target.target_node && // target found + !restriction_target.is_only) // and not an only_-restr. + { + return true; + } + if (node_w != restriction_target.target_node && // target not found + restriction_target.is_only) // and is an only restriction { return true; } diff --git a/data_structures/restriction_map.hpp b/data_structures/restriction_map.hpp index 7633faf4d..41eb17a8c 100644 --- a/data_structures/restriction_map.hpp +++ b/data_structures/restriction_map.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -28,14 +28,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef RESTRICTION_MAP_HPP #define RESTRICTION_MAP_HPP -#include - #include "restriction.hpp" #include "../Util/std_hash.hpp" #include "../typedefs.h" #include +#include #include #include #include @@ -136,6 +135,7 @@ class RestrictionMap const unsigned index = restriction_iterator->second; auto &bucket = m_restriction_bucket_list.at(index); + for (RestrictionTarget &restriction_target : bucket) { if (node_v == restriction_target.target_node) From 283550829218093a3e701c4878375d3daaf64474 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 16 Jan 2015 15:56:49 +0100 Subject: [PATCH 060/360] fixes #1346: - use const_iterator where it makes sense - fix renumbering of turn restriction members - remove redundant code - fix counting of usable turn restrictions --- extractor/extraction_containers.cpp | 64 +++++++++++------------------ 1 file changed, 25 insertions(+), 39 deletions(-) diff --git a/extractor/extraction_containers.cpp b/extractor/extraction_containers.cpp index 604f863cd..2927456f3 100644 --- a/extractor/extraction_containers.cpp +++ b/extractor/extraction_containers.cpp @@ -114,9 +114,9 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, std::cout << "[extractor] Fixing restriction starts ... " << std::flush; TIMER_START(fix_restriction_starts); auto restrictions_iterator = restrictions_list.begin(); - auto way_start_and_end_iterator = way_start_end_id_list.begin(); + auto way_start_and_end_iterator = way_start_end_id_list.cbegin(); - while (way_start_and_end_iterator != way_start_end_id_list.end() && + while (way_start_and_end_iterator != way_start_end_id_list.cend() && restrictions_iterator != restrictions_list.end()) { if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.from.way) @@ -137,21 +137,12 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, if (way_start_and_end_iterator->first_segment_source_id == via_node_id) { restrictions_iterator->restriction.from.node = - way_start_and_end_iterator->first_segment_source_id; - } - else if (way_start_and_end_iterator->first_segment_source_id == via_node_id) - { - restrictions_iterator->restriction.from.node = - way_start_and_end_iterator->first_segment_source_id; - } - else if (way_start_and_end_iterator->last_segment_source_id == via_node_id) - { - restrictions_iterator->restriction.from.node = - way_start_and_end_iterator->last_segment_target_id; + way_start_and_end_iterator->first_segment_target_id; } else if (way_start_and_end_iterator->last_segment_target_id == via_node_id) { - restrictions_iterator->restriction.from.node = way_start_and_end_iterator->last_segment_source_id; + restrictions_iterator->restriction.from.node = + way_start_and_end_iterator->last_segment_source_id; } ++restrictions_iterator; } @@ -168,12 +159,11 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, TIMER_STOP(sort_restrictions_to); std::cout << "ok, after " << TIMER_SEC(sort_restrictions_to) << "s" << std::endl; - unsigned number_of_useable_restrictions = 0; std::cout << "[extractor] Fixing restriction ends ... " << std::flush; TIMER_START(fix_restriction_ends); restrictions_iterator = restrictions_list.begin(); - way_start_and_end_iterator = way_start_end_id_list.begin(); - while (way_start_and_end_iterator != way_start_end_id_list.end() && + way_start_and_end_iterator = way_start_end_id_list.cbegin(); + while (way_start_and_end_iterator != way_start_end_id_list.cend() && restrictions_iterator != restrictions_list.end()) { if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.to.way) @@ -186,51 +176,47 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, ++restrictions_iterator; continue; } - NodeID via_node_id = restrictions_iterator->restriction.via.node; - if (way_start_and_end_iterator->last_segment_source_id == via_node_id) + BOOST_ASSERT(way_start_and_end_iterator->way_id == restrictions_iterator->restriction.to.way); + const NodeID via_node_id = restrictions_iterator->restriction.via.node; + + if (way_start_and_end_iterator->first_segment_source_id == via_node_id) { - restrictions_iterator->restriction.to.node = way_start_and_end_iterator->last_segment_target_id; + restrictions_iterator->restriction.to.node = + way_start_and_end_iterator->first_segment_target_id; } else if (way_start_and_end_iterator->last_segment_target_id == via_node_id) { - restrictions_iterator->restriction.to.node = way_start_and_end_iterator->last_segment_source_id; - } - else if (way_start_and_end_iterator->first_segment_source_id == via_node_id) - { - restrictions_iterator->restriction.to.node = way_start_and_end_iterator->first_segment_target_id; - } - else if (way_start_and_end_iterator->first_segment_target_id == via_node_id) - { - restrictions_iterator->restriction.to.node = way_start_and_end_iterator->first_segment_source_id; - } - - if (std::numeric_limits::max() != restrictions_iterator->restriction.from.node && - std::numeric_limits::max() != restrictions_iterator->restriction.to.node) - { - ++number_of_useable_restrictions; + restrictions_iterator->restriction.to.node = + way_start_and_end_iterator->last_segment_source_id; } ++restrictions_iterator; } TIMER_STOP(fix_restriction_ends); std::cout << "ok, after " << TIMER_SEC(fix_restriction_ends) << "s" << std::endl; - SimpleLogger().Write() << "usable restrictions: " << number_of_useable_restrictions; // serialize restrictions std::ofstream restrictions_out_stream; + unsigned written_restriction_count = 0; restrictions_out_stream.open(restrictions_file_name.c_str(), std::ios::binary); restrictions_out_stream.write((char *)&fingerprint, sizeof(FingerPrint)); - restrictions_out_stream.write((char *)&number_of_useable_restrictions, sizeof(unsigned)); + const auto count_position = restrictions_out_stream.tellp(); + restrictions_out_stream.write((char *)&written_restriction_count, sizeof(unsigned)); for(const auto & restriction_container : restrictions_list) { - if (std::numeric_limits::max() != restriction_container.restriction.from.node && - std::numeric_limits::max() != restriction_container.restriction.to.node) + if (SPECIAL_NODEID != restriction_container.restriction.from.node && + SPECIAL_NODEID != restriction_container.restriction.to.node) { restrictions_out_stream.write((char *)&(restriction_container.restriction), sizeof(TurnRestriction)); + ++written_restriction_count; } } + restrictions_out_stream.seekp(count_position); + restrictions_out_stream.write((char *)&written_restriction_count, sizeof(unsigned)); + restrictions_out_stream.close(); + SimpleLogger().Write() << "usable restrictions: " << written_restriction_count; std::ofstream file_out_stream; file_out_stream.open(output_file_name.c_str(), std::ios::binary); From 061d281d2ad96b71b4853fcb62c551bd22f8c49b Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 16 Jan 2015 17:10:31 +0100 Subject: [PATCH 061/360] serialize bitfields thru local member mockups --- extractor/extraction_containers.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/extractor/extraction_containers.cpp b/extractor/extraction_containers.cpp index 2927456f3..6e12db18a 100644 --- a/extractor/extraction_containers.cpp +++ b/extractor/extraction_containers.cpp @@ -338,9 +338,11 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, 1, (int)std::floor( (edge_iterator->is_duration_set ? edge_iterator->speed : weight) + .5)); - int integer_distance = std::max(1, (int)distance); - short zero = 0; - short one = 1; + const int integer_distance = std::max(1, (int)distance); + const short zero = 0; + const short one = 1; + const bool yes = true; + const bool no = false; file_out_stream.write((char *)&edge_iterator->start, sizeof(unsigned)); file_out_stream.write((char *)&edge_iterator->target, sizeof(unsigned)); @@ -365,15 +367,15 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, file_out_stream.write((char *)&integer_weight, sizeof(int)); file_out_stream.write((char *)&edge_iterator->name_id, sizeof(unsigned)); - file_out_stream.write((char *)&edge_iterator->is_roundabout, sizeof(bool)); - file_out_stream.write((char *)&edge_iterator->is_in_tiny_cc, sizeof(bool)); - file_out_stream.write((char *)&edge_iterator->is_access_restricted, sizeof(bool)); + file_out_stream.write((char *)&(edge_iterator->is_roundabout ? yes : no), sizeof(bool)); + file_out_stream.write((char *)&(edge_iterator->is_in_tiny_cc ? yes : no), sizeof(bool)); + file_out_stream.write((char *)&(edge_iterator->is_access_restricted ? yes : no), sizeof(bool)); // cannot take adress of bit field, so use local const TravelMode travel_mode = edge_iterator->travel_mode; file_out_stream.write((char *)&travel_mode, sizeof(TravelMode)); - file_out_stream.write((char *)&edge_iterator->is_split, sizeof(bool)); + file_out_stream.write((char *)&(edge_iterator->is_split ? yes : no), sizeof(bool)); ++number_of_used_edges; } ++edge_iterator; From 7ba9b97afc9fb529fe9066ae8cc96d11f7a9f810 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 16 Jan 2015 17:11:30 +0100 Subject: [PATCH 062/360] reorder members of internal extractor edge. 56->40 bytes --- extractor/internal_extractor_edge.hpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/extractor/internal_extractor_edge.hpp b/extractor/internal_extractor_edge.hpp index a852a905c..39616d345 100644 --- a/extractor/internal_extractor_edge.hpp +++ b/extractor/internal_extractor_edge.hpp @@ -38,9 +38,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct InternalExtractorEdge { InternalExtractorEdge() - : start(0), target(0), direction(0), speed(0), name_id(0), is_roundabout(false), + : start(0), target(0), speed(0), name_id(0), direction(0), is_roundabout(false), is_in_tiny_cc(false), is_duration_set(false), is_access_restricted(false), - travel_mode(TRAVEL_MODE_INACCESSIBLE), is_split(false) + is_split(false), travel_mode(TRAVEL_MODE_INACCESSIBLE) { } @@ -55,10 +55,10 @@ struct InternalExtractorEdge bool is_access_restricted, TravelMode travel_mode, bool is_split) - : start(start), target(target), direction(direction), speed(speed), - name_id(name_id), is_roundabout(is_roundabout), is_in_tiny_cc(is_in_tiny_cc), + : start(start), target(target), speed(speed), name_id(name_id), + direction(direction), is_roundabout(is_roundabout), is_in_tiny_cc(is_in_tiny_cc), is_duration_set(is_duration_set), is_access_restricted(is_access_restricted), - travel_mode(travel_mode), is_split(is_split) + is_split(is_split), travel_mode(travel_mode) { } @@ -75,15 +75,15 @@ struct InternalExtractorEdge NodeID start; NodeID target; - short direction; double speed; unsigned name_id; - bool is_roundabout; - bool is_in_tiny_cc; - bool is_duration_set; - bool is_access_restricted; + short direction; + bool is_roundabout:1; + bool is_in_tiny_cc:1; + bool is_duration_set:1; + bool is_access_restricted:1; + bool is_split:1; TravelMode travel_mode : 4; - bool is_split; FixedPointCoordinate source_coordinate; FixedPointCoordinate target_coordinate; From f3bc1ed3a9527bf0f184dcd29465d4cded20bdc9 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 16 Jan 2015 17:21:02 +0100 Subject: [PATCH 063/360] make floating point number literal a float --- unit_tests/data_structures/coordinate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unit_tests/data_structures/coordinate.cpp b/unit_tests/data_structures/coordinate.cpp index bf28666cf..818e057a1 100644 --- a/unit_tests/data_structures/coordinate.cpp +++ b/unit_tests/data_structures/coordinate.cpp @@ -15,6 +15,6 @@ BOOST_AUTO_TEST_CASE(regression_test_1347) FixedPointCoordinate nearest_location; float d2 = FixedPointCoordinate::ComputePerpendicularDistance(u, v, q, nearest_location, ratio); - BOOST_CHECK_LE(std::abs(d1 - d2), 0.01); + BOOST_CHECK_LE(std::abs(d1 - d2), 0.01f); } From 472a567f421a334f9300431ff10a4255c295b94d Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 16 Jan 2015 17:23:29 +0100 Subject: [PATCH 064/360] add cmath include to fix call to std::abs() on clang compiler, reorder includes --- unit_tests/data_structures/coordinate.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/unit_tests/data_structures/coordinate.cpp b/unit_tests/data_structures/coordinate.cpp index 818e057a1..925f44ccc 100644 --- a/unit_tests/data_structures/coordinate.cpp +++ b/unit_tests/data_structures/coordinate.cpp @@ -1,6 +1,8 @@ +#include + #include -#include +#include // Regression test for bug captured in #1347 BOOST_AUTO_TEST_CASE(regression_test_1347) From 46a7e46068db11c94c6b74c24d2c137c56b807f8 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 16 Jan 2015 18:12:21 +0100 Subject: [PATCH 065/360] serialize lvalues as MSVC barfs out on serializing the return value of the conditional operator --- extractor/extraction_containers.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/extractor/extraction_containers.cpp b/extractor/extraction_containers.cpp index 6e12db18a..3bfcb5cee 100644 --- a/extractor/extraction_containers.cpp +++ b/extractor/extraction_containers.cpp @@ -367,9 +367,24 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, file_out_stream.write((char *)&integer_weight, sizeof(int)); file_out_stream.write((char *)&edge_iterator->name_id, sizeof(unsigned)); - file_out_stream.write((char *)&(edge_iterator->is_roundabout ? yes : no), sizeof(bool)); - file_out_stream.write((char *)&(edge_iterator->is_in_tiny_cc ? yes : no), sizeof(bool)); - file_out_stream.write((char *)&(edge_iterator->is_access_restricted ? yes : no), sizeof(bool)); + if (edge_iterator->is_roundabout) + { + file_out_stream.write((char *)&yes, sizeof(bool)); + } else { + file_out_stream.write((char *)&no, sizeof(bool)); + } + if (edge_iterator->is_in_tiny_cc) + { + file_out_stream.write((char *)&yes, sizeof(bool)); + } else { + file_out_stream.write((char *)&no, sizeof(bool)); + } + if (edge_iterator->is_access_restricted) + { + file_out_stream.write((char *)&yes, sizeof(bool)); + } else { + file_out_stream.write((char *)&no, sizeof(bool)); + } // cannot take adress of bit field, so use local const TravelMode travel_mode = edge_iterator->travel_mode; From 08cc2bbd70b44faaaa8f2b9f5f504f947b6ca703 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 16 Jan 2015 18:22:20 +0100 Subject: [PATCH 066/360] move thread local variables out of parsing scope --- extractor/extractor.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/extractor/extractor.cpp b/extractor/extractor.cpp index 3533d291f..3f7c994ef 100644 --- a/extractor/extractor.cpp +++ b/extractor/extractor.cpp @@ -173,15 +173,14 @@ int Extractor::Run(int argc, char *argv[]) tbb::parallel_for(tbb::blocked_range(0, osm_elements.size()), [&](const tbb::blocked_range &range) { + ExtractionNode result_node; + ExtractionWay result_way; + lua_State * local_state = scripting_environment.get_lua_state(); + for (auto x = range.begin(); x != range.end(); ++x) { const auto entity = osm_elements[x]; - ExtractionNode result_node; - ExtractionWay result_way; - - lua_State * local_state = scripting_environment.get_lua_state(); - switch (entity->type()) { case osmium::item_type::node: From f4ff6950809ae91545577ff0e6422d9efe2aa6aa Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 20 Jan 2015 10:50:33 +0100 Subject: [PATCH 067/360] replace conditional operator by explicit serialization --- extractor/extraction_containers.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/extractor/extraction_containers.cpp b/extractor/extraction_containers.cpp index 3bfcb5cee..ff2f6e1dc 100644 --- a/extractor/extraction_containers.cpp +++ b/extractor/extraction_containers.cpp @@ -390,7 +390,12 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, const TravelMode travel_mode = edge_iterator->travel_mode; file_out_stream.write((char *)&travel_mode, sizeof(TravelMode)); - file_out_stream.write((char *)&(edge_iterator->is_split ? yes : no), sizeof(bool)); + if (edge_iterator->is_split) + { + file_out_stream.write((char *)&yes, sizeof(bool)); + } else { + file_out_stream.write((char *)&no, sizeof(bool)); + } ++number_of_used_edges; } ++edge_iterator; From 8f813fbc675acdcd343463ffb83cd0f766748fb3 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 20 Jan 2015 11:25:21 +0100 Subject: [PATCH 068/360] clear result nodes/way in parser for each parsed element --- extractor/extractor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extractor/extractor.cpp b/extractor/extractor.cpp index 3f7c994ef..d8a3d5563 100644 --- a/extractor/extractor.cpp +++ b/extractor/extractor.cpp @@ -184,6 +184,7 @@ int Extractor::Run(int argc, char *argv[]) switch (entity->type()) { case osmium::item_type::node: + result_node.clear(); ++number_of_nodes; luabind::call_function( local_state, @@ -193,6 +194,7 @@ int Extractor::Run(int argc, char *argv[]) resulting_nodes.push_back(std::make_pair(x, result_node)); break; case osmium::item_type::way: + result_way.clear(); ++number_of_ways; luabind::call_function( local_state, From 01f323741606346bee2b282f4ee5f7106914ef39 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 20 Jan 2015 16:24:49 +0100 Subject: [PATCH 069/360] speed up nearest neighbor query by pruning, move coordinate calculations away from library interface --- CMakeLists.txt | 2 +- Include/osrm/coordinate.hpp | 47 +-- data_structures/coordinate.cpp | 303 +------------- data_structures/coordinate_calculation.cpp | 422 ++++++++++++++++++++ data_structures/coordinate_calculation.hpp | 97 +++++ data_structures/rectangle.hpp | 36 +- data_structures/static_rtree.hpp | 88 ++-- data_structures/upper_bound.hpp | 75 ++++ descriptors/description_factory.cpp | 3 +- descriptors/descriptor_base.hpp | 1 + descriptors/gpx_descriptor.hpp | 6 +- extractor/extraction_containers.cpp | 3 +- unit_tests/data_structures/coordinate.cpp | 33 +- unit_tests/data_structures/static_rtree.cpp | 33 +- 14 files changed, 733 insertions(+), 416 deletions(-) create mode 100644 data_structures/coordinate_calculation.cpp create mode 100644 data_structures/coordinate_calculation.hpp create mode 100644 data_structures/upper_bound.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 356908071..c00006f33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,7 +72,7 @@ file(GLOB ServerGlob Server/*.cpp) file(GLOB DescriptorGlob descriptors/*.cpp) file(GLOB DatastructureGlob data_structures/search_engine_data.cpp data_structures/route_parameters.cpp Util/bearing.cpp) list(REMOVE_ITEM DatastructureGlob data_structures/Coordinate.cpp) -file(GLOB CoordinateGlob data_structures/coordinate.cpp) +file(GLOB CoordinateGlob data_structures/coordinate*.cpp) file(GLOB AlgorithmGlob algorithms/*.cpp) file(GLOB HttpGlob Server/Http/*.cpp) file(GLOB LibOSRMGlob Library/*.cpp) diff --git a/Include/osrm/coordinate.hpp b/Include/osrm/coordinate.hpp index 3229f256f..b6903930e 100644 --- a/Include/osrm/coordinate.hpp +++ b/Include/osrm/coordinate.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -36,6 +36,7 @@ namespace { constexpr static const float COORDINATE_PRECISION = 1000000.f; } + struct FixedPointCoordinate { int lat; @@ -56,52 +57,8 @@ struct FixedPointCoordinate bool is_valid() const; bool operator==(const FixedPointCoordinate &other) const; - static double - ApproximateDistance(const int lat1, const int lon1, const int lat2, const int lon2); - - static double ApproximateDistance(const FixedPointCoordinate &first_coordinate, - const FixedPointCoordinate &second_coordinate); - - static float ApproximateEuclideanDistance(const FixedPointCoordinate &first_coordinate, - const FixedPointCoordinate &second_coordinate); - - static float - ApproximateEuclideanDistance(const int lat1, const int lon1, const int lat2, const int lon2); - - static float ApproximateSquaredEuclideanDistance(const FixedPointCoordinate &first_coordinate, - const FixedPointCoordinate &second_coordinate); - - static void convertInternalLatLonToString(const int value, std::string &output); - - static void convertInternalCoordinateToString(const FixedPointCoordinate &coordinate, - std::string &output); - - static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coordinate, - std::string &output); - - static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source, - const FixedPointCoordinate &segment_target, - const FixedPointCoordinate &query_location); - - static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source, - const FixedPointCoordinate &segment_target, - const FixedPointCoordinate &query_location, - FixedPointCoordinate &nearest_location, - float &ratio); - - static int - OrderedPerpendicularDistanceApproximation(const FixedPointCoordinate &segment_source, - const FixedPointCoordinate &segment_target, - const FixedPointCoordinate &query_location); - - static float GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B); - float GetBearing(const FixedPointCoordinate &other) const; - void Output(std::ostream &out) const; - - static float DegreeToRadian(const float degree); - static float RadianToDegree(const float radian); }; inline std::ostream &operator<<(std::ostream &out_stream, FixedPointCoordinate const &coordinate) diff --git a/data_structures/coordinate.cpp b/data_structures/coordinate.cpp index 61fa433da..dbddc4742 100644 --- a/data_structures/coordinate.cpp +++ b/data_structures/coordinate.cpp @@ -25,20 +25,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "coordinate_calculation.hpp" + #include "../Util/mercator.hpp" -#ifndef NDEBUG #include "../Util/simple_logger.hpp" -#endif -#include "../Util/string_util.hpp" #include - #include +#include + #ifndef NDEBUG #include #endif -#include #include FixedPointCoordinate::FixedPointCoordinate() @@ -87,235 +86,21 @@ bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const return lat == other.lat && lon == other.lon; } -double FixedPointCoordinate::ApproximateDistance(const int lat1, - const int lon1, - const int lat2, - const int lon2) -{ - BOOST_ASSERT(lat1 != std::numeric_limits::min()); - BOOST_ASSERT(lon1 != std::numeric_limits::min()); - BOOST_ASSERT(lat2 != std::numeric_limits::min()); - BOOST_ASSERT(lon2 != std::numeric_limits::min()); - double RAD = 0.017453292519943295769236907684886; - double lt1 = lat1 / COORDINATE_PRECISION; - double ln1 = lon1 / COORDINATE_PRECISION; - double lt2 = lat2 / COORDINATE_PRECISION; - double ln2 = lon2 / COORDINATE_PRECISION; - double dlat1 = lt1 * (RAD); - - double dlong1 = ln1 * (RAD); - double dlat2 = lt2 * (RAD); - double dlong2 = ln2 * (RAD); - - double dLong = dlong1 - dlong2; - double dLat = dlat1 - dlat2; - - double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2); - double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv)); - // earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi) - // The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles) - const double earth = 6372797.560856; - return earth * cHarv; -} - -double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &coordinate_1, - const FixedPointCoordinate &coordinate_2) -{ - return ApproximateDistance( - coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon); -} - -float FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &coordinate_1, - const FixedPointCoordinate &coordinate_2) -{ - return ApproximateEuclideanDistance( - coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon); -} - -float FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1, - const int lon1, - const int lat2, - const int lon2) -{ - BOOST_ASSERT(lat1 != std::numeric_limits::min()); - BOOST_ASSERT(lon1 != std::numeric_limits::min()); - BOOST_ASSERT(lat2 != std::numeric_limits::min()); - BOOST_ASSERT(lon2 != std::numeric_limits::min()); - - const float RAD = 0.017453292519943295769236907684886f; - const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD; - const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD; - const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD; - const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD; - - const float x_value = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.f); - const float y_value = float_lat2 - float_lat1; - const float earth_radius = 6372797.560856f; - return sqrt(x_value * x_value + y_value * y_value) * earth_radius; -} - -float -FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate, - const FixedPointCoordinate &target_coordinate, - const FixedPointCoordinate &query_location) -{ - float ratio; - FixedPointCoordinate nearest_location; - - return ComputePerpendicularDistance(source_coordinate, - target_coordinate, - query_location, - nearest_location, - ratio); -} - -float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &segment_source, - const FixedPointCoordinate &segment_target, - const FixedPointCoordinate &query_location, - FixedPointCoordinate &nearest_location, - float &ratio) -{ - BOOST_ASSERT(query_location.is_valid()); - - // initialize values - const double x = mercator::lat2y(query_location.lat / COORDINATE_PRECISION); - const double y = query_location.lon / COORDINATE_PRECISION; - const double a = mercator::lat2y(segment_source.lat / COORDINATE_PRECISION); - const double b = segment_source.lon / COORDINATE_PRECISION; - const double c = mercator::lat2y(segment_target.lat / COORDINATE_PRECISION); - const double d = segment_target.lon / COORDINATE_PRECISION; - double p, q /*,mX*/, nY; - if (std::abs(a - c) > std::numeric_limits::epsilon()) - { - const double m = (d - b) / (c - a); // slope - // Projection of (x,y) on line joining (a,b) and (c,d) - p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m); - q = b + m * (p - a); - } - else - { - p = c; - q = y; - } - nY = (d * p - c * q) / (a * d - b * c); - - // discretize the result to coordinate precision. it's a hack! - if (std::abs(nY) < (1.f / COORDINATE_PRECISION)) - { - nY = 0.f; - } - - // compute ratio - ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need - // not calculate the explicit values of m an n as we - // are just interested in the ratio - if (std::isnan(ratio)) - { - ratio = (segment_target == query_location ? 1.f : 0.f); - } - else if (std::abs(ratio) <= std::numeric_limits::epsilon()) - { - ratio = 0.f; - } - else if (std::abs(ratio - 1.f) <= std::numeric_limits::epsilon()) - { - ratio = 1.f; - } - - // compute nearest location - BOOST_ASSERT(!std::isnan(ratio)); - if (ratio <= 0.f) - { - nearest_location = segment_source; - } - else if (ratio >= 1.f) - { - nearest_location = segment_target; - } - else - { - // point lies in between - nearest_location.lat = static_cast(mercator::y2lat(p) * COORDINATE_PRECISION); - nearest_location.lon = static_cast(q * COORDINATE_PRECISION); - } - BOOST_ASSERT(nearest_location.is_valid()); - - const float approximate_distance = - FixedPointCoordinate::ApproximateEuclideanDistance(query_location, nearest_location); - BOOST_ASSERT(0. <= approximate_distance); - return approximate_distance; -} - -void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output) -{ - char buffer[12]; - buffer[11] = 0; // zero termination - output = printInt<11, 6>(buffer, value); -} - -void FixedPointCoordinate::convertInternalCoordinateToString(const FixedPointCoordinate &coord, - std::string &output) -{ - std::string tmp; - tmp.reserve(23); - convertInternalLatLonToString(coord.lon, tmp); - output = tmp; - output += ","; - convertInternalLatLonToString(coord.lat, tmp); - output += tmp; -} - -void -FixedPointCoordinate::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord, - std::string &output) -{ - std::string tmp; - tmp.reserve(23); - convertInternalLatLonToString(coord.lat, tmp); - output = tmp; - output += ","; - convertInternalLatLonToString(coord.lon, tmp); - output += tmp; -} - void FixedPointCoordinate::Output(std::ostream &out) const { out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")"; } -float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &first_coordinate, - const FixedPointCoordinate &second_coordinate) -{ - const float lon_diff = - second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION; - const float lon_delta = DegreeToRadian(lon_diff); - const float lat1 = DegreeToRadian(first_coordinate.lat / COORDINATE_PRECISION); - const float lat2 = DegreeToRadian(second_coordinate.lat / COORDINATE_PRECISION); - const float y = sin(lon_delta) * cos(lat2); - const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon_delta); - float result = RadianToDegree(std::atan2(y, x)); - while (result < 0.f) - { - result += 360.f; - } - - while (result >= 360.f) - { - result -= 360.f; - } - return result; -} - float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const { const float lon_delta = - DegreeToRadian(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION); - const float lat1 = DegreeToRadian(other.lat / COORDINATE_PRECISION); - const float lat2 = DegreeToRadian(lat / COORDINATE_PRECISION); + coordinate_calculation::deg_to_rad(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION); + const float lat1 = coordinate_calculation::deg_to_rad(other.lat / COORDINATE_PRECISION); + const float lat2 = coordinate_calculation::deg_to_rad(lat / COORDINATE_PRECISION); const float y_value = std::sin(lon_delta) * std::cos(lat2); const float x_value = std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta); - float result = RadianToDegree(std::atan2(y_value, x_value)); + float result = coordinate_calculation::rad_to_deg(std::atan2(y_value, x_value)); while (result < 0.f) { @@ -328,75 +113,3 @@ float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const } return result; } - -float FixedPointCoordinate::DegreeToRadian(const float degree) -{ - return degree * (static_cast(M_PI) / 180.f); -} - -float FixedPointCoordinate::RadianToDegree(const float radian) -{ - return radian * (180.f * static_cast(M_1_PI)); -} - -// This distance computation does integer arithmetic only and is a lot faster than -// the other distance function which are numerically correct('ish). -// It preserves some order among the elements that make it useful for certain purposes -int FixedPointCoordinate::OrderedPerpendicularDistanceApproximation( - const FixedPointCoordinate &input_point, - const FixedPointCoordinate &segment_source, - const FixedPointCoordinate &segment_target) -{ - // initialize values - const float x = static_cast(mercator::lat2y(input_point.lat / COORDINATE_PRECISION)); - const float y = input_point.lon / COORDINATE_PRECISION; - const float a = static_cast(mercator::lat2y(segment_source.lat / COORDINATE_PRECISION)); - const float b = segment_source.lon / COORDINATE_PRECISION; - const float c = static_cast(mercator::lat2y(segment_target.lat / COORDINATE_PRECISION)); - const float d = segment_target.lon / COORDINATE_PRECISION; - - float p, q; - if (a == c) - { - p = c; - q = y; - } - else - { - const float m = (d - b) / (c - a); // slope - // Projection of (x,y) on line joining (a,b) and (c,d) - p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m); - q = b + m * (p - a); - } - - const float nY = (d * p - c * q) / (a * d - b * c); - float ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need - // not calculate the explicit values of m an n as we - // are just interested in the ratio - if (std::isnan(ratio)) - { - ratio = (segment_target == input_point) ? 1.f : 0.f; - } - - // compute target quasi-location - int dx, dy; - if (ratio < 0.f) - { - dx = input_point.lon - segment_source.lon; - dy = input_point.lat - segment_source.lat; - } - else if (ratio > 1.f) - { - dx = input_point.lon - segment_target.lon; - dy = input_point.lat - segment_target.lat; - } - else - { - // point lies in between - dx = input_point.lon - static_cast(q * COORDINATE_PRECISION); - dy = input_point.lat - static_cast(mercator::y2lat(p) * COORDINATE_PRECISION); - } - - // return an approximation in the plane - return static_cast(sqrt(dx * dx + dy * dy)); -} diff --git a/data_structures/coordinate_calculation.cpp b/data_structures/coordinate_calculation.cpp new file mode 100644 index 000000000..cc0474c79 --- /dev/null +++ b/data_structures/coordinate_calculation.cpp @@ -0,0 +1,422 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "coordinate_calculation.hpp" + +#include "../Util/mercator.hpp" +#include "../Util/string_util.hpp" + +#include + +#include + +#include + +namespace +{ +constexpr static const float RAD = 0.017453292519943295769236907684886; +constexpr static const float earth_radius = 6372797.560856f; +} + +double coordinate_calculation::ApproximateDistance(const int lat1, + const int lon1, + const int lat2, + const int lon2) +{ + BOOST_ASSERT(lat1 != std::numeric_limits::min()); + BOOST_ASSERT(lon1 != std::numeric_limits::min()); + BOOST_ASSERT(lat2 != std::numeric_limits::min()); + BOOST_ASSERT(lon2 != std::numeric_limits::min()); + double lt1 = lat1 / COORDINATE_PRECISION; + double ln1 = lon1 / COORDINATE_PRECISION; + double lt2 = lat2 / COORDINATE_PRECISION; + double ln2 = lon2 / COORDINATE_PRECISION; + double dlat1 = lt1 * (RAD); + + double dlong1 = ln1 * (RAD); + double dlat2 = lt2 * (RAD); + double dlong2 = ln2 * (RAD); + + double dLong = dlong1 - dlong2; + double dLat = dlat1 - dlat2; + + double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2); + double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv)); + // earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi) + // The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles) + return earth_radius * cHarv; +} + +double coordinate_calculation::ApproximateDistance(const FixedPointCoordinate &coordinate_1, + const FixedPointCoordinate &coordinate_2) +{ + return ApproximateDistance( + coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon); +} + +float coordinate_calculation::approx_euclidean_distance(const FixedPointCoordinate &coordinate_1, + const FixedPointCoordinate &coordinate_2) +{ + return approx_euclidean_distance( + coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon); +} + +float coordinate_calculation::approx_euclidean_distance(const int lat1, + const int lon1, + const int lat2, + const int lon2) +{ + BOOST_ASSERT(lat1 != std::numeric_limits::min()); + BOOST_ASSERT(lon1 != std::numeric_limits::min()); + BOOST_ASSERT(lat2 != std::numeric_limits::min()); + BOOST_ASSERT(lon2 != std::numeric_limits::min()); + + const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD; + const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD; + const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD; + const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD; + + const float x_value = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.f); + const float y_value = float_lat2 - float_lat1; + return sqrt(x_value * x_value + y_value * y_value) * earth_radius; +} + +float +coordinate_calculation::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate, + const FixedPointCoordinate &target_coordinate, + const FixedPointCoordinate &query_location) +{ + float ratio; + FixedPointCoordinate nearest_location; + + return ComputePerpendicularDistance(source_coordinate, + target_coordinate, + query_location, + nearest_location, + ratio); +} + +float coordinate_calculation::ComputePerpendicularDistance(const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target, + const FixedPointCoordinate &query_location, + FixedPointCoordinate &nearest_location, + float &ratio) +{ + BOOST_ASSERT(query_location.is_valid()); + + // initialize values + const double x = mercator::lat2y(query_location.lat / COORDINATE_PRECISION); + const double y = query_location.lon / COORDINATE_PRECISION; + const double a = mercator::lat2y(segment_source.lat / COORDINATE_PRECISION); + const double b = segment_source.lon / COORDINATE_PRECISION; + const double c = mercator::lat2y(segment_target.lat / COORDINATE_PRECISION); + const double d = segment_target.lon / COORDINATE_PRECISION; + double p, q /*,mX*/, nY; + if (std::abs(a - c) > std::numeric_limits::epsilon()) + { + const double m = (d - b) / (c - a); // slope + // Projection of (x,y) on line joining (a,b) and (c,d) + p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m); + q = b + m * (p - a); + } + else + { + p = c; + q = y; + } + nY = (d * p - c * q) / (a * d - b * c); + + // discretize the result to coordinate precision. it's a hack! + if (std::abs(nY) < (1.f / COORDINATE_PRECISION)) + { + nY = 0.f; + } + + // compute ratio + ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need + // not calculate the explicit values of m an n as we + // are just interested in the ratio + if (std::isnan(ratio)) + { + ratio = (segment_target == query_location ? 1.f : 0.f); + } + else if (std::abs(ratio) <= std::numeric_limits::epsilon()) + { + ratio = 0.f; + } + else if (std::abs(ratio - 1.f) <= std::numeric_limits::epsilon()) + { + ratio = 1.f; + } + + // compute nearest location + BOOST_ASSERT(!std::isnan(ratio)); + if (ratio <= 0.f) + { + nearest_location = segment_source; + } + else if (ratio >= 1.f) + { + nearest_location = segment_target; + } + else + { + // point lies in between + nearest_location.lat = static_cast(mercator::y2lat(p) * COORDINATE_PRECISION); + nearest_location.lon = static_cast(q * COORDINATE_PRECISION); + } + BOOST_ASSERT(nearest_location.is_valid()); + + const float approximate_distance = + coordinate_calculation::approx_euclidean_distance(query_location, nearest_location); + BOOST_ASSERT(0. <= approximate_distance); + return approximate_distance; +} + +float +coordinate_calculation::perpendicular_distance_from_projected_coordinate( + const FixedPointCoordinate &source_coordinate, + const FixedPointCoordinate &target_coordinate, + const FixedPointCoordinate &query_location, + const std::pair &projected_coordinate) +{ + float ratio; + FixedPointCoordinate nearest_location; + + return perpendicular_distance_from_projected_coordinate(source_coordinate, + target_coordinate, + query_location, + projected_coordinate, + nearest_location, + ratio); +} + +float coordinate_calculation::perpendicular_distance_from_projected_coordinate( + const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target, + const FixedPointCoordinate &query_location, + const std::pair &projected_coordinate, + FixedPointCoordinate &nearest_location, + float &ratio) +{ + BOOST_ASSERT(query_location.is_valid()); + + // initialize values + const double x = projected_coordinate.first; + const double y = projected_coordinate.second; + const double a = mercator::lat2y(segment_source.lat / COORDINATE_PRECISION); + const double b = segment_source.lon / COORDINATE_PRECISION; + const double c = mercator::lat2y(segment_target.lat / COORDINATE_PRECISION); + const double d = segment_target.lon / COORDINATE_PRECISION; + double p, q /*,mX*/, nY; + if (std::abs(a - c) > std::numeric_limits::epsilon()) + { + const double m = (d - b) / (c - a); // slope + // Projection of (x,y) on line joining (a,b) and (c,d) + p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m); + q = b + m * (p - a); + } + else + { + p = c; + q = y; + } + nY = (d * p - c * q) / (a * d - b * c); + + // discretize the result to coordinate precision. it's a hack! + if (std::abs(nY) < (1.f / COORDINATE_PRECISION)) + { + nY = 0.f; + } + + // compute ratio + ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need + // not calculate the explicit values of m an n as we + // are just interested in the ratio + if (std::isnan(ratio)) + { + ratio = (segment_target == query_location ? 1.f : 0.f); + } + else if (std::abs(ratio) <= std::numeric_limits::epsilon()) + { + ratio = 0.f; + } + else if (std::abs(ratio - 1.f) <= std::numeric_limits::epsilon()) + { + ratio = 1.f; + } + + // compute nearest location + BOOST_ASSERT(!std::isnan(ratio)); + if (ratio <= 0.f) + { + nearest_location = segment_source; + } + else if (ratio >= 1.f) + { + nearest_location = segment_target; + } + else + { + // point lies in between + nearest_location.lat = static_cast(mercator::y2lat(p) * COORDINATE_PRECISION); + nearest_location.lon = static_cast(q * COORDINATE_PRECISION); + } + BOOST_ASSERT(nearest_location.is_valid()); + + const float approximate_distance = + coordinate_calculation::approx_euclidean_distance(query_location, nearest_location); + BOOST_ASSERT(0. <= approximate_distance); + return approximate_distance; +} + +void coordinate_calculation::lat_or_lon_to_string(const int value, std::string &output) +{ + char buffer[12]; + buffer[11] = 0; // zero termination + output = printInt<11, 6>(buffer, value); +} + +void coordinate_calculation::convertInternalCoordinateToString(const FixedPointCoordinate &coord, + std::string &output) +{ + std::string tmp; + tmp.reserve(23); + lat_or_lon_to_string(coord.lon, tmp); + output = tmp; + output += ","; + lat_or_lon_to_string(coord.lat, tmp); + output += tmp; +} + +void +coordinate_calculation::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord, + std::string &output) +{ + std::string tmp; + tmp.reserve(23); + lat_or_lon_to_string(coord.lat, tmp); + output = tmp; + output += ","; + lat_or_lon_to_string(coord.lon, tmp); + output += tmp; +} + +float coordinate_calculation::GetBearing(const FixedPointCoordinate &first_coordinate, + const FixedPointCoordinate &second_coordinate) +{ + const float lon_diff = + second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION; + const float lon_delta = deg_to_rad(lon_diff); + const float lat1 = deg_to_rad(first_coordinate.lat / COORDINATE_PRECISION); + const float lat2 = deg_to_rad(second_coordinate.lat / COORDINATE_PRECISION); + const float y = sin(lon_delta) * cos(lat2); + const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon_delta); + float result = rad_to_deg(std::atan2(y, x)); + while (result < 0.f) + { + result += 360.f; + } + + while (result >= 360.f) + { + result -= 360.f; + } + return result; +} + +float coordinate_calculation::deg_to_rad(const float degree) +{ + return degree * (static_cast(M_PI) / 180.f); +} + +float coordinate_calculation::rad_to_deg(const float radian) +{ + return radian * (180.f * static_cast(M_1_PI)); +} + +// This distance computation does integer arithmetic only and is a lot faster than +// the other distance function which are numerically correct('ish). +// It preserves some order among the elements that make it useful for certain purposes +int coordinate_calculation::OrderedPerpendicularDistanceApproximation( + const FixedPointCoordinate &input_point, + const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target) +{ + // initialize values + const float x = static_cast(mercator::lat2y(input_point.lat / COORDINATE_PRECISION)); + const float y = input_point.lon / COORDINATE_PRECISION; + const float a = static_cast(mercator::lat2y(segment_source.lat / COORDINATE_PRECISION)); + const float b = segment_source.lon / COORDINATE_PRECISION; + const float c = static_cast(mercator::lat2y(segment_target.lat / COORDINATE_PRECISION)); + const float d = segment_target.lon / COORDINATE_PRECISION; + + float p, q; + if (a == c) + { + p = c; + q = y; + } + else + { + const float m = (d - b) / (c - a); // slope + // Projection of (x,y) on line joining (a,b) and (c,d) + p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m); + q = b + m * (p - a); + } + + const float nY = (d * p - c * q) / (a * d - b * c); + float ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need + // not calculate the explicit values of m an n as we + // are just interested in the ratio + if (std::isnan(ratio)) + { + ratio = (segment_target == input_point) ? 1.f : 0.f; + } + + // compute target quasi-location + int dx, dy; + if (ratio < 0.f) + { + dx = input_point.lon - segment_source.lon; + dy = input_point.lat - segment_source.lat; + } + else if (ratio > 1.f) + { + dx = input_point.lon - segment_target.lon; + dy = input_point.lat - segment_target.lat; + } + else + { + // point lies in between + dx = input_point.lon - static_cast(q * COORDINATE_PRECISION); + dy = input_point.lat - static_cast(mercator::y2lat(p) * COORDINATE_PRECISION); + } + + // return an approximation in the plane + return static_cast(sqrt(dx * dx + dy * dy)); +} diff --git a/data_structures/coordinate_calculation.hpp b/data_structures/coordinate_calculation.hpp new file mode 100644 index 000000000..7c76cb446 --- /dev/null +++ b/data_structures/coordinate_calculation.hpp @@ -0,0 +1,97 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef COORDINATE_CALCULATION +#define COORDINATE_CALCULATION + +#include + +#include //for std::ostream +#include +#include + +struct coordinate_calculation +{ + static double + ApproximateDistance(const int lat1, const int lon1, const int lat2, const int lon2); + + static double ApproximateDistance(const FixedPointCoordinate &first_coordinate, + const FixedPointCoordinate &second_coordinate); + + static float approx_euclidean_distance(const FixedPointCoordinate &first_coordinate, + const FixedPointCoordinate &second_coordinate); + + static float + approx_euclidean_distance(const int lat1, const int lon1, const int lat2, const int lon2); + + static float ApproximateSquaredEuclideanDistance(const FixedPointCoordinate &first_coordinate, + const FixedPointCoordinate &second_coordinate); + + static void lat_or_lon_to_string(const int value, std::string &output); + + static void convertInternalCoordinateToString(const FixedPointCoordinate &coordinate, + std::string &output); + + static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coordinate, + std::string &output); + + static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target, + const FixedPointCoordinate &query_location); + + static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target, + const FixedPointCoordinate &query_location, + FixedPointCoordinate &nearest_location, + float &ratio); + + static float perpendicular_distance_from_projected_coordinate( + const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target, + const FixedPointCoordinate &query_location, + const std::pair &projected_coordinate); + + static float perpendicular_distance_from_projected_coordinate( + const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target, + const FixedPointCoordinate &query_location, + const std::pair &projected_coordinate, + FixedPointCoordinate &nearest_location, + float &ratio); + + static int + OrderedPerpendicularDistanceApproximation(const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target, + const FixedPointCoordinate &query_location); + + static float GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B); + + static float deg_to_rad(const float degree); + static float rad_to_deg(const float radian); +}; + +#endif //COORDINATE_CALCULATION diff --git a/data_structures/rectangle.hpp b/data_structures/rectangle.hpp index 2f6815cac..43f389365 100644 --- a/data_structures/rectangle.hpp +++ b/data_structures/rectangle.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef RECTANGLE_HPP #define RECTANGLE_HPP +#include "coordinate_calculation.hpp" + #include #include @@ -115,28 +117,28 @@ struct RectangleInt2D switch (d) { case NORTH: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, location.lon)); + min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, location.lon)); break; case SOUTH: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, location.lon)); + min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, location.lon)); break; case WEST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, min_lon)); + min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(location.lat, min_lon)); break; case EAST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, max_lon)); + min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(location.lat, max_lon)); break; case NORTH_EAST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, max_lon)); + min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, max_lon)); break; case NORTH_WEST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, min_lon)); + min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, min_lon)); break; case SOUTH_EAST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, max_lon)); + min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, max_lon)); break; case SOUTH_WEST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, min_lon)); + min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, min_lon)); break; default: break; @@ -159,24 +161,24 @@ struct RectangleInt2D min_max_dist = std::min( min_max_dist, std::max( - FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left), - FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right))); + coordinate_calculation::approx_euclidean_distance(location, upper_left), + coordinate_calculation::approx_euclidean_distance(location, upper_right))); min_max_dist = std::min( min_max_dist, std::max( - FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right), - FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right))); + coordinate_calculation::approx_euclidean_distance(location, upper_right), + coordinate_calculation::approx_euclidean_distance(location, lower_right))); min_max_dist = std::min( min_max_dist, - std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right), - FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left))); + std::max(coordinate_calculation::approx_euclidean_distance(location, lower_right), + coordinate_calculation::approx_euclidean_distance(location, lower_left))); min_max_dist = std::min( min_max_dist, - std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left), - FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left))); + std::max(coordinate_calculation::approx_euclidean_distance(location, lower_left), + coordinate_calculation::approx_euclidean_distance(location, upper_left))); return min_max_dist; } diff --git a/data_structures/static_rtree.hpp b/data_structures/static_rtree.hpp index a8cccd1bf..fe83c1888 100644 --- a/data_structures/static_rtree.hpp +++ b/data_structures/static_rtree.hpp @@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "rectangle.hpp" #include "shared_memory_factory.hpp" #include "shared_memory_vector_wrapper.hpp" +#include "upper_bound.hpp" #include "../Util/floating_point.hpp" #include "../Util/integer_range.hpp" @@ -176,28 +177,28 @@ class StaticRTree switch (d) { case NORTH: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, location.lon)); + min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, location.lon)); break; case SOUTH: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, location.lon)); + min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, location.lon)); break; case WEST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, min_lon)); + min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(location.lat, min_lon)); break; case EAST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, max_lon)); + min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(location.lat, max_lon)); break; case NORTH_EAST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, max_lon)); + min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, max_lon)); break; case NORTH_WEST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, min_lon)); + min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, min_lon)); break; case SOUTH_EAST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, max_lon)); + min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, max_lon)); break; case SOUTH_WEST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, min_lon)); + min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, min_lon)); break; default: break; @@ -220,24 +221,24 @@ class StaticRTree min_max_dist = std::min( min_max_dist, std::max( - FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left), - FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right))); + coordinate_calculation::approx_euclidean_distance(location, upper_left), + coordinate_calculation::approx_euclidean_distance(location, upper_right))); min_max_dist = std::min( min_max_dist, std::max( - FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right), - FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right))); + coordinate_calculation::approx_euclidean_distance(location, upper_right), + coordinate_calculation::approx_euclidean_distance(location, lower_right))); min_max_dist = std::min( min_max_dist, - std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right), - FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left))); + std::max(coordinate_calculation::approx_euclidean_distance(location, lower_right), + coordinate_calculation::approx_euclidean_distance(location, lower_left))); min_max_dist = std::min( min_max_dist, - std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left), - FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left))); + std::max(coordinate_calculation::approx_euclidean_distance(location, lower_left), + coordinate_calculation::approx_euclidean_distance(location, upper_left))); return min_max_dist; } @@ -606,7 +607,7 @@ class StaticRTree } float current_minimum_distance = - FixedPointCoordinate::ApproximateEuclideanDistance( + coordinate_calculation::approx_euclidean_distance( input_coordinate.lat, input_coordinate.lon, m_coordinate_list->at(current_edge.u).lat, @@ -619,7 +620,7 @@ class StaticRTree } current_minimum_distance = - FixedPointCoordinate::ApproximateEuclideanDistance( + coordinate_calculation::approx_euclidean_distance( input_coordinate.lat, input_coordinate.lon, m_coordinate_list->at(current_edge.v).lat, @@ -661,6 +662,15 @@ class StaticRTree unsigned number_of_elements_from_big_cc = 0; unsigned number_of_elements_from_tiny_cc = 0; + unsigned pruned_elements = 0; + + std::pair projected_coordinate = + { mercator::lat2y(input_coordinate.lat / COORDINATE_PRECISION), + input_coordinate.lon / COORDINATE_PRECISION }; + + // upper bound pruning technique + upper_bound pruning_bound(max_number_of_phantom_nodes); + // initialize queue with root element std::priority_queue traversal_queue; traversal_queue.emplace(0.f, m_search_tree[0]); @@ -683,15 +693,22 @@ class StaticRTree { const auto ¤t_edge = current_leaf_node.objects[i]; const float current_perpendicular_distance = - FixedPointCoordinate::ComputePerpendicularDistance( + coordinate_calculation::perpendicular_distance_from_projected_coordinate( m_coordinate_list->at(current_edge.u), m_coordinate_list->at(current_edge.v), - input_coordinate); + input_coordinate, + projected_coordinate); // distance must be non-negative BOOST_ASSERT(0.f <= current_perpendicular_distance); - // put element in queue - traversal_queue.emplace(current_perpendicular_distance, current_edge); + if (pruning_bound.get() >= current_perpendicular_distance || + current_edge.is_in_tiny_cc()) + { + pruning_bound.insert(current_perpendicular_distance); + traversal_queue.emplace(current_perpendicular_distance, current_edge); + } else { + ++pruned_elements; + } } } else @@ -727,10 +744,11 @@ class StaticRTree float current_ratio = 0.f; FixedPointCoordinate foot_point_coordinate_on_segment; // const float current_perpendicular_distance = - FixedPointCoordinate::ComputePerpendicularDistance( + coordinate_calculation::perpendicular_distance_from_projected_coordinate( m_coordinate_list->at(current_segment.u), m_coordinate_list->at(current_segment.v), input_coordinate, + projected_coordinate, foot_point_coordinate_on_segment, current_ratio); @@ -766,13 +784,6 @@ class StaticRTree { // found an element in a big component ++number_of_elements_from_big_cc; } - - // SimpleLogger().Write() << "result_phantom_node_vector.size(): " << result_phantom_node_vector.size(); - // SimpleLogger().Write() << "max_number_of_phantom_nodes: " << max_number_of_phantom_nodes; - // SimpleLogger().Write() << "number_of_elements_from_big_cc: " << number_of_elements_from_big_cc; - // SimpleLogger().Write() << "number_of_elements_from_tiny_cc: " << number_of_elements_from_tiny_cc; - // SimpleLogger().Write() << "inspected_elements: " << inspected_elements; - // SimpleLogger().Write() << "max_checked_elements: " << max_checked_elements; } // stop the search by flushing the queue @@ -782,7 +793,14 @@ class StaticRTree traversal_queue = std::priority_queue{}; } } + // SimpleLogger().Write() << "result_phantom_node_vector.size(): " << result_phantom_node_vector.size(); + // SimpleLogger().Write() << "max_number_of_phantom_nodes: " << max_number_of_phantom_nodes; + // SimpleLogger().Write() << "number_of_elements_from_big_cc: " << number_of_elements_from_big_cc; + // SimpleLogger().Write() << "number_of_elements_from_tiny_cc: " << number_of_elements_from_tiny_cc; // SimpleLogger().Write() << "inspected_elements: " << inspected_elements; + // SimpleLogger().Write() << "max_checked_elements: " << max_checked_elements; + // SimpleLogger().Write() << "pruned_elements: " << pruned_elements; + return !result_phantom_node_vector.empty(); } @@ -828,7 +846,7 @@ class StaticRTree { const auto ¤t_edge = current_leaf_node.objects[i]; const float current_perpendicular_distance = - FixedPointCoordinate::ComputePerpendicularDistance( + coordinate_calculation::ComputePerpendicularDistance( m_coordinate_list->at(current_edge.u), m_coordinate_list->at(current_edge.v), input_coordinate); @@ -885,7 +903,7 @@ class StaticRTree float current_ratio = 0.; FixedPointCoordinate foot_point_coordinate_on_segment; const float current_perpendicular_distance = - FixedPointCoordinate::ComputePerpendicularDistance( + coordinate_calculation::ComputePerpendicularDistance( m_coordinate_list->at(current_segment.u), m_coordinate_list->at(current_segment.v), input_coordinate, @@ -985,7 +1003,7 @@ class StaticRTree float current_ratio = 0.; FixedPointCoordinate nearest; const float current_perpendicular_distance = - FixedPointCoordinate::ComputePerpendicularDistance( + coordinate_calculation::ComputePerpendicularDistance( m_coordinate_list->at(current_edge.u), m_coordinate_list->at(current_edge.v), input_coordinate, @@ -1042,9 +1060,9 @@ class StaticRTree inline void SetForwardAndReverseWeightsOnPhantomNode(const EdgeDataT & nearest_edge, PhantomNode &result_phantom_node) const { - const float distance_1 = FixedPointCoordinate::ApproximateEuclideanDistance( + const float distance_1 = coordinate_calculation::approx_euclidean_distance( m_coordinate_list->at(nearest_edge.u), result_phantom_node.location); - const float distance_2 = FixedPointCoordinate::ApproximateEuclideanDistance( + const float distance_2 = coordinate_calculation::approx_euclidean_distance( m_coordinate_list->at(nearest_edge.u), m_coordinate_list->at(nearest_edge.v)); const float ratio = std::min(1.f, distance_1 / distance_2); diff --git a/data_structures/upper_bound.hpp b/data_structures/upper_bound.hpp new file mode 100644 index 000000000..d39901e8f --- /dev/null +++ b/data_structures/upper_bound.hpp @@ -0,0 +1,75 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef LOWER_BOUND_HPP +#define LOWER_BOUND_HPP + +#include +#include +#include + +// max pq holds k elements +// insert if key is smaller than max +// if size > k then remove element +// get() always yields a bound to the k smallest element in the stream + +template +class upper_bound +{ + public: + upper_bound() = delete; + upper_bound(std::size_t size) : size(size) + { + } + + key_type get() const + { + if (queue.size() < size) + { + return std::numeric_limits::max(); + } + return queue.top(); + } + + void insert(const key_type key) + { + if (key < get()) + { + queue.emplace(key); + while (queue.size() > size) + { + queue.pop(); + } + } + } + + private: + std::priority_queue, std::less> queue; + const std::size_t size; +}; + +#endif // LOWER_BOUND_HPP diff --git a/descriptors/description_factory.cpp b/descriptors/description_factory.cpp index 87af445e5..4d41a3e03 100644 --- a/descriptors/description_factory.cpp +++ b/descriptors/description_factory.cpp @@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "description_factory.hpp" #include "../algorithms/polyline_formatter.hpp" +#include "../data_structures/coordinate_calculation.hpp" #include "../data_structures/internal_route_result.hpp" #include "../data_structures/turn_instructions.hpp" #include "../typedefs.h" @@ -134,7 +135,7 @@ void DescriptionFactory::Run(const unsigned zoom_level) { // move down names by one, q&d hack path_description[i - 1].name_id = path_description[i].name_id; - path_description[i].length = FixedPointCoordinate::ApproximateEuclideanDistance( + path_description[i].length = coordinate_calculation::approx_euclidean_distance( path_description[i - 1].location, path_description[i].location); } diff --git a/descriptors/descriptor_base.hpp b/descriptors/descriptor_base.hpp index 393d84440..8166afb7b 100644 --- a/descriptors/descriptor_base.hpp +++ b/descriptors/descriptor_base.hpp @@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef DESCRIPTOR_BASE_HPP #define DESCRIPTOR_BASE_HPP +#include "../data_structures/coordinate_calculation.hpp" #include "../data_structures/internal_route_result.hpp" #include "../data_structures/phantom_node.hpp" #include "../typedefs.h" diff --git a/descriptors/gpx_descriptor.hpp b/descriptors/gpx_descriptor.hpp index 0c7557917..a6af9f8dc 100644 --- a/descriptors/gpx_descriptor.hpp +++ b/descriptors/gpx_descriptor.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -49,10 +49,10 @@ template class GPXDescriptor final : public BaseDescriptortarget_coordinate.lat = node_iterator->lat; edge_iterator->target_coordinate.lon = node_iterator->lon; - const double distance = FixedPointCoordinate::ApproximateEuclideanDistance( + const double distance = coordinate_calculation::approx_euclidean_distance( edge_iterator->source_coordinate.lat, edge_iterator->source_coordinate.lon, node_iterator->lat, diff --git a/unit_tests/data_structures/coordinate.cpp b/unit_tests/data_structures/coordinate.cpp index 925f44ccc..1acb5e0df 100644 --- a/unit_tests/data_structures/coordinate.cpp +++ b/unit_tests/data_structures/coordinate.cpp @@ -1,5 +1,34 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + #include +#include "../../data_structures/coordinate_calculation.hpp" + #include #include @@ -11,11 +40,11 @@ BOOST_AUTO_TEST_CASE(regression_test_1347) FixedPointCoordinate v(10.001 * COORDINATE_PRECISION, -100.002 * COORDINATE_PRECISION); FixedPointCoordinate q(10.002 * COORDINATE_PRECISION, -100.001 * COORDINATE_PRECISION); - float d1 = FixedPointCoordinate::ComputePerpendicularDistance(u, v, q); + float d1 = coordinate_calculation::ComputePerpendicularDistance(u, v, q); float ratio; FixedPointCoordinate nearest_location; - float d2 = FixedPointCoordinate::ComputePerpendicularDistance(u, v, q, nearest_location, ratio); + float d2 = coordinate_calculation::ComputePerpendicularDistance(u, v, q, nearest_location, ratio); BOOST_CHECK_LE(std::abs(d1 - d2), 0.01f); } diff --git a/unit_tests/data_structures/static_rtree.cpp b/unit_tests/data_structures/static_rtree.cpp index 905e58a55..6202ecfa9 100644 --- a/unit_tests/data_structures/static_rtree.cpp +++ b/unit_tests/data_structures/static_rtree.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,6 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "../../data_structures/coordinate_calculation.hpp" #include "../../data_structures/static_rtree.hpp" #include "../../data_structures/query_node.hpp" #include "../../data_structures/edge_based_node.hpp" @@ -77,7 +78,7 @@ class LinearSearchNN { const FixedPointCoordinate &start = coords->at(e.u); const FixedPointCoordinate &end = coords->at(e.v); - float distance = FixedPointCoordinate::ApproximateEuclideanDistance( + float distance = coordinate_calculation::approx_euclidean_distance( input_coordinate.lat, input_coordinate.lon, start.lat, start.lon); if (distance < min_dist) { @@ -85,7 +86,7 @@ class LinearSearchNN min_dist = distance; } - distance = FixedPointCoordinate::ApproximateEuclideanDistance( + distance = coordinate_calculation::approx_euclidean_distance( input_coordinate.lat, input_coordinate.lon, end.lat, end.lon); if (distance < min_dist) { @@ -112,7 +113,7 @@ class LinearSearchNN float current_ratio = 0.; FixedPointCoordinate nearest; const float current_perpendicular_distance = - FixedPointCoordinate::ComputePerpendicularDistance( + coordinate_calculation::ComputePerpendicularDistance( coords->at(e.u), coords->at(e.v), input_coordinate, nearest, current_ratio); if ((current_perpendicular_distance < min_dist) && @@ -148,9 +149,9 @@ class LinearSearchNN result_phantom_node.location.lat = input_coordinate.lat; } - const float distance_1 = FixedPointCoordinate::ApproximateEuclideanDistance( + const float distance_1 = coordinate_calculation::approx_euclidean_distance( coords->at(nearest_edge.u), result_phantom_node.location); - const float distance_2 = FixedPointCoordinate::ApproximateEuclideanDistance( + const float distance_2 = coordinate_calculation::approx_euclidean_distance( coords->at(nearest_edge.u), coords->at(nearest_edge.v)); const float ratio = std::min(1.f, distance_1 / distance_2); @@ -285,10 +286,10 @@ void simple_verify_rtree(RTreeT &rtree, bool found_u = rtree.LocateClosestEndPointForCoordinate(pu, result_u, 1); bool found_v = rtree.LocateClosestEndPointForCoordinate(pv, result_v, 1); BOOST_CHECK(found_u && found_v); - float dist_u = FixedPointCoordinate::ApproximateEuclideanDistance( + float dist_u = coordinate_calculation::approx_euclidean_distance( result_u.lat, result_u.lon, pu.lat, pu.lon); BOOST_CHECK_LE(dist_u, std::numeric_limits::epsilon()); - float dist_v = FixedPointCoordinate::ApproximateEuclideanDistance( + float dist_v = coordinate_calculation::approx_euclidean_distance( result_v.lat, result_v.lon, pv.lat, pv.lon); BOOST_CHECK_LE(dist_v, std::numeric_limits::epsilon()); } @@ -449,30 +450,30 @@ void TestRectangle(double width, double height, double center_lat, double center /* Distance to line segments of rectangle */ BOOST_CHECK_EQUAL(rect.GetMinDist(north), - FixedPointCoordinate::ApproximateEuclideanDistance( + coordinate_calculation::approx_euclidean_distance( north, FixedPointCoordinate(rect.max_lat, north.lon))); BOOST_CHECK_EQUAL(rect.GetMinDist(south), - FixedPointCoordinate::ApproximateEuclideanDistance( + coordinate_calculation::approx_euclidean_distance( south, FixedPointCoordinate(rect.min_lat, south.lon))); BOOST_CHECK_EQUAL(rect.GetMinDist(west), - FixedPointCoordinate::ApproximateEuclideanDistance( + coordinate_calculation::approx_euclidean_distance( west, FixedPointCoordinate(west.lat, rect.min_lon))); BOOST_CHECK_EQUAL(rect.GetMinDist(east), - FixedPointCoordinate::ApproximateEuclideanDistance( + coordinate_calculation::approx_euclidean_distance( east, FixedPointCoordinate(east.lat, rect.max_lon))); /* Distance to corner points */ BOOST_CHECK_EQUAL(rect.GetMinDist(north_east), - FixedPointCoordinate::ApproximateEuclideanDistance( + coordinate_calculation::approx_euclidean_distance( north_east, FixedPointCoordinate(rect.max_lat, rect.max_lon))); BOOST_CHECK_EQUAL(rect.GetMinDist(north_west), - FixedPointCoordinate::ApproximateEuclideanDistance( + coordinate_calculation::approx_euclidean_distance( north_west, FixedPointCoordinate(rect.max_lat, rect.min_lon))); BOOST_CHECK_EQUAL(rect.GetMinDist(south_east), - FixedPointCoordinate::ApproximateEuclideanDistance( + coordinate_calculation::approx_euclidean_distance( south_east, FixedPointCoordinate(rect.min_lat, rect.max_lon))); BOOST_CHECK_EQUAL(rect.GetMinDist(south_west), - FixedPointCoordinate::ApproximateEuclideanDistance( + coordinate_calculation::approx_euclidean_distance( south_west, FixedPointCoordinate(rect.min_lat, rect.min_lon))); } From 087f08dad293c68dd931d9f78c18e283c44ca640 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 20 Jan 2015 17:56:30 +0100 Subject: [PATCH 070/360] also build tests on travis CI --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 643e00dff..6dbbde5e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,7 @@ before_script: - bundle install - mkdir build - cd build - - cmake .. $CMAKEOPTIONS + - cmake .. $CMAKEOPTIONS -DBUILD_TOOLS=1 script: - make -j 2 - make -j 2 tests From db2ba22bd642b266b249132491912ad12aaae9b1 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 20 Jan 2015 17:56:50 +0100 Subject: [PATCH 071/360] fix tests to run with new header coordinate_calculations --- tools/components.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/components.cpp b/tools/components.cpp index 59035ba89..e9a96773a 100644 --- a/tools/components.cpp +++ b/tools/components.cpp @@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../typedefs.h" #include "../algorithms/tiny_components.hpp" #include "../data_structures/static_graph.hpp" +#include "../data_structures/coordinate_calculation.hpp" #include "../Util/fingerprint.hpp" #include "../Util/graph_loader.hpp" #include "../Util/make_unique.hpp" @@ -243,7 +244,7 @@ int main(int argc, char *argv[]) if (source < target || graph->EndEdges(target) == graph->FindEdge(target, source)) { total_network_distance += - 100 * FixedPointCoordinate::ApproximateEuclideanDistance( + 100 * coordinate_calculation::approx_euclidean_distance( coordinate_list[source].lat, coordinate_list[source].lon, coordinate_list[target].lat, From ec9b2dbe42a87ccd6507ba38615980323123145e Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 20 Jan 2015 17:57:47 +0100 Subject: [PATCH 072/360] remove debug info from binaries --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c00006f33..2a732ce35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -131,7 +131,7 @@ if(CMAKE_BUILD_TYPE MATCHES Release) message(STATUS "Using gcc specific binutils for LTO.") set(CMAKE_AR "/usr/bin/gcc-ar") set(CMAKE_RANLIB "/usr/bin/gcc-ranlib") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3") +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3") endif() endif (HAS_LTO_FLAG) endif() From 501863a0ebadfc3bf293c38a8db0d716729207c2 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 20 Jan 2015 18:06:26 +0100 Subject: [PATCH 073/360] move external dependence mapbox/variant into third_party directory --- {Include => third_party}/variant/.gitignore | 0 {Include => third_party}/variant/.travis.yml | 0 {Include => third_party}/variant/Jamroot | 0 {Include => third_party}/variant/LICENSE | 0 {Include => third_party}/variant/Makefile | 0 {Include => third_party}/variant/README.md | 0 {Include => third_party}/variant/appveyor.yml | 0 {Include => third_party}/variant/common.gypi | 0 {Include => third_party}/variant/optional.hpp | 0 {Include => third_party}/variant/recursive_wrapper.hpp | 0 {Include => third_party}/variant/scripts/linux.sh | 0 {Include => third_party}/variant/scripts/osx.sh | 0 {Include => third_party}/variant/test/bench_variant.cpp | 0 {Include => third_party}/variant/test/binary_visitor_test.cpp | 0 .../variant/test/boost_variant_hello_world.cpp | 0 {Include => third_party}/variant/test/catch.hpp | 0 {Include => third_party}/variant/test/optional_unit.cpp | 0 {Include => third_party}/variant/test/recursive_wrapper_test.cpp | 0 {Include => third_party}/variant/test/unique_ptr_test.cpp | 0 {Include => third_party}/variant/test/unit.cpp | 0 {Include => third_party}/variant/test/variant_hello_world.cpp | 0 {Include => third_party}/variant/variant.gyp | 0 {Include => third_party}/variant/variant.hpp | 0 {Include => third_party}/variant/vcbuild.bat | 0 24 files changed, 0 insertions(+), 0 deletions(-) rename {Include => third_party}/variant/.gitignore (100%) rename {Include => third_party}/variant/.travis.yml (100%) rename {Include => third_party}/variant/Jamroot (100%) rename {Include => third_party}/variant/LICENSE (100%) rename {Include => third_party}/variant/Makefile (100%) rename {Include => third_party}/variant/README.md (100%) rename {Include => third_party}/variant/appveyor.yml (100%) rename {Include => third_party}/variant/common.gypi (100%) rename {Include => third_party}/variant/optional.hpp (100%) rename {Include => third_party}/variant/recursive_wrapper.hpp (100%) rename {Include => third_party}/variant/scripts/linux.sh (100%) rename {Include => third_party}/variant/scripts/osx.sh (100%) rename {Include => third_party}/variant/test/bench_variant.cpp (100%) rename {Include => third_party}/variant/test/binary_visitor_test.cpp (100%) rename {Include => third_party}/variant/test/boost_variant_hello_world.cpp (100%) rename {Include => third_party}/variant/test/catch.hpp (100%) rename {Include => third_party}/variant/test/optional_unit.cpp (100%) rename {Include => third_party}/variant/test/recursive_wrapper_test.cpp (100%) rename {Include => third_party}/variant/test/unique_ptr_test.cpp (100%) rename {Include => third_party}/variant/test/unit.cpp (100%) rename {Include => third_party}/variant/test/variant_hello_world.cpp (100%) rename {Include => third_party}/variant/variant.gyp (100%) rename {Include => third_party}/variant/variant.hpp (100%) rename {Include => third_party}/variant/vcbuild.bat (100%) diff --git a/Include/variant/.gitignore b/third_party/variant/.gitignore similarity index 100% rename from Include/variant/.gitignore rename to third_party/variant/.gitignore diff --git a/Include/variant/.travis.yml b/third_party/variant/.travis.yml similarity index 100% rename from Include/variant/.travis.yml rename to third_party/variant/.travis.yml diff --git a/Include/variant/Jamroot b/third_party/variant/Jamroot similarity index 100% rename from Include/variant/Jamroot rename to third_party/variant/Jamroot diff --git a/Include/variant/LICENSE b/third_party/variant/LICENSE similarity index 100% rename from Include/variant/LICENSE rename to third_party/variant/LICENSE diff --git a/Include/variant/Makefile b/third_party/variant/Makefile similarity index 100% rename from Include/variant/Makefile rename to third_party/variant/Makefile diff --git a/Include/variant/README.md b/third_party/variant/README.md similarity index 100% rename from Include/variant/README.md rename to third_party/variant/README.md diff --git a/Include/variant/appveyor.yml b/third_party/variant/appveyor.yml similarity index 100% rename from Include/variant/appveyor.yml rename to third_party/variant/appveyor.yml diff --git a/Include/variant/common.gypi b/third_party/variant/common.gypi similarity index 100% rename from Include/variant/common.gypi rename to third_party/variant/common.gypi diff --git a/Include/variant/optional.hpp b/third_party/variant/optional.hpp similarity index 100% rename from Include/variant/optional.hpp rename to third_party/variant/optional.hpp diff --git a/Include/variant/recursive_wrapper.hpp b/third_party/variant/recursive_wrapper.hpp similarity index 100% rename from Include/variant/recursive_wrapper.hpp rename to third_party/variant/recursive_wrapper.hpp diff --git a/Include/variant/scripts/linux.sh b/third_party/variant/scripts/linux.sh similarity index 100% rename from Include/variant/scripts/linux.sh rename to third_party/variant/scripts/linux.sh diff --git a/Include/variant/scripts/osx.sh b/third_party/variant/scripts/osx.sh similarity index 100% rename from Include/variant/scripts/osx.sh rename to third_party/variant/scripts/osx.sh diff --git a/Include/variant/test/bench_variant.cpp b/third_party/variant/test/bench_variant.cpp similarity index 100% rename from Include/variant/test/bench_variant.cpp rename to third_party/variant/test/bench_variant.cpp diff --git a/Include/variant/test/binary_visitor_test.cpp b/third_party/variant/test/binary_visitor_test.cpp similarity index 100% rename from Include/variant/test/binary_visitor_test.cpp rename to third_party/variant/test/binary_visitor_test.cpp diff --git a/Include/variant/test/boost_variant_hello_world.cpp b/third_party/variant/test/boost_variant_hello_world.cpp similarity index 100% rename from Include/variant/test/boost_variant_hello_world.cpp rename to third_party/variant/test/boost_variant_hello_world.cpp diff --git a/Include/variant/test/catch.hpp b/third_party/variant/test/catch.hpp similarity index 100% rename from Include/variant/test/catch.hpp rename to third_party/variant/test/catch.hpp diff --git a/Include/variant/test/optional_unit.cpp b/third_party/variant/test/optional_unit.cpp similarity index 100% rename from Include/variant/test/optional_unit.cpp rename to third_party/variant/test/optional_unit.cpp diff --git a/Include/variant/test/recursive_wrapper_test.cpp b/third_party/variant/test/recursive_wrapper_test.cpp similarity index 100% rename from Include/variant/test/recursive_wrapper_test.cpp rename to third_party/variant/test/recursive_wrapper_test.cpp diff --git a/Include/variant/test/unique_ptr_test.cpp b/third_party/variant/test/unique_ptr_test.cpp similarity index 100% rename from Include/variant/test/unique_ptr_test.cpp rename to third_party/variant/test/unique_ptr_test.cpp diff --git a/Include/variant/test/unit.cpp b/third_party/variant/test/unit.cpp similarity index 100% rename from Include/variant/test/unit.cpp rename to third_party/variant/test/unit.cpp diff --git a/Include/variant/test/variant_hello_world.cpp b/third_party/variant/test/variant_hello_world.cpp similarity index 100% rename from Include/variant/test/variant_hello_world.cpp rename to third_party/variant/test/variant_hello_world.cpp diff --git a/Include/variant/variant.gyp b/third_party/variant/variant.gyp similarity index 100% rename from Include/variant/variant.gyp rename to third_party/variant/variant.gyp diff --git a/Include/variant/variant.hpp b/third_party/variant/variant.hpp similarity index 100% rename from Include/variant/variant.hpp rename to third_party/variant/variant.hpp diff --git a/Include/variant/vcbuild.bat b/third_party/variant/vcbuild.bat similarity index 100% rename from Include/variant/vcbuild.bat rename to third_party/variant/vcbuild.bat From 50c460ebd5ed579c3567a9c5d617b1f6cc3d649e Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 20 Jan 2015 18:07:45 +0100 Subject: [PATCH 074/360] install mapbox/variant headers from third_party directory --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a732ce35..dcc7306cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -325,7 +325,7 @@ if(WITH_TOOLS OR BUILD_TOOLS) endif() file(GLOB InstallGlob Include/osrm/*.hpp Library/OSRM.h) -file(GLOB VariantGlob Include/variant/*.hpp) +file(GLOB VariantGlob third_party/variant/*.hpp) # Add RPATH info to executables so that when they are run after being installed # (i.e., from /usr/local/bin/) the linker can find library dependencies. For From ba10f97420c5f64cba1b00ddc2b3b0c2c9345a28 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 20 Jan 2015 18:23:10 +0100 Subject: [PATCH 075/360] add third_party directory node to the include dirs --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index dcc7306cd..7428b191b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ OPTION(WITH_TOOLS "Build OSRM tools" OFF) OPTION(BUILD_TOOLS "Build OSRM tools" OFF) include_directories(${CMAKE_SOURCE_DIR}/Include/) +include_directories(${CMAKE_SOURCE_DIR}/third_party/) include_directories(${CMAKE_SOURCE_DIR}/third_party/libosmium/include/) add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/fingerprint.cpp fingerprint.cpp.alwaysbuild From f662b9a08126cf4212a4367785e2d10b15c25ba0 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 20 Jan 2015 18:45:49 +0100 Subject: [PATCH 076/360] install libgdal-dev on Travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 6dbbde5e2..493cf27e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ install: - sudo apt-get -q install protobuf-compiler libprotoc-dev libprotobuf7 libprotobuf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev lua5.1 liblua5.1-0-dev rubygems libtbb-dev - sudo apt-get -q install g++-4.8 - sudo apt-get install libboost1.54-all-dev + - sudo apt-get install libgdal-dev # luabind - curl https://gist.githubusercontent.com/DennisOSRM/f2eb7b948e6fe1ae319e/raw/install-luabind.sh | sudo bash # osmosis From 044271a55c0f8b279dd7deb5ac437baf0a927b07 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 11:02:49 +0100 Subject: [PATCH 077/360] specialize insert function to pass by reference for non-fundamental types by using type traits --- data_structures/upper_bound.hpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/data_structures/upper_bound.hpp b/data_structures/upper_bound.hpp index d39901e8f..1fc77de38 100644 --- a/data_structures/upper_bound.hpp +++ b/data_structures/upper_bound.hpp @@ -31,20 +31,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include // max pq holds k elements // insert if key is smaller than max // if size > k then remove element // get() always yields a bound to the k smallest element in the stream -template -class upper_bound +template class upper_bound { + private: + using parameter_type = + typename std::conditional::value, key_type, key_type &>::type; + public: upper_bound() = delete; - upper_bound(std::size_t size) : size(size) - { - } + upper_bound(std::size_t size) : size(size) {} key_type get() const { @@ -55,12 +57,12 @@ class upper_bound return queue.top(); } - void insert(const key_type key) + void insert(const parameter_type key) { if (key < get()) { queue.emplace(key); - while (queue.size() > size) + while (queue.size() > size) { queue.pop(); } From cd523cc934cb0e4ffb177df6e663be300f2cf21b Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 12:10:18 +0100 Subject: [PATCH 078/360] conflate collapsable if statements --- descriptors/description_factory.cpp | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/descriptors/description_factory.cpp b/descriptors/description_factory.cpp index 4d41a3e03..7002f8ebb 100644 --- a/descriptors/description_factory.cpp +++ b/descriptors/description_factory.cpp @@ -204,25 +204,22 @@ void DescriptionFactory::Run(const unsigned zoom_level) } // Post-processing to remove empty or nearly empty path segments - if (std::numeric_limits::epsilon() > path_description.back().length) + if (path_description.size() > 2 && + std::numeric_limits::epsilon() > path_description.back().length) { - if (path_description.size() > 2) - { - path_description.pop_back(); - path_description.back().necessary = true; - path_description.back().turn_instruction = TurnInstruction::NoTurn; - target_phantom.name_id = (path_description.end() - 2)->name_id; - } + path_description.pop_back(); + path_description.back().necessary = true; + path_description.back().turn_instruction = TurnInstruction::NoTurn; + target_phantom.name_id = (path_description.end() - 2)->name_id; } - if (std::numeric_limits::epsilon() > path_description.front().length) + + if (path_description.size() > 2 && + std::numeric_limits::epsilon() > path_description.front().length) { - if (path_description.size() > 2) - { - path_description.erase(path_description.begin()); - path_description.front().turn_instruction = TurnInstruction::HeadOn; - path_description.front().necessary = true; - start_phantom.name_id = path_description.front().name_id; - } + path_description.erase(path_description.begin()); + path_description.front().turn_instruction = TurnInstruction::HeadOn; + path_description.front().necessary = true; + start_phantom.name_id = path_description.front().name_id; } // Generalize poly line From 0f8c3b19609d25fb20b5ade05b3705404f7a8297 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 12:18:48 +0100 Subject: [PATCH 079/360] fix copyright year --- algorithms/douglas_peucker.cpp | 2 +- algorithms/polyline_formatter.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/algorithms/douglas_peucker.cpp b/algorithms/douglas_peucker.cpp index 20f698d8f..fabea1810 100644 --- a/algorithms/douglas_peucker.cpp +++ b/algorithms/douglas_peucker.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/algorithms/polyline_formatter.cpp b/algorithms/polyline_formatter.cpp index e491b7570..22a1df369 100644 --- a/algorithms/polyline_formatter.cpp +++ b/algorithms/polyline_formatter.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, From baacd0e50c8ac6b35c5ac9e183d88f0c53e43b5b Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 12:19:11 +0100 Subject: [PATCH 080/360] reformat source files --- Server/RequestHandler.cpp | 20 +-- Util/compute_angle.cpp | 6 +- contractor/edge_based_graph_factory.cpp | 140 +++++++++------------ contractor/processing_chain.cpp | 64 ++++------ data_structures/coordinate.cpp | 4 +- data_structures/coordinate_calculation.cpp | 87 ++++++------- datastore.cpp | 12 +- extractor/extraction_containers.cpp | 81 ++++++------ extractor/extraction_containers.hpp | 16 +-- extractor/extraction_node.hpp | 7 +- extractor/extraction_way.hpp | 21 ++-- extractor/extractor.cpp | 103 ++++++++------- extractor/extractor_callbacks.cpp | 86 ++++++------- extractor/extractor_options.cpp | 12 +- extractor/internal_extractor_edge.hpp | 21 ++-- extractor/restriction_parser.cpp | 4 +- extractor/restriction_parser.hpp | 3 +- extractor/scripting_environment.cpp | 72 +++++------ extractor/scripting_environment.hpp | 4 +- routed.cpp | 23 ++-- tools/components.cpp | 2 +- tools/simpleclient.cpp | 12 +- unit_tests/data_structures/coordinate.cpp | 4 +- 23 files changed, 374 insertions(+), 430 deletions(-) diff --git a/Server/RequestHandler.cpp b/Server/RequestHandler.cpp index 277298dea..6aea27d7f 100644 --- a/Server/RequestHandler.cpp +++ b/Server/RequestHandler.cpp @@ -70,14 +70,15 @@ void RequestHandler::handle_request(const http::Request &req, http::Reply &reply time_stamp = localtime(<ime); // log timestamp - SimpleLogger().Write() << (time_stamp->tm_mday < 10 ? "0" : "") << time_stamp->tm_mday << "-" - << (time_stamp->tm_mon + 1 < 10 ? "0" : "") << (time_stamp->tm_mon + 1) << "-" - << 1900 + time_stamp->tm_year << " " << (time_stamp->tm_hour < 10 ? "0" : "") - << time_stamp->tm_hour << ":" << (time_stamp->tm_min < 10 ? "0" : "") << time_stamp->tm_min - << ":" << (time_stamp->tm_sec < 10 ? "0" : "") << time_stamp->tm_sec << " " - << req.endpoint.to_string() << " " << req.referrer - << (0 == req.referrer.length() ? "- " : " ") << req.agent - << (0 == req.agent.length() ? "- " : " ") << request; + SimpleLogger().Write() << (time_stamp->tm_mday < 10 ? "0" : "") << time_stamp->tm_mday + << "-" << (time_stamp->tm_mon + 1 < 10 ? "0" : "") + << (time_stamp->tm_mon + 1) << "-" << 1900 + time_stamp->tm_year + << " " << (time_stamp->tm_hour < 10 ? "0" : "") + << time_stamp->tm_hour << ":" << (time_stamp->tm_min < 10 ? "0" : "") + << time_stamp->tm_min << ":" << (time_stamp->tm_sec < 10 ? "0" : "") + << time_stamp->tm_sec << " " << req.endpoint.to_string() << " " + << req.referrer << (0 == req.referrer.length() ? "- " : " ") + << req.agent << (0 == req.agent.length() ? "- " : " ") << request; RouteParameters route_parameters; APIGrammarParser api_parser(&route_parameters); @@ -121,7 +122,8 @@ void RequestHandler::handle_request(const http::Request &req, http::Reply &reply return; } // set headers - reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size())); + reply.headers.emplace_back("Content-Length", + cast::integral_to_string(reply.content.size())); if ("gpx" == route_parameters.output_format) { // gpx file JSON::gpx_render(reply.content, json_result.values["route"]); diff --git a/Util/compute_angle.cpp b/Util/compute_angle.cpp index ca9d18980..5de872319 100644 --- a/Util/compute_angle.cpp +++ b/Util/compute_angle.cpp @@ -39,9 +39,11 @@ double ComputeAngle::OfThreeFixedPointCoordinates(const FixedPointCoordinate &A, const FixedPointCoordinate &B) { const double v1x = (A.lon - C.lon) / COORDINATE_PRECISION; - const double v1y = mercator::lat2y(A.lat / COORDINATE_PRECISION) - mercator::lat2y(C.lat / COORDINATE_PRECISION); + const double v1y = mercator::lat2y(A.lat / COORDINATE_PRECISION) - + mercator::lat2y(C.lat / COORDINATE_PRECISION); const double v2x = (B.lon - C.lon) / COORDINATE_PRECISION; - const double v2y = mercator::lat2y(B.lat / COORDINATE_PRECISION) - mercator::lat2y(C.lat / COORDINATE_PRECISION); + const double v2y = mercator::lat2y(B.lat / COORDINATE_PRECISION) - + mercator::lat2y(C.lat / COORDINATE_PRECISION); double angle = (atan2_lookup(v2y, v2x) - atan2_lookup(v1y, v1x)) * 180. / M_PI; while (angle < 0.) diff --git a/contractor/edge_based_graph_factory.cpp b/contractor/edge_based_graph_factory.cpp index 144b1faaf..6d9c43412 100644 --- a/contractor/edge_based_graph_factory.cpp +++ b/contractor/edge_based_graph_factory.cpp @@ -77,10 +77,9 @@ void EdgeBasedGraphFactory::GetEdgeBasedNodes(std::vector &nodes) nodes.swap(m_edge_based_node_list); } -void -EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, - const NodeID node_v, - const unsigned component_id) +void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, + const NodeID node_v, + const unsigned component_id) { // merge edges together into one EdgeBasedNode BOOST_ASSERT(node_u != SPECIAL_NODEID); @@ -172,20 +171,13 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id); // build edges - m_edge_based_node_list.emplace_back(forward_data.edgeBasedNodeID, - reverse_data.edgeBasedNodeID, - current_edge_source_coordinate_id, - current_edge_target_coordinate_id, - forward_data.nameID, - forward_geometry[i].second, - reverse_geometry[geometry_size - 1 - i].second, - forward_dist_prefix_sum[i], - reverse_dist_prefix_sum[i], - m_geometry_compressor.GetPositionForID(e1), - component_id, - i, - forward_data.travel_mode, - reverse_data.travel_mode); + m_edge_based_node_list.emplace_back( + forward_data.edgeBasedNodeID, reverse_data.edgeBasedNodeID, + current_edge_source_coordinate_id, current_edge_target_coordinate_id, + forward_data.nameID, forward_geometry[i].second, + reverse_geometry[geometry_size - 1 - i].second, forward_dist_prefix_sum[i], + reverse_dist_prefix_sum[i], m_geometry_compressor.GetPositionForID(e1), + component_id, i, forward_data.travel_mode, reverse_data.travel_mode); current_edge_source_coordinate_id = current_edge_target_coordinate_id; BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed()); @@ -224,20 +216,10 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, BOOST_ASSERT(forward_data.edgeBasedNodeID != SPECIAL_NODEID || reverse_data.edgeBasedNodeID != SPECIAL_NODEID); - m_edge_based_node_list.emplace_back(forward_data.edgeBasedNodeID, - reverse_data.edgeBasedNodeID, - node_u, - node_v, - forward_data.nameID, - forward_data.distance, - reverse_data.distance, - 0, - 0, - SPECIAL_EDGEID, - component_id, - 0, - forward_data.travel_mode, - reverse_data.travel_mode); + m_edge_based_node_list.emplace_back( + forward_data.edgeBasedNodeID, reverse_data.edgeBasedNodeID, node_u, node_v, + forward_data.nameID, forward_data.distance, reverse_data.distance, 0, 0, SPECIAL_EDGEID, + component_id, 0, forward_data.travel_mode, reverse_data.travel_mode); BOOST_ASSERT(!m_edge_based_node_list.back().IsCompressed()); } } @@ -245,7 +227,8 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, void EdgeBasedGraphFactory::FlushVectorToStream( std::ofstream &edge_data_file, std::vector &original_edge_data_vector) const { - if (original_edge_data_vector.empty()) { + if (original_edge_data_vector.empty()) + { return; } edge_data_file.write((char *)&(original_edge_data_vector[0]), @@ -342,15 +325,15 @@ void EdgeBasedGraphFactory::CompressGeometry() const EdgeData &fwd_edge_data1 = m_node_based_graph->GetEdgeData(forward_e1); const EdgeData &rev_edge_data1 = m_node_based_graph->GetEdgeData(reverse_e1); - if ((m_node_based_graph->FindEdge(node_u, node_w) != m_node_based_graph->EndEdges(node_u)) || + if ((m_node_based_graph->FindEdge(node_u, node_w) != + m_node_based_graph->EndEdges(node_u)) || (m_node_based_graph->FindEdge(node_w, node_u) != m_node_based_graph->EndEdges(node_w))) { continue; } if ( // TODO: rename to IsCompatibleTo - fwd_edge_data1.IsEqualTo(fwd_edge_data2) && - rev_edge_data1.IsEqualTo(rev_edge_data2)) + fwd_edge_data1.IsEqualTo(fwd_edge_data2) && rev_edge_data1.IsEqualTo(rev_edge_data2)) { // Get distances before graph is modified const int forward_weight1 = m_node_based_graph->GetEdgeData(forward_e1).distance; @@ -389,30 +372,21 @@ void EdgeBasedGraphFactory::CompressGeometry() // update any involved turn restrictions m_restriction_map->FixupStartingTurnRestriction(node_u, node_v, node_w); - m_restriction_map->FixupArrivingTurnRestriction(node_u, node_v, - node_w, + m_restriction_map->FixupArrivingTurnRestriction(node_u, node_v, node_w, m_node_based_graph); m_restriction_map->FixupStartingTurnRestriction(node_w, node_v, node_u); - m_restriction_map->FixupArrivingTurnRestriction(node_w, - node_v, - node_u, m_node_based_graph); + m_restriction_map->FixupArrivingTurnRestriction(node_w, node_v, node_u, + m_node_based_graph); // store compressed geometry in container m_geometry_compressor.CompressEdge( - forward_e1, - forward_e2, - node_v, - node_w, + forward_e1, forward_e2, node_v, node_w, forward_weight1 + (add_traffic_signal_penalty ? speed_profile.traffic_signal_penalty : 0), forward_weight2); m_geometry_compressor.CompressEdge( - reverse_e1, - reverse_e2, - node_v, - node_u, - reverse_weight1, + reverse_e1, reverse_e2, node_v, node_u, reverse_weight1, reverse_weight2 + (add_traffic_signal_penalty ? speed_profile.traffic_signal_penalty : 0)); ++removed_node_count; @@ -427,7 +401,7 @@ void EdgeBasedGraphFactory::CompressGeometry() unsigned new_node_count = 0; unsigned new_edge_count = 0; - for(const auto i : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes())) + for (const auto i : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes())) { if (m_node_based_graph->GetOutDegree(i) > 0) { @@ -436,10 +410,10 @@ void EdgeBasedGraphFactory::CompressGeometry() } } SimpleLogger().Write() << "new nodes: " << new_node_count << ", edges " << new_edge_count; - SimpleLogger().Write() << "Node compression ratio: " << new_node_count / - (double)original_number_of_nodes; - SimpleLogger().Write() << "Edge compression ratio: " << new_edge_count / - (double)original_number_of_edges; + SimpleLogger().Write() << "Node compression ratio: " + << new_node_count / (double)original_number_of_nodes; + SimpleLogger().Write() << "Edge compression ratio: " + << new_edge_count / (double)original_number_of_edges; } /** @@ -477,14 +451,16 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes() SimpleLogger().Write() << "Identifying components of the (compressed) road network"; // Run a BFS on the undirected graph and identify small components - TarjanSCC component_explorer( - m_node_based_graph, *m_restriction_map, m_barrier_nodes); + TarjanSCC component_explorer(m_node_based_graph, *m_restriction_map, + m_barrier_nodes); component_explorer.run(); - SimpleLogger().Write() << "identified: " << component_explorer.get_number_of_components() - removed_node_count + SimpleLogger().Write() << "identified: " + << component_explorer.get_number_of_components() - removed_node_count << " (compressed) components"; - SimpleLogger().Write() << "identified " << component_explorer.get_size_one_count() - removed_node_count + SimpleLogger().Write() << "identified " + << component_explorer.get_size_one_count() - removed_node_count << " (compressed) SCCs of size 1"; SimpleLogger().Write() << "generating edge-expanded nodes"; @@ -516,8 +492,10 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes() const unsigned size_of_component = std::min(component_explorer.get_component_size(u), component_explorer.get_component_size(v)); - const unsigned id_of_smaller_component = [u,v,&component_explorer] { - if (component_explorer.get_component_size(u) < component_explorer.get_component_size(v)) + const unsigned id_of_smaller_component = [u, v, &component_explorer] + { + if (component_explorer.get_component_size(u) < + component_explorer.get_component_size(v)) { return component_explorer.get_component_id(u); } @@ -544,9 +522,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes() /** * Actually it also generates OriginalEdgeData and serializes them... */ -void -EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename, - lua_State *lua_state) +void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( + const std::string &original_edge_data_filename, lua_State *lua_state) { SimpleLogger().Write() << "generating edge-expanded edges"; @@ -647,14 +624,16 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg } // unpack last node of first segment if packed - const auto first_coordinate = m_node_info_list[(m_geometry_compressor.HasEntryForID(e1) ? - m_geometry_compressor.GetLastNodeIDOfBucket(e1) : - u)]; + const auto first_coordinate = + m_node_info_list[(m_geometry_compressor.HasEntryForID(e1) + ? m_geometry_compressor.GetLastNodeIDOfBucket(e1) + : u)]; // unpack first node of second segment if packed - const auto third_coordinate = m_node_info_list[(m_geometry_compressor.HasEntryForID(e2) ? - m_geometry_compressor.GetFirstNodeIDOfBucket(e2) : - w)]; + const auto third_coordinate = + m_node_info_list[(m_geometry_compressor.HasEntryForID(e2) + ? m_geometry_compressor.GetFirstNodeIDOfBucket(e2) + : w)]; const double turn_angle = ComputeAngle::OfThreeFixedPointCoordinates( first_coordinate, m_node_info_list[v], third_coordinate); @@ -676,9 +655,7 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg original_edge_data_vector.emplace_back( (edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : v), - edge_data1.nameID, - turn_instruction, - edge_is_compressed, + edge_data1.nameID, turn_instruction, edge_is_compressed, edge_data2.travel_mode); ++original_edges_counter; @@ -691,12 +668,9 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg BOOST_ASSERT(SPECIAL_NODEID != edge_data1.edgeBasedNodeID); BOOST_ASSERT(SPECIAL_NODEID != edge_data2.edgeBasedNodeID); - m_edge_based_edge_list.emplace_back(EdgeBasedEdge(edge_data1.edgeBasedNodeID, - edge_data2.edgeBasedNodeID, - m_edge_based_edge_list.size(), - distance, - true, - false)); + m_edge_based_edge_list.emplace_back( + EdgeBasedEdge(edge_data1.edgeBasedNodeID, edge_data2.edgeBasedNodeID, + m_edge_based_edge_list.size(), distance, true, false)); } } } @@ -727,7 +701,10 @@ int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) co // call lua profile to compute turn penalty return luabind::call_function(lua_state, "turn_function", 180. - angle); } - catch (const luabind::error &er) { SimpleLogger().Write(logWARNING) << er.what(); } + catch (const luabind::error &er) + { + SimpleLogger().Write(logWARNING) << er.what(); + } } return 0; } @@ -735,8 +712,7 @@ int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) co TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID node_u, const NodeID node_v, const NodeID node_w, - const double angle) - const + const double angle) const { if (node_u == node_w) { diff --git a/contractor/processing_chain.cpp b/contractor/processing_chain.cpp index 23d406b2e..46c12d0dd 100644 --- a/contractor/processing_chain.cpp +++ b/contractor/processing_chain.cpp @@ -138,13 +138,9 @@ int Prepare::Process(int argc, char *argv[]) static_assert(sizeof(ImportEdge) == 20, "changing ImportEdge type has influence on memory consumption!"); #endif - NodeID number_of_node_based_nodes = - readBinaryOSRMGraphFromStream(input_stream, - edge_list, - barrier_node_list, - traffic_light_list, - &internal_to_external_node_map, - restriction_list); + NodeID number_of_node_based_nodes = readBinaryOSRMGraphFromStream( + input_stream, edge_list, barrier_node_list, traffic_light_list, + &internal_to_external_node_map, restriction_list); input_stream.close(); if (edge_list.empty()) @@ -162,11 +158,9 @@ int Prepare::Process(int argc, char *argv[]) DeallocatingVector edge_based_edge_list; // init node_based_edge_list, edge_based_edge_list by edgeList - number_of_edge_based_nodes = BuildEdgeExpandedGraph(lua_state, - number_of_node_based_nodes, - node_based_edge_list, - edge_based_edge_list, - speed_profile); + number_of_edge_based_nodes = + BuildEdgeExpandedGraph(lua_state, number_of_node_based_nodes, node_based_edge_list, + edge_based_edge_list, speed_profile); lua_close(lua_state); TIMER_STOP(expansion); @@ -343,9 +337,8 @@ bool Prepare::ParseArguments(int argc, char *argv[]) // declare a group of options that will be allowed only on command line boost::program_options::options_description generic_options("Options"); generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")( - "config,c", - boost::program_options::value(&config_file_path) - ->default_value("contractor.ini"), + "config,c", boost::program_options::value(&config_file_path) + ->default_value("contractor.ini"), "Path to a configuration file."); // declare a group of options that will be allowed both on command line and in config file @@ -354,21 +347,18 @@ bool Prepare::ParseArguments(int argc, char *argv[]) "restrictions,r", boost::program_options::value(&restrictions_path), "Restrictions file in .osrm.restrictions format")( - "profile,p", - boost::program_options::value(&profile_path) - ->default_value("profile.lua"), + "profile,p", boost::program_options::value(&profile_path) + ->default_value("profile.lua"), "Path to LUA routing profile")( - "threads,t", - boost::program_options::value(&requested_num_threads) - ->default_value(tbb::task_scheduler_init::default_num_threads()), + "threads,t", boost::program_options::value(&requested_num_threads) + ->default_value(tbb::task_scheduler_init::default_num_threads()), "Number of threads to use"); // hidden options, will be allowed both on command line and in config file, but will not be // shown to the user boost::program_options::options_description hidden_options("Hidden options"); hidden_options.add_options()( - "input,i", - boost::program_options::value(&input_path), + "input,i", boost::program_options::value(&input_path), "Input file in .osm, .osm.bz2 or .osm.pbf format"); // positional option @@ -394,10 +384,11 @@ bool Prepare::ParseArguments(int argc, char *argv[]) .run(), option_variables); - const auto& temp_config_path = option_variables["config"].as(); + const auto &temp_config_path = option_variables["config"].as(); if (boost::filesystem::is_regular_file(temp_config_path)) { - boost::program_options::store(boost::program_options::parse_config_file(temp_config_path.string().c_str(), cmdline_options, true), + boost::program_options::store(boost::program_options::parse_config_file( + temp_config_path.string().c_str(), cmdline_options, true), option_variables); } @@ -458,9 +449,8 @@ void Prepare::CheckRestrictionsFile(FingerPrint &fingerprint_orig) \brief Setups scripting environment (lua-scripting) Also initializes speed profile. */ -bool -Prepare::SetupScriptingEnvironment(lua_State *lua_state, - EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile) +bool Prepare::SetupScriptingEnvironment( + lua_State *lua_state, EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile) { // open utility libraries string library; luaL_openlibs(lua_state); @@ -509,14 +499,12 @@ Prepare::BuildEdgeExpandedGraph(lua_State *lua_state, SimpleLogger().Write() << "Generating edge-expanded graph representation"; std::shared_ptr node_based_graph = NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list); - std::unique_ptr restriction_map = osrm::make_unique(restriction_list); + std::unique_ptr restriction_map = + osrm::make_unique(restriction_list); std::shared_ptr edge_based_graph_factory = - std::make_shared(node_based_graph, - std::move(restriction_map), - barrier_node_list, - traffic_light_list, - internal_to_external_node_map, - speed_profile); + std::make_shared(node_based_graph, std::move(restriction_map), + barrier_node_list, traffic_light_list, + internal_to_external_node_map, speed_profile); edge_list.clear(); edge_list.shrink_to_fit(); @@ -574,8 +562,6 @@ void Prepare::WriteNodeMapping() void Prepare::BuildRTree(std::vector &node_based_edge_list) { SimpleLogger().Write() << "building r-tree ..."; - StaticRTree(node_based_edge_list, - rtree_nodes_path.c_str(), - rtree_leafs_path.c_str(), - internal_to_external_node_map); + StaticRTree(node_based_edge_list, rtree_nodes_path.c_str(), + rtree_leafs_path.c_str(), internal_to_external_node_map); } diff --git a/data_structures/coordinate.cpp b/data_structures/coordinate.cpp index dbddc4742..de0b696f0 100644 --- a/data_structures/coordinate.cpp +++ b/data_structures/coordinate.cpp @@ -93,8 +93,8 @@ void FixedPointCoordinate::Output(std::ostream &out) const float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const { - const float lon_delta = - coordinate_calculation::deg_to_rad(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION); + const float lon_delta = coordinate_calculation::deg_to_rad(lon / COORDINATE_PRECISION - + other.lon / COORDINATE_PRECISION); const float lat1 = coordinate_calculation::deg_to_rad(other.lat / COORDINATE_PRECISION); const float lat2 = coordinate_calculation::deg_to_rad(lat / COORDINATE_PRECISION); const float y_value = std::sin(lon_delta) * std::cos(lat2); diff --git a/data_structures/coordinate_calculation.cpp b/data_structures/coordinate_calculation.cpp index cc0474c79..3ea5ae96d 100644 --- a/data_structures/coordinate_calculation.cpp +++ b/data_structures/coordinate_calculation.cpp @@ -36,7 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -namespace +namespace { constexpr static const float RAD = 0.017453292519943295769236907684886; constexpr static const float earth_radius = 6372797.560856f; @@ -72,23 +72,23 @@ double coordinate_calculation::ApproximateDistance(const int lat1, } double coordinate_calculation::ApproximateDistance(const FixedPointCoordinate &coordinate_1, - const FixedPointCoordinate &coordinate_2) + const FixedPointCoordinate &coordinate_2) { - return ApproximateDistance( - coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon); + return ApproximateDistance(coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, + coordinate_2.lon); } float coordinate_calculation::approx_euclidean_distance(const FixedPointCoordinate &coordinate_1, - const FixedPointCoordinate &coordinate_2) + const FixedPointCoordinate &coordinate_2) { - return approx_euclidean_distance( - coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon); + return approx_euclidean_distance(coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, + coordinate_2.lon); } float coordinate_calculation::approx_euclidean_distance(const int lat1, - const int lon1, - const int lat2, - const int lon2) + const int lon1, + const int lat2, + const int lon2) { BOOST_ASSERT(lat1 != std::numeric_limits::min()); BOOST_ASSERT(lon1 != std::numeric_limits::min()); @@ -105,26 +105,24 @@ float coordinate_calculation::approx_euclidean_distance(const int lat1, return sqrt(x_value * x_value + y_value * y_value) * earth_radius; } -float -coordinate_calculation::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate, - const FixedPointCoordinate &target_coordinate, - const FixedPointCoordinate &query_location) +float coordinate_calculation::ComputePerpendicularDistance( + const FixedPointCoordinate &source_coordinate, + const FixedPointCoordinate &target_coordinate, + const FixedPointCoordinate &query_location) { float ratio; FixedPointCoordinate nearest_location; - return ComputePerpendicularDistance(source_coordinate, - target_coordinate, - query_location, - nearest_location, - ratio); + return ComputePerpendicularDistance(source_coordinate, target_coordinate, query_location, + nearest_location, ratio); } -float coordinate_calculation::ComputePerpendicularDistance(const FixedPointCoordinate &segment_source, - const FixedPointCoordinate &segment_target, - const FixedPointCoordinate &query_location, - FixedPointCoordinate &nearest_location, - float &ratio) +float coordinate_calculation::ComputePerpendicularDistance( + const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target, + const FixedPointCoordinate &query_location, + FixedPointCoordinate &nearest_location, + float &ratio) { BOOST_ASSERT(query_location.is_valid()); @@ -197,31 +195,27 @@ float coordinate_calculation::ComputePerpendicularDistance(const FixedPointCoord return approximate_distance; } -float -coordinate_calculation::perpendicular_distance_from_projected_coordinate( - const FixedPointCoordinate &source_coordinate, - const FixedPointCoordinate &target_coordinate, - const FixedPointCoordinate &query_location, - const std::pair &projected_coordinate) +float coordinate_calculation::perpendicular_distance_from_projected_coordinate( + const FixedPointCoordinate &source_coordinate, + const FixedPointCoordinate &target_coordinate, + const FixedPointCoordinate &query_location, + const std::pair &projected_coordinate) { float ratio; FixedPointCoordinate nearest_location; - return perpendicular_distance_from_projected_coordinate(source_coordinate, - target_coordinate, - query_location, - projected_coordinate, - nearest_location, - ratio); + return perpendicular_distance_from_projected_coordinate(source_coordinate, target_coordinate, + query_location, projected_coordinate, + nearest_location, ratio); } float coordinate_calculation::perpendicular_distance_from_projected_coordinate( - const FixedPointCoordinate &segment_source, - const FixedPointCoordinate &segment_target, - const FixedPointCoordinate &query_location, - const std::pair &projected_coordinate, - FixedPointCoordinate &nearest_location, - float &ratio) + const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target, + const FixedPointCoordinate &query_location, + const std::pair &projected_coordinate, + FixedPointCoordinate &nearest_location, + float &ratio) { BOOST_ASSERT(query_location.is_valid()); @@ -302,7 +296,7 @@ void coordinate_calculation::lat_or_lon_to_string(const int value, std::string & } void coordinate_calculation::convertInternalCoordinateToString(const FixedPointCoordinate &coord, - std::string &output) + std::string &output) { std::string tmp; tmp.reserve(23); @@ -313,9 +307,8 @@ void coordinate_calculation::convertInternalCoordinateToString(const FixedPointC output += tmp; } -void -coordinate_calculation::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord, - std::string &output) +void coordinate_calculation::convertInternalReversedCoordinateToString( + const FixedPointCoordinate &coord, std::string &output) { std::string tmp; tmp.reserve(23); @@ -327,7 +320,7 @@ coordinate_calculation::convertInternalReversedCoordinateToString(const FixedPoi } float coordinate_calculation::GetBearing(const FixedPointCoordinate &first_coordinate, - const FixedPointCoordinate &second_coordinate) + const FixedPointCoordinate &second_coordinate) { const float lon_diff = second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION; diff --git a/datastore.cpp b/datastore.cpp index 011fa09b6..14bde95bd 100644 --- a/datastore.cpp +++ b/datastore.cpp @@ -103,7 +103,8 @@ int main(const int argc, const char *argv[]) const bool lock_flags = MCL_CURRENT | MCL_FUTURE; if (-1 == mlockall(lock_flags)) { - SimpleLogger().Write(logWARNING) << "Process " << argv[0] << " could not request RAM lock"; + SimpleLogger().Write(logWARNING) << "Process " << argv[0] + << " could not request RAM lock"; } #endif try @@ -340,8 +341,8 @@ int main(const int argc, const char *argv[]) geometry_input_stream.read((char *)&number_of_geometries_indices, sizeof(unsigned)); shared_layout_ptr->SetBlockSize(SharedDataLayout::GEOMETRIES_INDEX, number_of_geometries_indices); - boost::iostreams::seek( - geometry_input_stream, number_of_geometries_indices * sizeof(unsigned), BOOST_IOS::cur); + boost::iostreams::seek(geometry_input_stream, + number_of_geometries_indices * sizeof(unsigned), BOOST_IOS::cur); geometry_input_stream.read((char *)&number_of_compressed_geometries, sizeof(unsigned)); shared_layout_ptr->SetBlockSize(SharedDataLayout::GEOMETRIES_LIST, number_of_compressed_geometries); @@ -410,9 +411,8 @@ int main(const int argc, const char *argv[]) unsigned *name_id_ptr = shared_layout_ptr->GetBlockPtr( shared_memory_ptr, SharedDataLayout::NAME_ID_LIST); - TravelMode *travel_mode_ptr = - shared_layout_ptr->GetBlockPtr( - shared_memory_ptr, SharedDataLayout::TRAVEL_MODE); + TravelMode *travel_mode_ptr = shared_layout_ptr->GetBlockPtr( + shared_memory_ptr, SharedDataLayout::TRAVEL_MODE); TurnInstruction *turn_instructions_ptr = shared_layout_ptr->GetBlockPtr( diff --git a/extractor/extraction_containers.cpp b/extractor/extraction_containers.cpp index 682fb1652..4675db2d2 100644 --- a/extractor/extraction_containers.cpp +++ b/extractor/extraction_containers.cpp @@ -83,32 +83,25 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, TIMER_STOP(erasing_dups); std::cout << "ok, after " << TIMER_SEC(erasing_dups) << "s" << std::endl; - std::cout << "[extractor] Sorting all nodes ... " << std::flush; TIMER_START(sorting_nodes); - stxxl::sort(all_nodes_list.begin(), - all_nodes_list.end(), - ExternalMemoryNodeSTXXLCompare(), + stxxl::sort(all_nodes_list.begin(), all_nodes_list.end(), ExternalMemoryNodeSTXXLCompare(), stxxl_memory); TIMER_STOP(sorting_nodes); std::cout << "ok, after " << TIMER_SEC(sorting_nodes) << "s" << std::endl; - std::cout << "[extractor] Sorting used ways ... " << std::flush; TIMER_START(sort_ways); - stxxl::sort(way_start_end_id_list.begin(), - way_start_end_id_list.end(), - FirstAndLastSegmentOfWayStxxlCompare(), - stxxl_memory); + stxxl::sort(way_start_end_id_list.begin(), way_start_end_id_list.end(), + FirstAndLastSegmentOfWayStxxlCompare(), stxxl_memory); TIMER_STOP(sort_ways); std::cout << "ok, after " << TIMER_SEC(sort_ways) << "s" << std::endl; - std::cout << "[extractor] Sorting " << restrictions_list.size() << " restrictions. by from... " << std::flush; + std::cout << "[extractor] Sorting " << restrictions_list.size() + << " restrictions. by from... " << std::flush; TIMER_START(sort_restrictions); - stxxl::sort(restrictions_list.begin(), - restrictions_list.end(), - CmpRestrictionContainerByFrom(), - stxxl_memory); + stxxl::sort(restrictions_list.begin(), restrictions_list.end(), + CmpRestrictionContainerByFrom(), stxxl_memory); TIMER_STOP(sort_restrictions); std::cout << "ok, after " << TIMER_SEC(sort_restrictions) << "s" << std::endl; @@ -132,7 +125,8 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, continue; } - BOOST_ASSERT(way_start_and_end_iterator->way_id == restrictions_iterator->restriction.from.way); + BOOST_ASSERT(way_start_and_end_iterator->way_id == + restrictions_iterator->restriction.from.way); const NodeID via_node_id = restrictions_iterator->restriction.via.node; if (way_start_and_end_iterator->first_segment_source_id == via_node_id) @@ -153,10 +147,8 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, std::cout << "[extractor] Sorting restrictions. by to ... " << std::flush; TIMER_START(sort_restrictions_to); - stxxl::sort(restrictions_list.begin(), - restrictions_list.end(), - CmpRestrictionContainerByTo(), - stxxl_memory); + stxxl::sort(restrictions_list.begin(), restrictions_list.end(), + CmpRestrictionContainerByTo(), stxxl_memory); TIMER_STOP(sort_restrictions_to); std::cout << "ok, after " << TIMER_SEC(sort_restrictions_to) << "s" << std::endl; @@ -177,7 +169,8 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, ++restrictions_iterator; continue; } - BOOST_ASSERT(way_start_and_end_iterator->way_id == restrictions_iterator->restriction.to.way); + BOOST_ASSERT(way_start_and_end_iterator->way_id == + restrictions_iterator->restriction.to.way); const NodeID via_node_id = restrictions_iterator->restriction.via.node; if (way_start_and_end_iterator->first_segment_source_id == via_node_id) @@ -203,7 +196,7 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, const auto count_position = restrictions_out_stream.tellp(); restrictions_out_stream.write((char *)&written_restriction_count, sizeof(unsigned)); - for(const auto & restriction_container : restrictions_list) + for (const auto &restriction_container : restrictions_list) { if (SPECIAL_NODEID != restriction_container.restriction.from.node && SPECIAL_NODEID != restriction_container.restriction.to.node) @@ -267,7 +260,6 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, TIMER_STOP(sort_edges_by_start); std::cout << "ok, after " << TIMER_SEC(sort_edges_by_start) << "s" << std::endl; - std::cout << "[extractor] Setting start coords ... " << std::flush; TIMER_START(set_start_coords); file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned)); @@ -298,7 +290,8 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, // Sort Edges by target std::cout << "[extractor] Sorting edges by target ... " << std::flush; TIMER_START(sort_edges_by_target); - stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByTargetID(), stxxl_memory); + stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByTargetID(), + stxxl_memory); TIMER_STOP(sort_edges_by_target); std::cout << "ok, after " << TIMER_SEC(sort_edges_by_target) << "s" << std::endl; @@ -329,16 +322,13 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, edge_iterator->target_coordinate.lon = node_iterator->lon; const double distance = coordinate_calculation::approx_euclidean_distance( - edge_iterator->source_coordinate.lat, - edge_iterator->source_coordinate.lon, - node_iterator->lat, - node_iterator->lon); + edge_iterator->source_coordinate.lat, edge_iterator->source_coordinate.lon, + node_iterator->lat, node_iterator->lon); const double weight = (distance * 10.) / (edge_iterator->speed / 3.6); int integer_weight = std::max( - 1, - (int)std::floor( - (edge_iterator->is_duration_set ? edge_iterator->speed : weight) + .5)); + 1, (int)std::floor( + (edge_iterator->is_duration_set ? edge_iterator->speed : weight) + .5)); const int integer_distance = std::max(1, (int)distance); const short zero = 0; const short one = 1; @@ -371,30 +361,38 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, if (edge_iterator->is_roundabout) { file_out_stream.write((char *)&yes, sizeof(bool)); - } else { + } + else + { file_out_stream.write((char *)&no, sizeof(bool)); } if (edge_iterator->is_in_tiny_cc) { file_out_stream.write((char *)&yes, sizeof(bool)); - } else { + } + else + { file_out_stream.write((char *)&no, sizeof(bool)); } if (edge_iterator->is_access_restricted) { file_out_stream.write((char *)&yes, sizeof(bool)); - } else { + } + else + { file_out_stream.write((char *)&no, sizeof(bool)); } // cannot take adress of bit field, so use local - const TravelMode travel_mode = edge_iterator->travel_mode; + const TravelMode travel_mode = edge_iterator->travel_mode; file_out_stream.write((char *)&travel_mode, sizeof(TravelMode)); if (edge_iterator->is_split) { file_out_stream.write((char *)&yes, sizeof(bool)); - } else { + } + else + { file_out_stream.write((char *)&no, sizeof(bool)); } ++number_of_used_edges; @@ -420,7 +418,8 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, std::vector name_lengths; for (const std::string &temp_string : name_list) { - const unsigned string_length = std::min(static_cast(temp_string.length()), 255u); + const unsigned string_length = + std::min(static_cast(temp_string.length()), 255u); name_lengths.push_back(string_length); total_length += string_length; } @@ -428,11 +427,12 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, RangeTable<> table(name_lengths); name_file_stream << table; - name_file_stream.write((char*) &total_length, sizeof(unsigned)); + name_file_stream.write((char *)&total_length, sizeof(unsigned)); // write all chars consecutively for (const std::string &temp_string : name_list) { - const unsigned string_length = std::min(static_cast(temp_string.length()), 255u); + const unsigned string_length = + std::min(static_cast(temp_string.length()), 255u); name_file_stream.write(temp_string.c_str(), string_length); } @@ -443,5 +443,8 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, SimpleLogger().Write() << "Processed " << number_of_used_nodes << " nodes and " << number_of_used_edges << " edges"; } - catch (const std::exception &e) { std::cerr << "Caught Execption:" << e.what() << std::endl; } + catch (const std::exception &e) + { + std::cerr << "Caught Execption:" << e.what() << std::endl; + } } diff --git a/extractor/extraction_containers.hpp b/extractor/extraction_containers.hpp index 68df14cff..588dcabb0 100644 --- a/extractor/extraction_containers.hpp +++ b/extractor/extraction_containers.hpp @@ -39,17 +39,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. class ExtractionContainers { #ifndef _MSC_VER - constexpr static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? std::numeric_limits::max() : std::numeric_limits::max()); + constexpr static unsigned stxxl_memory = + ((sizeof(std::size_t) == 4) ? std::numeric_limits::max() + : std::numeric_limits::max()); #else const static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? INT_MAX : UINT_MAX); #endif public: - using STXXLNodeIDVector = stxxl::vector; - using STXXLNodeVector = stxxl::vector; - using STXXLEdgeVector = stxxl::vector; - using STXXLStringVector = stxxl::vector; - using STXXLRestrictionsVector = stxxl::vector; - using STXXLWayIDStartEndVector = stxxl::vector; + using STXXLNodeIDVector = stxxl::vector; + using STXXLNodeVector = stxxl::vector; + using STXXLEdgeVector = stxxl::vector; + using STXXLStringVector = stxxl::vector; + using STXXLRestrictionsVector = stxxl::vector; + using STXXLWayIDStartEndVector = stxxl::vector; STXXLNodeIDVector used_node_id_list; STXXLNodeVector all_nodes_list; diff --git a/extractor/extraction_node.hpp b/extractor/extraction_node.hpp index defd33394..7fd7d7ca9 100644 --- a/extractor/extraction_node.hpp +++ b/extractor/extraction_node.hpp @@ -30,11 +30,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct ExtractionNode { - ExtractionNode() : traffic_lights(false), barrier(false) { } - void clear() - { - traffic_lights = barrier = false; - } + ExtractionNode() : traffic_lights(false), barrier(false) {} + void clear() { traffic_lights = barrier = false; } bool traffic_lights; bool barrier; }; diff --git a/extractor/extraction_way.hpp b/extractor/extraction_way.hpp index b41448758..97133b3af 100644 --- a/extractor/extraction_way.hpp +++ b/extractor/extraction_way.hpp @@ -52,10 +52,12 @@ struct ExtractionWay } enum Directions - { notSure = 0, - oneway, - bidirectional, - opposite }; + { + notSure = 0, + oneway, + bidirectional, + opposite + }; // These accessor methods exists to support the depreciated "way.direction" access // in LUA. Since the direction attribute was removed from ExtractionWay, the @@ -69,19 +71,20 @@ struct ExtractionWay } else if (Directions::opposite == m) { - forward_travel_mode = TRAVEL_MODE_INACCESSIBLE; - backward_travel_mode = TRAVEL_MODE_DEFAULT; + forward_travel_mode = TRAVEL_MODE_INACCESSIBLE; + backward_travel_mode = TRAVEL_MODE_DEFAULT; } else if (Directions::bidirectional == m) { - forward_travel_mode = TRAVEL_MODE_DEFAULT; - backward_travel_mode = TRAVEL_MODE_DEFAULT; + forward_travel_mode = TRAVEL_MODE_DEFAULT; + backward_travel_mode = TRAVEL_MODE_DEFAULT; } } Directions get_direction() const { - if (TRAVEL_MODE_INACCESSIBLE != forward_travel_mode && TRAVEL_MODE_INACCESSIBLE != backward_travel_mode) + if (TRAVEL_MODE_INACCESSIBLE != forward_travel_mode && + TRAVEL_MODE_INACCESSIBLE != backward_travel_mode) { return Directions::bidirectional; } diff --git a/extractor/extractor.cpp b/extractor/extractor.cpp index d8a3d5563..136789e14 100644 --- a/extractor/extractor.cpp +++ b/extractor/extractor.cpp @@ -99,7 +99,8 @@ int Extractor::Run(int argc, char *argv[]) } const unsigned recommended_num_threads = tbb::task_scheduler_init::default_num_threads(); - const auto number_of_threads = std::min(recommended_num_threads, extractor_config.requested_num_threads); + const auto number_of_threads = + std::min(recommended_num_threads, extractor_config.requested_num_threads); tbb::task_scheduler_init init(number_of_threads); SimpleLogger().Write() << "Input file: " << extractor_config.input_path.filename().string(); @@ -120,10 +121,10 @@ int Extractor::Run(int argc, char *argv[]) osmium::io::Reader reader(input_file); const osmium::io::Header header = reader.header(); - std::atomic number_of_nodes {0}; - std::atomic number_of_ways {0}; - std::atomic number_of_relations {0}; - std::atomic number_of_others {0}; + std::atomic number_of_nodes{0}; + std::atomic number_of_ways{0}; + std::atomic number_of_relations{0}; + std::atomic number_of_others{0}; SimpleLogger().Write() << "Parsing in progress.."; TIMER_START(parsing); @@ -160,7 +161,8 @@ int Extractor::Run(int argc, char *argv[]) { // create a vector of iterators into the buffer std::vector osm_elements; - for (auto iter = std::begin(buffer); iter != std::end(buffer); ++iter) { + for (auto iter = std::begin(buffer); iter != std::end(buffer); ++iter) + { osm_elements.push_back(iter); } @@ -170,56 +172,56 @@ int Extractor::Run(int argc, char *argv[]) resulting_restrictions.clear(); // parse OSM entities in parallel, store in resulting vectors - tbb::parallel_for(tbb::blocked_range(0, osm_elements.size()), - [&](const tbb::blocked_range &range) - { - ExtractionNode result_node; - ExtractionWay result_way; - lua_State * local_state = scripting_environment.get_lua_state(); - - for (auto x = range.begin(); x != range.end(); ++x) + tbb::parallel_for( + tbb::blocked_range(0, osm_elements.size()), + [&](const tbb::blocked_range &range) { - const auto entity = osm_elements[x]; + ExtractionNode result_node; + ExtractionWay result_way; + lua_State *local_state = scripting_environment.get_lua_state(); - switch (entity->type()) + for (auto x = range.begin(); x != range.end(); ++x) { - case osmium::item_type::node: - result_node.clear(); - ++number_of_nodes; - luabind::call_function( - local_state, - "node_function", - boost::cref(static_cast(*entity)), - boost::ref(result_node)); - resulting_nodes.push_back(std::make_pair(x, result_node)); - break; - case osmium::item_type::way: - result_way.clear(); - ++number_of_ways; - luabind::call_function( - local_state, - "way_function", - boost::cref(static_cast(*entity)), - boost::ref(result_way)); - resulting_ways.push_back(std::make_pair(x, result_way)); - break; - case osmium::item_type::relation: - ++number_of_relations; - resulting_restrictions.push_back( - restriction_parser.TryParse(static_cast(*entity))); - break; - default: - ++number_of_others; - break; + const auto entity = osm_elements[x]; + + switch (entity->type()) + { + case osmium::item_type::node: + result_node.clear(); + ++number_of_nodes; + luabind::call_function( + local_state, "node_function", + boost::cref(static_cast(*entity)), + boost::ref(result_node)); + resulting_nodes.push_back(std::make_pair(x, result_node)); + break; + case osmium::item_type::way: + result_way.clear(); + ++number_of_ways; + luabind::call_function( + local_state, "way_function", + boost::cref(static_cast(*entity)), + boost::ref(result_way)); + resulting_ways.push_back(std::make_pair(x, result_way)); + break; + case osmium::item_type::relation: + ++number_of_relations; + resulting_restrictions.push_back(restriction_parser.TryParse( + static_cast(*entity))); + break; + default: + ++number_of_others; + break; + } } - } - }); + }); // put parsed objects thru extractor callbacks for (const auto &result : resulting_nodes) { extractor_callbacks->ProcessNode( - static_cast(*(osm_elements[result.first])), result.second); + static_cast(*(osm_elements[result.first])), + result.second); } for (const auto &result : resulting_ways) { @@ -238,11 +240,8 @@ int Extractor::Run(int argc, char *argv[]) unsigned nw = number_of_ways; unsigned nr = number_of_relations; unsigned no = number_of_others; - SimpleLogger().Write() << "Raw input contains " - << nn << " nodes, " - << nw << " ways, and " - << nr << " relations, and " - << no << " unknown entities"; + SimpleLogger().Write() << "Raw input contains " << nn << " nodes, " << nw << " ways, and " + << nr << " relations, and " << no << " unknown entities"; extractor_callbacks.reset(); diff --git a/extractor/extractor_callbacks.cpp b/extractor/extractor_callbacks.cpp index 7ab0fc409..361c7e5ce 100644 --- a/extractor/extractor_callbacks.cpp +++ b/extractor/extractor_callbacks.cpp @@ -51,13 +51,12 @@ ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containe void ExtractorCallbacks::ProcessNode(const osmium::Node &input_node, const ExtractionNode &result_node) { - external_memory.all_nodes_list.push_back({ - static_cast(input_node.location().lat() * COORDINATE_PRECISION), - static_cast(input_node.location().lon() * COORDINATE_PRECISION), - static_cast(input_node.id()), - result_node.barrier, - result_node.traffic_lights - }); + external_memory.all_nodes_list.push_back( + {static_cast(input_node.location().lat() * COORDINATE_PRECISION), + static_cast(input_node.location().lon() * COORDINATE_PRECISION), + static_cast(input_node.id()), + result_node.barrier, + result_node.traffic_lights}); } void ExtractorCallbacks::ProcessRestriction( @@ -69,7 +68,8 @@ void ExtractorCallbacks::ProcessRestriction( // SimpleLogger().Write() << "from: " << restriction.get().restriction.from.node << // ",via: " << restriction.get().restriction.via.node << // ", to: " << restriction.get().restriction.to.node << - // ", only: " << (restriction.get().restriction.flags.is_only ? "y" : "n"); + // ", only: " << (restriction.get().restriction.flags.is_only ? + // "y" : "n"); } } /** warning: caller needs to take care of synchronization! */ @@ -99,8 +99,10 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti { // TODO: iterate all way segments and set duration corresponding to the length of each // segment - const_cast(parsed_way).forward_speed = parsed_way.duration / (input_way.nodes().size() - 1); - const_cast(parsed_way).backward_speed = parsed_way.duration / (input_way.nodes().size() - 1); + const_cast(parsed_way).forward_speed = + parsed_way.duration / (input_way.nodes().size() - 1); + const_cast(parsed_way).backward_speed = + parsed_way.duration / (input_way.nodes().size() - 1); } if (std::numeric_limits::epsilon() >= std::abs(-1. - parsed_way.forward_speed)) @@ -129,41 +131,36 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti ((parsed_way.forward_speed != parsed_way.backward_speed) || (parsed_way.forward_travel_mode != parsed_way.backward_travel_mode)); - auto pair_wise_segment_split = [&](const osmium::NodeRef &first_node, - const osmium::NodeRef &last_node) + auto pair_wise_segment_split = + [&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) { // SimpleLogger().Write() << "adding edge (" << first_node.ref() << "," << // last_node.ref() << "), fwd speed: " << parsed_way.forward_speed; external_memory.all_edges_list.push_back(InternalExtractorEdge( - first_node.ref(), - last_node.ref(), + first_node.ref(), last_node.ref(), ((split_edge || TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode) ? ExtractionWay::oneway : ExtractionWay::bidirectional), - parsed_way.forward_speed, - name_id, - parsed_way.roundabout, - parsed_way.ignore_in_grid, - (0 < parsed_way.duration), - parsed_way.is_access_restricted, - parsed_way.forward_travel_mode, - split_edge)); + parsed_way.forward_speed, name_id, parsed_way.roundabout, parsed_way.ignore_in_grid, + (0 < parsed_way.duration), parsed_way.is_access_restricted, + parsed_way.forward_travel_mode, split_edge)); external_memory.used_node_id_list.push_back(first_node.ref()); }; const bool is_opposite_way = TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode; if (is_opposite_way) { - const_cast(parsed_way).forward_travel_mode = parsed_way.backward_travel_mode; - const_cast(parsed_way).backward_travel_mode = TRAVEL_MODE_INACCESSIBLE; - osrm::for_each_pair( - input_way.nodes().crbegin(), input_way.nodes().crend(), pair_wise_segment_split); + const_cast(parsed_way).forward_travel_mode = + parsed_way.backward_travel_mode; + const_cast(parsed_way).backward_travel_mode = TRAVEL_MODE_INACCESSIBLE; + osrm::for_each_pair(input_way.nodes().crbegin(), input_way.nodes().crend(), + pair_wise_segment_split); external_memory.used_node_id_list.push_back(input_way.nodes().front().ref()); } else { - osrm::for_each_pair( - input_way.nodes().cbegin(), input_way.nodes().cend(), pair_wise_segment_split); + osrm::for_each_pair(input_way.nodes().cbegin(), input_way.nodes().cend(), + pair_wise_segment_split); external_memory.used_node_id_list.push_back(input_way.nodes().back().ref()); } @@ -177,39 +174,30 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti if (split_edge) { // Only true if the way should be split - BOOST_ASSERT(parsed_way.backward_travel_mode>0); - auto pair_wise_segment_split_2 = [&](const osmium::NodeRef &first_node, - const osmium::NodeRef &last_node) + BOOST_ASSERT(parsed_way.backward_travel_mode > 0); + auto pair_wise_segment_split_2 = + [&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) { // SimpleLogger().Write() << "adding edge (" << last_node.ref() << "," << // first_node.ref() << "), bwd speed: " << parsed_way.backward_speed; - external_memory.all_edges_list.push_back( - InternalExtractorEdge(last_node.ref(), - first_node.ref(), - ExtractionWay::oneway, - parsed_way.backward_speed, - name_id, - parsed_way.roundabout, - parsed_way.ignore_in_grid, - (0 < parsed_way.duration), - parsed_way.is_access_restricted, - parsed_way.backward_travel_mode, - split_edge)); + external_memory.all_edges_list.push_back(InternalExtractorEdge( + last_node.ref(), first_node.ref(), ExtractionWay::oneway, parsed_way.backward_speed, + name_id, parsed_way.roundabout, parsed_way.ignore_in_grid, + (0 < parsed_way.duration), parsed_way.is_access_restricted, + parsed_way.backward_travel_mode, split_edge)); }; if (is_opposite_way) { // SimpleLogger().Write() << "opposite2"; - osrm::for_each_pair(input_way.nodes().crbegin(), - input_way.nodes().crend(), - pair_wise_segment_split_2); + osrm::for_each_pair(input_way.nodes().crbegin(), input_way.nodes().crend(), + pair_wise_segment_split_2); external_memory.used_node_id_list.push_back(input_way.nodes().front().ref()); } else { - osrm::for_each_pair(input_way.nodes().cbegin(), - input_way.nodes().cend(), - pair_wise_segment_split_2); + osrm::for_each_pair(input_way.nodes().cbegin(), input_way.nodes().cend(), + pair_wise_segment_split_2); external_memory.used_node_id_list.push_back(input_way.nodes().back().ref()); } diff --git a/extractor/extractor_options.cpp b/extractor/extractor_options.cpp index d14d8d9f8..8f58580cb 100644 --- a/extractor/extractor_options.cpp +++ b/extractor/extractor_options.cpp @@ -41,9 +41,8 @@ bool ExtractorOptions::ParseArguments(int argc, char *argv[], ExtractorConfig &e // declare a group of options that will be allowed only on command line boost::program_options::options_description generic_options("Options"); generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")( - "config,c", - boost::program_options::value(&extractor_config.config_file_path) - ->default_value("extractor.ini"), + "config,c", boost::program_options::value( + &extractor_config.config_file_path)->default_value("extractor.ini"), "Path to a configuration file."); // declare a group of options that will be allowed both on command line and in config file @@ -60,10 +59,9 @@ bool ExtractorOptions::ParseArguments(int argc, char *argv[], ExtractorConfig &e // hidden options, will be allowed both on command line and in config file, but will not be // shown to the user boost::program_options::options_description hidden_options("Hidden options"); - hidden_options.add_options()( - "input,i", - boost::program_options::value(&extractor_config.input_path), - "Input file in .osm, .osm.bz2 or .osm.pbf format"); + hidden_options.add_options()("input,i", boost::program_options::value( + &extractor_config.input_path), + "Input file in .osm, .osm.bz2 or .osm.pbf format"); // positional option boost::program_options::positional_options_description positional_options; diff --git a/extractor/internal_extractor_edge.hpp b/extractor/internal_extractor_edge.hpp index 39616d345..2760f7256 100644 --- a/extractor/internal_extractor_edge.hpp +++ b/extractor/internal_extractor_edge.hpp @@ -55,8 +55,8 @@ struct InternalExtractorEdge bool is_access_restricted, TravelMode travel_mode, bool is_split) - : start(start), target(target), speed(speed), name_id(name_id), - direction(direction), is_roundabout(is_roundabout), is_in_tiny_cc(is_in_tiny_cc), + : start(start), target(target), speed(speed), name_id(name_id), direction(direction), + is_roundabout(is_roundabout), is_in_tiny_cc(is_in_tiny_cc), is_duration_set(is_duration_set), is_access_restricted(is_access_restricted), is_split(is_split), travel_mode(travel_mode) { @@ -65,12 +65,13 @@ struct InternalExtractorEdge // necessary static util functions for stxxl's sorting static InternalExtractorEdge min_value() { - return InternalExtractorEdge(0, 0, 0, 0, 0, false, false, false, false, TRAVEL_MODE_INACCESSIBLE, false); + return InternalExtractorEdge(0, 0, 0, 0, 0, false, false, false, false, + TRAVEL_MODE_INACCESSIBLE, false); } static InternalExtractorEdge max_value() { - return InternalExtractorEdge( - SPECIAL_NODEID, SPECIAL_NODEID, 0, 0, 0, false, false, false, false, TRAVEL_MODE_INACCESSIBLE, false); + return InternalExtractorEdge(SPECIAL_NODEID, SPECIAL_NODEID, 0, 0, 0, false, false, false, + false, TRAVEL_MODE_INACCESSIBLE, false); } NodeID start; @@ -78,11 +79,11 @@ struct InternalExtractorEdge double speed; unsigned name_id; short direction; - bool is_roundabout:1; - bool is_in_tiny_cc:1; - bool is_duration_set:1; - bool is_access_restricted:1; - bool is_split:1; + bool is_roundabout : 1; + bool is_in_tiny_cc : 1; + bool is_duration_set : 1; + bool is_access_restricted : 1; + bool is_split : 1; TravelMode travel_mode : 4; FixedPointCoordinate source_coordinate; diff --git a/extractor/restriction_parser.cpp b/extractor/restriction_parser.cpp index 2f53d33c3..dd4855508 100644 --- a/extractor/restriction_parser.cpp +++ b/extractor/restriction_parser.cpp @@ -85,8 +85,8 @@ void RestrictionParser::ReadRestrictionExceptions(lua_State *lua_state) { luabind::set_pcall_callback(&lua_error_callback); // get list of turn restriction exceptions - luabind::call_function( - lua_state, "get_exceptions", boost::ref(restriction_exceptions)); + luabind::call_function(lua_state, "get_exceptions", + boost::ref(restriction_exceptions)); const unsigned exception_count = restriction_exceptions.size(); SimpleLogger().Write() << "Found " << exception_count << " exceptions to turn restrictions:"; diff --git a/extractor/restriction_parser.hpp b/extractor/restriction_parser.hpp index d5adb4317..8347de306 100644 --- a/extractor/restriction_parser.hpp +++ b/extractor/restriction_parser.hpp @@ -46,7 +46,8 @@ class RestrictionParser public: // RestrictionParser(ScriptingEnvironment &scripting_environment); RestrictionParser(lua_State *lua_state); - mapbox::util::optional TryParse(const osmium::Relation &relation) const; + mapbox::util::optional + TryParse(const osmium::Relation &relation) const; private: void ReadUseRestrictionsSetting(lua_State *lua_state); diff --git a/extractor/scripting_environment.cpp b/extractor/scripting_environment.cpp index c51651e40..d50161c12 100644 --- a/extractor/scripting_environment.cpp +++ b/extractor/scripting_environment.cpp @@ -41,10 +41,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -namespace { +namespace +{ // wrapper method as luabind doesn't automatically overload funcs w/ default parameters -template -auto get_value_by_key(T const& object, const char *key) -> decltype(object.get_value_by_key(key)) +template +auto get_value_by_key(T const &object, const char *key) -> decltype(object.get_value_by_key(key)) { return object.get_value_by_key(key, ""); } @@ -59,16 +60,14 @@ int lua_error_callback(lua_State *L) // This is so I can use my own function as } } - -ScriptingEnvironment::ScriptingEnvironment(const std::string &file_name) -: file_name(file_name) +ScriptingEnvironment::ScriptingEnvironment(const std::string &file_name) : file_name(file_name) { SimpleLogger().Write() << "Using script " << file_name; } -void ScriptingEnvironment::init_lua_state(lua_State* lua_state) +void ScriptingEnvironment::init_lua_state(lua_State *lua_state) { - typedef double (osmium::Location::* location_member_ptr_type)() const; + typedef double (osmium::Location::*location_member_ptr_type)() const; luabind::open(lua_state); // open utility libraries string library; @@ -83,41 +82,44 @@ void ScriptingEnvironment::init_lua_state(lua_State* lua_state) luabind::def("parseDuration", parseDuration), luabind::class_>("vector") - .def("Add", static_cast::*)(const std::string &)>(&std::vector::push_back)), + .def("Add", static_cast::*)(const std::string &)>( + &std::vector::push_back)), luabind::class_("Location") - .def("lat", &osmium::Location::lat) - .def("lon", &osmium::Location::lon), + .def("lat", &osmium::Location::lat) + .def("lon", &osmium::Location::lon), luabind::class_("Node") - // .def("tags", &osmium::Node::tags) - .def("get_value_by_key", &osmium::Node::get_value_by_key) - .def("get_value_by_key", &get_value_by_key), + // .def("tags", &osmium::Node::tags) + .def("get_value_by_key", &osmium::Node::get_value_by_key) + .def("get_value_by_key", &get_value_by_key), luabind::class_("ResultNode") - .def_readwrite("traffic_lights", &ExtractionNode::traffic_lights) - .def_readwrite("barrier", &ExtractionNode::barrier), + .def_readwrite("traffic_lights", &ExtractionNode::traffic_lights) + .def_readwrite("barrier", &ExtractionNode::barrier), luabind::class_("ResultWay") - // .def(luabind::constructor<>()) - .def_readwrite("forward_speed", &ExtractionWay::forward_speed) - .def_readwrite("backward_speed", &ExtractionWay::backward_speed) - .def_readwrite("name", &ExtractionWay::name) - .def_readwrite("roundabout", &ExtractionWay::roundabout) - .def_readwrite("is_access_restricted", &ExtractionWay::is_access_restricted) - .def_readwrite("ignore_in_index", &ExtractionWay::ignore_in_grid) - .def_readwrite("duration", &ExtractionWay::duration) - .property("forward_mode", &ExtractionWay::get_forward_mode, &ExtractionWay::set_forward_mode) - .property("backward_mode", &ExtractionWay::get_backward_mode, &ExtractionWay::set_backward_mode) - .enum_("constants")[ - luabind::value("notSure", 0), - luabind::value("oneway", 1), - luabind::value("bidirectional", 2), - luabind::value("opposite", 3) - ], + // .def(luabind::constructor<>()) + .def_readwrite("forward_speed", &ExtractionWay::forward_speed) + .def_readwrite("backward_speed", &ExtractionWay::backward_speed) + .def_readwrite("name", &ExtractionWay::name) + .def_readwrite("roundabout", &ExtractionWay::roundabout) + .def_readwrite("is_access_restricted", &ExtractionWay::is_access_restricted) + .def_readwrite("ignore_in_index", &ExtractionWay::ignore_in_grid) + .def_readwrite("duration", &ExtractionWay::duration) + .property("forward_mode", &ExtractionWay::get_forward_mode, + &ExtractionWay::set_forward_mode) + .property("backward_mode", &ExtractionWay::get_backward_mode, + &ExtractionWay::set_backward_mode) + .enum_("constants")[ + luabind::value("notSure", 0), + luabind::value("oneway", 1), + luabind::value("bidirectional", 2), + luabind::value("opposite", 3) + ], luabind::class_("Way") - .def("get_value_by_key", &osmium::Way::get_value_by_key) - .def("get_value_by_key", &get_value_by_key) + .def("get_value_by_key", &osmium::Way::get_value_by_key) + .def("get_value_by_key", &get_value_by_key) ]; if (0 != luaL_dofile(lua_state, file_name.c_str())) @@ -133,7 +135,7 @@ lua_State *ScriptingEnvironment::get_lua_state() { std::lock_guard lock(init_mutex); bool initialized = false; - auto& ref = script_contexts.local(initialized); + auto &ref = script_contexts.local(initialized); if (!initialized) { std::shared_ptr state(luaL_newstate(), lua_close); diff --git a/extractor/scripting_environment.hpp b/extractor/scripting_environment.hpp index 6e0b079c9..8cc862a6a 100644 --- a/extractor/scripting_environment.hpp +++ b/extractor/scripting_environment.hpp @@ -44,8 +44,8 @@ class ScriptingEnvironment lua_State *get_lua_state(); private: - void init_lua_state(lua_State* lua_state); - std::mutex init_mutex; + void init_lua_state(lua_State *lua_state); + std::mutex init_mutex; std::string file_name; tbb::enumerable_thread_specific> script_contexts; }; diff --git a/routed.cpp b/routed.cpp index a0caac1f4..5768c3d03 100644 --- a/routed.cpp +++ b/routed.cpp @@ -75,15 +75,9 @@ int main(int argc, const char *argv[]) libosrm_config lib_config; - const unsigned init_result = GenerateServerProgramOptions(argc, - argv, - lib_config.server_paths, - ip_address, - ip_port, - requested_thread_num, - lib_config.use_shared_memory, - trial_run, - lib_config.max_locations_distance_table); + const unsigned init_result = GenerateServerProgramOptions( + argc, argv, lib_config.server_paths, ip_address, ip_port, requested_thread_num, + lib_config.use_shared_memory, trial_run, lib_config.max_locations_distance_table); if (init_result == INIT_OK_DO_NOT_START_ENGINE) { return 0; @@ -119,8 +113,7 @@ int main(int argc, const char *argv[]) #endif OSRM osrm_lib(lib_config); - auto routing_server = - Server::CreateServer(ip_address, ip_port, requested_thread_num); + auto routing_server = Server::CreateServer(ip_address, ip_port, requested_thread_num); routing_server->GetRequestHandlerPtr().RegisterRoutingMachine(&osrm_lib); @@ -130,7 +123,11 @@ int main(int argc, const char *argv[]) } else { - std::packaged_task server_task([&]()->int{ routing_server->Run(); return 0; }); + std::packaged_task server_task([&]() -> int + { + routing_server->Run(); + return 0; + }); auto future = server_task.get_future(); std::thread server_thread(std::move(server_task)); @@ -159,7 +156,7 @@ int main(int argc, const char *argv[]) if (status == std::future_status::ready) { - server_thread.join(); + server_thread.join(); } else { diff --git a/tools/components.cpp b/tools/components.cpp index e9a96773a..f5fe73547 100644 --- a/tools/components.cpp +++ b/tools/components.cpp @@ -191,7 +191,7 @@ int main(int argc, char *argv[]) tarjan->run(); SimpleLogger().Write() << "identified: " << tarjan->get_number_of_components() << " many components"; - SimpleLogger().Write() << "identified " << tarjan->get_size_one_count() << " SCCs of size 1"; + SimpleLogger().Write() << "identified " << tarjan->get_size_one_count() << " size 1 SCCs"; // output TIMER_START(SCC_RUN_SETUP); diff --git a/tools/simpleclient.cpp b/tools/simpleclient.cpp index 0bb47599b..11b4f9a89 100644 --- a/tools/simpleclient.cpp +++ b/tools/simpleclient.cpp @@ -46,15 +46,9 @@ int main(int argc, const char *argv[]) int ip_port, requested_thread_num; bool trial_run = false; libosrm_config lib_config; - const unsigned init_result = GenerateServerProgramOptions(argc, - argv, - lib_config.server_paths, - ip_address, - ip_port, - requested_thread_num, - lib_config.use_shared_memory, - trial_run, - lib_config.max_locations_distance_table); + const unsigned init_result = GenerateServerProgramOptions( + argc, argv, lib_config.server_paths, ip_address, ip_port, requested_thread_num, + lib_config.use_shared_memory, trial_run, lib_config.max_locations_distance_table); if (init_result == INIT_OK_DO_NOT_START_ENGINE) { diff --git a/unit_tests/data_structures/coordinate.cpp b/unit_tests/data_structures/coordinate.cpp index 1acb5e0df..c3c8b2a8e 100644 --- a/unit_tests/data_structures/coordinate.cpp +++ b/unit_tests/data_structures/coordinate.cpp @@ -44,8 +44,8 @@ BOOST_AUTO_TEST_CASE(regression_test_1347) float ratio; FixedPointCoordinate nearest_location; - float d2 = coordinate_calculation::ComputePerpendicularDistance(u, v, q, nearest_location, ratio); + float d2 = + coordinate_calculation::ComputePerpendicularDistance(u, v, q, nearest_location, ratio); BOOST_CHECK_LE(std::abs(d1 - d2), 0.01f); } - From a8db29399f3467f6431c6741167cf269a45673d5 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 12:28:00 +0100 Subject: [PATCH 081/360] remove unneeded else block in if statement --- Library/OSRM_impl.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Library/OSRM_impl.cpp b/Library/OSRM_impl.cpp index 6b67a675d..b03cc5e2d 100644 --- a/Library/OSRM_impl.cpp +++ b/Library/OSRM_impl.cpp @@ -143,10 +143,7 @@ int OSRM_impl::RunQuery(RouteParameters &route_parameters, JSON::Object &json_re } return 200; } - else - { - return 400; - } + return 400; } // proxy code for compilation firewall From c881aa7b32954a45017c747f2a170ed91f4fb35d Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 12:35:46 +0100 Subject: [PATCH 082/360] Use early exit/continue to simplify code and reduce indentation, move increase/decrease query count into functions --- Library/OSRM_impl.cpp | 98 ++++++++++++++++++++++++------------------- Library/OSRM_impl.h | 5 +++ 2 files changed, 61 insertions(+), 42 deletions(-) diff --git a/Library/OSRM_impl.cpp b/Library/OSRM_impl.cpp index b03cc5e2d..aa8eb3d1e 100644 --- a/Library/OSRM_impl.cpp +++ b/Library/OSRM_impl.cpp @@ -100,54 +100,68 @@ void OSRM_impl::RegisterPlugin(BasePlugin *plugin) int OSRM_impl::RunQuery(RouteParameters &route_parameters, JSON::Object &json_result) { - const PluginMap::const_iterator &iter = plugin_map.find(route_parameters.service); + const auto &plugin_iterator = plugin_map.find(route_parameters.service); - if (plugin_map.end() != iter) + if (plugin_map.end() == plugin_iterator) { - if (barrier) - { - // lock update pending - boost::interprocess::scoped_lock pending_lock( - barrier->pending_update_mutex); - - // lock query - boost::interprocess::scoped_lock query_lock( - barrier->query_mutex); - - // unlock update pending - pending_lock.unlock(); - - // increment query count - ++(barrier->number_of_queries); - - (static_cast *>(query_data_facade)) - ->CheckAndReloadFacade(); - } - - iter->second->HandleRequest(route_parameters, json_result); - if (barrier) - { - // lock query - boost::interprocess::scoped_lock query_lock( - barrier->query_mutex); - - // decrement query count - --(barrier->number_of_queries); - BOOST_ASSERT_MSG(0 <= barrier->number_of_queries, "invalid number of queries"); - - // notify all processes that were waiting for this condition - if (0 == barrier->number_of_queries) - { - barrier->no_running_queries_condition.notify_all(); - } - } - return 200; + return 400; } - return 400; + + increase_concurrent_query_count(); + plugin_iterator->second->HandleRequest(route_parameters, json_result); + decrease_concurrent_query_count(); + return 200; +} + +// decrease number of concurrent queries +void OSRM_impl::decrease_concurrent_query_count() +{ + if (!barrier) + { + return; + } + // lock query + boost::interprocess::scoped_lock query_lock( + barrier->query_mutex); + + // decrement query count + --(barrier->number_of_queries); + BOOST_ASSERT_MSG(0 <= barrier->number_of_queries, "invalid number of queries"); + + // notify all processes that were waiting for this condition + if (0 == barrier->number_of_queries) + { + barrier->no_running_queries_condition.notify_all(); + } +} + +// increase number of concurrent queries +void OSRM_impl::increase_concurrent_query_count() +{ + if (!barrier) + { + return; + } + + // lock update pending + boost::interprocess::scoped_lock pending_lock( + barrier->pending_update_mutex); + + // lock query + boost::interprocess::scoped_lock query_lock( + barrier->query_mutex); + + // unlock update pending + pending_lock.unlock(); + + // increment query count + ++(barrier->number_of_queries); + + (static_cast *>(query_data_facade)) + ->CheckAndReloadFacade(); } // proxy code for compilation firewall - OSRM::OSRM(libosrm_config &lib_config) : OSRM_pimpl_(osrm::make_unique(lib_config)) { diff --git a/Library/OSRM_impl.h b/Library/OSRM_impl.h index 625fc19ca..4568f47d3 100644 --- a/Library/OSRM_impl.h +++ b/Library/OSRM_impl.h @@ -62,6 +62,11 @@ class OSRM_impl std::unique_ptr barrier; // base class pointer to the objects BaseDataFacade *query_data_facade; + + // decrease number of concurrent queries + void decrease_concurrent_query_count(); + // increase number of concurrent queries + void increase_concurrent_query_count(); }; #endif // OSRM_IMPL_H From cfa83658dce783df73e92d4fb046ce1e3b0b7d9f Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 12:39:41 +0100 Subject: [PATCH 083/360] Use early exit/continue to simplify code and reduce indentation --- data_structures/restriction_map.cpp | 30 +++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/data_structures/restriction_map.cpp b/data_structures/restriction_map.cpp index b43be579c..0f230f819 100644 --- a/data_structures/restriction_map.cpp +++ b/data_structures/restriction_map.cpp @@ -145,23 +145,25 @@ bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID node_u, } const auto restriction_iter = m_restriction_map.find({node_u, node_v}); - if (restriction_iter != m_restriction_map.end()) + if (restriction_iter == m_restriction_map.end()) { - const unsigned index = restriction_iter->second; - const auto &bucket = m_restriction_bucket_list.at(index); + return false; + } - for (const RestrictionTarget &restriction_target : bucket) + const unsigned index = restriction_iter->second; + const auto &bucket = m_restriction_bucket_list.at(index); + + for (const RestrictionTarget &restriction_target : bucket) + { + if (node_w == restriction_target.target_node && // target found + !restriction_target.is_only) // and not an only_-restr. { - if (node_w == restriction_target.target_node && // target found - !restriction_target.is_only) // and not an only_-restr. - { - return true; - } - if (node_w != restriction_target.target_node && // target not found - restriction_target.is_only) // and is an only restriction - { - return true; - } + return true; + } + if (node_w != restriction_target.target_node && // target not found + restriction_target.is_only) // and is an only restriction + { + return true; } } return false; From e67f82283f13a5b2ca2658ae6b937cf438f03583 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 13:47:31 +0100 Subject: [PATCH 084/360] replace temporary variable with short name by atomic<>.load call --- extractor/extractor.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/extractor/extractor.cpp b/extractor/extractor.cpp index 136789e14..e3a5090e9 100644 --- a/extractor/extractor.cpp +++ b/extractor/extractor.cpp @@ -236,12 +236,11 @@ int Extractor::Run(int argc, char *argv[]) TIMER_STOP(parsing); SimpleLogger().Write() << "Parsing finished after " << TIMER_SEC(parsing) << " seconds"; - unsigned nn = number_of_nodes; - unsigned nw = number_of_ways; - unsigned nr = number_of_relations; - unsigned no = number_of_others; - SimpleLogger().Write() << "Raw input contains " << nn << " nodes, " << nw << " ways, and " - << nr << " relations, and " << no << " unknown entities"; + SimpleLogger().Write() << "Raw input contains " + << number_of_nodes.load() << " nodes, " + << number_of_ways.load() << " ways, and " + << number_of_relations.load() << " relations, and " + << number_of_others.load() << " unknown entities"; extractor_callbacks.reset(); From 887032881a93fe37d576450589249c17bb9ff231 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 15:09:24 +0100 Subject: [PATCH 085/360] use std::any_of() algorithm instead of hand-rolled logic --- extractor/restriction_parser.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/extractor/restriction_parser.cpp b/extractor/restriction_parser.cpp index dd4855508..7965e78ec 100644 --- a/extractor/restriction_parser.cpp +++ b/extractor/restriction_parser.cpp @@ -39,6 +39,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include + namespace { int lua_error_callback(lua_State *lua_state) @@ -228,14 +230,16 @@ bool RestrictionParser::ShouldIgnoreRestriction(const std::string &except_tag_st // only a few exceptions are actually defined. std::vector exceptions; boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*")); - for (std::string ¤t_string : exceptions) - { - const auto string_iterator = - std::find(restriction_exceptions.begin(), restriction_exceptions.end(), current_string); - if (restriction_exceptions.end() != string_iterator) - { - return true; - } - } - return false; + + return std::any_of(std::begin(exceptions), std::end(exceptions), + [&](const std::string ¤t_string) + { + if (restriction_exceptions.end() != + std::find(restriction_exceptions.begin(), + restriction_exceptions.end(), current_string)) + { + return true; + } + return false; + }); } From 9175fb7da8514db6466cfa4ef67d2c082e7bfcae Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 15:19:43 +0100 Subject: [PATCH 086/360] remove unused debug code --- extractor/restriction_parser.cpp | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/extractor/restriction_parser.cpp b/extractor/restriction_parser.cpp index 7965e78ec..4038adaa1 100644 --- a/extractor/restriction_parser.cpp +++ b/extractor/restriction_parser.cpp @@ -168,9 +168,8 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const continue; } BOOST_ASSERT(0 == strcmp("via", role)); - // set the via node id - // SimpleLogger().Write() << "via: " << member.ref(); + // set via node id restriction_container.restriction.via.node = member.ref(); break; @@ -179,19 +178,17 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const 0 == strcmp("via", role)); if (0 == strcmp("from", role)) { - // SimpleLogger().Write() << "from: " << member.ref(); restriction_container.restriction.from.way = member.ref(); } else if (0 == strcmp("to", role)) { - // SimpleLogger().Write() << "to: " << member.ref(); restriction_container.restriction.to.way = member.ref(); } - else if (0 == strcmp("via", role)) - { - // not yet suppported - // restriction_container.restriction.via.way = member.ref(); - } + // else if (0 == strcmp("via", role)) + // { + // not yet suppported + // restriction_container.restriction.via.way = member.ref(); + // } break; case osmium::item_type::relation: // not yet supported, but who knows what the future holds... @@ -202,14 +199,6 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const break; } } - - // SimpleLogger().Write() << (restriction_container.restriction.flags.is_only ? "only" : "no") - // << "-restriction " - // << "<" << restriction_container.restriction.from.node << "->" - // << restriction_container.restriction.via.node << "->" << - // restriction_container.restriction.to.node - // << ">"; - return mapbox::util::optional(restriction_container); } @@ -234,9 +223,9 @@ bool RestrictionParser::ShouldIgnoreRestriction(const std::string &except_tag_st return std::any_of(std::begin(exceptions), std::end(exceptions), [&](const std::string ¤t_string) { - if (restriction_exceptions.end() != - std::find(restriction_exceptions.begin(), - restriction_exceptions.end(), current_string)) + if (std::end(restriction_exceptions) != + std::find(std::begin(restriction_exceptions), + std::end(restriction_exceptions), current_string)) { return true; } From 547a2aec09391f9ab517915d93a8521456384913 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 15:50:04 +0100 Subject: [PATCH 087/360] remove dead/redundant code --- data_structures/coordinate_calculation.cpp | 158 ++------------------- data_structures/coordinate_calculation.hpp | 21 ++- data_structures/static_rtree.hpp | 8 +- 3 files changed, 27 insertions(+), 160 deletions(-) diff --git a/data_structures/coordinate_calculation.cpp b/data_structures/coordinate_calculation.cpp index 3ea5ae96d..2a1b8d5c4 100644 --- a/data_structures/coordinate_calculation.cpp +++ b/data_structures/coordinate_calculation.cpp @@ -105,94 +105,28 @@ float coordinate_calculation::approx_euclidean_distance(const int lat1, return sqrt(x_value * x_value + y_value * y_value) * earth_radius; } -float coordinate_calculation::ComputePerpendicularDistance( - const FixedPointCoordinate &source_coordinate, - const FixedPointCoordinate &target_coordinate, - const FixedPointCoordinate &query_location) +float coordinate_calculation::perpendicular_distance(const FixedPointCoordinate &source_coordinate, + const FixedPointCoordinate &target_coordinate, + const FixedPointCoordinate &query_location) { float ratio; FixedPointCoordinate nearest_location; - return ComputePerpendicularDistance(source_coordinate, target_coordinate, query_location, - nearest_location, ratio); + return perpendicular_distance(source_coordinate, target_coordinate, query_location, + nearest_location, ratio); } -float coordinate_calculation::ComputePerpendicularDistance( - const FixedPointCoordinate &segment_source, - const FixedPointCoordinate &segment_target, - const FixedPointCoordinate &query_location, - FixedPointCoordinate &nearest_location, - float &ratio) +float coordinate_calculation::perpendicular_distance(const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target, + const FixedPointCoordinate &query_location, + FixedPointCoordinate &nearest_location, + float &ratio) { - BOOST_ASSERT(query_location.is_valid()); - - // initialize values - const double x = mercator::lat2y(query_location.lat / COORDINATE_PRECISION); - const double y = query_location.lon / COORDINATE_PRECISION; - const double a = mercator::lat2y(segment_source.lat / COORDINATE_PRECISION); - const double b = segment_source.lon / COORDINATE_PRECISION; - const double c = mercator::lat2y(segment_target.lat / COORDINATE_PRECISION); - const double d = segment_target.lon / COORDINATE_PRECISION; - double p, q /*,mX*/, nY; - if (std::abs(a - c) > std::numeric_limits::epsilon()) - { - const double m = (d - b) / (c - a); // slope - // Projection of (x,y) on line joining (a,b) and (c,d) - p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m); - q = b + m * (p - a); - } - else - { - p = c; - q = y; - } - nY = (d * p - c * q) / (a * d - b * c); - - // discretize the result to coordinate precision. it's a hack! - if (std::abs(nY) < (1.f / COORDINATE_PRECISION)) - { - nY = 0.f; - } - - // compute ratio - ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need - // not calculate the explicit values of m an n as we - // are just interested in the ratio - if (std::isnan(ratio)) - { - ratio = (segment_target == query_location ? 1.f : 0.f); - } - else if (std::abs(ratio) <= std::numeric_limits::epsilon()) - { - ratio = 0.f; - } - else if (std::abs(ratio - 1.f) <= std::numeric_limits::epsilon()) - { - ratio = 1.f; - } - - // compute nearest location - BOOST_ASSERT(!std::isnan(ratio)); - if (ratio <= 0.f) - { - nearest_location = segment_source; - } - else if (ratio >= 1.f) - { - nearest_location = segment_target; - } - else - { - // point lies in between - nearest_location.lat = static_cast(mercator::y2lat(p) * COORDINATE_PRECISION); - nearest_location.lon = static_cast(q * COORDINATE_PRECISION); - } - BOOST_ASSERT(nearest_location.is_valid()); - - const float approximate_distance = - coordinate_calculation::approx_euclidean_distance(query_location, nearest_location); - BOOST_ASSERT(0. <= approximate_distance); - return approximate_distance; + return perpendicular_distance_from_projected_coordinate( + segment_source, segment_target, query_location, + {mercator::lat2y(query_location.lat / COORDINATE_PRECISION), + query_location.lon / COORDINATE_PRECISION}, + nearest_location, ratio); } float coordinate_calculation::perpendicular_distance_from_projected_coordinate( @@ -351,65 +285,3 @@ float coordinate_calculation::rad_to_deg(const float radian) { return radian * (180.f * static_cast(M_1_PI)); } - -// This distance computation does integer arithmetic only and is a lot faster than -// the other distance function which are numerically correct('ish). -// It preserves some order among the elements that make it useful for certain purposes -int coordinate_calculation::OrderedPerpendicularDistanceApproximation( - const FixedPointCoordinate &input_point, - const FixedPointCoordinate &segment_source, - const FixedPointCoordinate &segment_target) -{ - // initialize values - const float x = static_cast(mercator::lat2y(input_point.lat / COORDINATE_PRECISION)); - const float y = input_point.lon / COORDINATE_PRECISION; - const float a = static_cast(mercator::lat2y(segment_source.lat / COORDINATE_PRECISION)); - const float b = segment_source.lon / COORDINATE_PRECISION; - const float c = static_cast(mercator::lat2y(segment_target.lat / COORDINATE_PRECISION)); - const float d = segment_target.lon / COORDINATE_PRECISION; - - float p, q; - if (a == c) - { - p = c; - q = y; - } - else - { - const float m = (d - b) / (c - a); // slope - // Projection of (x,y) on line joining (a,b) and (c,d) - p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m); - q = b + m * (p - a); - } - - const float nY = (d * p - c * q) / (a * d - b * c); - float ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need - // not calculate the explicit values of m an n as we - // are just interested in the ratio - if (std::isnan(ratio)) - { - ratio = (segment_target == input_point) ? 1.f : 0.f; - } - - // compute target quasi-location - int dx, dy; - if (ratio < 0.f) - { - dx = input_point.lon - segment_source.lon; - dy = input_point.lat - segment_source.lat; - } - else if (ratio > 1.f) - { - dx = input_point.lon - segment_target.lon; - dy = input_point.lat - segment_target.lat; - } - else - { - // point lies in between - dx = input_point.lon - static_cast(q * COORDINATE_PRECISION); - dy = input_point.lat - static_cast(mercator::y2lat(p) * COORDINATE_PRECISION); - } - - // return an approximation in the plane - return static_cast(sqrt(dx * dx + dy * dy)); -} diff --git a/data_structures/coordinate_calculation.hpp b/data_structures/coordinate_calculation.hpp index 7c76cb446..a1f1cb6f9 100644 --- a/data_structures/coordinate_calculation.hpp +++ b/data_structures/coordinate_calculation.hpp @@ -59,15 +59,15 @@ struct coordinate_calculation static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coordinate, std::string &output); - static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source, - const FixedPointCoordinate &segment_target, - const FixedPointCoordinate &query_location); + static float perpendicular_distance(const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target, + const FixedPointCoordinate &query_location); - static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source, - const FixedPointCoordinate &segment_target, - const FixedPointCoordinate &query_location, - FixedPointCoordinate &nearest_location, - float &ratio); + static float perpendicular_distance(const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target, + const FixedPointCoordinate &query_location, + FixedPointCoordinate &nearest_location, + float &ratio); static float perpendicular_distance_from_projected_coordinate( const FixedPointCoordinate &segment_source, @@ -83,11 +83,6 @@ struct coordinate_calculation FixedPointCoordinate &nearest_location, float &ratio); - static int - OrderedPerpendicularDistanceApproximation(const FixedPointCoordinate &segment_source, - const FixedPointCoordinate &segment_target, - const FixedPointCoordinate &query_location); - static float GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B); static float deg_to_rad(const float degree); diff --git a/data_structures/static_rtree.hpp b/data_structures/static_rtree.hpp index fe83c1888..16d7ced99 100644 --- a/data_structures/static_rtree.hpp +++ b/data_structures/static_rtree.hpp @@ -664,7 +664,7 @@ class StaticRTree unsigned pruned_elements = 0; - std::pair projected_coordinate = + std::pair projected_coordinate = { mercator::lat2y(input_coordinate.lat / COORDINATE_PRECISION), input_coordinate.lon / COORDINATE_PRECISION }; @@ -846,7 +846,7 @@ class StaticRTree { const auto ¤t_edge = current_leaf_node.objects[i]; const float current_perpendicular_distance = - coordinate_calculation::ComputePerpendicularDistance( + coordinate_calculation::perpendicular_distance( m_coordinate_list->at(current_edge.u), m_coordinate_list->at(current_edge.v), input_coordinate); @@ -903,7 +903,7 @@ class StaticRTree float current_ratio = 0.; FixedPointCoordinate foot_point_coordinate_on_segment; const float current_perpendicular_distance = - coordinate_calculation::ComputePerpendicularDistance( + coordinate_calculation::perpendicular_distance( m_coordinate_list->at(current_segment.u), m_coordinate_list->at(current_segment.v), input_coordinate, @@ -1003,7 +1003,7 @@ class StaticRTree float current_ratio = 0.; FixedPointCoordinate nearest; const float current_perpendicular_distance = - coordinate_calculation::ComputePerpendicularDistance( + coordinate_calculation::perpendicular_distance( m_coordinate_list->at(current_edge.u), m_coordinate_list->at(current_edge.v), input_coordinate, From 3fa12445a53a71560c565d01a89ead450a58cc57 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 16:28:40 +0100 Subject: [PATCH 088/360] rename coordinate calculation functions, remove code clutter --- data_structures/coordinate_calculation.cpp | 56 +++++++++++----------- data_structures/coordinate_calculation.hpp | 13 ++--- data_structures/rectangle.hpp | 32 ++++++------- data_structures/static_rtree.hpp | 40 ++++++++-------- descriptors/description_factory.cpp | 2 +- extractor/extraction_containers.cpp | 2 +- tools/components.cpp | 2 +- 7 files changed, 72 insertions(+), 75 deletions(-) diff --git a/data_structures/coordinate_calculation.cpp b/data_structures/coordinate_calculation.cpp index 2a1b8d5c4..0f5a94976 100644 --- a/data_structures/coordinate_calculation.cpp +++ b/data_structures/coordinate_calculation.cpp @@ -42,53 +42,53 @@ constexpr static const float RAD = 0.017453292519943295769236907684886; constexpr static const float earth_radius = 6372797.560856f; } -double coordinate_calculation::ApproximateDistance(const int lat1, - const int lon1, - const int lat2, - const int lon2) +double coordinate_calculation::great_circle_distance(const int lat1, + const int lon1, + const int lat2, + const int lon2) { BOOST_ASSERT(lat1 != std::numeric_limits::min()); BOOST_ASSERT(lon1 != std::numeric_limits::min()); BOOST_ASSERT(lat2 != std::numeric_limits::min()); BOOST_ASSERT(lon2 != std::numeric_limits::min()); - double lt1 = lat1 / COORDINATE_PRECISION; - double ln1 = lon1 / COORDINATE_PRECISION; - double lt2 = lat2 / COORDINATE_PRECISION; - double ln2 = lon2 / COORDINATE_PRECISION; - double dlat1 = lt1 * (RAD); + const double lt1 = lat1 / COORDINATE_PRECISION; + const double ln1 = lon1 / COORDINATE_PRECISION; + const double lt2 = lat2 / COORDINATE_PRECISION; + const double ln2 = lon2 / COORDINATE_PRECISION; + const double dlat1 = lt1 * (RAD); - double dlong1 = ln1 * (RAD); - double dlat2 = lt2 * (RAD); - double dlong2 = ln2 * (RAD); + const double dlong1 = ln1 * (RAD); + const double dlat2 = lt2 * (RAD); + const double dlong2 = ln2 * (RAD); - double dLong = dlong1 - dlong2; - double dLat = dlat1 - dlat2; + const double dLong = dlong1 - dlong2; + const double dLat = dlat1 - dlat2; - double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2); - double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv)); + const double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2); + const double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv)); // earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi) // The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles) return earth_radius * cHarv; } -double coordinate_calculation::ApproximateDistance(const FixedPointCoordinate &coordinate_1, - const FixedPointCoordinate &coordinate_2) +double coordinate_calculation::great_circle_distance(const FixedPointCoordinate &coordinate_1, + const FixedPointCoordinate &coordinate_2) { - return ApproximateDistance(coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, - coordinate_2.lon); + return great_circle_distance(coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, + coordinate_2.lon); } -float coordinate_calculation::approx_euclidean_distance(const FixedPointCoordinate &coordinate_1, - const FixedPointCoordinate &coordinate_2) +float coordinate_calculation::euclidean_distance(const FixedPointCoordinate &coordinate_1, + const FixedPointCoordinate &coordinate_2) { - return approx_euclidean_distance(coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, + return euclidean_distance(coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon); } -float coordinate_calculation::approx_euclidean_distance(const int lat1, - const int lon1, - const int lat2, - const int lon2) +float coordinate_calculation::euclidean_distance(const int lat1, + const int lon1, + const int lat2, + const int lon2) { BOOST_ASSERT(lat1 != std::numeric_limits::min()); BOOST_ASSERT(lon1 != std::numeric_limits::min()); @@ -217,7 +217,7 @@ float coordinate_calculation::perpendicular_distance_from_projected_coordinate( BOOST_ASSERT(nearest_location.is_valid()); const float approximate_distance = - coordinate_calculation::approx_euclidean_distance(query_location, nearest_location); + coordinate_calculation::euclidean_distance(query_location, nearest_location); BOOST_ASSERT(0. <= approximate_distance); return approximate_distance; } diff --git a/data_structures/coordinate_calculation.hpp b/data_structures/coordinate_calculation.hpp index a1f1cb6f9..201c1ce04 100644 --- a/data_structures/coordinate_calculation.hpp +++ b/data_structures/coordinate_calculation.hpp @@ -37,19 +37,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct coordinate_calculation { static double - ApproximateDistance(const int lat1, const int lon1, const int lat2, const int lon2); + great_circle_distance(const int lat1, const int lon1, const int lat2, const int lon2); - static double ApproximateDistance(const FixedPointCoordinate &first_coordinate, - const FixedPointCoordinate &second_coordinate); + static double great_circle_distance(const FixedPointCoordinate &first_coordinate, + const FixedPointCoordinate &second_coordinate); - static float approx_euclidean_distance(const FixedPointCoordinate &first_coordinate, + static float euclidean_distance(const FixedPointCoordinate &first_coordinate, const FixedPointCoordinate &second_coordinate); static float - approx_euclidean_distance(const int lat1, const int lon1, const int lat2, const int lon2); - - static float ApproximateSquaredEuclideanDistance(const FixedPointCoordinate &first_coordinate, - const FixedPointCoordinate &second_coordinate); + euclidean_distance(const int lat1, const int lon1, const int lat2, const int lon2); static void lat_or_lon_to_string(const int value, std::string &output); diff --git a/data_structures/rectangle.hpp b/data_structures/rectangle.hpp index 43f389365..110f22794 100644 --- a/data_structures/rectangle.hpp +++ b/data_structures/rectangle.hpp @@ -117,28 +117,28 @@ struct RectangleInt2D switch (d) { case NORTH: - min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, location.lon)); + min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(max_lat, location.lon)); break; case SOUTH: - min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, location.lon)); + min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(min_lat, location.lon)); break; case WEST: - min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(location.lat, min_lon)); + min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(location.lat, min_lon)); break; case EAST: - min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(location.lat, max_lon)); + min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(location.lat, max_lon)); break; case NORTH_EAST: - min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, max_lon)); + min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(max_lat, max_lon)); break; case NORTH_WEST: - min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, min_lon)); + min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(max_lat, min_lon)); break; case SOUTH_EAST: - min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, max_lon)); + min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(min_lat, max_lon)); break; case SOUTH_WEST: - min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, min_lon)); + min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(min_lat, min_lon)); break; default: break; @@ -161,24 +161,24 @@ struct RectangleInt2D min_max_dist = std::min( min_max_dist, std::max( - coordinate_calculation::approx_euclidean_distance(location, upper_left), - coordinate_calculation::approx_euclidean_distance(location, upper_right))); + coordinate_calculation::euclidean_distance(location, upper_left), + coordinate_calculation::euclidean_distance(location, upper_right))); min_max_dist = std::min( min_max_dist, std::max( - coordinate_calculation::approx_euclidean_distance(location, upper_right), - coordinate_calculation::approx_euclidean_distance(location, lower_right))); + coordinate_calculation::euclidean_distance(location, upper_right), + coordinate_calculation::euclidean_distance(location, lower_right))); min_max_dist = std::min( min_max_dist, - std::max(coordinate_calculation::approx_euclidean_distance(location, lower_right), - coordinate_calculation::approx_euclidean_distance(location, lower_left))); + std::max(coordinate_calculation::euclidean_distance(location, lower_right), + coordinate_calculation::euclidean_distance(location, lower_left))); min_max_dist = std::min( min_max_dist, - std::max(coordinate_calculation::approx_euclidean_distance(location, lower_left), - coordinate_calculation::approx_euclidean_distance(location, upper_left))); + std::max(coordinate_calculation::euclidean_distance(location, lower_left), + coordinate_calculation::euclidean_distance(location, upper_left))); return min_max_dist; } diff --git a/data_structures/static_rtree.hpp b/data_structures/static_rtree.hpp index 16d7ced99..8ab7fe4c1 100644 --- a/data_structures/static_rtree.hpp +++ b/data_structures/static_rtree.hpp @@ -177,28 +177,28 @@ class StaticRTree switch (d) { case NORTH: - min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, location.lon)); + min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(max_lat, location.lon)); break; case SOUTH: - min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, location.lon)); + min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(min_lat, location.lon)); break; case WEST: - min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(location.lat, min_lon)); + min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(location.lat, min_lon)); break; case EAST: - min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(location.lat, max_lon)); + min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(location.lat, max_lon)); break; case NORTH_EAST: - min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, max_lon)); + min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(max_lat, max_lon)); break; case NORTH_WEST: - min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, min_lon)); + min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(max_lat, min_lon)); break; case SOUTH_EAST: - min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, max_lon)); + min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(min_lat, max_lon)); break; case SOUTH_WEST: - min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, min_lon)); + min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(min_lat, min_lon)); break; default: break; @@ -221,24 +221,24 @@ class StaticRTree min_max_dist = std::min( min_max_dist, std::max( - coordinate_calculation::approx_euclidean_distance(location, upper_left), - coordinate_calculation::approx_euclidean_distance(location, upper_right))); + coordinate_calculation::euclidean_distance(location, upper_left), + coordinate_calculation::euclidean_distance(location, upper_right))); min_max_dist = std::min( min_max_dist, std::max( - coordinate_calculation::approx_euclidean_distance(location, upper_right), - coordinate_calculation::approx_euclidean_distance(location, lower_right))); + coordinate_calculation::euclidean_distance(location, upper_right), + coordinate_calculation::euclidean_distance(location, lower_right))); min_max_dist = std::min( min_max_dist, - std::max(coordinate_calculation::approx_euclidean_distance(location, lower_right), - coordinate_calculation::approx_euclidean_distance(location, lower_left))); + std::max(coordinate_calculation::euclidean_distance(location, lower_right), + coordinate_calculation::euclidean_distance(location, lower_left))); min_max_dist = std::min( min_max_dist, - std::max(coordinate_calculation::approx_euclidean_distance(location, lower_left), - coordinate_calculation::approx_euclidean_distance(location, upper_left))); + std::max(coordinate_calculation::euclidean_distance(location, lower_left), + coordinate_calculation::euclidean_distance(location, upper_left))); return min_max_dist; } @@ -607,7 +607,7 @@ class StaticRTree } float current_minimum_distance = - coordinate_calculation::approx_euclidean_distance( + coordinate_calculation::euclidean_distance( input_coordinate.lat, input_coordinate.lon, m_coordinate_list->at(current_edge.u).lat, @@ -620,7 +620,7 @@ class StaticRTree } current_minimum_distance = - coordinate_calculation::approx_euclidean_distance( + coordinate_calculation::euclidean_distance( input_coordinate.lat, input_coordinate.lon, m_coordinate_list->at(current_edge.v).lat, @@ -1060,9 +1060,9 @@ class StaticRTree inline void SetForwardAndReverseWeightsOnPhantomNode(const EdgeDataT & nearest_edge, PhantomNode &result_phantom_node) const { - const float distance_1 = coordinate_calculation::approx_euclidean_distance( + const float distance_1 = coordinate_calculation::euclidean_distance( m_coordinate_list->at(nearest_edge.u), result_phantom_node.location); - const float distance_2 = coordinate_calculation::approx_euclidean_distance( + const float distance_2 = coordinate_calculation::euclidean_distance( m_coordinate_list->at(nearest_edge.u), m_coordinate_list->at(nearest_edge.v)); const float ratio = std::min(1.f, distance_1 / distance_2); diff --git a/descriptors/description_factory.cpp b/descriptors/description_factory.cpp index 7002f8ebb..0977d611d 100644 --- a/descriptors/description_factory.cpp +++ b/descriptors/description_factory.cpp @@ -135,7 +135,7 @@ void DescriptionFactory::Run(const unsigned zoom_level) { // move down names by one, q&d hack path_description[i - 1].name_id = path_description[i].name_id; - path_description[i].length = coordinate_calculation::approx_euclidean_distance( + path_description[i].length = coordinate_calculation::euclidean_distance( path_description[i - 1].location, path_description[i].location); } diff --git a/extractor/extraction_containers.cpp b/extractor/extraction_containers.cpp index 4675db2d2..387f01d97 100644 --- a/extractor/extraction_containers.cpp +++ b/extractor/extraction_containers.cpp @@ -321,7 +321,7 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, edge_iterator->target_coordinate.lat = node_iterator->lat; edge_iterator->target_coordinate.lon = node_iterator->lon; - const double distance = coordinate_calculation::approx_euclidean_distance( + const double distance = coordinate_calculation::euclidean_distance( edge_iterator->source_coordinate.lat, edge_iterator->source_coordinate.lon, node_iterator->lat, node_iterator->lon); diff --git a/tools/components.cpp b/tools/components.cpp index f5fe73547..f7308d724 100644 --- a/tools/components.cpp +++ b/tools/components.cpp @@ -244,7 +244,7 @@ int main(int argc, char *argv[]) if (source < target || graph->EndEdges(target) == graph->FindEdge(target, source)) { total_network_distance += - 100 * coordinate_calculation::approx_euclidean_distance( + 100 * coordinate_calculation::euclidean_distance( coordinate_list[source].lat, coordinate_list[source].lon, coordinate_list[target].lat, From 814d9aa01b0db96bd8ff32046e9cb422a7c7bd5a Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 16:33:27 +0100 Subject: [PATCH 089/360] reformat code source file --- data_structures/coordinate_calculation.cpp | 11 +++++---- data_structures/coordinate_calculation.hpp | 27 +++++++++++----------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/data_structures/coordinate_calculation.cpp b/data_structures/coordinate_calculation.cpp index 0f5a94976..118890ed0 100644 --- a/data_structures/coordinate_calculation.cpp +++ b/data_structures/coordinate_calculation.cpp @@ -39,6 +39,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace { constexpr static const float RAD = 0.017453292519943295769236907684886; +// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi) +// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles) constexpr static const float earth_radius = 6372797.560856f; } @@ -64,10 +66,9 @@ double coordinate_calculation::great_circle_distance(const int lat1, const double dLong = dlong1 - dlong2; const double dLat = dlat1 - dlat2; - const double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2); + const double aHarv = + pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2); const double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv)); - // earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi) - // The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles) return earth_radius * cHarv; } @@ -75,14 +76,14 @@ double coordinate_calculation::great_circle_distance(const FixedPointCoordinate const FixedPointCoordinate &coordinate_2) { return great_circle_distance(coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, - coordinate_2.lon); + coordinate_2.lon); } float coordinate_calculation::euclidean_distance(const FixedPointCoordinate &coordinate_1, const FixedPointCoordinate &coordinate_2) { return euclidean_distance(coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, - coordinate_2.lon); + coordinate_2.lon); } float coordinate_calculation::euclidean_distance(const int lat1, diff --git a/data_structures/coordinate_calculation.hpp b/data_structures/coordinate_calculation.hpp index 201c1ce04..1bae6cf03 100644 --- a/data_structures/coordinate_calculation.hpp +++ b/data_structures/coordinate_calculation.hpp @@ -43,10 +43,9 @@ struct coordinate_calculation const FixedPointCoordinate &second_coordinate); static float euclidean_distance(const FixedPointCoordinate &first_coordinate, - const FixedPointCoordinate &second_coordinate); + const FixedPointCoordinate &second_coordinate); - static float - euclidean_distance(const int lat1, const int lon1, const int lat2, const int lon2); + static float euclidean_distance(const int lat1, const int lon1, const int lat2, const int lon2); static void lat_or_lon_to_string(const int value, std::string &output); @@ -67,18 +66,18 @@ struct coordinate_calculation float &ratio); static float perpendicular_distance_from_projected_coordinate( - const FixedPointCoordinate &segment_source, - const FixedPointCoordinate &segment_target, - const FixedPointCoordinate &query_location, - const std::pair &projected_coordinate); + const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target, + const FixedPointCoordinate &query_location, + const std::pair &projected_coordinate); static float perpendicular_distance_from_projected_coordinate( - const FixedPointCoordinate &segment_source, - const FixedPointCoordinate &segment_target, - const FixedPointCoordinate &query_location, - const std::pair &projected_coordinate, - FixedPointCoordinate &nearest_location, - float &ratio); + const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target, + const FixedPointCoordinate &query_location, + const std::pair &projected_coordinate, + FixedPointCoordinate &nearest_location, + float &ratio); static float GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B); @@ -86,4 +85,4 @@ struct coordinate_calculation static float rad_to_deg(const float radian); }; -#endif //COORDINATE_CALCULATION +#endif // COORDINATE_CALCULATION From 0ea7fd9c3d51846aae3006526fed2f2e47916978 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 16:40:29 +0100 Subject: [PATCH 090/360] remove more dead/unused functions --- data_structures/coordinate_calculation.cpp | 47 ---------------------- data_structures/coordinate_calculation.hpp | 8 ---- 2 files changed, 55 deletions(-) diff --git a/data_structures/coordinate_calculation.cpp b/data_structures/coordinate_calculation.cpp index 118890ed0..27a054ded 100644 --- a/data_structures/coordinate_calculation.cpp +++ b/data_structures/coordinate_calculation.cpp @@ -230,53 +230,6 @@ void coordinate_calculation::lat_or_lon_to_string(const int value, std::string & output = printInt<11, 6>(buffer, value); } -void coordinate_calculation::convertInternalCoordinateToString(const FixedPointCoordinate &coord, - std::string &output) -{ - std::string tmp; - tmp.reserve(23); - lat_or_lon_to_string(coord.lon, tmp); - output = tmp; - output += ","; - lat_or_lon_to_string(coord.lat, tmp); - output += tmp; -} - -void coordinate_calculation::convertInternalReversedCoordinateToString( - const FixedPointCoordinate &coord, std::string &output) -{ - std::string tmp; - tmp.reserve(23); - lat_or_lon_to_string(coord.lat, tmp); - output = tmp; - output += ","; - lat_or_lon_to_string(coord.lon, tmp); - output += tmp; -} - -float coordinate_calculation::GetBearing(const FixedPointCoordinate &first_coordinate, - const FixedPointCoordinate &second_coordinate) -{ - const float lon_diff = - second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION; - const float lon_delta = deg_to_rad(lon_diff); - const float lat1 = deg_to_rad(first_coordinate.lat / COORDINATE_PRECISION); - const float lat2 = deg_to_rad(second_coordinate.lat / COORDINATE_PRECISION); - const float y = sin(lon_delta) * cos(lat2); - const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon_delta); - float result = rad_to_deg(std::atan2(y, x)); - while (result < 0.f) - { - result += 360.f; - } - - while (result >= 360.f) - { - result -= 360.f; - } - return result; -} - float coordinate_calculation::deg_to_rad(const float degree) { return degree * (static_cast(M_PI) / 180.f); diff --git a/data_structures/coordinate_calculation.hpp b/data_structures/coordinate_calculation.hpp index 1bae6cf03..adf076a66 100644 --- a/data_structures/coordinate_calculation.hpp +++ b/data_structures/coordinate_calculation.hpp @@ -49,12 +49,6 @@ struct coordinate_calculation static void lat_or_lon_to_string(const int value, std::string &output); - static void convertInternalCoordinateToString(const FixedPointCoordinate &coordinate, - std::string &output); - - static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coordinate, - std::string &output); - static float perpendicular_distance(const FixedPointCoordinate &segment_source, const FixedPointCoordinate &segment_target, const FixedPointCoordinate &query_location); @@ -79,8 +73,6 @@ struct coordinate_calculation FixedPointCoordinate &nearest_location, float &ratio); - static float GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B); - static float deg_to_rad(const float degree); static float rad_to_deg(const float radian); }; From 2e5cc1e6aec0025065506416bf508a5da144cac2 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 16:48:53 +0100 Subject: [PATCH 091/360] remove redundant code and streamline coordinate interface --- Include/osrm/coordinate.hpp | 21 +++++++++------- data_structures/coordinate.cpp | 28 ++++------------------ data_structures/coordinate_calculation.cpp | 23 ++++++++++++++++++ data_structures/coordinate_calculation.hpp | 3 +++ descriptors/description_factory.cpp | 2 +- 5 files changed, 44 insertions(+), 33 deletions(-) diff --git a/Include/osrm/coordinate.hpp b/Include/osrm/coordinate.hpp index b6903930e..7a74498fc 100644 --- a/Include/osrm/coordinate.hpp +++ b/Include/osrm/coordinate.hpp @@ -45,25 +45,28 @@ struct FixedPointCoordinate FixedPointCoordinate(); FixedPointCoordinate(int lat, int lon); - template - FixedPointCoordinate(const T &coordinate) : lat(coordinate.lat), lon(coordinate.lon) + template + FixedPointCoordinate(const T &coordinate) + : lat(coordinate.lat), lon(coordinate.lon) { - static_assert(std::is_same::value, "coordinate types incompatible"); - static_assert(std::is_same::value, "coordinate types incompatible"); + static_assert(std::is_same::value, + "coordinate types incompatible"); + static_assert(std::is_same::value, + "coordinate types incompatible"); } - void Reset(); - bool isSet() const; + void reset(); + bool is_set() const; bool is_valid() const; bool operator==(const FixedPointCoordinate &other) const; - float GetBearing(const FixedPointCoordinate &other) const; - void Output(std::ostream &out) const; + float bearing(const FixedPointCoordinate &other) const; + void output(std::ostream &out) const; }; inline std::ostream &operator<<(std::ostream &out_stream, FixedPointCoordinate const &coordinate) { - coordinate.Output(out_stream); + coordinate.output(out_stream); return out_stream; } diff --git a/data_structures/coordinate.cpp b/data_structures/coordinate.cpp index de0b696f0..00cacfeef 100644 --- a/data_structures/coordinate.cpp +++ b/data_structures/coordinate.cpp @@ -63,12 +63,12 @@ FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon #endif } -void FixedPointCoordinate::Reset() +void FixedPointCoordinate::reset() { lat = std::numeric_limits::min(); lon = std::numeric_limits::min(); } -bool FixedPointCoordinate::isSet() const +bool FixedPointCoordinate::is_set() const { return (std::numeric_limits::min() != lat) && (std::numeric_limits::min() != lon); } @@ -86,30 +86,12 @@ bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const return lat == other.lat && lon == other.lon; } -void FixedPointCoordinate::Output(std::ostream &out) const +void FixedPointCoordinate::output(std::ostream &out) const { out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")"; } -float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const +float FixedPointCoordinate::bearing(const FixedPointCoordinate &other) const { - const float lon_delta = coordinate_calculation::deg_to_rad(lon / COORDINATE_PRECISION - - other.lon / COORDINATE_PRECISION); - const float lat1 = coordinate_calculation::deg_to_rad(other.lat / COORDINATE_PRECISION); - const float lat2 = coordinate_calculation::deg_to_rad(lat / COORDINATE_PRECISION); - const float y_value = std::sin(lon_delta) * std::cos(lat2); - const float x_value = - std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta); - float result = coordinate_calculation::rad_to_deg(std::atan2(y_value, x_value)); - - while (result < 0.f) - { - result += 360.f; - } - - while (result >= 360.f) - { - result -= 360.f; - } - return result; + return coordinate_calculation::bearing(*this, other); } diff --git a/data_structures/coordinate_calculation.cpp b/data_structures/coordinate_calculation.cpp index 27a054ded..1b8dd618e 100644 --- a/data_structures/coordinate_calculation.cpp +++ b/data_structures/coordinate_calculation.cpp @@ -239,3 +239,26 @@ float coordinate_calculation::rad_to_deg(const float radian) { return radian * (180.f * static_cast(M_1_PI)); } + +float coordinate_calculation::bearing(const FixedPointCoordinate &first_coordinate, + const FixedPointCoordinate &second_coordinate) +{ + const float lon_diff = + second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION; + const float lon_delta = deg_to_rad(lon_diff); + const float lat1 = deg_to_rad(first_coordinate.lat / COORDINATE_PRECISION); + const float lat2 = deg_to_rad(second_coordinate.lat / COORDINATE_PRECISION); + const float y = sin(lon_delta) * cos(lat2); + const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon_delta); + float result = rad_to_deg(std::atan2(y, x)); + while (result < 0.f) + { + result += 360.f; + } + + while (result >= 360.f) + { + result -= 360.f; + } + return result; +} diff --git a/data_structures/coordinate_calculation.hpp b/data_structures/coordinate_calculation.hpp index adf076a66..359fdb585 100644 --- a/data_structures/coordinate_calculation.hpp +++ b/data_structures/coordinate_calculation.hpp @@ -75,6 +75,9 @@ struct coordinate_calculation static float deg_to_rad(const float degree); static float rad_to_deg(const float radian); + + static float bearing(const FixedPointCoordinate &first_coordinate, + const FixedPointCoordinate &second_coordinate); }; #endif // COORDINATE_CALCULATION diff --git a/descriptors/description_factory.cpp b/descriptors/description_factory.cpp index 0977d611d..18bd44328 100644 --- a/descriptors/description_factory.cpp +++ b/descriptors/description_factory.cpp @@ -237,7 +237,7 @@ void DescriptionFactory::Run(const unsigned zoom_level) via_indices.push_back(necessary_pieces); } const double angle = - path_description[i + 1].location.GetBearing(path_description[i].location); + path_description[i + 1].location.bearing(path_description[i].location); path_description[i].bearing = static_cast(angle * 10); } } From 90f17c21404e6bfd527c9fd8bc1b931c962e6c56 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 16:55:34 +0100 Subject: [PATCH 092/360] remove is_set() and reset() functions from coordinate --- Include/osrm/coordinate.hpp | 2 -- data_structures/coordinate.cpp | 9 --------- 2 files changed, 11 deletions(-) diff --git a/Include/osrm/coordinate.hpp b/Include/osrm/coordinate.hpp index 7a74498fc..546515d49 100644 --- a/Include/osrm/coordinate.hpp +++ b/Include/osrm/coordinate.hpp @@ -55,8 +55,6 @@ struct FixedPointCoordinate "coordinate types incompatible"); } - void reset(); - bool is_set() const; bool is_valid() const; bool operator==(const FixedPointCoordinate &other) const; diff --git a/data_structures/coordinate.cpp b/data_structures/coordinate.cpp index 00cacfeef..b7057d674 100644 --- a/data_structures/coordinate.cpp +++ b/data_structures/coordinate.cpp @@ -63,15 +63,6 @@ FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon #endif } -void FixedPointCoordinate::reset() -{ - lat = std::numeric_limits::min(); - lon = std::numeric_limits::min(); -} -bool FixedPointCoordinate::is_set() const -{ - return (std::numeric_limits::min() != lat) && (std::numeric_limits::min() != lon); -} bool FixedPointCoordinate::is_valid() const { if (lat > 90 * COORDINATE_PRECISION || lat < -90 * COORDINATE_PRECISION || From e80ca6553db16c1f64d44e2bfee898806aaa8588 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 16:58:45 +0100 Subject: [PATCH 093/360] use new coordinate interface in unit tests --- unit_tests/data_structures/coordinate.cpp | 4 +-- unit_tests/data_structures/static_rtree.cpp | 30 ++++++++++----------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/unit_tests/data_structures/coordinate.cpp b/unit_tests/data_structures/coordinate.cpp index c3c8b2a8e..6569e2f4b 100644 --- a/unit_tests/data_structures/coordinate.cpp +++ b/unit_tests/data_structures/coordinate.cpp @@ -40,12 +40,12 @@ BOOST_AUTO_TEST_CASE(regression_test_1347) FixedPointCoordinate v(10.001 * COORDINATE_PRECISION, -100.002 * COORDINATE_PRECISION); FixedPointCoordinate q(10.002 * COORDINATE_PRECISION, -100.001 * COORDINATE_PRECISION); - float d1 = coordinate_calculation::ComputePerpendicularDistance(u, v, q); + float d1 = coordinate_calculation::perpendicular_distance(u, v, q); float ratio; FixedPointCoordinate nearest_location; float d2 = - coordinate_calculation::ComputePerpendicularDistance(u, v, q, nearest_location, ratio); + coordinate_calculation::perpendicular_distance(u, v, q, nearest_location, ratio); BOOST_CHECK_LE(std::abs(d1 - d2), 0.01f); } diff --git a/unit_tests/data_structures/static_rtree.cpp b/unit_tests/data_structures/static_rtree.cpp index 6202ecfa9..a4c21606c 100644 --- a/unit_tests/data_structures/static_rtree.cpp +++ b/unit_tests/data_structures/static_rtree.cpp @@ -78,7 +78,7 @@ class LinearSearchNN { const FixedPointCoordinate &start = coords->at(e.u); const FixedPointCoordinate &end = coords->at(e.v); - float distance = coordinate_calculation::approx_euclidean_distance( + float distance = coordinate_calculation::euclidean_distance( input_coordinate.lat, input_coordinate.lon, start.lat, start.lon); if (distance < min_dist) { @@ -86,7 +86,7 @@ class LinearSearchNN min_dist = distance; } - distance = coordinate_calculation::approx_euclidean_distance( + distance = coordinate_calculation::euclidean_distance( input_coordinate.lat, input_coordinate.lon, end.lat, end.lon); if (distance < min_dist) { @@ -113,7 +113,7 @@ class LinearSearchNN float current_ratio = 0.; FixedPointCoordinate nearest; const float current_perpendicular_distance = - coordinate_calculation::ComputePerpendicularDistance( + coordinate_calculation::perpendicular_distance( coords->at(e.u), coords->at(e.v), input_coordinate, nearest, current_ratio); if ((current_perpendicular_distance < min_dist) && @@ -149,9 +149,9 @@ class LinearSearchNN result_phantom_node.location.lat = input_coordinate.lat; } - const float distance_1 = coordinate_calculation::approx_euclidean_distance( + const float distance_1 = coordinate_calculation::euclidean_distance( coords->at(nearest_edge.u), result_phantom_node.location); - const float distance_2 = coordinate_calculation::approx_euclidean_distance( + const float distance_2 = coordinate_calculation::euclidean_distance( coords->at(nearest_edge.u), coords->at(nearest_edge.v)); const float ratio = std::min(1.f, distance_1 / distance_2); @@ -286,10 +286,10 @@ void simple_verify_rtree(RTreeT &rtree, bool found_u = rtree.LocateClosestEndPointForCoordinate(pu, result_u, 1); bool found_v = rtree.LocateClosestEndPointForCoordinate(pv, result_v, 1); BOOST_CHECK(found_u && found_v); - float dist_u = coordinate_calculation::approx_euclidean_distance( + float dist_u = coordinate_calculation::euclidean_distance( result_u.lat, result_u.lon, pu.lat, pu.lon); BOOST_CHECK_LE(dist_u, std::numeric_limits::epsilon()); - float dist_v = coordinate_calculation::approx_euclidean_distance( + float dist_v = coordinate_calculation::euclidean_distance( result_v.lat, result_v.lon, pv.lat, pv.lon); BOOST_CHECK_LE(dist_v, std::numeric_limits::epsilon()); } @@ -450,30 +450,30 @@ void TestRectangle(double width, double height, double center_lat, double center /* Distance to line segments of rectangle */ BOOST_CHECK_EQUAL(rect.GetMinDist(north), - coordinate_calculation::approx_euclidean_distance( + coordinate_calculation::euclidean_distance( north, FixedPointCoordinate(rect.max_lat, north.lon))); BOOST_CHECK_EQUAL(rect.GetMinDist(south), - coordinate_calculation::approx_euclidean_distance( + coordinate_calculation::euclidean_distance( south, FixedPointCoordinate(rect.min_lat, south.lon))); BOOST_CHECK_EQUAL(rect.GetMinDist(west), - coordinate_calculation::approx_euclidean_distance( + coordinate_calculation::euclidean_distance( west, FixedPointCoordinate(west.lat, rect.min_lon))); BOOST_CHECK_EQUAL(rect.GetMinDist(east), - coordinate_calculation::approx_euclidean_distance( + coordinate_calculation::euclidean_distance( east, FixedPointCoordinate(east.lat, rect.max_lon))); /* Distance to corner points */ BOOST_CHECK_EQUAL(rect.GetMinDist(north_east), - coordinate_calculation::approx_euclidean_distance( + coordinate_calculation::euclidean_distance( north_east, FixedPointCoordinate(rect.max_lat, rect.max_lon))); BOOST_CHECK_EQUAL(rect.GetMinDist(north_west), - coordinate_calculation::approx_euclidean_distance( + coordinate_calculation::euclidean_distance( north_west, FixedPointCoordinate(rect.max_lat, rect.min_lon))); BOOST_CHECK_EQUAL(rect.GetMinDist(south_east), - coordinate_calculation::approx_euclidean_distance( + coordinate_calculation::euclidean_distance( south_east, FixedPointCoordinate(rect.min_lat, rect.max_lon))); BOOST_CHECK_EQUAL(rect.GetMinDist(south_west), - coordinate_calculation::approx_euclidean_distance( + coordinate_calculation::euclidean_distance( south_west, FixedPointCoordinate(rect.min_lat, rect.min_lon))); } From bcd73e604c21d3a52df7a202ce3eb5067371f4a8 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 17:00:48 +0100 Subject: [PATCH 094/360] reformat coordinate and rtree test code --- unit_tests/data_structures/coordinate.cpp | 3 +- unit_tests/data_structures/static_rtree.cpp | 49 +++++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/unit_tests/data_structures/coordinate.cpp b/unit_tests/data_structures/coordinate.cpp index 6569e2f4b..b371368be 100644 --- a/unit_tests/data_structures/coordinate.cpp +++ b/unit_tests/data_structures/coordinate.cpp @@ -44,8 +44,7 @@ BOOST_AUTO_TEST_CASE(regression_test_1347) float ratio; FixedPointCoordinate nearest_location; - float d2 = - coordinate_calculation::perpendicular_distance(u, v, q, nearest_location, ratio); + float d2 = coordinate_calculation::perpendicular_distance(u, v, q, nearest_location, ratio); BOOST_CHECK_LE(std::abs(d1 - d2), 0.01f); } diff --git a/unit_tests/data_structures/static_rtree.cpp b/unit_tests/data_structures/static_rtree.cpp index a4c21606c..1e2676b4e 100644 --- a/unit_tests/data_structures/static_rtree.cpp +++ b/unit_tests/data_structures/static_rtree.cpp @@ -260,17 +260,17 @@ struct GraphFixture }; typedef RandomGraphFixture -TestRandomGraphFixture_LeafHalfFull; + TestRandomGraphFixture_LeafHalfFull; typedef RandomGraphFixture -TestRandomGraphFixture_LeafFull; + TestRandomGraphFixture_LeafFull; typedef RandomGraphFixture -TestRandomGraphFixture_TwoLeaves; + TestRandomGraphFixture_TwoLeaves; typedef RandomGraphFixture -TestRandomGraphFixture_Branch; + TestRandomGraphFixture_Branch; typedef RandomGraphFixture -TestRandomGraphFixture_MultipleLevels; + TestRandomGraphFixture_MultipleLevels; template void simple_verify_rtree(RTreeT &rtree, @@ -286,11 +286,11 @@ void simple_verify_rtree(RTreeT &rtree, bool found_u = rtree.LocateClosestEndPointForCoordinate(pu, result_u, 1); bool found_v = rtree.LocateClosestEndPointForCoordinate(pv, result_v, 1); BOOST_CHECK(found_u && found_v); - float dist_u = coordinate_calculation::euclidean_distance( - result_u.lat, result_u.lon, pu.lat, pu.lon); + float dist_u = + coordinate_calculation::euclidean_distance(result_u.lat, result_u.lon, pu.lat, pu.lon); BOOST_CHECK_LE(dist_u, std::numeric_limits::epsilon()); - float dist_v = coordinate_calculation::euclidean_distance( - result_v.lat, result_v.lon, pv.lat, pv.lon); + float dist_v = + coordinate_calculation::euclidean_distance(result_v.lat, result_v.lon, pv.lat, pv.lon); BOOST_CHECK_LE(dist_v, std::numeric_limits::epsilon()); } } @@ -389,30 +389,31 @@ BOOST_AUTO_TEST_CASE(regression_test) { typedef std::pair Coord; typedef std::pair Edge; - GraphFixture fixture({ - Coord(40.0, 0.0), - Coord(35.0, 5.0), + GraphFixture fixture( + { + Coord(40.0, 0.0), + Coord(35.0, 5.0), - Coord(5.0, 5.0), - Coord(0.0, 10.0), + Coord(5.0, 5.0), + Coord(0.0, 10.0), - Coord(20.0, 10.0), - Coord(20.0, 5.0), + Coord(20.0, 10.0), + Coord(20.0, 5.0), - Coord(40.0, 100.0), - Coord(35.0, 105.0), + Coord(40.0, 100.0), + Coord(35.0, 105.0), - Coord(5.0, 105.0), - Coord(0.0, 110.0), - }, - {Edge(0, 1), Edge(2, 3), Edge(4, 5), Edge(6, 7), Edge(8, 9)}); + Coord(5.0, 105.0), + Coord(0.0, 110.0), + }, + {Edge(0, 1), Edge(2, 3), Edge(4, 5), Edge(6, 7), Edge(8, 9)}); typedef StaticRTree, false, 2, 3> MiniStaticRTree; std::string leaves_path; std::string nodes_path; - build_rtree( - "test_regression", &fixture, leaves_path, nodes_path); + build_rtree("test_regression", &fixture, leaves_path, + nodes_path); MiniStaticRTree rtree(nodes_path, leaves_path, fixture.coords); // query a node just right of the center of the gap From 29354a1586013d5be341aaf4d89635b87298c853 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 17:07:04 +0100 Subject: [PATCH 095/360] fix bearing computation --- data_structures/coordinate.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/data_structures/coordinate.cpp b/data_structures/coordinate.cpp index b7057d674..7bed19751 100644 --- a/data_structures/coordinate.cpp +++ b/data_structures/coordinate.cpp @@ -28,8 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "coordinate_calculation.hpp" #include "../Util/mercator.hpp" +#ifndef NDEBUG #include "../Util/simple_logger.hpp" - +#endif #include #include @@ -84,5 +85,5 @@ void FixedPointCoordinate::output(std::ostream &out) const float FixedPointCoordinate::bearing(const FixedPointCoordinate &other) const { - return coordinate_calculation::bearing(*this, other); + return coordinate_calculation::bearing(other, *this); } From 796cbafde49bcdad1185eaff9b8bd7c7def47dcf Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 22 Jan 2015 17:57:38 +0100 Subject: [PATCH 096/360] add missing include in release build --- data_structures/coordinate.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/data_structures/coordinate.cpp b/data_structures/coordinate.cpp index 7bed19751..992c63df9 100644 --- a/data_structures/coordinate.cpp +++ b/data_structures/coordinate.cpp @@ -39,6 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef NDEBUG #include #endif +#include #include FixedPointCoordinate::FixedPointCoordinate() From 8e105af2324dcd59b9967d145e5048d09c763e1d Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 09:25:05 +0100 Subject: [PATCH 097/360] remove redundant code from switch statement in restriction parser --- extractor/restriction_parser.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/extractor/restriction_parser.cpp b/extractor/restriction_parser.cpp index 4038adaa1..3cd53ffff 100644 --- a/extractor/restriction_parser.cpp +++ b/extractor/restriction_parser.cpp @@ -192,10 +192,9 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const break; case osmium::item_type::relation: // not yet supported, but who knows what the future holds... - continue; break; default: - BOOST_ASSERT(false); + // shouldn't ever happen break; } } From bd1928e4451d2b5aa0a5dbf80f966dff2b5a9f48 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 09:47:44 +0100 Subject: [PATCH 098/360] rename short variable names to be more telling --- Util/compute_angle.cpp | 18 +++++++++--------- Util/compute_angle.hpp | 13 +++++++------ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Util/compute_angle.cpp b/Util/compute_angle.cpp index 5de872319..445b67f12 100644 --- a/Util/compute_angle.cpp +++ b/Util/compute_angle.cpp @@ -34,16 +34,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -double ComputeAngle::OfThreeFixedPointCoordinates(const FixedPointCoordinate &A, - const FixedPointCoordinate &C, - const FixedPointCoordinate &B) +double ComputeAngle::OfThreeFixedPointCoordinates(const FixedPointCoordinate &first, + const FixedPointCoordinate &second, + const FixedPointCoordinate &third) { - const double v1x = (A.lon - C.lon) / COORDINATE_PRECISION; - const double v1y = mercator::lat2y(A.lat / COORDINATE_PRECISION) - - mercator::lat2y(C.lat / COORDINATE_PRECISION); - const double v2x = (B.lon - C.lon) / COORDINATE_PRECISION; - const double v2y = mercator::lat2y(B.lat / COORDINATE_PRECISION) - - mercator::lat2y(C.lat / COORDINATE_PRECISION); + const double v1x = (first.lon - second.lon) / COORDINATE_PRECISION; + const double v1y = mercator::lat2y(first.lat / COORDINATE_PRECISION) - + mercator::lat2y(second.lat / COORDINATE_PRECISION); + const double v2x = (third.lon - second.lon) / COORDINATE_PRECISION; + const double v2y = mercator::lat2y(third.lat / COORDINATE_PRECISION) - + mercator::lat2y(second.lat / COORDINATE_PRECISION); double angle = (atan2_lookup(v2y, v2x) - atan2_lookup(v1y, v1x)) * 180. / M_PI; while (angle < 0.) diff --git a/Util/compute_angle.hpp b/Util/compute_angle.hpp index 72c861a45..73682bceb 100644 --- a/Util/compute_angle.hpp +++ b/Util/compute_angle.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -29,13 +29,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define COMPUTE_ANGLE_HPP struct FixedPointCoordinate; -struct NodeInfo; struct ComputeAngle { - /* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/ - static double OfThreeFixedPointCoordinates(const FixedPointCoordinate &A, - const FixedPointCoordinate &C, - const FixedPointCoordinate &B); + // Get angle of line segment (A,C)->(C,B) + // atan2 magic, formerly cosine theorem + static double OfThreeFixedPointCoordinates(const FixedPointCoordinate &first, + const FixedPointCoordinate &second, + const FixedPointCoordinate &third); }; + #endif // COMPUTE_ANGLE_HPP From 0e7eff396322579b76a4e36fff4ecde84d4b1802 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 11:04:21 +0100 Subject: [PATCH 099/360] rename short variable names in mercator to be more telling --- Util/mercator.cpp | 8 +-- Util/mercator.hpp | 4 +- contractor/edge_based_graph_factory.cpp | 73 +++++++++++++------------ 3 files changed, 44 insertions(+), 41 deletions(-) diff --git a/Util/mercator.cpp b/Util/mercator.cpp index 707fd5535..ddd80685d 100644 --- a/Util/mercator.cpp +++ b/Util/mercator.cpp @@ -29,12 +29,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -double mercator::y2lat(const double a) +double mercator::y2lat(const double value) { - return 180. * M_1_PI * (2. * std::atan(std::exp(a * M_PI / 180.)) - M_PI_2); + return 180. * M_1_PI * (2. * std::atan(std::exp(value * M_PI / 180.)) - M_PI_2); } -double mercator::lat2y(const double a) +double mercator::lat2y(const double latitude) { - return 180. * M_1_PI * std::log(std::tan(M_PI_4 + a * (M_PI / 180.) / 2.)); + return 180. * M_1_PI * std::log(std::tan(M_PI_4 + latitude * (M_PI / 180.) / 2.)); } diff --git a/Util/mercator.hpp b/Util/mercator.hpp index 0ea22d034..2929db2f9 100644 --- a/Util/mercator.hpp +++ b/Util/mercator.hpp @@ -30,9 +30,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct mercator { - static double y2lat(const double a); + static double y2lat(const double value); - static double lat2y(const double a); + static double lat2y(const double latitude); }; #endif // MERCATOR_HPP diff --git a/contractor/edge_based_graph_factory.cpp b/contractor/edge_based_graph_factory.cpp index 6d9c43412..692bf2aa2 100644 --- a/contractor/edge_based_graph_factory.cpp +++ b/contractor/edge_based_graph_factory.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -86,23 +86,23 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, BOOST_ASSERT(node_v != SPECIAL_NODEID); // find forward edge id and - const EdgeID e1 = m_node_based_graph->FindEdge(node_u, node_v); - BOOST_ASSERT(e1 != SPECIAL_EDGEID); + const EdgeID edge_id_1 = m_node_based_graph->FindEdge(node_u, node_v); + BOOST_ASSERT(edge_id_1 != SPECIAL_EDGEID); - const EdgeData &forward_data = m_node_based_graph->GetEdgeData(e1); + const EdgeData &forward_data = m_node_based_graph->GetEdgeData(edge_id_1); // find reverse edge id and - const EdgeID e2 = m_node_based_graph->FindEdge(node_v, node_u); + const EdgeID edge_id_2 = m_node_based_graph->FindEdge(node_v, node_u); #ifndef NDEBUG - if (e2 == m_node_based_graph->EndEdges(node_v)) + if (edge_id_2 == m_node_based_graph->EndEdges(node_v)) { SimpleLogger().Write(logWARNING) << "Did not find edge (" << node_v << "," << node_u << ")"; } #endif - BOOST_ASSERT(e2 != SPECIAL_EDGEID); - BOOST_ASSERT(e2 < m_node_based_graph->EndEdges(node_v)); - const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(e2); + BOOST_ASSERT(edge_id_2 != SPECIAL_EDGEID); + BOOST_ASSERT(edge_id_2 < m_node_based_graph->EndEdges(node_v)); + const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(edge_id_2); if (forward_data.edgeBasedNodeID == SPECIAL_NODEID && reverse_data.edgeBasedNodeID == SPECIAL_NODEID) @@ -110,17 +110,17 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, return; } - BOOST_ASSERT(m_geometry_compressor.HasEntryForID(e1) == - m_geometry_compressor.HasEntryForID(e2)); - if (m_geometry_compressor.HasEntryForID(e1)) + BOOST_ASSERT(m_geometry_compressor.HasEntryForID(edge_id_1) == + m_geometry_compressor.HasEntryForID(edge_id_2)); + if (m_geometry_compressor.HasEntryForID(edge_id_1)) { - BOOST_ASSERT(m_geometry_compressor.HasEntryForID(e2)); + BOOST_ASSERT(m_geometry_compressor.HasEntryForID(edge_id_2)); // reconstruct geometry and put in each individual edge with its offset const std::vector &forward_geometry = - m_geometry_compressor.GetBucketReference(e1); + m_geometry_compressor.GetBucketReference(edge_id_1); const std::vector &reverse_geometry = - m_geometry_compressor.GetBucketReference(e2); + m_geometry_compressor.GetBucketReference(edge_id_2); BOOST_ASSERT(forward_geometry.size() == reverse_geometry.size()); BOOST_ASSERT(0 != forward_geometry.size()); const unsigned geometry_size = static_cast(forward_geometry.size()); @@ -176,7 +176,7 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, current_edge_source_coordinate_id, current_edge_target_coordinate_id, forward_data.nameID, forward_geometry[i].second, reverse_geometry[geometry_size - 1 - i].second, forward_dist_prefix_sum[i], - reverse_dist_prefix_sum[i], m_geometry_compressor.GetPositionForID(e1), + reverse_dist_prefix_sum[i], m_geometry_compressor.GetPositionForID(edge_id_1), component_id, i, forward_data.travel_mode, reverse_data.travel_mode); current_edge_source_coordinate_id = current_edge_target_coordinate_id; @@ -194,7 +194,7 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, } else { - BOOST_ASSERT(!m_geometry_compressor.HasEntryForID(e2)); + BOOST_ASSERT(!m_geometry_compressor.HasEntryForID(edge_id_2)); if (forward_data.edgeBasedNodeID != SPECIAL_NODEID) { @@ -467,50 +467,53 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes() Percent progress(m_node_based_graph->GetNumberOfNodes()); // loop over all edges and generate new set of nodes - for (const auto u : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes())) + for (const auto node_u : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes())) { - BOOST_ASSERT(u != SPECIAL_NODEID); - BOOST_ASSERT(u < m_node_based_graph->GetNumberOfNodes()); - progress.printStatus(u); - for (EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(u)) + BOOST_ASSERT(node_u != SPECIAL_NODEID); + BOOST_ASSERT(node_u < m_node_based_graph->GetNumberOfNodes()); + progress.printStatus(node_u); + for (EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(node_u)) { const EdgeData &edge_data = m_node_based_graph->GetEdgeData(e1); BOOST_ASSERT(e1 != SPECIAL_EDGEID); - const NodeID v = m_node_based_graph->GetTarget(e1); + const NodeID node_v = m_node_based_graph->GetTarget(e1); - BOOST_ASSERT(SPECIAL_NODEID != v); + BOOST_ASSERT(SPECIAL_NODEID != node_v); // pick only every other edge - if (u > v) + if (node_u > node_v) { continue; } - BOOST_ASSERT(u < v); + BOOST_ASSERT(node_u < node_v); // Note: edges that end on barrier nodes or on a turn restriction // may actually be in two distinct components. We choose the smallest - const unsigned size_of_component = std::min(component_explorer.get_component_size(u), - component_explorer.get_component_size(v)); + const unsigned size_of_component = + std::min(component_explorer.get_component_size(node_u), + component_explorer.get_component_size(node_v)); - const unsigned id_of_smaller_component = [u, v, &component_explorer] + const unsigned id_of_smaller_component = [node_u, node_v, &component_explorer] { - if (component_explorer.get_component_size(u) < - component_explorer.get_component_size(v)) + if (component_explorer.get_component_size(node_u) < + component_explorer.get_component_size(node_v)) { - return component_explorer.get_component_id(u); + return component_explorer.get_component_id(node_u); } - return component_explorer.get_component_id(v); + return component_explorer.get_component_id(node_v); }(); const bool component_is_tiny = (size_of_component < 1000); if (edge_data.edgeBasedNodeID == SPECIAL_NODEID) { - InsertEdgeBasedNode(v, u, (component_is_tiny ? id_of_smaller_component + 1 : 0)); + InsertEdgeBasedNode(node_v, node_u, + (component_is_tiny ? id_of_smaller_component + 1 : 0)); } else { - InsertEdgeBasedNode(u, v, (component_is_tiny ? id_of_smaller_component + 1 : 0)); + InsertEdgeBasedNode(node_u, node_v, + (component_is_tiny ? id_of_smaller_component + 1 : 0)); } } } From 9135c56ac6413d53071fb733a7626f4dabe41ab1 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 11:26:47 +0100 Subject: [PATCH 100/360] fix implicit float/double conversion, use casts --- data_structures/coordinate_calculation.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/data_structures/coordinate_calculation.cpp b/data_structures/coordinate_calculation.cpp index 1b8dd618e..4ca281115 100644 --- a/data_structures/coordinate_calculation.cpp +++ b/data_structures/coordinate_calculation.cpp @@ -183,18 +183,19 @@ float coordinate_calculation::perpendicular_distance_from_projected_coordinate( } // compute ratio - ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need + ratio = + static_cast((p - nY * a) / c); // These values are actually n/m+n and m/m+n , we need // not calculate the explicit values of m an n as we // are just interested in the ratio if (std::isnan(ratio)) { ratio = (segment_target == query_location ? 1.f : 0.f); } - else if (std::abs(ratio) <= std::numeric_limits::epsilon()) + else if (std::abs(ratio) <= std::numeric_limits::epsilon()) { ratio = 0.f; } - else if (std::abs(ratio - 1.f) <= std::numeric_limits::epsilon()) + else if (std::abs(ratio - 1.f) <= std::numeric_limits::epsilon()) { ratio = 1.f; } @@ -219,7 +220,7 @@ float coordinate_calculation::perpendicular_distance_from_projected_coordinate( const float approximate_distance = coordinate_calculation::euclidean_distance(query_location, nearest_location); - BOOST_ASSERT(0. <= approximate_distance); + BOOST_ASSERT(0.f <= approximate_distance); return approximate_distance; } From d6e76fd1c0b4bea519a8732248af438dac44c520 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 11:38:47 +0100 Subject: [PATCH 101/360] add whitespace --- data_structures/coordinate.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/data_structures/coordinate.cpp b/data_structures/coordinate.cpp index 992c63df9..031fafdce 100644 --- a/data_structures/coordinate.cpp +++ b/data_structures/coordinate.cpp @@ -74,6 +74,7 @@ bool FixedPointCoordinate::is_valid() const } return true; } + bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const { return lat == other.lat && lon == other.lon; From 62f2a42f28664bd9b29fe84f0ce531cac3fd9ce3 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 11:44:35 +0100 Subject: [PATCH 102/360] reduce cyclomatic complexity in double->string bearing conversion --- Util/bearing.cpp | 42 +++++++++++++-------------- Util/bearing.hpp | 12 ++++---- descriptors/json_descriptor.hpp | 50 +++++++++++++++++---------------- 3 files changed, 53 insertions(+), 51 deletions(-) diff --git a/Util/bearing.cpp b/Util/bearing.cpp index 1cdcf3009..92c47e6b8 100644 --- a/Util/bearing.cpp +++ b/Util/bearing.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -27,37 +27,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "bearing.hpp" -std::string Bearing::Get(const double heading) +std::string bearing::get(const double heading) { + if (heading <= 22.5) + { + return "N"; + } + if (heading <= 67.5) + { + return "NE"; + } + if (heading <= 112.5) + { + return "E"; + } + if (heading <= 157.5) + { + return "SE"; + } if (heading <= 202.5) { - if (heading >= 0. && heading <= 22.5) - { - return "N"; - } - if (heading > 22.5 && heading <= 67.5) - { - return "NE"; - } - if (heading > 67.5 && heading <= 112.5) - { - return "E"; - } - if (heading > 112.5 && heading <= 157.5) - { - return "SE"; - } return "S"; } - if (heading > 202.5 && heading <= 247.5) + if (heading <= 247.5) { return "SW"; } - if (heading > 247.5 && heading <= 292.5) + if (heading <= 292.5) { return "W"; } - if (heading > 292.5 && heading <= 337.5) + if (heading <= 337.5) { return "NW"; } diff --git a/Util/bearing.hpp b/Util/bearing.hpp index a30ec2fb2..0066e9e02 100644 --- a/Util/bearing.hpp +++ b/Util/bearing.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,14 +25,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BEARING_HPP_ -#define BEARING_HPP_ +#ifndef BEARING_HPP +#define BEARING_HPP #include -struct Bearing +struct bearing { - static std::string Get(const double heading); + static std::string get(const double heading); }; -#endif // BEARING_HPP_ +#endif // BEARING_HPP diff --git a/descriptors/json_descriptor.hpp b/descriptors/json_descriptor.hpp index 74850d8f5..79d4a3d1e 100644 --- a/descriptors/json_descriptor.hpp +++ b/descriptors/json_descriptor.hpp @@ -73,7 +73,9 @@ template class JSONDescriptor final : public BaseDescriptor< ExtractRouteNames GenerateRouteNames; public: - explicit JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0) {} + explicit JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0) + { + } void SetConfig(const DescriptorConfig &c) final { config = c; } @@ -91,8 +93,8 @@ template class JSONDescriptor final : public BaseDescriptor< description_factory.AppendSegment(current_coordinate, path_data); ++added_element_count; } - description_factory.SetEndSegment( - leg_phantoms.target_phantom, target_traversed_in_reverse, is_via_leg); + description_factory.SetEndSegment(leg_phantoms.target_phantom, target_traversed_in_reverse, + is_via_leg); ++added_element_count; BOOST_ASSERT((route_leg.size() + 1) == added_element_count); return added_element_count; @@ -130,8 +132,7 @@ template class JSONDescriptor final : public BaseDescriptor< #endif DescribeLeg(raw_route.unpacked_path_segments[i], raw_route.segment_end_coordinates[i], - raw_route.target_traversed_in_reverse[i], - raw_route.is_via_leg(i)); + raw_route.target_traversed_in_reverse[i], raw_route.is_via_leg(i)); BOOST_ASSERT(0 < added_segments); } description_factory.Run(config.zoom_level); @@ -145,10 +146,8 @@ template class JSONDescriptor final : public BaseDescriptor< if (config.instructions) { JSON::Array json_route_instructions; - BuildTextualDescription(description_factory, - json_route_instructions, - raw_route.shortest_path_length, - shortest_path_segments); + BuildTextualDescription(description_factory, json_route_instructions, + raw_route.shortest_path_length, shortest_path_segments); json_result.values["route_instructions"] = json_route_instructions; } description_factory.BuildRouteSummary(description_factory.get_entire_length(), @@ -225,15 +224,15 @@ template class JSONDescriptor final : public BaseDescriptor< JSON::Array json_current_alt_instructions; if (config.instructions) { - BuildTextualDescription(alternate_description_factory, - json_current_alt_instructions, - raw_route.alternative_path_length, - alternative_path_segments); + BuildTextualDescription( + alternate_description_factory, json_current_alt_instructions, + raw_route.alternative_path_length, alternative_path_segments); json_alt_instructions.values.push_back(json_current_alt_instructions); json_result.values["alternative_instructions"] = json_alt_instructions; } alternate_description_factory.BuildRouteSummary( - alternate_description_factory.get_entire_length(), raw_route.alternative_path_length); + alternate_description_factory.get_entire_length(), + raw_route.alternative_path_length); JSON::Object json_alternate_route_summary; JSON::Array json_alternate_route_summary_array; @@ -285,10 +284,12 @@ template class JSONDescriptor final : public BaseDescriptor< std::string hint; for (const auto i : osrm::irange(0, raw_route.segment_end_coordinates.size())) { - ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint); + ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates[i].source_phantom, + hint); json_location_hint_array.values.push_back(hint); } - ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint); + ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates.back().target_phantom, + hint); json_location_hint_array.values.push_back(hint); json_hint_object.values["locations"] = json_location_hint_array; json_result.values["hint_data"] = json_hint_object; @@ -331,8 +332,8 @@ template class JSONDescriptor final : public BaseDescriptor< std::string current_turn_instruction; if (TurnInstruction::LeaveRoundAbout == current_instruction) { - temp_instruction = - cast::integral_to_string(cast::enum_to_underlying(TurnInstruction::EnterRoundAbout)); + temp_instruction = cast::integral_to_string( + cast::enum_to_underlying(TurnInstruction::EnterRoundAbout)); current_turn_instruction += temp_instruction; current_turn_instruction += "-"; temp_instruction = cast::integral_to_string(round_about.leave_at_exit + 1); @@ -341,7 +342,8 @@ template class JSONDescriptor final : public BaseDescriptor< } else { - temp_instruction = cast::integral_to_string(cast::enum_to_underlying(current_instruction)); + temp_instruction = + cast::integral_to_string(cast::enum_to_underlying(current_instruction)); current_turn_instruction += temp_instruction; } json_instruction_row.values.push_back(current_turn_instruction); @@ -354,14 +356,13 @@ template class JSONDescriptor final : public BaseDescriptor< json_instruction_row.values.push_back( cast::integral_to_string(static_cast(segment.length)) + "m"); const double bearing_value = (segment.bearing / 10.); - json_instruction_row.values.push_back(Bearing::Get(bearing_value)); + json_instruction_row.values.push_back(bearing::get(bearing_value)); json_instruction_row.values.push_back( static_cast(round(bearing_value))); json_instruction_row.values.push_back(segment.travel_mode); route_segments_list.emplace_back( - segment.name_id, - static_cast(segment.length), + segment.name_id, static_cast(segment.length), static_cast(route_segments_list.size())); json_instruction_array.values.push_back(json_instruction_row); } @@ -377,14 +378,15 @@ template class JSONDescriptor final : public BaseDescriptor< } JSON::Array json_last_instruction_row; - temp_instruction = cast::integral_to_string(cast::enum_to_underlying(TurnInstruction::ReachedYourDestination)); + temp_instruction = cast::integral_to_string( + cast::enum_to_underlying(TurnInstruction::ReachedYourDestination)); json_last_instruction_row.values.push_back(temp_instruction); json_last_instruction_row.values.push_back(""); json_last_instruction_row.values.push_back(0); json_last_instruction_row.values.push_back(necessary_segments_running_index - 1); json_last_instruction_row.values.push_back(0); json_last_instruction_row.values.push_back("0m"); - json_last_instruction_row.values.push_back(Bearing::Get(0.0)); + json_last_instruction_row.values.push_back(bearing::get(0.0)); json_last_instruction_row.values.push_back(0.); json_instruction_array.values.push_back(json_last_instruction_row); } From ccd803416e130d5a30a727aa808080eb9af36313 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 11:49:02 +0100 Subject: [PATCH 103/360] fix unintended float/epsilon comparison --- descriptors/description_factory.cpp | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/descriptors/description_factory.cpp b/descriptors/description_factory.cpp index 18bd44328..9df22f548 100644 --- a/descriptors/description_factory.cpp +++ b/descriptors/description_factory.cpp @@ -44,9 +44,8 @@ void DescriptionFactory::SetStartSegment(const PhantomNode &source, const bool t (traversed_in_reverse ? source.reverse_weight : source.forward_weight); const TravelMode travel_mode = (traversed_in_reverse ? source.backward_travel_mode : source.forward_travel_mode); - AppendSegment( - source.location, - PathData(0, source.name_id, TurnInstruction::HeadOn, segment_duration, travel_mode)); + AppendSegment(source.location, PathData(0, source.name_id, TurnInstruction::HeadOn, + segment_duration, travel_mode)); BOOST_ASSERT(path_description.back().duration == segment_duration); } @@ -59,15 +58,10 @@ void DescriptionFactory::SetEndSegment(const PhantomNode &target, (traversed_in_reverse ? target.reverse_weight : target.forward_weight); const TravelMode travel_mode = (traversed_in_reverse ? target.backward_travel_mode : target.forward_travel_mode); - path_description.emplace_back(target.location, - target.name_id, - segment_duration, - 0.f, + path_description.emplace_back(target.location, target.name_id, segment_duration, 0.f, is_via_location ? TurnInstruction::ReachViaLocation : TurnInstruction::NoTurn, - true, - true, - travel_mode); + true, true, travel_mode); BOOST_ASSERT(path_description.back().duration == segment_duration); } @@ -98,12 +92,8 @@ void DescriptionFactory::AppendSegment(const FixedPointCoordinate &coordinate, return path_point.turn_instruction; }(); - path_description.emplace_back(coordinate, - path_point.name_id, - path_point.segment_duration, - 0.f, - turn, - path_point.travel_mode); + path_description.emplace_back(coordinate, path_point.name_id, path_point.segment_duration, 0.f, + turn, path_point.travel_mode); } JSON::Value DescriptionFactory::AppendGeometryString(const bool return_encoded) @@ -205,7 +195,7 @@ void DescriptionFactory::Run(const unsigned zoom_level) // Post-processing to remove empty or nearly empty path segments if (path_description.size() > 2 && - std::numeric_limits::epsilon() > path_description.back().length) + std::numeric_limits::epsilon() > path_description.back().length) { path_description.pop_back(); path_description.back().necessary = true; @@ -214,7 +204,7 @@ void DescriptionFactory::Run(const unsigned zoom_level) } if (path_description.size() > 2 && - std::numeric_limits::epsilon() > path_description.front().length) + std::numeric_limits::epsilon() > path_description.front().length) { path_description.erase(path_description.begin()); path_description.front().turn_instruction = TurnInstruction::HeadOn; From 1c12b468a8c1a7d05bcc0376f4373da5808e5e72 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 12:10:32 +0100 Subject: [PATCH 104/360] replace for loop with hand-rolled pair-wise traverse of container with call to for_each_pair; fix target type of cast --- descriptors/description_factory.cpp | 35 ++++++++++++++++------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/descriptors/description_factory.cpp b/descriptors/description_factory.cpp index 9df22f548..9411eaadc 100644 --- a/descriptors/description_factory.cpp +++ b/descriptors/description_factory.cpp @@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/coordinate_calculation.hpp" #include "../data_structures/internal_route_result.hpp" #include "../data_structures/turn_instructions.hpp" +#include "../Util/container.hpp" #include "../typedefs.h" DescriptionFactory::DescriptionFactory() : entire_length(0) { via_indices.push_back(0); } @@ -216,23 +217,27 @@ void DescriptionFactory::Run(const unsigned zoom_level) polyline_generalizer.Run(path_description.begin(), path_description.end(), zoom_level); // fix what needs to be fixed else - unsigned necessary_pieces = 0; // a running index that counts the necessary pieces - for (unsigned i = 0; i < path_description.size() - 1 && path_description.size() >= 2; ++i) - { - if (path_description[i].necessary) + unsigned necessary_segments = 0; // a running index that counts the necessary pieces + osrm::for_each_pair( + path_description, [&](SegmentInformation &first, const SegmentInformation &second) { - ++necessary_pieces; - if (path_description[i].is_via_location) - { // mark the end of a leg - via_indices.push_back(necessary_pieces); + if (!first.necessary) + { + return; } - const double angle = - path_description[i + 1].location.bearing(path_description[i].location); - path_description[i].bearing = static_cast(angle * 10); - } - } - via_indices.push_back(necessary_pieces + 1); + + ++necessary_segments; + + if (first.is_via_location) + { // mark the end of a leg (of several segments) + via_indices.push_back(necessary_segments); + } + + const double angle = coordinate_calculation::bearing(first.location, second.location); + first.bearing = static_cast(angle * 10); + }); + + via_indices.push_back(necessary_segments + 1); BOOST_ASSERT(via_indices.size() >= 2); - // BOOST_ASSERT(0 != necessary_pieces || path_description.empty()); return; } From 53e01952bed944a110d435eed329cf263d026c0b Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 12:19:01 +0100 Subject: [PATCH 105/360] replace for loops with counters by range-based for loops --- descriptors/description_factory.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/descriptors/description_factory.cpp b/descriptors/description_factory.cpp index 9411eaadc..89742287f 100644 --- a/descriptors/description_factory.cpp +++ b/descriptors/description_factory.cpp @@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/internal_route_result.hpp" #include "../data_structures/turn_instructions.hpp" #include "../Util/container.hpp" +#include "../Util/integer_range.hpp" #include "../typedefs.h" DescriptionFactory::DescriptionFactory() : entire_length(0) { via_indices.push_back(0); } @@ -122,7 +123,7 @@ void DescriptionFactory::Run(const unsigned zoom_level) /** starts at index 1 */ path_description[0].length = 0; - for (unsigned i = 1; i < path_description.size(); ++i) + for (const auto i : osrm::irange(0, path_description.size())) { // move down names by one, q&d hack path_description[i - 1].name_id = path_description[i].name_id; @@ -174,10 +175,10 @@ void DescriptionFactory::Run(const unsigned zoom_level) // } float segment_length = 0.; - unsigned segment_duration = 0; - unsigned segment_start_index = 0; + EdgeWeight segment_duration = 0; + std::size_t segment_start_index = 0; - for (unsigned i = 1; i < path_description.size(); ++i) + for (const auto i : osrm::irange(1, path_description.size())) { entire_length += path_description[i].length; segment_length += path_description[i].length; From 93b33c0518bc6f6ffda1d8b7250fda58af7dfb46 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 13:52:28 +0100 Subject: [PATCH 106/360] fix cast to be explicit --- descriptors/description_factory.hpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/descriptors/description_factory.hpp b/descriptors/description_factory.hpp index 18a9f169b..2b377f687 100644 --- a/descriptors/description_factory.hpp +++ b/descriptors/description_factory.hpp @@ -72,7 +72,7 @@ class DescriptionFactory { // compute distance/duration for route summary distance = static_cast(std::round(raw_distance)); - duration = static_cast(std::round(raw_duration / 10.)); + duration = static_cast(std::round(raw_duration / 10.)); } } summary; @@ -88,10 +88,7 @@ class DescriptionFactory JSON::Value AppendGeometryString(const bool return_encoded); std::vector const &GetViaIndices() const; - double get_entire_length() const - { - return entire_length; - } + double get_entire_length() const { return entire_length; } void Run(const unsigned zoom_level); }; From 1c2c87e03d3fb3568a6847df9379f1bc29595395 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 13:52:44 +0100 Subject: [PATCH 107/360] fix boundary edge case --- descriptors/description_factory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/descriptors/description_factory.cpp b/descriptors/description_factory.cpp index 89742287f..5c19c34e5 100644 --- a/descriptors/description_factory.cpp +++ b/descriptors/description_factory.cpp @@ -122,8 +122,8 @@ void DescriptionFactory::Run(const unsigned zoom_level) } /** starts at index 1 */ - path_description[0].length = 0; - for (const auto i : osrm::irange(0, path_description.size())) + path_description[0].length = 0.f; + for (const auto i : osrm::irange(1, path_description.size())) { // move down names by one, q&d hack path_description[i - 1].name_id = path_description[i].name_id; From efbcce0ffe7eff21d64a612b30609fde5348e45c Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 13:53:02 +0100 Subject: [PATCH 108/360] use bitfields to reduce struct size of segment information. size goes down from 28->24 bytes --- data_structures/segment_information.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/data_structures/segment_information.hpp b/data_structures/segment_information.hpp index 117bd3972..d9f84e089 100644 --- a/data_structures/segment_information.hpp +++ b/data_structures/segment_information.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SEGMENT_INFORMATION_H -#define SEGMENT_INFORMATION_H +#ifndef SEGMENT_INFORMATION_HPP +#define SEGMENT_INFORMATION_HPP #include "turn_instructions.hpp" @@ -44,9 +44,9 @@ struct SegmentInformation float length; short bearing; // more than enough [0..3600] fits into 12 bits TurnInstruction turn_instruction; - TravelMode travel_mode; - bool necessary; - bool is_via_location; + TravelMode travel_mode : 4; + bool necessary : 1; + bool is_via_location : 1; explicit SegmentInformation(const FixedPointCoordinate &location, const NodeID name_id, @@ -75,4 +75,4 @@ struct SegmentInformation } }; -#endif /* SEGMENT_INFORMATION_H */ +#endif /* SEGMENT_INFORMATION_HPP */ From a15450af914b04e35bd2fa12c11571dd8b353187 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 14:24:02 +0100 Subject: [PATCH 109/360] manually revert previous change as g++ doesnt convert bitfields properly --- data_structures/segment_information.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data_structures/segment_information.hpp b/data_structures/segment_information.hpp index d9f84e089..5729380cc 100644 --- a/data_structures/segment_information.hpp +++ b/data_structures/segment_information.hpp @@ -44,9 +44,9 @@ struct SegmentInformation float length; short bearing; // more than enough [0..3600] fits into 12 bits TurnInstruction turn_instruction; - TravelMode travel_mode : 4; - bool necessary : 1; - bool is_via_location : 1; + TravelMode travel_mode; + bool necessary; + bool is_via_location; explicit SegmentInformation(const FixedPointCoordinate &location, const NodeID name_id, From dc7f21513ab8bbe05f56a0cc0b449c7ede84d2b3 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 16:28:27 +0100 Subject: [PATCH 110/360] move initialization of extractor config into main method and out out extraction logic --- extract.cpp | 37 +++++++++++++++++++++++++++++---- extractor/extractor.cpp | 34 ++---------------------------- extractor/extractor.hpp | 36 ++++++++++++++++++++++++++------ extractor/extractor_options.hpp | 5 +++-- 4 files changed, 68 insertions(+), 44 deletions(-) diff --git a/extract.cpp b/extract.cpp index 2ad1f7af8..4a59191b7 100644 --- a/extract.cpp +++ b/extract.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -26,17 +26,46 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "extractor/extractor.hpp" +#include "extractor/extractor_options.hpp" #include "Util/simple_logger.hpp" -int main (int argc, char *argv[]) +int main(int argc, char *argv[]) { try { - return Extractor().Run(argc, argv); + LogPolicy::GetInstance().Unmute(); + ExtractorConfig extractor_config; + + if (!ExtractorOptions::ParseArguments(argc, argv, extractor_config)) + { + return 0; + } + ExtractorOptions::GenerateOutputFilesNames(extractor_config); + + if (1 > extractor_config.requested_num_threads) + { + SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger"; + return 1; + } + + if (!boost::filesystem::is_regular_file(extractor_config.input_path)) + { + SimpleLogger().Write(logWARNING) + << "Input file " << extractor_config.input_path.string() << " not found!"; + return 1; + } + + if (!boost::filesystem::is_regular_file(extractor_config.profile_path)) + { + SimpleLogger().Write(logWARNING) << "Profile " << extractor_config.profile_path.string() + << " not found!"; + return 1; + } + + return extractor().run(extractor_config); } catch (const std::exception &e) { SimpleLogger().Write(logWARNING) << "[exception] " << e.what(); } - } diff --git a/extractor/extractor.cpp b/extractor/extractor.cpp index e3a5090e9..a4c31e04e 100644 --- a/extractor/extractor.cpp +++ b/extractor/extractor.cpp @@ -31,7 +31,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "extraction_node.hpp" #include "extraction_way.hpp" #include "extractor_callbacks.hpp" -#include "extractor_options.hpp" #include "restriction_parser.hpp" #include "scripting_environment.hpp" @@ -63,41 +62,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -int Extractor::Run(int argc, char *argv[]) +int extractor::run(const ExtractorConfig &extractor_config) { - ExtractorConfig extractor_config; - try { LogPolicy::GetInstance().Unmute(); TIMER_START(extracting); - if (!ExtractorOptions::ParseArguments(argc, argv, extractor_config)) - { - return 0; - } - ExtractorOptions::GenerateOutputFilesNames(extractor_config); - - if (1 > extractor_config.requested_num_threads) - { - SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger"; - return 1; - } - - if (!boost::filesystem::is_regular_file(extractor_config.input_path)) - { - SimpleLogger().Write(logWARNING) - << "Input file " << extractor_config.input_path.string() << " not found!"; - return 1; - } - - if (!boost::filesystem::is_regular_file(extractor_config.profile_path)) - { - SimpleLogger().Write(logWARNING) << "Profile " << extractor_config.profile_path.string() - << " not found!"; - return 1; - } - const unsigned recommended_num_threads = tbb::task_scheduler_init::default_num_threads(); const auto number_of_threads = std::min(recommended_num_threads, extractor_config.requested_num_threads); @@ -236,8 +207,7 @@ int Extractor::Run(int argc, char *argv[]) TIMER_STOP(parsing); SimpleLogger().Write() << "Parsing finished after " << TIMER_SEC(parsing) << " seconds"; - SimpleLogger().Write() << "Raw input contains " - << number_of_nodes.load() << " nodes, " + SimpleLogger().Write() << "Raw input contains " << number_of_nodes.load() << " nodes, " << number_of_ways.load() << " ways, and " << number_of_relations.load() << " relations, and " << number_of_others.load() << " unknown entities"; diff --git a/extractor/extractor.hpp b/extractor/extractor.hpp index e9edbea54..c06968c55 100644 --- a/extractor/extractor.hpp +++ b/extractor/extractor.hpp @@ -1,13 +1,37 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + #ifndef EXTRACTOR_HPP #define EXTRACTOR_HPP -#include +#include "extractor_options.hpp" -#include - -/** \brief Class of 'extract' utility. */ -struct Extractor +struct extractor { - int Run(int argc, char *argv[]); + int run(const ExtractorConfig &extractor_config); }; #endif /* EXTRACTOR_HPP */ diff --git a/extractor/extractor_options.hpp b/extractor/extractor_options.hpp index 118da78d9..36e3f4d41 100644 --- a/extractor/extractor_options.hpp +++ b/extractor/extractor_options.hpp @@ -28,12 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef EXTRACTOR_OPTIONS_HPP #define EXTRACTOR_OPTIONS_HPP -#include "extractor.hpp" +#include struct ExtractorConfig { ExtractorConfig() noexcept : requested_num_threads(0) {} - unsigned requested_num_threads; boost::filesystem::path config_file_path; boost::filesystem::path input_path; boost::filesystem::path profile_path; @@ -41,6 +40,8 @@ struct ExtractorConfig std::string output_file_name; std::string restriction_file_name; std::string timestamp_file_name; + + unsigned requested_num_threads; }; struct ExtractorOptions From cf21074f10da598291c8969278ac04ecf724f669 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 16:59:13 +0100 Subject: [PATCH 111/360] use enum as return code instead of boolean logic in extractor --- extract.cpp | 12 ++++- extractor/extractor_options.cpp | 81 ++++++++++++++++++--------------- extractor/extractor_options.hpp | 9 +++- 3 files changed, 63 insertions(+), 39 deletions(-) diff --git a/extract.cpp b/extract.cpp index 4a59191b7..9f496f115 100644 --- a/extract.cpp +++ b/extract.cpp @@ -36,10 +36,18 @@ int main(int argc, char *argv[]) LogPolicy::GetInstance().Unmute(); ExtractorConfig extractor_config; - if (!ExtractorOptions::ParseArguments(argc, argv, extractor_config)) + const return_code result = ExtractorOptions::ParseArguments(argc, argv, extractor_config); + + if (return_code::fail == result) + { + return 1; + } + + if (return_code::exit == result) { return 0; } + ExtractorOptions::GenerateOutputFilesNames(extractor_config); if (1 > extractor_config.requested_num_threads) @@ -61,11 +69,11 @@ int main(int argc, char *argv[]) << " not found!"; return 1; } - return extractor().run(extractor_config); } catch (const std::exception &e) { SimpleLogger().Write(logWARNING) << "[exception] " << e.what(); + return 1; } } diff --git a/extractor/extractor_options.cpp b/extractor/extractor_options.cpp index 8f58580cb..6514ef647 100644 --- a/extractor/extractor_options.cpp +++ b/extractor/extractor_options.cpp @@ -36,7 +36,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -bool ExtractorOptions::ParseArguments(int argc, char *argv[], ExtractorConfig &extractor_config) +return_code +ExtractorOptions::ParseArguments(int argc, char *argv[], ExtractorConfig &extractor_config) { // declare a group of options that will be allowed only on command line boost::program_options::options_description generic_options("Options"); @@ -79,46 +80,54 @@ bool ExtractorOptions::ParseArguments(int argc, char *argv[], ExtractorConfig &e visible_options.add(generic_options).add(config_options); // parse command line options - boost::program_options::variables_map option_variables; - boost::program_options::store(boost::program_options::command_line_parser(argc, argv) - .options(cmdline_options) - .positional(positional_options) - .run(), - option_variables); - - if (option_variables.count("version")) + try { - SimpleLogger().Write() << g_GIT_DESCRIPTION; - return false; - } - - if (option_variables.count("help")) - { - SimpleLogger().Write() << visible_options; - return false; - } - - boost::program_options::notify(option_variables); - - // parse config file - if (boost::filesystem::is_regular_file(extractor_config.config_file_path)) - { - SimpleLogger().Write() << "Reading options from: " - << extractor_config.config_file_path.string(); - std::string ini_file_contents = - ReadIniFileAndLowerContents(extractor_config.config_file_path); - std::stringstream config_stream(ini_file_contents); - boost::program_options::store(parse_config_file(config_stream, config_file_options), + boost::program_options::variables_map option_variables; + boost::program_options::store(boost::program_options::command_line_parser(argc, argv) + .options(cmdline_options) + .positional(positional_options) + .run(), option_variables); + if (option_variables.count("version")) + { + SimpleLogger().Write() << g_GIT_DESCRIPTION; + return return_code::exit; + } + + if (option_variables.count("help")) + { + SimpleLogger().Write() << visible_options; + return return_code::exit; + } + boost::program_options::notify(option_variables); + + // parse config file + if (boost::filesystem::is_regular_file(extractor_config.config_file_path)) + { + SimpleLogger().Write() + << "Reading options from: " << extractor_config.config_file_path.string(); + std::string ini_file_contents = + ReadIniFileAndLowerContents(extractor_config.config_file_path); + std::stringstream config_stream(ini_file_contents); + boost::program_options::store(parse_config_file(config_stream, config_file_options), + option_variables); + boost::program_options::notify(option_variables); + } + + if (!option_variables.count("input")) + { + SimpleLogger().Write() << visible_options; + return return_code::exit; + } + } + catch (std::exception &e) + { + SimpleLogger().Write(logWARNING) << e.what(); + return return_code::fail; } - if (!option_variables.count("input")) - { - SimpleLogger().Write() << visible_options; - return false; - } - return true; + return return_code::ok; } void ExtractorOptions::GenerateOutputFilesNames(ExtractorConfig &extractor_config) diff --git a/extractor/extractor_options.hpp b/extractor/extractor_options.hpp index 36e3f4d41..0813896d7 100644 --- a/extractor/extractor_options.hpp +++ b/extractor/extractor_options.hpp @@ -30,6 +30,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +enum class return_code : unsigned +{ + ok, + fail, + exit +}; + struct ExtractorConfig { ExtractorConfig() noexcept : requested_num_threads(0) {} @@ -46,7 +53,7 @@ struct ExtractorConfig struct ExtractorOptions { - static bool ParseArguments(int argc, char *argv[], ExtractorConfig &extractor_config); + static return_code ParseArguments(int argc, char *argv[], ExtractorConfig &extractor_config); static void GenerateOutputFilesNames(ExtractorConfig &extractor_config); }; From 69b3457e83171fba5d58fd8aa95e70d51bbf039c Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 17:14:12 +0100 Subject: [PATCH 112/360] replace boost::tuple by std::tuple --- Server/Connection.cpp | 34 +++++++++++---------------- Server/RequestParser.cpp | 6 ++--- Server/RequestParser.h | 51 +++++++++++++++++++++------------------- 3 files changed, 44 insertions(+), 47 deletions(-) diff --git a/Server/Connection.cpp b/Server/Connection.cpp index 82402a649..8777eb215 100644 --- a/Server/Connection.cpp +++ b/Server/Connection.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -52,8 +52,7 @@ void Connection::start() { TCP_socket.async_read_some( boost::asio::buffer(incoming_data_buffer), - strand.wrap(boost::bind(&Connection::handle_read, - this->shared_from_this(), + strand.wrap(boost::bind(&Connection::handle_read, this->shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); } @@ -68,11 +67,9 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t // no error detected, let's parse the request CompressionType compression_type(noCompression); boost::tribool result; - boost::tie(result, boost::tuples::ignore) = - RequestParser().Parse(request, - incoming_data_buffer.data(), - incoming_data_buffer.data() + bytes_transferred, - compression_type); + std::tie(result, std::ignore) = + RequestParser().Parse(request, incoming_data_buffer.data(), + incoming_data_buffer.data() + bytes_transferred, compression_type); // the request has been parsed if (result) @@ -110,29 +107,26 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t break; } // write result to stream - boost::asio::async_write(TCP_socket, - output_buffer, - strand.wrap(boost::bind(&Connection::handle_write, - this->shared_from_this(), - boost::asio::placeholders::error))); + boost::asio::async_write( + TCP_socket, output_buffer, + strand.wrap(boost::bind(&Connection::handle_write, this->shared_from_this(), + boost::asio::placeholders::error))); } else if (!result) { // request is not parseable reply = Reply::StockReply(Reply::badRequest); - boost::asio::async_write(TCP_socket, - reply.ToBuffers(), - strand.wrap(boost::bind(&Connection::handle_write, - this->shared_from_this(), - boost::asio::placeholders::error))); + boost::asio::async_write( + TCP_socket, reply.ToBuffers(), + strand.wrap(boost::bind(&Connection::handle_write, this->shared_from_this(), + boost::asio::placeholders::error))); } else { // we don't have a result yet, so continue reading TCP_socket.async_read_some( boost::asio::buffer(incoming_data_buffer), - strand.wrap(boost::bind(&Connection::handle_read, - this->shared_from_this(), + strand.wrap(boost::bind(&Connection::handle_read, this->shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); } diff --git a/Server/RequestParser.cpp b/Server/RequestParser.cpp index a599381f0..2c8358f8b 100644 --- a/Server/RequestParser.cpp +++ b/Server/RequestParser.cpp @@ -36,7 +36,7 @@ RequestParser::RequestParser() : state_(method_start), header({"", ""}) {} void RequestParser::Reset() { state_ = method_start; } -boost::tuple +std::tuple RequestParser::Parse(Request &req, char *begin, char *end, http::CompressionType &compression_type) { while (begin != end) @@ -44,11 +44,11 @@ RequestParser::Parse(Request &req, char *begin, char *end, http::CompressionType boost::tribool result = consume(req, *begin++, compression_type); if (result || !result) { - return boost::make_tuple(result, begin); + return std::make_tuple(result, begin); } } boost::tribool result = boost::indeterminate; - return boost::make_tuple(result, begin); + return std::make_tuple(result, begin); } boost::tribool diff --git a/Server/RequestParser.h b/Server/RequestParser.h index 07cdd86da..40c22954b 100644 --- a/Server/RequestParser.h +++ b/Server/RequestParser.h @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -32,7 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Http/Header.h" #include -#include + +#include namespace http { @@ -45,7 +46,7 @@ class RequestParser RequestParser(); void Reset(); - boost::tuple + std::tuple Parse(Request &req, char *begin, char *end, CompressionType &compression_type); private: @@ -60,27 +61,29 @@ class RequestParser inline bool isDigit(int c); enum state - { method_start, - method, - uri_start, - uri, - http_version_h, - http_version_t_1, - http_version_t_2, - http_version_p, - http_version_slash, - http_version_major_start, - http_version_major, - http_version_minor_start, - http_version_minor, - expecting_newline_1, - header_line_start, - header_lws, - header_name, - space_before_header_value, - header_value, - expecting_newline_2, - expecting_newline_3 } state_; + { + method_start, + method, + uri_start, + uri, + http_version_h, + http_version_t_1, + http_version_t_2, + http_version_p, + http_version_slash, + http_version_major_start, + http_version_major, + http_version_minor_start, + http_version_minor, + expecting_newline_1, + header_line_start, + header_lws, + header_name, + space_before_header_value, + header_value, + expecting_newline_2, + expecting_newline_3 + } state_; Header header; }; From b89304a24b323a83727074fb62f8e0888999533e Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 17:43:21 +0100 Subject: [PATCH 113/360] add enum class based tribool implementation --- data_structures/tribool.hpp | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 data_structures/tribool.hpp diff --git a/data_structures/tribool.hpp b/data_structures/tribool.hpp new file mode 100644 index 000000000..446bf31ea --- /dev/null +++ b/data_structures/tribool.hpp @@ -0,0 +1,40 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TRIBOOL_HPP +#define TRIBOOL_HPP + +namespace osrm +{ +enum class tribool : char +{ + yes, + no, + indeterminate +}; +} +#endif // TRIBOOL_HPP From fb3bc22c64dabf4cbeccb63419a09c6d58fc5381 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 17:46:40 +0100 Subject: [PATCH 114/360] replace boost::tribool with enum based implementation --- Server/Connection.cpp | 6 +- Server/RequestParser.cpp | 116 +++++++++++++++++++-------------------- Server/RequestParser.h | 8 ++- 3 files changed, 66 insertions(+), 64 deletions(-) diff --git a/Server/Connection.cpp b/Server/Connection.cpp index 8777eb215..27faf004f 100644 --- a/Server/Connection.cpp +++ b/Server/Connection.cpp @@ -66,13 +66,13 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t // no error detected, let's parse the request CompressionType compression_type(noCompression); - boost::tribool result; + osrm::tribool result; std::tie(result, std::ignore) = RequestParser().Parse(request, incoming_data_buffer.data(), incoming_data_buffer.data() + bytes_transferred, compression_type); // the request has been parsed - if (result) + if (result == osrm::tribool::yes) { request.endpoint = TCP_socket.remote_endpoint().address(); request_handler.handle_request(request, reply); @@ -112,7 +112,7 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t strand.wrap(boost::bind(&Connection::handle_write, this->shared_from_this(), boost::asio::placeholders::error))); } - else if (!result) + else if (result == osrm::tribool::no) { // request is not parseable reply = Reply::StockReply(Reply::badRequest); diff --git a/Server/RequestParser.cpp b/Server/RequestParser.cpp index 2c8358f8b..b3a6beebf 100644 --- a/Server/RequestParser.cpp +++ b/Server/RequestParser.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -36,22 +36,22 @@ RequestParser::RequestParser() : state_(method_start), header({"", ""}) {} void RequestParser::Reset() { state_ = method_start; } -std::tuple +std::tuple RequestParser::Parse(Request &req, char *begin, char *end, http::CompressionType &compression_type) { while (begin != end) { - boost::tribool result = consume(req, *begin++, compression_type); - if (result || !result) + osrm::tribool result = consume(req, *begin++, compression_type); + if (result == osrm::tribool::yes || result == osrm::tribool::no) { return std::make_tuple(result, begin); } } - boost::tribool result = boost::indeterminate; + osrm::tribool result = osrm::tribool::indeterminate; return std::make_tuple(result, begin); } -boost::tribool +osrm::tribool RequestParser::consume(Request &req, char input, http::CompressionType &compression_type) { switch (state_) @@ -59,119 +59,119 @@ RequestParser::consume(Request &req, char input, http::CompressionType &compress case method_start: if (!isChar(input) || isCTL(input) || isTSpecial(input)) { - return false; + return osrm::tribool::no; } state_ = method; - return boost::indeterminate; + return osrm::tribool::indeterminate; case method: if (input == ' ') { state_ = uri; - return boost::indeterminate; + return osrm::tribool::indeterminate; } if (!isChar(input) || isCTL(input) || isTSpecial(input)) { - return false; + return osrm::tribool::no; } - return boost::indeterminate; + return osrm::tribool::indeterminate; case uri_start: if (isCTL(input)) { - return false; + return osrm::tribool::no; } state_ = uri; req.uri.push_back(input); - return boost::indeterminate; + return osrm::tribool::indeterminate; case uri: if (input == ' ') { state_ = http_version_h; - return boost::indeterminate; + return osrm::tribool::indeterminate; } if (isCTL(input)) { - return false; + return osrm::tribool::no; } req.uri.push_back(input); - return boost::indeterminate; + return osrm::tribool::indeterminate; case http_version_h: if (input == 'H') { state_ = http_version_t_1; - return boost::indeterminate; + return osrm::tribool::indeterminate; } - return false; + return osrm::tribool::no; case http_version_t_1: if (input == 'T') { state_ = http_version_t_2; - return boost::indeterminate; + return osrm::tribool::indeterminate; } - return false; + return osrm::tribool::no; case http_version_t_2: if (input == 'T') { state_ = http_version_p; - return boost::indeterminate; + return osrm::tribool::indeterminate; } - return false; + return osrm::tribool::no; case http_version_p: if (input == 'P') { state_ = http_version_slash; - return boost::indeterminate; + return osrm::tribool::indeterminate; } - return false; + return osrm::tribool::no; case http_version_slash: if (input == '/') { state_ = http_version_major_start; - return boost::indeterminate; + return osrm::tribool::indeterminate; } - return false; + return osrm::tribool::no; case http_version_major_start: if (isDigit(input)) { state_ = http_version_major; - return boost::indeterminate; + return osrm::tribool::indeterminate; } - return false; + return osrm::tribool::no; case http_version_major: if (input == '.') { state_ = http_version_minor_start; - return boost::indeterminate; + return osrm::tribool::indeterminate; } if (isDigit(input)) { - return boost::indeterminate; + return osrm::tribool::indeterminate; } - return false; + return osrm::tribool::no; case http_version_minor_start: if (isDigit(input)) { state_ = http_version_minor; - return boost::indeterminate; + return osrm::tribool::indeterminate; } - return false; + return osrm::tribool::no; case http_version_minor: if (input == '\r') { state_ = expecting_newline_1; - return boost::indeterminate; + return osrm::tribool::indeterminate; } if (isDigit(input)) { - return boost::indeterminate; + return osrm::tribool::indeterminate; } - return false; + return osrm::tribool::no; case expecting_newline_1: if (input == '\n') { state_ = header_line_start; - return boost::indeterminate; + return osrm::tribool::indeterminate; } - return false; + return osrm::tribool::no; case header_line_start: if (header.name == "Accept-Encoding") { @@ -199,74 +199,74 @@ RequestParser::consume(Request &req, char input, http::CompressionType &compress if (input == '\r') { state_ = expecting_newline_3; - return boost::indeterminate; + return osrm::tribool::indeterminate; } if (!isChar(input) || isCTL(input) || isTSpecial(input)) { - return false; + return osrm::tribool::no; } state_ = header_name; header.Clear(); header.name.push_back(input); - return boost::indeterminate; + return osrm::tribool::indeterminate; case header_lws: if (input == '\r') { state_ = expecting_newline_2; - return boost::indeterminate; + return osrm::tribool::indeterminate; } if (input == ' ' || input == '\t') { - return boost::indeterminate; + return osrm::tribool::indeterminate; } if (isCTL(input)) { - return false; + return osrm::tribool::no; } state_ = header_value; - return boost::indeterminate; + return osrm::tribool::indeterminate; case header_name: if (input == ':') { state_ = space_before_header_value; - return boost::indeterminate; + return osrm::tribool::indeterminate; } if (!isChar(input) || isCTL(input) || isTSpecial(input)) { - return false; + return osrm::tribool::no; } header.name.push_back(input); - return boost::indeterminate; + return osrm::tribool::indeterminate; case space_before_header_value: if (input == ' ') { state_ = header_value; - return boost::indeterminate; + return osrm::tribool::indeterminate; } - return false; + return osrm::tribool::no; case header_value: if (input == '\r') { state_ = expecting_newline_2; - return boost::indeterminate; + return osrm::tribool::indeterminate; } if (isCTL(input)) { - return false; + return osrm::tribool::no; } header.value.push_back(input); - return boost::indeterminate; + return osrm::tribool::indeterminate; case expecting_newline_2: if (input == '\n') { state_ = header_line_start; - return boost::indeterminate; + return osrm::tribool::indeterminate; } - return false; - default: // expecting_newline_3: - return (input == '\n'); + return osrm::tribool::no; + default: // expecting_newline_3 + return (input == '\n' ? osrm::tribool::yes : osrm::tribool::no); // default: - // return false; + // return osrm::tribool::no; } } diff --git a/Server/RequestParser.h b/Server/RequestParser.h index 40c22954b..9a01c4484 100644 --- a/Server/RequestParser.h +++ b/Server/RequestParser.h @@ -31,7 +31,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Http/CompressionType.h" #include "Http/Header.h" -#include +#include "../data_structures/tribool.hpp" + +// #include #include @@ -46,11 +48,11 @@ class RequestParser RequestParser(); void Reset(); - std::tuple + std::tuple Parse(Request &req, char *begin, char *end, CompressionType &compression_type); private: - boost::tribool consume(Request &req, char input, CompressionType &compression_type); + osrm::tribool consume(Request &req, char input, CompressionType &compression_type); inline bool isChar(int c); From 9dfe6d1e852cb54a1bc856864f69300a4a6a1fc3 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 18:53:37 +0100 Subject: [PATCH 115/360] use std::tuple to return multiple return values, hope for copy elision. Also, removes two cases of parameter reassignment --- Server/Connection.cpp | 5 ++--- Server/Connection.h | 22 ++++++---------------- Server/RequestParser.cpp | 13 ++++++------- Server/RequestParser.h | 6 +++--- 4 files changed, 17 insertions(+), 29 deletions(-) diff --git a/Server/Connection.cpp b/Server/Connection.cpp index 27faf004f..366bb8619 100644 --- a/Server/Connection.cpp +++ b/Server/Connection.cpp @@ -67,9 +67,8 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t // no error detected, let's parse the request CompressionType compression_type(noCompression); osrm::tribool result; - std::tie(result, std::ignore) = - RequestParser().Parse(request, incoming_data_buffer.data(), - incoming_data_buffer.data() + bytes_transferred, compression_type); + std::tie(result, compression_type) = RequestParser().Parse( + request, incoming_data_buffer.data(), incoming_data_buffer.data() + bytes_transferred); // the request has been parsed if (result == osrm::tribool::yes) diff --git a/Server/Connection.h b/Server/Connection.h index 54e4e6305..024501055 100644 --- a/Server/Connection.h +++ b/Server/Connection.h @@ -28,7 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef CONNECTION_H #define CONNECTION_H -// #include "RequestParser.h" #include "Http/CompressionType.h" #include "Http/Reply.h" #include "Http/Request.h" @@ -38,30 +37,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include - #include - #include +#include +#include -//workaround for incomplete std::shared_ptr compatibility in old boost versions +// workaround for incomplete std::shared_ptr compatibility in old boost versions #if BOOST_VERSION < 105300 || defined BOOST_NO_CXX11_SMART_PTR -namespace boost { -template -const T* get_pointer(std::shared_ptr const& p) +namespace boost { - return p.get(); -} +template const T *get_pointer(std::shared_ptr const &p) { return p.get(); } -template -T* get_pointer(std::shared_ptr& p) -{ - return p.get(); -} +template T *get_pointer(std::shared_ptr &p) { return p.get(); } } // namespace boost #endif - - class RequestHandler; namespace http diff --git a/Server/RequestParser.cpp b/Server/RequestParser.cpp index b3a6beebf..89c56f1e8 100644 --- a/Server/RequestParser.cpp +++ b/Server/RequestParser.cpp @@ -36,23 +36,22 @@ RequestParser::RequestParser() : state_(method_start), header({"", ""}) {} void RequestParser::Reset() { state_ = method_start; } -std::tuple -RequestParser::Parse(Request &req, char *begin, char *end, http::CompressionType &compression_type) +std::tuple +RequestParser::Parse(Request &req, char *begin, char *end) { while (begin != end) { - osrm::tribool result = consume(req, *begin++, compression_type); + osrm::tribool result = consume(req, *begin++); if (result == osrm::tribool::yes || result == osrm::tribool::no) { - return std::make_tuple(result, begin); + return std::make_tuple(result, compression_type); } } osrm::tribool result = osrm::tribool::indeterminate; - return std::make_tuple(result, begin); + return std::make_tuple(result, compression_type); } -osrm::tribool -RequestParser::consume(Request &req, char input, http::CompressionType &compression_type) +osrm::tribool RequestParser::consume(Request &req, char input) { switch (state_) { diff --git a/Server/RequestParser.h b/Server/RequestParser.h index 9a01c4484..d177b7269 100644 --- a/Server/RequestParser.h +++ b/Server/RequestParser.h @@ -48,11 +48,10 @@ class RequestParser RequestParser(); void Reset(); - std::tuple - Parse(Request &req, char *begin, char *end, CompressionType &compression_type); + std::tuple Parse(Request &req, char *begin, char *end); private: - osrm::tribool consume(Request &req, char input, CompressionType &compression_type); + osrm::tribool consume(Request &req, char input); inline bool isChar(int c); @@ -88,6 +87,7 @@ class RequestParser } state_; Header header; + CompressionType compression_type; }; } // namespace http From 29949eae1bf25af705ba99a50bf36d964fa08eb5 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 23 Jan 2015 18:55:58 +0100 Subject: [PATCH 116/360] remove unneeded include to boost/tribool --- Server/RequestParser.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/Server/RequestParser.h b/Server/RequestParser.h index d177b7269..9ec67b5b3 100644 --- a/Server/RequestParser.h +++ b/Server/RequestParser.h @@ -30,11 +30,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Http/CompressionType.h" #include "Http/Header.h" - #include "../data_structures/tribool.hpp" -// #include - #include namespace http From 601eff1af6e5c56102b406d7d3eb8a39a206bad7 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 26 Jan 2015 11:25:10 +0100 Subject: [PATCH 117/360] initialize compression type to be no compression --- Server/RequestParser.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Server/RequestParser.cpp b/Server/RequestParser.cpp index 89c56f1e8..348e71313 100644 --- a/Server/RequestParser.cpp +++ b/Server/RequestParser.cpp @@ -32,7 +32,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace http { -RequestParser::RequestParser() : state_(method_start), header({"", ""}) {} +RequestParser::RequestParser() + : state_(method_start), header({"", ""}), compression_type(noCompression) +{ +} void RequestParser::Reset() { state_ = method_start; } From fe7b436a8cacc6d38a422111de5d29739c794fef Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 26 Jan 2015 13:20:22 +0100 Subject: [PATCH 118/360] refactor request parser to use C++11 idioms, plus a couple of consts --- Server/RequestParser.cpp | 124 +++++++++++++++++++-------------------- Server/RequestParser.h | 12 ++-- 2 files changed, 67 insertions(+), 69 deletions(-) diff --git a/Server/RequestParser.cpp b/Server/RequestParser.cpp index 348e71313..10384471e 100644 --- a/Server/RequestParser.cpp +++ b/Server/RequestParser.cpp @@ -33,11 +33,11 @@ namespace http { RequestParser::RequestParser() - : state_(method_start), header({"", ""}), compression_type(noCompression) + : state(internal_state::method_start), header({"", ""}), compression_type(noCompression) { } -void RequestParser::Reset() { state_ = method_start; } +void RequestParser::Reset() { state = internal_state::method_start; } std::tuple RequestParser::Parse(Request &req, char *begin, char *end) @@ -56,125 +56,125 @@ RequestParser::Parse(Request &req, char *begin, char *end) osrm::tribool RequestParser::consume(Request &req, char input) { - switch (state_) + switch (state) { - case method_start: - if (!isChar(input) || isCTL(input) || isTSpecial(input)) + case internal_state::method_start: + if (!is_char(input) || is_CTL(input) || is_special(input)) { return osrm::tribool::no; } - state_ = method; + state = internal_state::method; return osrm::tribool::indeterminate; - case method: + case internal_state::method: if (input == ' ') { - state_ = uri; + state = internal_state::uri; return osrm::tribool::indeterminate; } - if (!isChar(input) || isCTL(input) || isTSpecial(input)) + if (!is_char(input) || is_CTL(input) || is_special(input)) { return osrm::tribool::no; } return osrm::tribool::indeterminate; - case uri_start: - if (isCTL(input)) + case internal_state::uri_start: + if (is_CTL(input)) { return osrm::tribool::no; } - state_ = uri; + state = internal_state::uri; req.uri.push_back(input); return osrm::tribool::indeterminate; - case uri: + case internal_state::uri: if (input == ' ') { - state_ = http_version_h; + state = internal_state::http_version_h; return osrm::tribool::indeterminate; } - if (isCTL(input)) + if (is_CTL(input)) { return osrm::tribool::no; } req.uri.push_back(input); return osrm::tribool::indeterminate; - case http_version_h: + case internal_state::http_version_h: if (input == 'H') { - state_ = http_version_t_1; + state = internal_state::http_version_t_1; return osrm::tribool::indeterminate; } return osrm::tribool::no; - case http_version_t_1: + case internal_state::http_version_t_1: if (input == 'T') { - state_ = http_version_t_2; + state = internal_state::http_version_t_2; return osrm::tribool::indeterminate; } return osrm::tribool::no; - case http_version_t_2: + case internal_state::http_version_t_2: if (input == 'T') { - state_ = http_version_p; + state = internal_state::http_version_p; return osrm::tribool::indeterminate; } return osrm::tribool::no; - case http_version_p: + case internal_state::http_version_p: if (input == 'P') { - state_ = http_version_slash; + state = internal_state::http_version_slash; return osrm::tribool::indeterminate; } return osrm::tribool::no; - case http_version_slash: + case internal_state::http_version_slash: if (input == '/') { - state_ = http_version_major_start; + state = internal_state::http_version_major_start; return osrm::tribool::indeterminate; } return osrm::tribool::no; - case http_version_major_start: - if (isDigit(input)) + case internal_state::http_version_major_start: + if (is_digit(input)) { - state_ = http_version_major; + state = internal_state::http_version_major; return osrm::tribool::indeterminate; } return osrm::tribool::no; - case http_version_major: + case internal_state::http_version_major: if (input == '.') { - state_ = http_version_minor_start; + state = internal_state::http_version_minor_start; return osrm::tribool::indeterminate; } - if (isDigit(input)) + if (is_digit(input)) { return osrm::tribool::indeterminate; } return osrm::tribool::no; - case http_version_minor_start: - if (isDigit(input)) + case internal_state::http_version_minor_start: + if (is_digit(input)) { - state_ = http_version_minor; + state = internal_state::http_version_minor; return osrm::tribool::indeterminate; } return osrm::tribool::no; - case http_version_minor: + case internal_state::http_version_minor: if (input == '\r') { - state_ = expecting_newline_1; + state = internal_state::expecting_newline_1; return osrm::tribool::indeterminate; } - if (isDigit(input)) + if (is_digit(input)) { return osrm::tribool::indeterminate; } return osrm::tribool::no; - case expecting_newline_1: + case internal_state::expecting_newline_1: if (input == '\n') { - state_ = header_line_start; + state = internal_state::header_line_start; return osrm::tribool::indeterminate; } return osrm::tribool::no; - case header_line_start: + case internal_state::header_line_start: if (header.name == "Accept-Encoding") { /* giving gzip precedence over deflate */ @@ -200,86 +200,84 @@ osrm::tribool RequestParser::consume(Request &req, char input) if (input == '\r') { - state_ = expecting_newline_3; + state = internal_state::expecting_newline_3; return osrm::tribool::indeterminate; } - if (!isChar(input) || isCTL(input) || isTSpecial(input)) + if (!is_char(input) || is_CTL(input) || is_special(input)) { return osrm::tribool::no; } - state_ = header_name; + state = internal_state::header_name; header.Clear(); header.name.push_back(input); return osrm::tribool::indeterminate; - case header_lws: + case internal_state::header_lws: if (input == '\r') { - state_ = expecting_newline_2; + state = internal_state::expecting_newline_2; return osrm::tribool::indeterminate; } if (input == ' ' || input == '\t') { return osrm::tribool::indeterminate; } - if (isCTL(input)) + if (is_CTL(input)) { return osrm::tribool::no; } - state_ = header_value; + state = internal_state::header_value; return osrm::tribool::indeterminate; - case header_name: + case internal_state::header_name: if (input == ':') { - state_ = space_before_header_value; + state = internal_state::space_before_header_value; return osrm::tribool::indeterminate; } - if (!isChar(input) || isCTL(input) || isTSpecial(input)) + if (!is_char(input) || is_CTL(input) || is_special(input)) { return osrm::tribool::no; } header.name.push_back(input); return osrm::tribool::indeterminate; - case space_before_header_value: + case internal_state::space_before_header_value: if (input == ' ') { - state_ = header_value; + state = internal_state::header_value; return osrm::tribool::indeterminate; } return osrm::tribool::no; - case header_value: + case internal_state::header_value: if (input == '\r') { - state_ = expecting_newline_2; + state = internal_state::expecting_newline_2; return osrm::tribool::indeterminate; } - if (isCTL(input)) + if (is_CTL(input)) { return osrm::tribool::no; } header.value.push_back(input); return osrm::tribool::indeterminate; - case expecting_newline_2: + case internal_state::expecting_newline_2: if (input == '\n') { - state_ = header_line_start; + state = internal_state::header_line_start; return osrm::tribool::indeterminate; } return osrm::tribool::no; default: // expecting_newline_3 return (input == '\n' ? osrm::tribool::yes : osrm::tribool::no); - // default: - // return osrm::tribool::no; } } -inline bool RequestParser::isChar(int character) { return character >= 0 && character <= 127; } +bool RequestParser::is_char(int character) const { return character >= 0 && character <= 127; } -inline bool RequestParser::isCTL(int character) +bool RequestParser::is_CTL(int character) const { return (character >= 0 && character <= 31) || (character == 127); } -inline bool RequestParser::isTSpecial(int character) +bool RequestParser::is_special(int character) const { switch (character) { @@ -308,5 +306,5 @@ inline bool RequestParser::isTSpecial(int character) } } -inline bool RequestParser::isDigit(int character) { return character >= '0' && character <= '9'; } +bool RequestParser::is_digit(int character) const { return character >= '0' && character <= '9'; } } diff --git a/Server/RequestParser.h b/Server/RequestParser.h index 9ec67b5b3..0ea90c6ca 100644 --- a/Server/RequestParser.h +++ b/Server/RequestParser.h @@ -50,15 +50,15 @@ class RequestParser private: osrm::tribool consume(Request &req, char input); - inline bool isChar(int c); + bool is_char(int c) const; - inline bool isCTL(int c); + bool is_CTL(int c) const; - inline bool isTSpecial(int c); + bool is_special(int c) const; - inline bool isDigit(int c); + bool is_digit(int c) const; - enum state + enum class internal_state : unsigned char { method_start, method, @@ -81,7 +81,7 @@ class RequestParser header_value, expecting_newline_2, expecting_newline_3 - } state_; + } state; Header header; CompressionType compression_type; From 37a9813482159e5079b19758ba0d12c0b4146e62 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 26 Jan 2015 13:26:21 +0100 Subject: [PATCH 119/360] replace boost::array by std::array --- Server/Connection.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Server/Connection.h b/Server/Connection.h index 024501055..da0745450 100644 --- a/Server/Connection.h +++ b/Server/Connection.h @@ -32,7 +32,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Http/Reply.h" #include "Http/Request.h" -#include #include #include #include @@ -83,7 +82,7 @@ class Connection : public std::enable_shared_from_this boost::asio::io_service::strand strand; boost::asio::ip::tcp::socket TCP_socket; RequestHandler &request_handler; - boost::array incoming_data_buffer; + std::array incoming_data_buffer; Request request; Reply reply; }; From 06a08a874f518dc8bc5d1b9840447451c378e107 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 26 Jan 2015 13:35:24 +0100 Subject: [PATCH 120/360] fix performance regression in output generation, use copy elision and return result char array --- Server/Connection.cpp | 13 +++++++------ Server/Connection.h | 7 +++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Server/Connection.cpp b/Server/Connection.cpp index 366bb8619..af66f4a6a 100644 --- a/Server/Connection.cpp +++ b/Server/Connection.cpp @@ -86,7 +86,7 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t case deflateRFC1951: // use deflate for compression reply.headers.insert(reply.headers.begin(), {"Content-Encoding", "deflate"}); - CompressBufferCollection(reply.content, compression_type, compressed_output); + compressed_output = compress_buffers(reply.content, compression_type); reply.SetSize(static_cast(compressed_output.size())); output_buffer = reply.HeaderstoBuffers(); output_buffer.push_back(boost::asio::buffer(compressed_output)); @@ -94,7 +94,7 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t case gzipRFC1952: // use gzip for compression reply.headers.insert(reply.headers.begin(), {"Content-Encoding", "gzip"}); - CompressBufferCollection(reply.content, compression_type, compressed_output); + compressed_output = compress_buffers(reply.content, compression_type); reply.SetSize(static_cast(compressed_output.size())); output_buffer = reply.HeaderstoBuffers(); output_buffer.push_back(boost::asio::buffer(compressed_output)); @@ -142,9 +142,8 @@ void Connection::handle_write(const boost::system::error_code &error) } } -void Connection::CompressBufferCollection(std::vector uncompressed_data, - CompressionType compression_type, - std::vector &compressed_data) +std::vector Connection::compress_buffers(const std::vector &uncompressed_data, + const CompressionType compression_type) { boost::iostreams::gzip_params compression_parameters; @@ -156,12 +155,14 @@ void Connection::CompressBufferCollection(std::vector uncompressed_data, compression_parameters.noheader = true; } - BOOST_ASSERT(compressed_data.empty()); + std::vector compressed_data; // plug data into boost's compression stream boost::iostreams::filtering_ostream gzip_stream; gzip_stream.push(boost::iostreams::gzip_compressor(compression_parameters)); gzip_stream.push(boost::iostreams::back_inserter(compressed_data)); gzip_stream.write(&uncompressed_data[0], uncompressed_data.size()); boost::iostreams::close(gzip_stream); + + return compressed_data; } } diff --git a/Server/Connection.h b/Server/Connection.h index da0745450..cf59cddd6 100644 --- a/Server/Connection.h +++ b/Server/Connection.h @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -75,9 +75,8 @@ class Connection : public std::enable_shared_from_this /// Handle completion of a write operation. void handle_write(const boost::system::error_code &e); - void CompressBufferCollection(std::vector uncompressed_data, - CompressionType compression_type, - std::vector &compressed_data); + std::vector compress_buffers(const std::vector &uncompressed_data, + const CompressionType compression_type); boost::asio::io_service::strand strand; boost::asio::ip::tcp::socket TCP_socket; From 7a3748b8f63007f02f72110a08541feb8bef2229 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 26 Jan 2015 16:34:05 +0100 Subject: [PATCH 121/360] remove redundant c'tor call --- Server/Server.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Server/Server.h b/Server/Server.h index 8e0b10130..0098dd5a5 100644 --- a/Server/Server.h +++ b/Server/Server.h @@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "RequestHandler.h" #include "../Util/cast.hpp" -#include "../Util/make_unique.hpp" +#include "../Util/integer_range.hpp" #include "../Util/simple_logger.hpp" #include @@ -48,9 +48,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. class Server { public: - // Note: returns a shared instead of a unique ptr as it is captured in a lambda somewhere else - static std::shared_ptr CreateServer(std::string &ip_address, int ip_port, unsigned requested_num_threads) + static std::shared_ptr + CreateServer(std::string &ip_address, int ip_port, unsigned requested_num_threads) { SimpleLogger().Write() << "http 1.1 compression handled by zlib version " << zlibVersion(); const unsigned hardware_threads = std::max(1u, std::thread::hardware_concurrency()); @@ -60,7 +60,7 @@ class Server explicit Server(const std::string &address, const int port, const unsigned thread_pool_size) : thread_pool_size(thread_pool_size), acceptor(io_service), - new_connection(std::make_shared(io_service, request_handler)), request_handler() + new_connection(std::make_shared(io_service, request_handler)) { const std::string port_string = cast::integral_to_string(port); From dd6dd63798965742c37463c3a3a68f323c3fa961 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 26 Jan 2015 16:35:16 +0100 Subject: [PATCH 122/360] rename iterator variable to be more telling --- Server/RequestHandler.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Server/RequestHandler.cpp b/Server/RequestHandler.cpp index 6aea27d7f..2b137ad67 100644 --- a/Server/RequestHandler.cpp +++ b/Server/RequestHandler.cpp @@ -83,16 +83,16 @@ void RequestHandler::handle_request(const http::Request &req, http::Reply &reply RouteParameters route_parameters; APIGrammarParser api_parser(&route_parameters); - auto iter = request.begin(); - const bool result = boost::spirit::qi::parse(iter, request.end(), api_parser); + auto api_iterator = request.begin(); + const bool result = boost::spirit::qi::parse(api_iterator, request.end(), api_parser); JSON::Object json_result; // check if the was an error with the request - if (!result || (iter != request.end())) + if (!result || (api_iterator != request.end())) { reply = http::Reply::StockReply(http::Reply::badRequest); reply.content.clear(); - const auto position = std::distance(request.begin(), iter); + const auto position = std::distance(request.begin(), api_iterator); json_result.values["status"] = 400; std::string message = "Query string malformed close to position "; From ad4fb5afe340036fd54aaf0c31cd487264b91eb2 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 26 Jan 2015 17:37:37 +0100 Subject: [PATCH 123/360] revert previous commit that replace boost::array by std::array. not compatible with clang-3.5/boost1.54 --- Server/Connection.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Server/Connection.h b/Server/Connection.h index cf59cddd6..4624c9fd3 100644 --- a/Server/Connection.h +++ b/Server/Connection.h @@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Http/Reply.h" #include "Http/Request.h" +#include #include #include #include @@ -81,7 +82,7 @@ class Connection : public std::enable_shared_from_this boost::asio::io_service::strand strand; boost::asio::ip::tcp::socket TCP_socket; RequestHandler &request_handler; - std::array incoming_data_buffer; + boost::array incoming_data_buffer; Request request; Reply reply; }; From 69e59b0ceda6e2cb05bce6c95e1683a4e1ade656 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 09:57:14 +0100 Subject: [PATCH 124/360] rename clear() function to reduce camel case noise --- Server/Http/Header.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Server/Http/Header.h b/Server/Http/Header.h index d126c4c98..12728cecf 100644 --- a/Server/Http/Header.h +++ b/Server/Http/Header.h @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -35,11 +35,11 @@ namespace http { struct Header { - Header& operator=(const Header& other) = default; - Header(const std::string & name, const std::string & value) : name(name), value(value) {} - Header(Header && other) : name(std::move(other.name)), value(std::move(other.value)) {} + Header &operator=(const Header &other) = default; + Header(const std::string &name, const std::string &value) : name(name), value(value) {} + Header(Header &&other) : name(std::move(other.name)), value(std::move(other.value)) {} - void Clear() + void clear() { name.clear(); value.clear(); From f0d3d23b5fb379c898ac87420060b2b1743cc459 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 09:58:26 +0100 Subject: [PATCH 125/360] make http header parsing case insensitive, and remove some dead code (reset function) --- Server/Connection.cpp | 2 +- Server/RequestParser.cpp | 46 +++++++++++++++++++++++----------------- Server/RequestParser.h | 13 ++++++------ 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/Server/Connection.cpp b/Server/Connection.cpp index af66f4a6a..d9686ff31 100644 --- a/Server/Connection.cpp +++ b/Server/Connection.cpp @@ -67,7 +67,7 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t // no error detected, let's parse the request CompressionType compression_type(noCompression); osrm::tribool result; - std::tie(result, compression_type) = RequestParser().Parse( + std::tie(result, compression_type) = RequestParser().parse( request, incoming_data_buffer.data(), incoming_data_buffer.data() + bytes_transferred); // the request has been parsed diff --git a/Server/RequestParser.cpp b/Server/RequestParser.cpp index 10384471e..bcad9b55b 100644 --- a/Server/RequestParser.cpp +++ b/Server/RequestParser.cpp @@ -29,6 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Http/Request.h" +#include + namespace http { @@ -37,15 +39,13 @@ RequestParser::RequestParser() { } -void RequestParser::Reset() { state = internal_state::method_start; } - std::tuple -RequestParser::Parse(Request &req, char *begin, char *end) +RequestParser::parse(Request &request, char *begin, char *end) { while (begin != end) { - osrm::tribool result = consume(req, *begin++); - if (result == osrm::tribool::yes || result == osrm::tribool::no) + osrm::tribool result = consume(request, *begin++); + if (result != osrm::tribool::indeterminate) { return std::make_tuple(result, compression_type); } @@ -54,7 +54,7 @@ RequestParser::Parse(Request &req, char *begin, char *end) return std::make_tuple(result, compression_type); } -osrm::tribool RequestParser::consume(Request &req, char input) +osrm::tribool RequestParser::consume(Request &request, const char input) { switch (state) { @@ -82,7 +82,7 @@ osrm::tribool RequestParser::consume(Request &req, char input) return osrm::tribool::no; } state = internal_state::uri; - req.uri.push_back(input); + request.uri.push_back(input); return osrm::tribool::indeterminate; case internal_state::uri: if (input == ' ') @@ -94,7 +94,7 @@ osrm::tribool RequestParser::consume(Request &req, char input) { return osrm::tribool::no; } - req.uri.push_back(input); + request.uri.push_back(input); return osrm::tribool::indeterminate; case internal_state::http_version_h: if (input == 'H') @@ -175,27 +175,27 @@ osrm::tribool RequestParser::consume(Request &req, char input) } return osrm::tribool::no; case internal_state::header_line_start: - if (header.name == "Accept-Encoding") + if (boost::iequals(header.name, "Accept-Encoding")) { /* giving gzip precedence over deflate */ - if (header.value.find("deflate") != std::string::npos) + if (boost::icontains(header.value, "deflate")) { compression_type = deflateRFC1951; } - if (header.value.find("gzip") != std::string::npos) + if (boost::icontains(header.value, "gzip")) { compression_type = gzipRFC1952; } } - if ("Referer" == header.name) + if (boost::iequals(header.name, "Referer")) { - req.referrer = header.value; + request.referrer = header.value; } - if ("User-Agent" == header.name) + if (boost::iequals(header.name, "User-Agent")) { - req.agent = header.value; + request.agent = header.value; } if (input == '\r') @@ -208,7 +208,7 @@ osrm::tribool RequestParser::consume(Request &req, char input) return osrm::tribool::no; } state = internal_state::header_name; - header.Clear(); + header.clear(); header.name.push_back(input); return osrm::tribool::indeterminate; case internal_state::header_lws: @@ -270,14 +270,17 @@ osrm::tribool RequestParser::consume(Request &req, char input) } } -bool RequestParser::is_char(int character) const { return character >= 0 && character <= 127; } +bool RequestParser::is_char(const int character) const +{ + return character >= 0 && character <= 127; +} -bool RequestParser::is_CTL(int character) const +bool RequestParser::is_CTL(const int character) const { return (character >= 0 && character <= 31) || (character == 127); } -bool RequestParser::is_special(int character) const +bool RequestParser::is_special(const int character) const { switch (character) { @@ -306,5 +309,8 @@ bool RequestParser::is_special(int character) const } } -bool RequestParser::is_digit(int character) const { return character >= '0' && character <= '9'; } +bool RequestParser::is_digit(const int character) const +{ + return character >= '0' && character <= '9'; +} } diff --git a/Server/RequestParser.h b/Server/RequestParser.h index 0ea90c6ca..791b51513 100644 --- a/Server/RequestParser.h +++ b/Server/RequestParser.h @@ -43,20 +43,19 @@ class RequestParser { public: RequestParser(); - void Reset(); - std::tuple Parse(Request &req, char *begin, char *end); + std::tuple parse(Request &request, char *begin, char *end); private: - osrm::tribool consume(Request &req, char input); + osrm::tribool consume(Request &req, const char input); - bool is_char(int c) const; + bool is_char(const int character) const; - bool is_CTL(int c) const; + bool is_CTL(const int character) const; - bool is_special(int c) const; + bool is_special(const int character) const; - bool is_digit(int c) const; + bool is_digit(const int character) const; enum class internal_state : unsigned char { From 3e47fe54fa9de17da759c5401efe752bd68f0bf8 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 11:45:33 +0100 Subject: [PATCH 126/360] refactor Server/Http to remove camel case --- Server/Connection.cpp | 28 ++-- Server/Connection.h | 12 +- Server/Http/Reply.cpp | 54 ++++---- Server/RequestHandler.cpp | 82 ++++++----- Server/RequestHandler.h | 6 +- Server/RequestParser.cpp | 24 ++-- Server/RequestParser.h | 15 +- Server/Server.h | 2 +- .../compression_type.hpp} | 19 +-- Server/{Http/Header.h => http/header.hpp} | 14 +- Server/http/reply.cpp | 130 ++++++++++++++++++ Server/{Http/Reply.h => http/reply.hpp} | 49 +++---- Server/{Http/Request.h => http/request.hpp} | 10 +- 13 files changed, 293 insertions(+), 152 deletions(-) rename Server/{Http/CompressionType.h => http/compression_type.hpp} (84%) rename Server/{Http/Header.h => http/header.hpp} (85%) create mode 100644 Server/http/reply.cpp rename Server/{Http/Reply.h => http/reply.hpp} (55%) rename Server/{Http/Request.h => http/request.hpp} (91%) diff --git a/Server/Connection.cpp b/Server/Connection.cpp index d9686ff31..38f64a116 100644 --- a/Server/Connection.cpp +++ b/Server/Connection.cpp @@ -65,7 +65,7 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t } // no error detected, let's parse the request - CompressionType compression_type(noCompression); + compression_type compression_type(no_compression); osrm::tribool result; std::tie(result, compression_type) = RequestParser().parse( request, incoming_data_buffer.data(), incoming_data_buffer.data() + bytes_transferred); @@ -83,26 +83,26 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t // compress the result w/ gzip/deflate if requested switch (compression_type) { - case deflateRFC1951: + case deflate_rfc1951: // use deflate for compression reply.headers.insert(reply.headers.begin(), {"Content-Encoding", "deflate"}); compressed_output = compress_buffers(reply.content, compression_type); - reply.SetSize(static_cast(compressed_output.size())); - output_buffer = reply.HeaderstoBuffers(); + reply.set_size(static_cast(compressed_output.size())); + output_buffer = reply.headers_to_buffers(); output_buffer.push_back(boost::asio::buffer(compressed_output)); break; - case gzipRFC1952: + case gzip_rfc1952: // use gzip for compression reply.headers.insert(reply.headers.begin(), {"Content-Encoding", "gzip"}); compressed_output = compress_buffers(reply.content, compression_type); - reply.SetSize(static_cast(compressed_output.size())); - output_buffer = reply.HeaderstoBuffers(); + reply.set_size(static_cast(compressed_output.size())); + output_buffer = reply.headers_to_buffers(); output_buffer.push_back(boost::asio::buffer(compressed_output)); break; - case noCompression: + case no_compression: // don't use any compression - reply.SetUncompressedSize(); - output_buffer = reply.ToBuffers(); + reply.set_uncompressed_size(); + output_buffer = reply.to_buffers(); break; } // write result to stream @@ -113,10 +113,10 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t } else if (result == osrm::tribool::no) { // request is not parseable - reply = Reply::StockReply(Reply::badRequest); + reply = reply::stock_reply(reply::bad_request); boost::asio::async_write( - TCP_socket, reply.ToBuffers(), + TCP_socket, reply.to_buffers(), strand.wrap(boost::bind(&Connection::handle_write, this->shared_from_this(), boost::asio::placeholders::error))); } @@ -143,14 +143,14 @@ void Connection::handle_write(const boost::system::error_code &error) } std::vector Connection::compress_buffers(const std::vector &uncompressed_data, - const CompressionType compression_type) + const compression_type compression_type) { boost::iostreams::gzip_params compression_parameters; // there's a trade-off between speed and size. speed wins compression_parameters.level = boost::iostreams::zlib::best_speed; // check which compression flavor is used - if (deflateRFC1951 == compression_type) + if (deflate_rfc1951 == compression_type) { compression_parameters.noheader = true; } diff --git a/Server/Connection.h b/Server/Connection.h index 4624c9fd3..8d0cfda7d 100644 --- a/Server/Connection.h +++ b/Server/Connection.h @@ -28,9 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef CONNECTION_H #define CONNECTION_H -#include "Http/CompressionType.h" -#include "Http/Reply.h" -#include "Http/Request.h" +#include "http/compression_type.hpp" +#include "http/reply.hpp" +#include "http/request.hpp" #include #include @@ -77,14 +77,14 @@ class Connection : public std::enable_shared_from_this void handle_write(const boost::system::error_code &e); std::vector compress_buffers(const std::vector &uncompressed_data, - const CompressionType compression_type); + const compression_type compression_type); boost::asio::io_service::strand strand; boost::asio::ip::tcp::socket TCP_socket; RequestHandler &request_handler; boost::array incoming_data_buffer; - Request request; - Reply reply; + request request; + reply reply; }; } // namespace http diff --git a/Server/Http/Reply.cpp b/Server/Http/Reply.cpp index a03bf38e9..df71489fc 100644 --- a/Server/Http/Reply.cpp +++ b/Server/Http/Reply.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,16 +25,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "Reply.h" +#include "reply.hpp" #include "../../Util/cast.hpp" namespace http { -void Reply::SetSize(const unsigned size) +const char okHTML[] = ""; +const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}"; +const char internalServerErrorHTML[] = + "{\"status\": 500,\"status_message\":\"Internal Server Error\"}"; +const char seperators[] = {':', ' '}; +const char crlf[] = {'\r', '\n'}; +const std::string okString = "HTTP/1.0 200 OK\r\n"; +const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n"; +const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n"; + +void reply::set_size(const std::size_t size) { - for (Header &h : headers) + for (header &h : headers) { if ("Content-Length" == h.name) { @@ -43,14 +53,13 @@ void Reply::SetSize(const unsigned size) } } -// Sets the size of the uncompressed output. -void Reply::SetUncompressedSize() { SetSize(static_cast(content.size())); } +void reply::set_uncompressed_size() { set_size(content.size()); } -std::vector Reply::ToBuffers() +std::vector reply::to_buffers() { std::vector buffers; - buffers.push_back(ToBuffer(status)); - for (const Header &h : headers) + buffers.push_back(status_to_buffer(status)); + for (const header &h : headers) { buffers.push_back(boost::asio::buffer(h.name)); buffers.push_back(boost::asio::buffer(seperators)); @@ -62,13 +71,12 @@ std::vector Reply::ToBuffers() return buffers; } -std::vector Reply::HeaderstoBuffers() +std::vector reply::headers_to_buffers() { std::vector buffers; - buffers.push_back(ToBuffer(status)); - for (std::size_t i = 0; i < headers.size(); ++i) + buffers.push_back(status_to_buffer(status)); + for (const header ¤t_header : headers) { - Header ¤t_header = headers[i]; buffers.push_back(boost::asio::buffer(current_header.name)); buffers.push_back(boost::asio::buffer(seperators)); buffers.push_back(boost::asio::buffer(current_header.value)); @@ -78,13 +86,13 @@ std::vector Reply::HeaderstoBuffers() return buffers; } -Reply Reply::StockReply(Reply::status_type status) +reply reply::stock_reply(const reply::status_type status) { - Reply reply; + reply reply; reply.status = status; reply.content.clear(); - const std::string status_string = reply.ToString(status); + const std::string status_string = reply.status_to_string(status); reply.content.insert(reply.content.end(), status_string.begin(), status_string.end()); reply.headers.emplace_back("Access-Control-Allow-Origin", "*"); reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size())); @@ -92,31 +100,31 @@ Reply Reply::StockReply(Reply::status_type status) return reply; } -std::string Reply::ToString(Reply::status_type status) +std::string reply::status_to_string(const reply::status_type status) { - if (Reply::ok == status) + if (reply::ok == status) { return okHTML; } - if (Reply::badRequest == status) + if (reply::bad_request == status) { return badRequestHTML; } return internalServerErrorHTML; } -boost::asio::const_buffer Reply::ToBuffer(Reply::status_type status) +boost::asio::const_buffer reply::status_to_buffer(const reply::status_type status) { - if (Reply::ok == status) + if (reply::ok == status) { return boost::asio::buffer(okString); } - if (Reply::internalServerError == status) + if (reply::internal_server_error == status) { return boost::asio::buffer(internalServerErrorString); } return boost::asio::buffer(badRequestString); } -Reply::Reply() : status(ok) {} +reply::reply() : status(ok) {} } diff --git a/Server/RequestHandler.cpp b/Server/RequestHandler.cpp index 2b137ad67..1ff82e24e 100644 --- a/Server/RequestHandler.cpp +++ b/Server/RequestHandler.cpp @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "RequestHandler.h" #include "APIGrammar.h" -#include "Http/Reply.h" -#include "Http/Request.h" +#include "http/reply.hpp" +#include "http/request.hpp" #include "../Library/OSRM.h" #include "../Util/json_renderer.hpp" @@ -48,20 +48,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. RequestHandler::RequestHandler() : routing_machine(nullptr) {} -void RequestHandler::handle_request(const http::Request &req, http::Reply &reply) +void RequestHandler::handle_request(const http::request ¤t_request, + http::reply ¤t_reply) { // parse command try { - std::string request; - URIDecode(req.uri, request); + std::string request_string; + URIDecode(current_request.uri, request_string); // deactivated as GCC apparently does not implement that, not even in 4.9 // std::time_t t = std::time(nullptr); // SimpleLogger().Write() << std::put_time(std::localtime(&t), "%m-%d-%Y %H:%M:%S") << - // " " << req.endpoint.to_string() << " " << - // req.referrer << ( 0 == req.referrer.length() ? "- " :" ") << - // req.agent << ( 0 == req.agent.length() ? "- " :" ") << request; + // " " << current_request.endpoint.to_string() << " " << + // current_request.referrer << ( 0 == current_request.referrer.length() ? "- " :" ") << + // current_request.agent << ( 0 == current_request.agent.length() ? "- " :" ") << + // request; time_t ltime; struct tm *time_stamp; @@ -76,29 +78,33 @@ void RequestHandler::handle_request(const http::Request &req, http::Reply &reply << " " << (time_stamp->tm_hour < 10 ? "0" : "") << time_stamp->tm_hour << ":" << (time_stamp->tm_min < 10 ? "0" : "") << time_stamp->tm_min << ":" << (time_stamp->tm_sec < 10 ? "0" : "") - << time_stamp->tm_sec << " " << req.endpoint.to_string() << " " - << req.referrer << (0 == req.referrer.length() ? "- " : " ") - << req.agent << (0 == req.agent.length() ? "- " : " ") << request; + << time_stamp->tm_sec << " " << current_request.endpoint.to_string() + << " " << current_request.referrer + << (0 == current_request.referrer.length() ? "- " : " ") + << current_request.agent + << (0 == current_request.agent.length() ? "- " : " ") + << request_string; RouteParameters route_parameters; APIGrammarParser api_parser(&route_parameters); - auto api_iterator = request.begin(); - const bool result = boost::spirit::qi::parse(api_iterator, request.end(), api_parser); + auto api_iterator = request_string.begin(); + const bool result = + boost::spirit::qi::parse(api_iterator, request_string.end(), api_parser); JSON::Object json_result; // check if the was an error with the request - if (!result || (api_iterator != request.end())) + if (!result || (api_iterator != request_string.end())) { - reply = http::Reply::StockReply(http::Reply::badRequest); - reply.content.clear(); - const auto position = std::distance(request.begin(), api_iterator); + current_reply = http::reply::stock_reply(http::reply::bad_request); + current_reply.content.clear(); + const auto position = std::distance(request_string.begin(), api_iterator); json_result.values["status"] = 400; std::string message = "Query string malformed close to position "; message += cast::integral_to_string(position); json_result.values["status_message"] = message; - JSON::render(reply.content, json_result); + JSON::render(current_reply.content, json_result); return; } @@ -108,50 +114,54 @@ void RequestHandler::handle_request(const http::Request &req, http::Reply &reply if (!route_parameters.jsonp_parameter.empty()) { // prepend response with jsonp parameter const std::string json_p = (route_parameters.jsonp_parameter + "("); - reply.content.insert(reply.content.end(), json_p.begin(), json_p.end()); + current_reply.content.insert(current_reply.content.end(), json_p.begin(), json_p.end()); } const auto return_code = routing_machine->RunQuery(route_parameters, json_result); if (200 != return_code) { - reply = http::Reply::StockReply(http::Reply::badRequest); - reply.content.clear(); + current_reply = http::reply::stock_reply(http::reply::bad_request); + current_reply.content.clear(); json_result.values["status"] = 400; std::string message = "Bad Request"; json_result.values["status_message"] = message; - JSON::render(reply.content, json_result); + JSON::render(current_reply.content, json_result); return; } // set headers - reply.headers.emplace_back("Content-Length", - cast::integral_to_string(reply.content.size())); + current_reply.headers.emplace_back("Content-Length", + cast::integral_to_string(current_reply.content.size())); if ("gpx" == route_parameters.output_format) { // gpx file - JSON::gpx_render(reply.content, json_result.values["route"]); - reply.headers.emplace_back("Content-Type", "application/gpx+xml; charset=UTF-8"); - reply.headers.emplace_back("Content-Disposition", "attachment; filename=\"route.gpx\""); + JSON::gpx_render(current_reply.content, json_result.values["route"]); + current_reply.headers.emplace_back("Content-Type", + "application/gpx+xml; charset=UTF-8"); + current_reply.headers.emplace_back("Content-Disposition", + "attachment; filename=\"route.gpx\""); } else if (route_parameters.jsonp_parameter.empty()) { // json file - JSON::render(reply.content, json_result); - reply.headers.emplace_back("Content-Type", "application/json; charset=UTF-8"); - reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.json\""); + JSON::render(current_reply.content, json_result); + current_reply.headers.emplace_back("Content-Type", "application/json; charset=UTF-8"); + current_reply.headers.emplace_back("Content-Disposition", + "inline; filename=\"response.json\""); } else { // jsonp - JSON::render(reply.content, json_result); - reply.headers.emplace_back("Content-Type", "text/javascript; charset=UTF-8"); - reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.js\""); + JSON::render(current_reply.content, json_result); + current_reply.headers.emplace_back("Content-Type", "text/javascript; charset=UTF-8"); + current_reply.headers.emplace_back("Content-Disposition", + "inline; filename=\"response.js\""); } if (!route_parameters.jsonp_parameter.empty()) { // append brace to jsonp response - reply.content.push_back(')'); + current_reply.content.push_back(')'); } } catch (const std::exception &e) { - reply = http::Reply::StockReply(http::Reply::internalServerError); + current_reply = http::reply::stock_reply(http::reply::internal_server_error); SimpleLogger().Write(logWARNING) << "[server error] code: " << e.what() - << ", uri: " << req.uri; + << ", uri: " << current_request.uri; return; } } diff --git a/Server/RequestHandler.h b/Server/RequestHandler.h index 7263dad4e..2f0fd878f 100644 --- a/Server/RequestHandler.h +++ b/Server/RequestHandler.h @@ -36,8 +36,8 @@ class OSRM; namespace http { -class Reply; -struct Request; +class reply; +struct request; } class RequestHandler @@ -49,7 +49,7 @@ class RequestHandler RequestHandler(); RequestHandler(const RequestHandler &) = delete; - void handle_request(const http::Request &req, http::Reply &rep); + void handle_request(const http::request ¤t_request, http::reply ¤t_reply); void RegisterRoutingMachine(OSRM *osrm); private: diff --git a/Server/RequestParser.cpp b/Server/RequestParser.cpp index bcad9b55b..25bfddf67 100644 --- a/Server/RequestParser.cpp +++ b/Server/RequestParser.cpp @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "RequestParser.h" -#include "Http/Request.h" +#include "http/request.hpp" #include @@ -35,16 +35,16 @@ namespace http { RequestParser::RequestParser() - : state(internal_state::method_start), header({"", ""}), compression_type(noCompression) + : state(internal_state::method_start), header({"", ""}), compression_type(no_compression) { } -std::tuple -RequestParser::parse(Request &request, char *begin, char *end) +std::tuple +RequestParser::parse(request ¤t_request, char *begin, char *end) { while (begin != end) { - osrm::tribool result = consume(request, *begin++); + osrm::tribool result = consume(current_request, *begin++); if (result != osrm::tribool::indeterminate) { return std::make_tuple(result, compression_type); @@ -54,7 +54,7 @@ RequestParser::parse(Request &request, char *begin, char *end) return std::make_tuple(result, compression_type); } -osrm::tribool RequestParser::consume(Request &request, const char input) +osrm::tribool RequestParser::consume(request ¤t_request, const char input) { switch (state) { @@ -82,7 +82,7 @@ osrm::tribool RequestParser::consume(Request &request, const char input) return osrm::tribool::no; } state = internal_state::uri; - request.uri.push_back(input); + current_request.uri.push_back(input); return osrm::tribool::indeterminate; case internal_state::uri: if (input == ' ') @@ -94,7 +94,7 @@ osrm::tribool RequestParser::consume(Request &request, const char input) { return osrm::tribool::no; } - request.uri.push_back(input); + current_request.uri.push_back(input); return osrm::tribool::indeterminate; case internal_state::http_version_h: if (input == 'H') @@ -180,22 +180,22 @@ osrm::tribool RequestParser::consume(Request &request, const char input) /* giving gzip precedence over deflate */ if (boost::icontains(header.value, "deflate")) { - compression_type = deflateRFC1951; + compression_type = deflate_rfc1951; } if (boost::icontains(header.value, "gzip")) { - compression_type = gzipRFC1952; + compression_type = gzip_rfc1952; } } if (boost::iequals(header.name, "Referer")) { - request.referrer = header.value; + current_request.referrer = header.value; } if (boost::iequals(header.name, "User-Agent")) { - request.agent = header.value; + current_request.agent = header.value; } if (input == '\r') diff --git a/Server/RequestParser.h b/Server/RequestParser.h index 791b51513..0df106e68 100644 --- a/Server/RequestParser.h +++ b/Server/RequestParser.h @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef REQUEST_PARSER_H #define REQUEST_PARSER_H -#include "Http/CompressionType.h" -#include "Http/Header.h" +#include "http/compression_type.hpp" +#include "http/header.hpp" #include "../data_structures/tribool.hpp" #include @@ -37,17 +37,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace http { -struct Request; +struct request; class RequestParser { public: RequestParser(); - std::tuple parse(Request &request, char *begin, char *end); + std::tuple + parse(request ¤t_request, char *begin, char *end); private: - osrm::tribool consume(Request &req, const char input); + osrm::tribool consume(request ¤t_request, const char input); bool is_char(const int character) const; @@ -82,8 +83,8 @@ class RequestParser expecting_newline_3 } state; - Header header; - CompressionType compression_type; + header header; + compression_type compression_type; }; } // namespace http diff --git a/Server/Server.h b/Server/Server.h index 0098dd5a5..b3d618efe 100644 --- a/Server/Server.h +++ b/Server/Server.h @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/Server/Http/CompressionType.h b/Server/http/compression_type.hpp similarity index 84% rename from Server/Http/CompressionType.h rename to Server/http/compression_type.hpp index 3836cd749..49163adab 100644 --- a/Server/Http/CompressionType.h +++ b/Server/http/compression_type.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,17 +25,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef COMPRESSION_TYPE_H -#define COMPRESSION_TYPE_H +#ifndef COMPRESSION_TYPE_HPP +#define COMPRESSION_TYPE_HPP namespace http { -enum CompressionType -{ noCompression, - gzipRFC1952, - deflateRFC1951 }; - +enum compression_type +{ + no_compression, + gzip_rfc1952, + deflate_rfc1951 +}; } -#endif // COMPRESSION_TYPE_H +#endif // COMPRESSION_TYPE_HPP diff --git a/Server/Http/Header.h b/Server/http/header.hpp similarity index 85% rename from Server/Http/Header.h rename to Server/http/header.hpp index 12728cecf..8867da6d9 100644 --- a/Server/Http/Header.h +++ b/Server/http/header.hpp @@ -25,19 +25,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef HTTP_HEADER_H -#define HTTP_HEADER_H +#ifndef HEADER_HPP +#define HEADER_HPP #include #include namespace http { -struct Header +struct header { - Header &operator=(const Header &other) = default; - Header(const std::string &name, const std::string &value) : name(name), value(value) {} - Header(Header &&other) : name(std::move(other.name)), value(std::move(other.value)) {} + header &operator=(const header &other) = default; + header(const std::string &name, const std::string &value) : name(name), value(value) {} + header(header &&other) : name(std::move(other.name)), value(std::move(other.value)) {} void clear() { @@ -50,4 +50,4 @@ struct Header }; } -#endif // HTTP_HEADER_H +#endif // HEADER_HPP diff --git a/Server/http/reply.cpp b/Server/http/reply.cpp new file mode 100644 index 000000000..df71489fc --- /dev/null +++ b/Server/http/reply.cpp @@ -0,0 +1,130 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "reply.hpp" + +#include "../../Util/cast.hpp" + +namespace http +{ + +const char okHTML[] = ""; +const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}"; +const char internalServerErrorHTML[] = + "{\"status\": 500,\"status_message\":\"Internal Server Error\"}"; +const char seperators[] = {':', ' '}; +const char crlf[] = {'\r', '\n'}; +const std::string okString = "HTTP/1.0 200 OK\r\n"; +const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n"; +const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n"; + +void reply::set_size(const std::size_t size) +{ + for (header &h : headers) + { + if ("Content-Length" == h.name) + { + h.value = cast::integral_to_string(size); + } + } +} + +void reply::set_uncompressed_size() { set_size(content.size()); } + +std::vector reply::to_buffers() +{ + std::vector buffers; + buffers.push_back(status_to_buffer(status)); + for (const header &h : headers) + { + buffers.push_back(boost::asio::buffer(h.name)); + buffers.push_back(boost::asio::buffer(seperators)); + buffers.push_back(boost::asio::buffer(h.value)); + buffers.push_back(boost::asio::buffer(crlf)); + } + buffers.push_back(boost::asio::buffer(crlf)); + buffers.push_back(boost::asio::buffer(content)); + return buffers; +} + +std::vector reply::headers_to_buffers() +{ + std::vector buffers; + buffers.push_back(status_to_buffer(status)); + for (const header ¤t_header : headers) + { + buffers.push_back(boost::asio::buffer(current_header.name)); + buffers.push_back(boost::asio::buffer(seperators)); + buffers.push_back(boost::asio::buffer(current_header.value)); + buffers.push_back(boost::asio::buffer(crlf)); + } + buffers.push_back(boost::asio::buffer(crlf)); + return buffers; +} + +reply reply::stock_reply(const reply::status_type status) +{ + reply reply; + reply.status = status; + reply.content.clear(); + + const std::string status_string = reply.status_to_string(status); + reply.content.insert(reply.content.end(), status_string.begin(), status_string.end()); + reply.headers.emplace_back("Access-Control-Allow-Origin", "*"); + reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size())); + reply.headers.emplace_back("Content-Type", "text/html"); + return reply; +} + +std::string reply::status_to_string(const reply::status_type status) +{ + if (reply::ok == status) + { + return okHTML; + } + if (reply::bad_request == status) + { + return badRequestHTML; + } + return internalServerErrorHTML; +} + +boost::asio::const_buffer reply::status_to_buffer(const reply::status_type status) +{ + if (reply::ok == status) + { + return boost::asio::buffer(okString); + } + if (reply::internal_server_error == status) + { + return boost::asio::buffer(internalServerErrorString); + } + return boost::asio::buffer(badRequestString); +} + +reply::reply() : status(ok) {} +} diff --git a/Server/Http/Reply.h b/Server/http/reply.hpp similarity index 55% rename from Server/Http/Reply.h rename to Server/http/reply.hpp index a2ee1f486..a4b6cb69b 100644 --- a/Server/Http/Reply.h +++ b/Server/http/reply.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,10 +25,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef REPLY_H -#define REPLY_H +#ifndef REPLY_HPP +#define REPLY_HPP -#include "Header.h" +#include "header.hpp" #include @@ -36,39 +36,30 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace http { - -const char okHTML[] = ""; -const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}"; -const char internalServerErrorHTML[] = - "{\"status\": 500,\"status_message\":\"Internal Server Error\"}"; -const char seperators[] = {':', ' '}; -const char crlf[] = {'\r', '\n'}; -const std::string okString = "HTTP/1.0 200 OK\r\n"; -const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n"; -const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n"; - -class Reply +class reply { public: enum status_type - { ok = 200, - badRequest = 400, - internalServerError = 500 } status; + { + ok = 200, + bad_request = 400, + internal_server_error = 500 + } status; - std::vector
headers; - std::vector ToBuffers(); - std::vector HeaderstoBuffers(); + std::vector
headers; + std::vector to_buffers(); + std::vector headers_to_buffers(); std::vector content; - static Reply StockReply(status_type status); - void SetSize(const unsigned size); - void SetUncompressedSize(); + static reply stock_reply(const status_type status); + void set_size(const std::size_t size); + void set_uncompressed_size(); - Reply(); + reply(); private: - std::string ToString(Reply::status_type status); - boost::asio::const_buffer ToBuffer(Reply::status_type status); + std::string status_to_string(reply::status_type status); + boost::asio::const_buffer status_to_buffer(reply::status_type status); }; } -#endif // REPLY_H +#endif // REPLY_HPP diff --git a/Server/Http/Request.h b/Server/http/request.hpp similarity index 91% rename from Server/Http/Request.h rename to Server/http/request.hpp index 4746a5ec2..0ad622580 100644 --- a/Server/Http/Request.h +++ b/Server/http/request.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef REQUEST_H -#define REQUEST_H +#ifndef REQUEST_HPP +#define REQUEST_HPP #include @@ -35,7 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace http { -struct Request +struct request { std::string uri; std::string referrer; @@ -45,4 +45,4 @@ struct Request } // namespace http -#endif // REQUEST_H +#endif // REQUEST_HPP From 872cb2d9c8046ae50c3abc486c5ae0f353a18ace Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 11:52:56 +0100 Subject: [PATCH 127/360] rename string literal names to replace odd camel case --- Server/Http/Reply.cpp | 24 ++++++++++++------------ Server/http/header.hpp | 1 + Server/http/reply.cpp | 24 ++++++++++++------------ 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/Server/Http/Reply.cpp b/Server/Http/Reply.cpp index df71489fc..89b931b05 100644 --- a/Server/Http/Reply.cpp +++ b/Server/Http/Reply.cpp @@ -32,15 +32,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace http { -const char okHTML[] = ""; -const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}"; -const char internalServerErrorHTML[] = +const char ok_html[] = ""; +const char bad_request_html[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}"; +const char internal_server_error_html[] = "{\"status\": 500,\"status_message\":\"Internal Server Error\"}"; const char seperators[] = {':', ' '}; const char crlf[] = {'\r', '\n'}; -const std::string okString = "HTTP/1.0 200 OK\r\n"; -const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n"; -const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n"; +const std::string http_ok_string = "HTTP/1.0 200 OK\r\n"; +const std::string http_bad_request_string = "HTTP/1.0 400 Bad Request\r\n"; +const std::string http_internal_server_error_string = "HTTP/1.0 500 Internal Server Error\r\n"; void reply::set_size(const std::size_t size) { @@ -104,26 +104,26 @@ std::string reply::status_to_string(const reply::status_type status) { if (reply::ok == status) { - return okHTML; + return ok_html; } if (reply::bad_request == status) { - return badRequestHTML; + return bad_request_html; } - return internalServerErrorHTML; + return internal_server_error_html; } boost::asio::const_buffer reply::status_to_buffer(const reply::status_type status) { if (reply::ok == status) { - return boost::asio::buffer(okString); + return boost::asio::buffer(http_ok_string); } if (reply::internal_server_error == status) { - return boost::asio::buffer(internalServerErrorString); + return boost::asio::buffer(http_internal_server_error_string); } - return boost::asio::buffer(badRequestString); + return boost::asio::buffer(http_bad_request_string); } reply::reply() : status(ok) {} diff --git a/Server/http/header.hpp b/Server/http/header.hpp index 8867da6d9..7996be439 100644 --- a/Server/http/header.hpp +++ b/Server/http/header.hpp @@ -35,6 +35,7 @@ namespace http { struct header { + // explicitly use default copy c'tor as adding move c'tor header &operator=(const header &other) = default; header(const std::string &name, const std::string &value) : name(name), value(value) {} header(header &&other) : name(std::move(other.name)), value(std::move(other.value)) {} diff --git a/Server/http/reply.cpp b/Server/http/reply.cpp index df71489fc..89b931b05 100644 --- a/Server/http/reply.cpp +++ b/Server/http/reply.cpp @@ -32,15 +32,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace http { -const char okHTML[] = ""; -const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}"; -const char internalServerErrorHTML[] = +const char ok_html[] = ""; +const char bad_request_html[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}"; +const char internal_server_error_html[] = "{\"status\": 500,\"status_message\":\"Internal Server Error\"}"; const char seperators[] = {':', ' '}; const char crlf[] = {'\r', '\n'}; -const std::string okString = "HTTP/1.0 200 OK\r\n"; -const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n"; -const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n"; +const std::string http_ok_string = "HTTP/1.0 200 OK\r\n"; +const std::string http_bad_request_string = "HTTP/1.0 400 Bad Request\r\n"; +const std::string http_internal_server_error_string = "HTTP/1.0 500 Internal Server Error\r\n"; void reply::set_size(const std::size_t size) { @@ -104,26 +104,26 @@ std::string reply::status_to_string(const reply::status_type status) { if (reply::ok == status) { - return okHTML; + return ok_html; } if (reply::bad_request == status) { - return badRequestHTML; + return bad_request_html; } - return internalServerErrorHTML; + return internal_server_error_html; } boost::asio::const_buffer reply::status_to_buffer(const reply::status_type status) { if (reply::ok == status) { - return boost::asio::buffer(okString); + return boost::asio::buffer(http_ok_string); } if (reply::internal_server_error == status) { - return boost::asio::buffer(internalServerErrorString); + return boost::asio::buffer(http_internal_server_error_string); } - return boost::asio::buffer(badRequestString); + return boost::asio::buffer(http_bad_request_string); } reply::reply() : status(ok) {} From 0c1101739dbf8e13441075339d8a3b3341b52c82 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 12:14:08 +0100 Subject: [PATCH 128/360] renamed: Server/DataStructures/*.h -> Server/data_structures/*.hpp --- CMakeLists.txt | 2 +- Library/OSRM_impl.cpp | 25 +-- .../datafacade_base.hpp} | 8 +- .../internal_datafacade.hpp} | 34 ++-- .../shared_barriers.hpp} | 8 +- .../shared_datafacade.hpp} | 54 +++--- .../shared_datatype.hpp} | 158 +++++++++++------- cmake/FingerPrint-Config.cmake | 2 +- datastore.cpp | 6 +- tools/springclean.cpp | 6 +- tools/unlock_all_mutexes.cpp | 2 +- 11 files changed, 164 insertions(+), 141 deletions(-) rename Server/{DataStructures/BaseDataFacade.h => data_structures/datafacade_base.hpp} (97%) rename Server/{DataStructures/InternalDataFacade.h => data_structures/internal_datafacade.hpp} (95%) rename Server/{DataStructures/SharedBarriers.h => data_structures/shared_barriers.hpp} (94%) rename Server/{DataStructures/SharedDataFacade.h => data_structures/shared_datafacade.hpp} (91%) rename Server/{DataStructures/SharedDataType.h => data_structures/shared_datatype.hpp} (53%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7428b191b..14703f433 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,7 +75,7 @@ file(GLOB DatastructureGlob data_structures/search_engine_data.cpp data_structur list(REMOVE_ITEM DatastructureGlob data_structures/Coordinate.cpp) file(GLOB CoordinateGlob data_structures/coordinate*.cpp) file(GLOB AlgorithmGlob algorithms/*.cpp) -file(GLOB HttpGlob Server/Http/*.cpp) +file(GLOB HttpGlob Server/http/*.cpp) file(GLOB LibOSRMGlob Library/*.cpp) file(GLOB DataStructureTestsGlob unit_tests/data_structures/*.cpp data_structures/hilbert_value.cpp) file(GLOB AlgorithmTestsGlob unit_tests/algorithms/*.cpp) diff --git a/Library/OSRM_impl.cpp b/Library/OSRM_impl.cpp index aa8eb3d1e..4a9fdbd76 100644 --- a/Library/OSRM_impl.cpp +++ b/Library/OSRM_impl.cpp @@ -25,7 +25,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -namespace boost { namespace interprocess { class named_mutex; } } +namespace boost +{ +namespace interprocess +{ +class named_mutex; +} +} #include "OSRM_impl.h" #include "OSRM.h" @@ -36,10 +42,10 @@ namespace boost { namespace interprocess { class named_mutex; } } #include "../plugins/nearest.hpp" #include "../plugins/timestamp.hpp" #include "../plugins/viaroute.hpp" -#include "../Server/DataStructures/BaseDataFacade.h" -#include "../Server/DataStructures/InternalDataFacade.h" -#include "../Server/DataStructures/SharedBarriers.h" -#include "../Server/DataStructures/SharedDataFacade.h" +#include "../Server/data_structures/datafacade_base.hpp" +#include "../Server/data_structures/internal_datafacade.hpp" +#include "../Server/data_structures/shared_barriers.hpp" +#include "../Server/data_structures/shared_datafacade.hpp" #include "../Util/make_unique.hpp" #include "../Util/ProgramOptions.h" #include "../Util/simple_logger.hpp" @@ -70,8 +76,8 @@ OSRM_impl::OSRM_impl(libosrm_config &lib_config) } // The following plugins handle all requests. - RegisterPlugin(new DistanceTablePlugin>(query_data_facade, - lib_config.max_locations_distance_table)); + RegisterPlugin(new DistanceTablePlugin>( + query_data_facade, lib_config.max_locations_distance_table)); RegisterPlugin(new HelloWorldPlugin()); RegisterPlugin(new LocatePlugin>(query_data_facade)); RegisterPlugin(new NearestPlugin>(query_data_facade)); @@ -162,10 +168,7 @@ void OSRM_impl::increase_concurrent_query_count() } // proxy code for compilation firewall -OSRM::OSRM(libosrm_config &lib_config) - : OSRM_pimpl_(osrm::make_unique(lib_config)) -{ -} +OSRM::OSRM(libosrm_config &lib_config) : OSRM_pimpl_(osrm::make_unique(lib_config)) {} OSRM::~OSRM() { OSRM_pimpl_.reset(); } diff --git a/Server/DataStructures/BaseDataFacade.h b/Server/data_structures/datafacade_base.hpp similarity index 97% rename from Server/DataStructures/BaseDataFacade.h rename to Server/data_structures/datafacade_base.hpp index 9ba454f19..2de79f915 100644 --- a/Server/DataStructures/BaseDataFacade.h +++ b/Server/data_structures/datafacade_base.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BASE_DATA_FACADE_H -#define BASE_DATA_FACADE_H +#ifndef DATAFACADE_BASE_HPP +#define DATAFACADE_BASE_HPP // Exposes all data access interfaces to the algorithms via base class ptr @@ -123,4 +123,4 @@ template class BaseDataFacade virtual std::string GetTimestamp() const = 0; }; -#endif // BASE_DATA_FACADE_H +#endif // DATAFACADE_BASE_HPP diff --git a/Server/DataStructures/InternalDataFacade.h b/Server/data_structures/internal_datafacade.hpp similarity index 95% rename from Server/DataStructures/InternalDataFacade.h rename to Server/data_structures/internal_datafacade.hpp index 15927c785..a9949e383 100644 --- a/Server/DataStructures/InternalDataFacade.h +++ b/Server/data_structures/internal_datafacade.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,12 +25,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef INTERNAL_DATA_FACADE -#define INTERNAL_DATA_FACADE +#ifndef INTERNAL_DATAFACADE_HPP +#define INTERNAL_DATAFACADE_HPP // implements all data storage when shared memory is _NOT_ used -#include "BaseDataFacade.h" +#include "datafacade_base.hpp" #include "../../data_structures/original_edge_data.hpp" #include "../../data_structures/query_node.hpp" @@ -359,10 +359,7 @@ template class InternalDataFacade : public BaseDataFacade class InternalDataFacade : public BaseDataFacadeLocateClosestEndPointForCoordinate( - input_coordinate, result, zoom_level); + return m_static_rtree->LocateClosestEndPointForCoordinate(input_coordinate, result, + zoom_level); } - bool - IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, - PhantomNode &resulting_phantom_node) final + bool IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, + PhantomNode &resulting_phantom_node) final { std::vector resulting_phantom_node_vector; auto result = IncrementalFindPhantomNodeForCoordinate(input_coordinate, - resulting_phantom_node_vector, - 1); + resulting_phantom_node_vector, 1); if (result) { BOOST_ASSERT(!resulting_phantom_node_vector.empty()); @@ -428,8 +423,7 @@ template class InternalDataFacade : public BaseDataFacade class InternalDataFacade : public BaseDataFacade #include @@ -57,4 +57,4 @@ struct SharedBarriers int number_of_queries; }; -#endif // SHARED_BARRIER_H +#endif // SHARED_BARRIERS_HPP diff --git a/Server/DataStructures/SharedDataFacade.h b/Server/data_structures/shared_datafacade.hpp similarity index 91% rename from Server/DataStructures/SharedDataFacade.h rename to Server/data_structures/shared_datafacade.hpp index 9120f8236..11a295e27 100644 --- a/Server/DataStructures/SharedDataFacade.h +++ b/Server/data_structures/shared_datafacade.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,13 +25,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SHARED_DATA_FACADE_H -#define SHARED_DATA_FACADE_H +#ifndef SHARED_DATAFACADE_HPP +#define SHARED_DATAFACADE_HPP // implements all data storage when shared memory _IS_ used -#include "BaseDataFacade.h" -#include "SharedDataType.h" +#include "datafacade_base.hpp" +#include "shared_datatype.hpp" #include "../../data_structures/range_table.hpp" #include "../../data_structures/static_graph.hpp" @@ -112,12 +112,11 @@ template class SharedDataFacade : public BaseDataFacadeGetBlockPtr(shared_memory, SharedDataLayout::R_SEARCH_TREE); - m_static_rtree.reset(new TimeStampedRTreePair(CURRENT_TIMESTAMP, + m_static_rtree.reset(new TimeStampedRTreePair( + CURRENT_TIMESTAMP, osrm::make_unique( - tree_ptr, - data_layout->num_entries[SharedDataLayout::R_SEARCH_TREE], - file_index_path, - m_coordinate_list))); + tree_ptr, data_layout->num_entries[SharedDataLayout::R_SEARCH_TREE], + file_index_path, m_coordinate_list))); } void LoadGraph() @@ -143,11 +142,10 @@ template class SharedDataFacade : public BaseDataFacade::vector>( coordinate_list_ptr, data_layout->num_entries[SharedDataLayout::COORDINATE_LIST]); - TravelMode *travel_mode_list_ptr = data_layout->GetBlockPtr( - shared_memory, SharedDataLayout::TRAVEL_MODE); + TravelMode *travel_mode_list_ptr = + data_layout->GetBlockPtr(shared_memory, SharedDataLayout::TRAVEL_MODE); typename ShM::vector travel_mode_list( - travel_mode_list_ptr, - data_layout->num_entries[SharedDataLayout::TRAVEL_MODE]); + travel_mode_list_ptr, data_layout->num_entries[SharedDataLayout::TRAVEL_MODE]); m_travel_mode_list.swap(travel_mode_list); TurnInstruction *turn_instruction_list_ptr = data_layout->GetBlockPtr( @@ -259,7 +257,7 @@ template class SharedDataFacade : public BaseDataFacade class SharedDataFacade : public BaseDataFacade class SharedDataFacade : public BaseDataFacade class SharedDataFacade : public BaseDataFacadesecond->LocateClosestEndPointForCoordinate( - input_coordinate, result, zoom_level); + return m_static_rtree->second->LocateClosestEndPointForCoordinate(input_coordinate, result, + zoom_level); } - bool - IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, - PhantomNode &resulting_phantom_node) final + bool IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, + PhantomNode &resulting_phantom_node) final { std::vector resulting_phantom_node_vector; auto result = IncrementalFindPhantomNodeForCoordinate(input_coordinate, - resulting_phantom_node_vector, - 1); + resulting_phantom_node_vector, 1); if (result) { BOOST_ASSERT(!resulting_phantom_node_vector.empty()); @@ -420,12 +413,11 @@ template class SharedDataFacade : public BaseDataFacade +namespace +{ // Added at the start and end of each block as sanity check -static const char CANARY[] = "OSRM"; +constexpr static const char CANARY[] = "OSRM"; +} struct SharedDataLayout { - enum BlockID { + enum BlockID + { NAME_OFFSETS = 0, NAME_BLOCKS, NAME_CHAR_LIST, @@ -64,54 +68,81 @@ struct SharedDataLayout std::array num_entries; std::array entry_size; - SharedDataLayout() - : num_entries() - , entry_size() - { - } + SharedDataLayout() : num_entries(), entry_size() {} void PrintInformation() const { SimpleLogger().Write(logDEBUG) << "-"; - SimpleLogger().Write(logDEBUG) << "name_offsets_size: " << num_entries[NAME_OFFSETS]; - SimpleLogger().Write(logDEBUG) << "name_blocks_size: " << num_entries[NAME_BLOCKS]; - SimpleLogger().Write(logDEBUG) << "name_char_list_size: " << num_entries[NAME_CHAR_LIST]; - SimpleLogger().Write(logDEBUG) << "name_id_list_size: " << num_entries[NAME_ID_LIST]; - SimpleLogger().Write(logDEBUG) << "via_node_list_size: " << num_entries[VIA_NODE_LIST]; - SimpleLogger().Write(logDEBUG) << "graph_node_list_size: " << num_entries[GRAPH_NODE_LIST]; - SimpleLogger().Write(logDEBUG) << "graph_edge_list_size: " << num_entries[GRAPH_EDGE_LIST]; + SimpleLogger().Write(logDEBUG) + << "name_offsets_size: " << num_entries[NAME_OFFSETS]; + SimpleLogger().Write(logDEBUG) + << "name_blocks_size: " << num_entries[NAME_BLOCKS]; + SimpleLogger().Write(logDEBUG) + << "name_char_list_size: " << num_entries[NAME_CHAR_LIST]; + SimpleLogger().Write(logDEBUG) + << "name_id_list_size: " << num_entries[NAME_ID_LIST]; + SimpleLogger().Write(logDEBUG) + << "via_node_list_size: " << num_entries[VIA_NODE_LIST]; + SimpleLogger().Write(logDEBUG) + << "graph_node_list_size: " << num_entries[GRAPH_NODE_LIST]; + SimpleLogger().Write(logDEBUG) + << "graph_edge_list_size: " << num_entries[GRAPH_EDGE_LIST]; SimpleLogger().Write(logDEBUG) << "timestamp_length: " << num_entries[TIMESTAMP]; - SimpleLogger().Write(logDEBUG) << "coordinate_list_size: " << num_entries[COORDINATE_LIST]; - SimpleLogger().Write(logDEBUG) << "turn_instruction_list_size: " << num_entries[TURN_INSTRUCTION]; - SimpleLogger().Write(logDEBUG) << "travel_mode_list_size: " << num_entries[TRAVEL_MODE]; - SimpleLogger().Write(logDEBUG) << "r_search_tree_size: " << num_entries[R_SEARCH_TREE]; - SimpleLogger().Write(logDEBUG) << "geometries_indicators: " << num_entries[GEOMETRIES_INDICATORS] - << "/" << ((num_entries[GEOMETRIES_INDICATORS] / 8) + 1); - SimpleLogger().Write(logDEBUG) << "geometries_index_list_size: " << num_entries[GEOMETRIES_INDEX]; - SimpleLogger().Write(logDEBUG) << "geometries_list_size: " << num_entries[GEOMETRIES_LIST]; - SimpleLogger().Write(logDEBUG) << "sizeof(checksum): " << entry_size[HSGR_CHECKSUM]; + SimpleLogger().Write(logDEBUG) + << "coordinate_list_size: " << num_entries[COORDINATE_LIST]; + SimpleLogger().Write(logDEBUG) + << "turn_instruction_list_size: " << num_entries[TURN_INSTRUCTION]; + SimpleLogger().Write(logDEBUG) + << "travel_mode_list_size: " << num_entries[TRAVEL_MODE]; + SimpleLogger().Write(logDEBUG) + << "r_search_tree_size: " << num_entries[R_SEARCH_TREE]; + SimpleLogger().Write(logDEBUG) + << "geometries_indicators: " << num_entries[GEOMETRIES_INDICATORS] << "/" + << ((num_entries[GEOMETRIES_INDICATORS] / 8) + 1); + SimpleLogger().Write(logDEBUG) + << "geometries_index_list_size: " << num_entries[GEOMETRIES_INDEX]; + SimpleLogger().Write(logDEBUG) + << "geometries_list_size: " << num_entries[GEOMETRIES_LIST]; + SimpleLogger().Write(logDEBUG) + << "sizeof(checksum): " << entry_size[HSGR_CHECKSUM]; - SimpleLogger().Write(logDEBUG) << "NAME_OFFSETS " << ": " << GetBlockSize(NAME_OFFSETS ); - SimpleLogger().Write(logDEBUG) << "NAME_BLOCKS " << ": " << GetBlockSize(NAME_BLOCKS ); - SimpleLogger().Write(logDEBUG) << "NAME_CHAR_LIST " << ": " << GetBlockSize(NAME_CHAR_LIST ); - SimpleLogger().Write(logDEBUG) << "NAME_ID_LIST " << ": " << GetBlockSize(NAME_ID_LIST ); - SimpleLogger().Write(logDEBUG) << "VIA_NODE_LIST " << ": " << GetBlockSize(VIA_NODE_LIST ); - SimpleLogger().Write(logDEBUG) << "GRAPH_NODE_LIST " << ": " << GetBlockSize(GRAPH_NODE_LIST ); - SimpleLogger().Write(logDEBUG) << "GRAPH_EDGE_LIST " << ": " << GetBlockSize(GRAPH_EDGE_LIST ); - SimpleLogger().Write(logDEBUG) << "COORDINATE_LIST " << ": " << GetBlockSize(COORDINATE_LIST ); - SimpleLogger().Write(logDEBUG) << "TURN_INSTRUCTION " << ": " << GetBlockSize(TURN_INSTRUCTION ); - SimpleLogger().Write(logDEBUG) << "TRAVEL_MODE " << ": " << GetBlockSize(TRAVEL_MODE ); - SimpleLogger().Write(logDEBUG) << "R_SEARCH_TREE " << ": " << GetBlockSize(R_SEARCH_TREE ); - SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDEX " << ": " << GetBlockSize(GEOMETRIES_INDEX ); - SimpleLogger().Write(logDEBUG) << "GEOMETRIES_LIST " << ": " << GetBlockSize(GEOMETRIES_LIST ); - SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDICATORS" << ": " << GetBlockSize(GEOMETRIES_INDICATORS); - SimpleLogger().Write(logDEBUG) << "HSGR_CHECKSUM " << ": " << GetBlockSize(HSGR_CHECKSUM ); - SimpleLogger().Write(logDEBUG) << "TIMESTAMP " << ": " << GetBlockSize(TIMESTAMP ); - SimpleLogger().Write(logDEBUG) << "FILE_INDEX_PATH " << ": " << GetBlockSize(FILE_INDEX_PATH ); + SimpleLogger().Write(logDEBUG) << "NAME_OFFSETS " + << ": " << GetBlockSize(NAME_OFFSETS); + SimpleLogger().Write(logDEBUG) << "NAME_BLOCKS " + << ": " << GetBlockSize(NAME_BLOCKS); + SimpleLogger().Write(logDEBUG) << "NAME_CHAR_LIST " + << ": " << GetBlockSize(NAME_CHAR_LIST); + SimpleLogger().Write(logDEBUG) << "NAME_ID_LIST " + << ": " << GetBlockSize(NAME_ID_LIST); + SimpleLogger().Write(logDEBUG) << "VIA_NODE_LIST " + << ": " << GetBlockSize(VIA_NODE_LIST); + SimpleLogger().Write(logDEBUG) << "GRAPH_NODE_LIST " + << ": " << GetBlockSize(GRAPH_NODE_LIST); + SimpleLogger().Write(logDEBUG) << "GRAPH_EDGE_LIST " + << ": " << GetBlockSize(GRAPH_EDGE_LIST); + SimpleLogger().Write(logDEBUG) << "COORDINATE_LIST " + << ": " << GetBlockSize(COORDINATE_LIST); + SimpleLogger().Write(logDEBUG) << "TURN_INSTRUCTION " + << ": " << GetBlockSize(TURN_INSTRUCTION); + SimpleLogger().Write(logDEBUG) << "TRAVEL_MODE " + << ": " << GetBlockSize(TRAVEL_MODE); + SimpleLogger().Write(logDEBUG) << "R_SEARCH_TREE " + << ": " << GetBlockSize(R_SEARCH_TREE); + SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDEX " + << ": " << GetBlockSize(GEOMETRIES_INDEX); + SimpleLogger().Write(logDEBUG) << "GEOMETRIES_LIST " + << ": " << GetBlockSize(GEOMETRIES_LIST); + SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDICATORS" + << ": " << GetBlockSize(GEOMETRIES_INDICATORS); + SimpleLogger().Write(logDEBUG) << "HSGR_CHECKSUM " + << ": " << GetBlockSize(HSGR_CHECKSUM); + SimpleLogger().Write(logDEBUG) << "TIMESTAMP " + << ": " << GetBlockSize(TIMESTAMP); + SimpleLogger().Write(logDEBUG) << "FILE_INDEX_PATH " + << ": " << GetBlockSize(FILE_INDEX_PATH); } - template - inline void SetBlockSize(BlockID bid, uint64_t entries) + template inline void SetBlockSize(BlockID bid, uint64_t entries) { num_entries[bid] = entries; entry_size[bid] = sizeof(T); @@ -122,7 +153,8 @@ struct SharedDataLayout // special encoding if (bid == GEOMETRIES_INDICATORS) { - return (num_entries[GEOMETRIES_INDICATORS]/32 + 1) * entry_size[GEOMETRIES_INDICATORS]; + return (num_entries[GEOMETRIES_INDICATORS] / 32 + 1) * + entry_size[GEOMETRIES_INDICATORS]; } return num_entries[bid] * entry_size[bid]; @@ -130,7 +162,7 @@ struct SharedDataLayout inline uint64_t GetSizeOfLayout() const { - return GetBlockOffset(NUM_BLOCKS) + NUM_BLOCKS*2*sizeof(CANARY); + return GetBlockOffset(NUM_BLOCKS) + NUM_BLOCKS * 2 * sizeof(CANARY); } inline uint64_t GetBlockOffset(BlockID bid) const @@ -138,26 +170,26 @@ struct SharedDataLayout uint64_t result = sizeof(CANARY); for (auto i = 0; i < bid; i++) { - result += GetBlockSize((BlockID) i) + 2*sizeof(CANARY); + result += GetBlockSize((BlockID)i) + 2 * sizeof(CANARY); } return result; } - template - inline T* GetBlockPtr(char* shared_memory, BlockID bid) + template + inline T *GetBlockPtr(char *shared_memory, BlockID bid) { - T* ptr = (T*)(shared_memory + GetBlockOffset(bid)); + T *ptr = (T *)(shared_memory + GetBlockOffset(bid)); if (WRITE_CANARY) { - char* start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY); - char* end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid); + char *start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY); + char *end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid); std::copy(CANARY, CANARY + sizeof(CANARY), start_canary_ptr); std::copy(CANARY, CANARY + sizeof(CANARY), end_canary_ptr); } else { - char* start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY); - char* end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid); + char *start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY); + char *end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid); bool start_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), start_canary_ptr); bool end_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), end_canary_ptr); if (!start_canary_alive) @@ -175,13 +207,15 @@ struct SharedDataLayout }; enum SharedDataType -{ CURRENT_REGIONS, - LAYOUT_1, - DATA_1, - LAYOUT_2, - DATA_2, - LAYOUT_NONE, - DATA_NONE }; +{ + CURRENT_REGIONS, + LAYOUT_1, + DATA_1, + LAYOUT_2, + DATA_2, + LAYOUT_NONE, + DATA_NONE +}; struct SharedDataTimestamp { @@ -190,4 +224,4 @@ struct SharedDataTimestamp unsigned timestamp; }; -#endif /* SHARED_DATA_TYPE_H_ */ +#endif /* SHARED_DATA_TYPE_HPP */ diff --git a/cmake/FingerPrint-Config.cmake b/cmake/FingerPrint-Config.cmake index 7d0de9122..9ea843519 100644 --- a/cmake/FingerPrint-Config.cmake +++ b/cmake/FingerPrint-Config.cmake @@ -5,6 +5,6 @@ endif() file(MD5 ${SOURCE_DIR}/prepare.cpp MD5PREPARE) file(MD5 ${SOURCE_DIR}/data_structures/static_rtree.hpp MD5RTREE) file(MD5 ${SOURCE_DIR}/Util/graph_loader.hpp MD5GRAPH) -file(MD5 ${SOURCE_DIR}/Server/DataStructures/InternalDataFacade.h MD5OBJECTS) +file(MD5 ${SOURCE_DIR}/server/data_structures/internal_datafacade.hpp MD5OBJECTS) CONFIGURE_FILE( ${SOURCE_DIR}/Util/fingerprint.cpp.in ${SOURCE_DIR}/Util/fingerprint.cpp ) diff --git a/datastore.cpp b/datastore.cpp index 14bde95bd..9acb4fe57 100644 --- a/datastore.cpp +++ b/datastore.cpp @@ -33,9 +33,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "data_structures/static_graph.hpp" #include "data_structures/static_rtree.hpp" #include "data_structures/turn_instructions.hpp" -#include "Server/DataStructures/BaseDataFacade.h" -#include "Server/DataStructures/SharedDataType.h" -#include "Server/DataStructures/SharedBarriers.h" +#include "Server/data_structures/datafacade_base.hpp" +#include "Server/data_structures/shared_datatype.hpp" +#include "Server/data_structures/shared_barriers.hpp" #include "Util/BoostFileSystemFix.h" #include "Util/DataStoreOptions.h" #include "Util/simple_logger.hpp" diff --git a/tools/springclean.cpp b/tools/springclean.cpp index 878940ae2..7cf98e9e3 100644 --- a/tools/springclean.cpp +++ b/tools/springclean.cpp @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "../data_structures/shared_memory_factory.hpp" -#include "../Server/DataStructures/SharedDataType.h" +#include "../Server/data_structures/shared_datatype.hpp" #include "../Util/git_sha.hpp" #include "../Util/simple_logger.hpp" @@ -83,8 +83,8 @@ int main() SimpleLogger().Write() << "----------------------"; SimpleLogger().Write() << "This tool may put osrm-routed into an undefined state!"; SimpleLogger().Write() << "Type 'Y' to acknowledge that you know what your are doing."; - SimpleLogger().Write() << "\n\nDo you want to purge all shared memory allocated " << - "by osrm-datastore? [type 'Y' to confirm]"; + SimpleLogger().Write() << "\n\nDo you want to purge all shared memory allocated " + << "by osrm-datastore? [type 'Y' to confirm]"; const auto letter = getchar(); if (letter != 'Y') diff --git a/tools/unlock_all_mutexes.cpp b/tools/unlock_all_mutexes.cpp index faef736f7..78fa6dcbf 100644 --- a/tools/unlock_all_mutexes.cpp +++ b/tools/unlock_all_mutexes.cpp @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../Util/git_sha.hpp" #include "../Util/simple_logger.hpp" -#include "../Server/DataStructures/SharedBarriers.h" +#include "../Server/data_structures/shared_barriers.hpp" #include From 9672f00ec319c41c811714cce6a5c9c5a063a4f7 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 12:35:29 +0100 Subject: [PATCH 129/360] renamed: Server/*/*.h -> server/*/*.hpp --- CMakeLists.txt | 4 +- Library/OSRM_impl.cpp | 8 +- Server/APIGrammar.h | 74 --- Server/Connection.cpp | 6 +- Util/ProgramOptions.h | 37 +- datastore.cpp | 6 +- routed.cpp | 2 +- server/Http/Reply.cpp | 130 +++++ server/api_grammar.hpp | 92 ++++ server/connection.cpp | 168 +++++++ Server/Connection.h => server/connection.hpp | 6 +- server/data_structures/datafacade_base.hpp | 126 +++++ .../data_structures/internal_datafacade.hpp | 449 ++++++++++++++++++ server/data_structures/shared_barriers.hpp | 60 +++ server/data_structures/shared_datafacade.hpp | 423 +++++++++++++++++ server/data_structures/shared_datatype.hpp | 227 +++++++++ server/http/compression_type.hpp | 42 ++ server/http/header.hpp | 54 +++ server/http/reply.cpp | 130 +++++ server/http/reply.hpp | 65 +++ server/http/request.hpp | 48 ++ .../request_handler.cpp | 6 +- .../request_handler.hpp | 8 +- .../request_parser.cpp | 2 +- .../request_parser.hpp | 6 +- Server/Server.h => server/server.hpp | 10 +- tools/springclean.cpp | 2 +- tools/unlock_all_mutexes.cpp | 2 +- 28 files changed, 2061 insertions(+), 132 deletions(-) delete mode 100644 Server/APIGrammar.h create mode 100644 server/Http/Reply.cpp create mode 100644 server/api_grammar.hpp create mode 100644 server/connection.cpp rename Server/Connection.h => server/connection.hpp (97%) create mode 100644 server/data_structures/datafacade_base.hpp create mode 100644 server/data_structures/internal_datafacade.hpp create mode 100644 server/data_structures/shared_barriers.hpp create mode 100644 server/data_structures/shared_datafacade.hpp create mode 100644 server/data_structures/shared_datatype.hpp create mode 100644 server/http/compression_type.hpp create mode 100644 server/http/header.hpp create mode 100644 server/http/reply.cpp create mode 100644 server/http/reply.hpp create mode 100644 server/http/request.hpp rename Server/RequestHandler.cpp => server/request_handler.cpp (98%) rename Server/RequestHandler.h => server/request_handler.hpp (92%) rename Server/RequestParser.cpp => server/request_parser.cpp (99%) rename Server/RequestParser.h => server/request_parser.hpp (96%) rename Server/Server.h => server/server.hpp (97%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 14703f433..7d9a6906d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,13 +69,13 @@ file(GLOB PrepareGlob contractor/*.cpp data_structures/hilbert_value.cpp Util/co set(PrepareSources prepare.cpp ${PrepareGlob}) add_executable(osrm-prepare ${PrepareSources} $ $ $ $ $ $ $ $) -file(GLOB ServerGlob Server/*.cpp) +file(GLOB ServerGlob server/*.cpp) file(GLOB DescriptorGlob descriptors/*.cpp) file(GLOB DatastructureGlob data_structures/search_engine_data.cpp data_structures/route_parameters.cpp Util/bearing.cpp) list(REMOVE_ITEM DatastructureGlob data_structures/Coordinate.cpp) file(GLOB CoordinateGlob data_structures/coordinate*.cpp) file(GLOB AlgorithmGlob algorithms/*.cpp) -file(GLOB HttpGlob Server/http/*.cpp) +file(GLOB HttpGlob server/http/*.cpp) file(GLOB LibOSRMGlob Library/*.cpp) file(GLOB DataStructureTestsGlob unit_tests/data_structures/*.cpp data_structures/hilbert_value.cpp) file(GLOB AlgorithmTestsGlob unit_tests/algorithms/*.cpp) diff --git a/Library/OSRM_impl.cpp b/Library/OSRM_impl.cpp index 4a9fdbd76..cbb33a904 100644 --- a/Library/OSRM_impl.cpp +++ b/Library/OSRM_impl.cpp @@ -42,10 +42,10 @@ class named_mutex; #include "../plugins/nearest.hpp" #include "../plugins/timestamp.hpp" #include "../plugins/viaroute.hpp" -#include "../Server/data_structures/datafacade_base.hpp" -#include "../Server/data_structures/internal_datafacade.hpp" -#include "../Server/data_structures/shared_barriers.hpp" -#include "../Server/data_structures/shared_datafacade.hpp" +#include "../server/data_structures/datafacade_base.hpp" +#include "../server/data_structures/internal_datafacade.hpp" +#include "../server/data_structures/shared_barriers.hpp" +#include "../server/data_structures/shared_datafacade.hpp" #include "../Util/make_unique.hpp" #include "../Util/ProgramOptions.h" #include "../Util/simple_logger.hpp" diff --git a/Server/APIGrammar.h b/Server/APIGrammar.h deleted file mode 100644 index 83a5cd03b..000000000 --- a/Server/APIGrammar.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - -Copyright (c) 2013, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef APIGRAMMAR_H_ -#define APIGRAMMAR_H_ - -#include -#include -#include - -namespace qi = boost::spirit::qi; - -template -struct APIGrammar : qi::grammar -{ - explicit APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) - { - api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query) >> -(uturns); - query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | u | cmp | language | instruction | geometry | alt_route | old_API | num_results) ) ; - - zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)]; - output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)]; - jsonp = (-qi::lit('&')) >> qi::lit("jsonp") >> '=' >> stringwithPercent[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)]; - checksum = (-qi::lit('&')) >> qi::lit("checksum") >> '=' >> qi::uint_[boost::bind(&HandlerT::setChecksum, handler, ::_1)]; - instruction = (-qi::lit('&')) >> qi::lit("instructions") >> '=' >> qi::bool_[boost::bind(&HandlerT::setInstructionFlag, handler, ::_1)]; - geometry = (-qi::lit('&')) >> qi::lit("geometry") >> '=' >> qi::bool_[boost::bind(&HandlerT::setGeometryFlag, handler, ::_1)]; - cmp = (-qi::lit('&')) >> qi::lit("compression") >> '=' >> qi::bool_[boost::bind(&HandlerT::setCompressionFlag, handler, ::_1)]; - location = (-qi::lit('&')) >> qi::lit("loc") >> '=' >> (qi::double_ >> qi::lit(',') >> qi::double_)[boost::bind(&HandlerT::addCoordinate, handler, ::_1)]; - hint = (-qi::lit('&')) >> qi::lit("hint") >> '=' >> stringwithDot[boost::bind(&HandlerT::addHint, handler, ::_1)]; - u = (-qi::lit('&')) >> qi::lit("u") >> '=' >> qi::bool_[boost::bind(&HandlerT::setUTurn, handler, ::_1)]; - uturns = (-qi::lit('&')) >> qi::lit("uturns") >> '=' >> qi::bool_[boost::bind(&HandlerT::setAllUTurns, handler, ::_1)]; - language = (-qi::lit('&')) >> qi::lit("hl") >> '=' >> string[boost::bind(&HandlerT::setLanguage, handler, ::_1)]; - alt_route = (-qi::lit('&')) >> qi::lit("alt") >> '=' >> qi::bool_[boost::bind(&HandlerT::setAlternateRouteFlag, handler, ::_1)]; - old_API = (-qi::lit('&')) >> qi::lit("geomformat") >> '=' >> string[boost::bind(&HandlerT::setDeprecatedAPIFlag, handler, ::_1)]; - num_results = (-qi::lit('&')) >> qi::lit("num_results") >> '=' >> qi::short_[boost::bind(&HandlerT::setNumberOfResults, handler, ::_1)]; - - string = +(qi::char_("a-zA-Z")); - stringwithDot = +(qi::char_("a-zA-Z0-9_.-")); - stringwithPercent = +(qi::char_("a-zA-Z0-9_.-") | qi::char_('[') | qi::char_(']') | (qi::char_('%') >> qi::char_("0-9A-Z") >> qi::char_("0-9A-Z") )); - } - - qi::rule api_call, query; - qi::rule service, zoom, output, string, jsonp, checksum, location, hint, - stringwithDot, stringwithPercent, language, instruction, geometry, - cmp, alt_route, u, uturns, old_API, num_results; - - HandlerT * handler; -}; - -#endif /* APIGRAMMAR_H_ */ diff --git a/Server/Connection.cpp b/Server/Connection.cpp index 38f64a116..1dd5ae5f1 100644 --- a/Server/Connection.cpp +++ b/Server/Connection.cpp @@ -25,9 +25,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "Connection.h" -#include "RequestHandler.h" -#include "RequestParser.h" +#include "connection.hpp" +#include "request_handler.hpp" +#include "request_parser.hpp" #include #include diff --git a/Util/ProgramOptions.h b/Util/ProgramOptions.h index 3e2471189..0c350fc75 100644 --- a/Util/ProgramOptions.h +++ b/Util/ProgramOptions.h @@ -40,7 +40,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include - const static unsigned INIT_OK_START_ENGINE = 0; const static unsigned INIT_OK_DO_NOT_START_ENGINE = 1; const static unsigned INIT_FAILED = -1; @@ -157,45 +156,36 @@ inline unsigned GenerateServerProgramOptions(const int argc, // declare a group of options that will be allowed only on command line boost::program_options::options_description generic_options("Options"); generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")( - "config,c", - boost::program_options::value(&paths["config"]) - ->default_value("server.ini"), + "config,c", boost::program_options::value(&paths["config"]) + ->default_value("server.ini"), "Path to a configuration file")( - "trial", - boost::program_options::value(&trial)->implicit_value(true), + "trial", boost::program_options::value(&trial)->implicit_value(true), "Quit after initialization"); // declare a group of options that will be allowed both on command line // as well as in a config file boost::program_options::options_description config_options("Configuration"); config_options.add_options()( - "hsgrdata", - boost::program_options::value(&paths["hsgrdata"]), + "hsgrdata", boost::program_options::value(&paths["hsgrdata"]), ".hsgr file")("nodesdata", boost::program_options::value(&paths["nodesdata"]), ".nodes file")( - "edgesdata", - boost::program_options::value(&paths["edgesdata"]), + "edgesdata", boost::program_options::value(&paths["edgesdata"]), ".edges file")("geometry", boost::program_options::value(&paths["geometries"]), ".geometry file")( - "ramindex", - boost::program_options::value(&paths["ramindex"]), + "ramindex", boost::program_options::value(&paths["ramindex"]), ".ramIndex file")( - "fileindex", - boost::program_options::value(&paths["fileindex"]), + "fileindex", boost::program_options::value(&paths["fileindex"]), "File index file")( - "namesdata", - boost::program_options::value(&paths["namesdata"]), + "namesdata", boost::program_options::value(&paths["namesdata"]), ".names file")("timestamp", boost::program_options::value(&paths["timestamp"]), ".timestamp file")( - "ip,i", - boost::program_options::value(&ip_address)->default_value("0.0.0.0"), - "IP address")( - "port,p", boost::program_options::value(&ip_port)->default_value(5000), "TCP/IP port")( - "threads,t", - boost::program_options::value(&requested_num_threads)->default_value(8), + "ip,i", boost::program_options::value(&ip_address)->default_value("0.0.0.0"), + "IP address")("port,p", boost::program_options::value(&ip_port)->default_value(5000), + "TCP/IP port")( + "threads,t", boost::program_options::value(&requested_num_threads)->default_value(8), "Number of threads to use")( "shared-memory,s", boost::program_options::value(&use_shared_memory)->implicit_value(true), @@ -208,8 +198,7 @@ inline unsigned GenerateServerProgramOptions(const int argc, // file, but will not be shown to the user boost::program_options::options_description hidden_options("Hidden options"); hidden_options.add_options()( - "base,b", - boost::program_options::value(&paths["base"]), + "base,b", boost::program_options::value(&paths["base"]), "base path to .osrm file"); // positional option diff --git a/datastore.cpp b/datastore.cpp index 9acb4fe57..d33f6f603 100644 --- a/datastore.cpp +++ b/datastore.cpp @@ -33,9 +33,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "data_structures/static_graph.hpp" #include "data_structures/static_rtree.hpp" #include "data_structures/turn_instructions.hpp" -#include "Server/data_structures/datafacade_base.hpp" -#include "Server/data_structures/shared_datatype.hpp" -#include "Server/data_structures/shared_barriers.hpp" +#include "server/data_structures/datafacade_base.hpp" +#include "server/data_structures/shared_datatype.hpp" +#include "server/data_structures/shared_barriers.hpp" #include "Util/BoostFileSystemFix.h" #include "Util/DataStoreOptions.h" #include "Util/simple_logger.hpp" diff --git a/routed.cpp b/routed.cpp index 5768c3d03..96b20133f 100644 --- a/routed.cpp +++ b/routed.cpp @@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "Library/OSRM.h" -#include "Server/Server.h" +#include "server/server.hpp" #include "Util/git_sha.hpp" #include "Util/ProgramOptions.h" #include "Util/simple_logger.hpp" diff --git a/server/Http/Reply.cpp b/server/Http/Reply.cpp new file mode 100644 index 000000000..89b931b05 --- /dev/null +++ b/server/Http/Reply.cpp @@ -0,0 +1,130 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "reply.hpp" + +#include "../../Util/cast.hpp" + +namespace http +{ + +const char ok_html[] = ""; +const char bad_request_html[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}"; +const char internal_server_error_html[] = + "{\"status\": 500,\"status_message\":\"Internal Server Error\"}"; +const char seperators[] = {':', ' '}; +const char crlf[] = {'\r', '\n'}; +const std::string http_ok_string = "HTTP/1.0 200 OK\r\n"; +const std::string http_bad_request_string = "HTTP/1.0 400 Bad Request\r\n"; +const std::string http_internal_server_error_string = "HTTP/1.0 500 Internal Server Error\r\n"; + +void reply::set_size(const std::size_t size) +{ + for (header &h : headers) + { + if ("Content-Length" == h.name) + { + h.value = cast::integral_to_string(size); + } + } +} + +void reply::set_uncompressed_size() { set_size(content.size()); } + +std::vector reply::to_buffers() +{ + std::vector buffers; + buffers.push_back(status_to_buffer(status)); + for (const header &h : headers) + { + buffers.push_back(boost::asio::buffer(h.name)); + buffers.push_back(boost::asio::buffer(seperators)); + buffers.push_back(boost::asio::buffer(h.value)); + buffers.push_back(boost::asio::buffer(crlf)); + } + buffers.push_back(boost::asio::buffer(crlf)); + buffers.push_back(boost::asio::buffer(content)); + return buffers; +} + +std::vector reply::headers_to_buffers() +{ + std::vector buffers; + buffers.push_back(status_to_buffer(status)); + for (const header ¤t_header : headers) + { + buffers.push_back(boost::asio::buffer(current_header.name)); + buffers.push_back(boost::asio::buffer(seperators)); + buffers.push_back(boost::asio::buffer(current_header.value)); + buffers.push_back(boost::asio::buffer(crlf)); + } + buffers.push_back(boost::asio::buffer(crlf)); + return buffers; +} + +reply reply::stock_reply(const reply::status_type status) +{ + reply reply; + reply.status = status; + reply.content.clear(); + + const std::string status_string = reply.status_to_string(status); + reply.content.insert(reply.content.end(), status_string.begin(), status_string.end()); + reply.headers.emplace_back("Access-Control-Allow-Origin", "*"); + reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size())); + reply.headers.emplace_back("Content-Type", "text/html"); + return reply; +} + +std::string reply::status_to_string(const reply::status_type status) +{ + if (reply::ok == status) + { + return ok_html; + } + if (reply::bad_request == status) + { + return bad_request_html; + } + return internal_server_error_html; +} + +boost::asio::const_buffer reply::status_to_buffer(const reply::status_type status) +{ + if (reply::ok == status) + { + return boost::asio::buffer(http_ok_string); + } + if (reply::internal_server_error == status) + { + return boost::asio::buffer(http_internal_server_error_string); + } + return boost::asio::buffer(http_bad_request_string); +} + +reply::reply() : status(ok) {} +} diff --git a/server/api_grammar.hpp b/server/api_grammar.hpp new file mode 100644 index 000000000..0697e21c8 --- /dev/null +++ b/server/api_grammar.hpp @@ -0,0 +1,92 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef API_GRAMMAR_HPP +#define API_GRAMMAR_HPP + +#include +#include +#include + +namespace qi = boost::spirit::qi; + +template struct APIGrammar : qi::grammar +{ + explicit APIGrammar(HandlerT *h) : APIGrammar::base_type(api_call), handler(h) + { + api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> + *(query) >> -(uturns); + query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | u | cmp | + language | instruction | geometry | alt_route | old_API | num_results)); + + zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> + qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)]; + output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> + string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)]; + jsonp = (-qi::lit('&')) >> qi::lit("jsonp") >> '=' >> + stringwithPercent[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)]; + checksum = (-qi::lit('&')) >> qi::lit("checksum") >> '=' >> + qi::uint_[boost::bind(&HandlerT::setChecksum, handler, ::_1)]; + instruction = (-qi::lit('&')) >> qi::lit("instructions") >> '=' >> + qi::bool_[boost::bind(&HandlerT::setInstructionFlag, handler, ::_1)]; + geometry = (-qi::lit('&')) >> qi::lit("geometry") >> '=' >> + qi::bool_[boost::bind(&HandlerT::setGeometryFlag, handler, ::_1)]; + cmp = (-qi::lit('&')) >> qi::lit("compression") >> '=' >> + qi::bool_[boost::bind(&HandlerT::setCompressionFlag, handler, ::_1)]; + location = (-qi::lit('&')) >> qi::lit("loc") >> '=' >> + (qi::double_ >> qi::lit(',') >> + qi::double_)[boost::bind(&HandlerT::addCoordinate, handler, ::_1)]; + hint = (-qi::lit('&')) >> qi::lit("hint") >> '=' >> + stringwithDot[boost::bind(&HandlerT::addHint, handler, ::_1)]; + u = (-qi::lit('&')) >> qi::lit("u") >> '=' >> + qi::bool_[boost::bind(&HandlerT::setUTurn, handler, ::_1)]; + uturns = (-qi::lit('&')) >> qi::lit("uturns") >> '=' >> + qi::bool_[boost::bind(&HandlerT::setAllUTurns, handler, ::_1)]; + language = (-qi::lit('&')) >> qi::lit("hl") >> '=' >> + string[boost::bind(&HandlerT::setLanguage, handler, ::_1)]; + alt_route = (-qi::lit('&')) >> qi::lit("alt") >> '=' >> + qi::bool_[boost::bind(&HandlerT::setAlternateRouteFlag, handler, ::_1)]; + old_API = (-qi::lit('&')) >> qi::lit("geomformat") >> '=' >> + string[boost::bind(&HandlerT::setDeprecatedAPIFlag, handler, ::_1)]; + num_results = (-qi::lit('&')) >> qi::lit("num_results") >> '=' >> + qi::short_[boost::bind(&HandlerT::setNumberOfResults, handler, ::_1)]; + + string = +(qi::char_("a-zA-Z")); + stringwithDot = +(qi::char_("a-zA-Z0-9_.-")); + stringwithPercent = +(qi::char_("a-zA-Z0-9_.-") | qi::char_('[') | qi::char_(']') | + (qi::char_('%') >> qi::char_("0-9A-Z") >> qi::char_("0-9A-Z"))); + } + + qi::rule api_call, query; + qi::rule service, zoom, output, string, jsonp, checksum, location, + hint, stringwithDot, stringwithPercent, language, instruction, geometry, cmp, alt_route, u, + uturns, old_API, num_results; + + HandlerT *handler; +}; + +#endif /* API_GRAMMAR_HPP */ diff --git a/server/connection.cpp b/server/connection.cpp new file mode 100644 index 000000000..1dd5ae5f1 --- /dev/null +++ b/server/connection.cpp @@ -0,0 +1,168 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "connection.hpp" +#include "request_handler.hpp" +#include "request_parser.hpp" + +#include +#include +#include +#include + +#include +#include + +namespace http +{ + +Connection::Connection(boost::asio::io_service &io_service, RequestHandler &handler) + : strand(io_service), TCP_socket(io_service), request_handler(handler) +{ +} + +boost::asio::ip::tcp::socket &Connection::socket() { return TCP_socket; } + +/// Start the first asynchronous operation for the connection. +void Connection::start() +{ + TCP_socket.async_read_some( + boost::asio::buffer(incoming_data_buffer), + strand.wrap(boost::bind(&Connection::handle_read, this->shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); +} + +void Connection::handle_read(const boost::system::error_code &error, std::size_t bytes_transferred) +{ + if (error) + { + return; + } + + // no error detected, let's parse the request + compression_type compression_type(no_compression); + osrm::tribool result; + std::tie(result, compression_type) = RequestParser().parse( + request, incoming_data_buffer.data(), incoming_data_buffer.data() + bytes_transferred); + + // the request has been parsed + if (result == osrm::tribool::yes) + { + request.endpoint = TCP_socket.remote_endpoint().address(); + request_handler.handle_request(request, reply); + + // Header compression_header; + std::vector compressed_output; + std::vector output_buffer; + + // compress the result w/ gzip/deflate if requested + switch (compression_type) + { + case deflate_rfc1951: + // use deflate for compression + reply.headers.insert(reply.headers.begin(), {"Content-Encoding", "deflate"}); + compressed_output = compress_buffers(reply.content, compression_type); + reply.set_size(static_cast(compressed_output.size())); + output_buffer = reply.headers_to_buffers(); + output_buffer.push_back(boost::asio::buffer(compressed_output)); + break; + case gzip_rfc1952: + // use gzip for compression + reply.headers.insert(reply.headers.begin(), {"Content-Encoding", "gzip"}); + compressed_output = compress_buffers(reply.content, compression_type); + reply.set_size(static_cast(compressed_output.size())); + output_buffer = reply.headers_to_buffers(); + output_buffer.push_back(boost::asio::buffer(compressed_output)); + break; + case no_compression: + // don't use any compression + reply.set_uncompressed_size(); + output_buffer = reply.to_buffers(); + break; + } + // write result to stream + boost::asio::async_write( + TCP_socket, output_buffer, + strand.wrap(boost::bind(&Connection::handle_write, this->shared_from_this(), + boost::asio::placeholders::error))); + } + else if (result == osrm::tribool::no) + { // request is not parseable + reply = reply::stock_reply(reply::bad_request); + + boost::asio::async_write( + TCP_socket, reply.to_buffers(), + strand.wrap(boost::bind(&Connection::handle_write, this->shared_from_this(), + boost::asio::placeholders::error))); + } + else + { + // we don't have a result yet, so continue reading + TCP_socket.async_read_some( + boost::asio::buffer(incoming_data_buffer), + strand.wrap(boost::bind(&Connection::handle_read, this->shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); + } +} + +/// Handle completion of a write operation. +void Connection::handle_write(const boost::system::error_code &error) +{ + if (!error) + { + // Initiate graceful connection closure. + boost::system::error_code ignore_error; + TCP_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignore_error); + } +} + +std::vector Connection::compress_buffers(const std::vector &uncompressed_data, + const compression_type compression_type) +{ + boost::iostreams::gzip_params compression_parameters; + + // there's a trade-off between speed and size. speed wins + compression_parameters.level = boost::iostreams::zlib::best_speed; + // check which compression flavor is used + if (deflate_rfc1951 == compression_type) + { + compression_parameters.noheader = true; + } + + std::vector compressed_data; + // plug data into boost's compression stream + boost::iostreams::filtering_ostream gzip_stream; + gzip_stream.push(boost::iostreams::gzip_compressor(compression_parameters)); + gzip_stream.push(boost::iostreams::back_inserter(compressed_data)); + gzip_stream.write(&uncompressed_data[0], uncompressed_data.size()); + boost::iostreams::close(gzip_stream); + + return compressed_data; +} +} diff --git a/Server/Connection.h b/server/connection.hpp similarity index 97% rename from Server/Connection.h rename to server/connection.hpp index 8d0cfda7d..ad9335523 100644 --- a/Server/Connection.h +++ b/server/connection.hpp @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CONNECTION_H -#define CONNECTION_H +#ifndef CONNECTION_HPP +#define CONNECTION_HPP #include "http/compression_type.hpp" #include "http/reply.hpp" @@ -89,4 +89,4 @@ class Connection : public std::enable_shared_from_this } // namespace http -#endif // CONNECTION_H +#endif // CONNECTION_HPP diff --git a/server/data_structures/datafacade_base.hpp b/server/data_structures/datafacade_base.hpp new file mode 100644 index 000000000..2de79f915 --- /dev/null +++ b/server/data_structures/datafacade_base.hpp @@ -0,0 +1,126 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef DATAFACADE_BASE_HPP +#define DATAFACADE_BASE_HPP + +// Exposes all data access interfaces to the algorithms via base class ptr + +#include "../../data_structures/edge_based_node.hpp" +#include "../../data_structures/external_memory_node.hpp" +#include "../../data_structures/phantom_node.hpp" +#include "../../data_structures/turn_instructions.hpp" +#include "../../Util/integer_range.hpp" +#include "../../Util/osrm_exception.hpp" +#include "../../Util/string_util.hpp" +#include "../../typedefs.h" + +#include + +#include + +typedef osrm::range EdgeRange; + +template class BaseDataFacade +{ + public: + typedef EdgeBasedNode RTreeLeaf; + typedef EdgeDataT EdgeData; + BaseDataFacade() {} + virtual ~BaseDataFacade() {} + + // search graph access + virtual unsigned GetNumberOfNodes() const = 0; + + virtual unsigned GetNumberOfEdges() const = 0; + + virtual unsigned GetOutDegree(const NodeID n) const = 0; + + virtual NodeID GetTarget(const EdgeID e) const = 0; + + // virtual EdgeDataT &GetEdgeData(const EdgeID e) = 0; + + virtual const EdgeDataT &GetEdgeData(const EdgeID e) const = 0; + + virtual EdgeID BeginEdges(const NodeID n) const = 0; + + virtual EdgeID EndEdges(const NodeID n) const = 0; + + virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0; + + // searches for a specific edge + virtual EdgeID FindEdge(const NodeID from, const NodeID to) const = 0; + + virtual EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const = 0; + + virtual EdgeID + FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const = 0; + + // node and edge information access + virtual FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const = 0; + + virtual bool EdgeIsCompressed(const unsigned id) const = 0; + + virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const = 0; + + virtual void GetUncompressedGeometry(const unsigned id, + std::vector &result_nodes) const = 0; + + virtual TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const = 0; + + virtual TravelMode GetTravelModeForEdgeID(const unsigned id) const = 0; + + virtual bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate, + FixedPointCoordinate &result, + const unsigned zoom_level = 18) = 0; + + virtual bool + IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, + std::vector &resulting_phantom_node_vector, + const unsigned number_of_results) = 0; + + virtual bool + IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, + PhantomNode &resulting_phantom_node) = 0; + + virtual unsigned GetCheckSum() const = 0; + + virtual unsigned GetNameIndexFromEdgeID(const unsigned id) const = 0; + + virtual void GetName(const unsigned name_id, std::string &result) const = 0; + + std::string GetEscapedNameForNameID(const unsigned name_id) const + { + std::string temporary_string; + GetName(name_id, temporary_string); + return EscapeJSONString(temporary_string); + } + + virtual std::string GetTimestamp() const = 0; +}; + +#endif // DATAFACADE_BASE_HPP diff --git a/server/data_structures/internal_datafacade.hpp b/server/data_structures/internal_datafacade.hpp new file mode 100644 index 000000000..a9949e383 --- /dev/null +++ b/server/data_structures/internal_datafacade.hpp @@ -0,0 +1,449 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef INTERNAL_DATAFACADE_HPP +#define INTERNAL_DATAFACADE_HPP + +// implements all data storage when shared memory is _NOT_ used + +#include "datafacade_base.hpp" + +#include "../../data_structures/original_edge_data.hpp" +#include "../../data_structures/query_node.hpp" +#include "../../data_structures/query_edge.hpp" +#include "../../data_structures/shared_memory_vector_wrapper.hpp" +#include "../../data_structures/static_graph.hpp" +#include "../../data_structures/static_rtree.hpp" +#include "../../data_structures/range_table.hpp" +#include "../../Util/BoostFileSystemFix.h" +#include "../../Util/graph_loader.hpp" +#include "../../Util/simple_logger.hpp" + +#include +#include + +template class InternalDataFacade : public BaseDataFacade +{ + + private: + typedef BaseDataFacade super; + typedef StaticGraph QueryGraph; + typedef typename QueryGraph::InputEdge InputEdge; + typedef typename super::RTreeLeaf RTreeLeaf; + + InternalDataFacade() {} + + unsigned m_check_sum; + unsigned m_number_of_nodes; + QueryGraph *m_query_graph; + std::string m_timestamp; + + std::shared_ptr::vector> m_coordinate_list; + ShM::vector m_via_node_list; + ShM::vector m_name_ID_list; + ShM::vector m_turn_instruction_list; + ShM::vector m_travel_mode_list; + ShM::vector m_names_char_list; + ShM::vector m_edge_is_compressed; + ShM::vector m_geometry_indices; + ShM::vector m_geometry_list; + + boost::thread_specific_ptr< + StaticRTree::vector, false>> m_static_rtree; + boost::filesystem::path ram_index_path; + boost::filesystem::path file_index_path; + RangeTable<16, false> m_name_table; + + void LoadTimestamp(const boost::filesystem::path ×tamp_path) + { + if (boost::filesystem::exists(timestamp_path)) + { + SimpleLogger().Write() << "Loading Timestamp"; + boost::filesystem::ifstream timestamp_stream(timestamp_path); + if (!timestamp_stream) + { + SimpleLogger().Write(logWARNING) << timestamp_path << " not found"; + } + getline(timestamp_stream, m_timestamp); + timestamp_stream.close(); + } + if (m_timestamp.empty()) + { + m_timestamp = "n/a"; + } + if (25 < m_timestamp.length()) + { + m_timestamp.resize(25); + } + } + + void LoadGraph(const boost::filesystem::path &hsgr_path) + { + typename ShM::vector node_list; + typename ShM::vector edge_list; + + SimpleLogger().Write() << "loading graph from " << hsgr_path.string(); + + m_number_of_nodes = readHSGRFromStream(hsgr_path, node_list, edge_list, &m_check_sum); + + BOOST_ASSERT_MSG(0 != node_list.size(), "node list empty"); + // BOOST_ASSERT_MSG(0 != edge_list.size(), "edge list empty"); + SimpleLogger().Write() << "loaded " << node_list.size() << " nodes and " << edge_list.size() + << " edges"; + m_query_graph = new QueryGraph(node_list, edge_list); + + BOOST_ASSERT_MSG(0 == node_list.size(), "node list not flushed"); + BOOST_ASSERT_MSG(0 == edge_list.size(), "edge list not flushed"); + SimpleLogger().Write() << "Data checksum is " << m_check_sum; + } + + void LoadNodeAndEdgeInformation(const boost::filesystem::path &nodes_file, + const boost::filesystem::path &edges_file) + { + boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary); + + QueryNode current_node; + unsigned number_of_coordinates = 0; + nodes_input_stream.read((char *)&number_of_coordinates, sizeof(unsigned)); + m_coordinate_list = + std::make_shared>(number_of_coordinates); + for (unsigned i = 0; i < number_of_coordinates; ++i) + { + nodes_input_stream.read((char *)¤t_node, sizeof(QueryNode)); + m_coordinate_list->at(i) = FixedPointCoordinate(current_node.lat, current_node.lon); + BOOST_ASSERT((std::abs(m_coordinate_list->at(i).lat) >> 30) == 0); + BOOST_ASSERT((std::abs(m_coordinate_list->at(i).lon) >> 30) == 0); + } + nodes_input_stream.close(); + + boost::filesystem::ifstream edges_input_stream(edges_file, std::ios::binary); + unsigned number_of_edges = 0; + edges_input_stream.read((char *)&number_of_edges, sizeof(unsigned)); + m_via_node_list.resize(number_of_edges); + m_name_ID_list.resize(number_of_edges); + m_turn_instruction_list.resize(number_of_edges); + m_travel_mode_list.resize(number_of_edges); + m_edge_is_compressed.resize(number_of_edges); + + unsigned compressed = 0; + + OriginalEdgeData current_edge_data; + for (unsigned i = 0; i < number_of_edges; ++i) + { + edges_input_stream.read((char *)&(current_edge_data), sizeof(OriginalEdgeData)); + m_via_node_list[i] = current_edge_data.via_node; + m_name_ID_list[i] = current_edge_data.name_id; + m_turn_instruction_list[i] = current_edge_data.turn_instruction; + m_travel_mode_list[i] = current_edge_data.travel_mode; + m_edge_is_compressed[i] = current_edge_data.compressed_geometry; + if (m_edge_is_compressed[i]) + { + ++compressed; + } + } + + edges_input_stream.close(); + } + + void LoadGeometries(const boost::filesystem::path &geometry_file) + { + std::ifstream geometry_stream(geometry_file.string().c_str(), std::ios::binary); + unsigned number_of_indices = 0; + unsigned number_of_compressed_geometries = 0; + + geometry_stream.read((char *)&number_of_indices, sizeof(unsigned)); + + m_geometry_indices.resize(number_of_indices); + if (number_of_indices > 0) + { + geometry_stream.read((char *)&(m_geometry_indices[0]), + number_of_indices * sizeof(unsigned)); + } + + geometry_stream.read((char *)&number_of_compressed_geometries, sizeof(unsigned)); + + BOOST_ASSERT(m_geometry_indices.back() == number_of_compressed_geometries); + m_geometry_list.resize(number_of_compressed_geometries); + + if (number_of_compressed_geometries > 0) + { + geometry_stream.read((char *)&(m_geometry_list[0]), + number_of_compressed_geometries * sizeof(unsigned)); + } + geometry_stream.close(); + } + + void LoadRTree() + { + BOOST_ASSERT_MSG(!m_coordinate_list->empty(), "coordinates must be loaded before r-tree"); + + m_static_rtree.reset( + new StaticRTree(ram_index_path, file_index_path, m_coordinate_list)); + } + + void LoadStreetNames(const boost::filesystem::path &names_file) + { + boost::filesystem::ifstream name_stream(names_file, std::ios::binary); + + name_stream >> m_name_table; + + unsigned number_of_chars = 0; + name_stream.read((char *)&number_of_chars, sizeof(unsigned)); + BOOST_ASSERT_MSG(0 != number_of_chars, "name file broken"); + m_names_char_list.resize(number_of_chars + 1); //+1 gives sentinel element + name_stream.read((char *)&m_names_char_list[0], number_of_chars * sizeof(char)); + if (0 == m_names_char_list.size()) + { + SimpleLogger().Write(logWARNING) << "list of street names is empty"; + } + name_stream.close(); + } + + public: + virtual ~InternalDataFacade() + { + delete m_query_graph; + m_static_rtree.reset(); + } + + explicit InternalDataFacade(const ServerPaths &server_paths) + { + // generate paths of data files + if (server_paths.find("hsgrdata") == server_paths.end()) + { + throw osrm::exception("no hsgr file given in ini file"); + } + if (server_paths.find("ramindex") == server_paths.end()) + { + throw osrm::exception("no ram index file given in ini file"); + } + if (server_paths.find("fileindex") == server_paths.end()) + { + throw osrm::exception("no leaf index file given in ini file"); + } + if (server_paths.find("geometries") == server_paths.end()) + { + throw osrm::exception("no geometries file given in ini file"); + } + if (server_paths.find("nodesdata") == server_paths.end()) + { + throw osrm::exception("no nodes file given in ini file"); + } + if (server_paths.find("edgesdata") == server_paths.end()) + { + throw osrm::exception("no edges file given in ini file"); + } + if (server_paths.find("namesdata") == server_paths.end()) + { + throw osrm::exception("no names file given in ini file"); + } + + ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata"); + BOOST_ASSERT(server_paths.end() != paths_iterator); + const boost::filesystem::path &hsgr_path = paths_iterator->second; + paths_iterator = server_paths.find("timestamp"); + BOOST_ASSERT(server_paths.end() != paths_iterator); + const boost::filesystem::path ×tamp_path = paths_iterator->second; + paths_iterator = server_paths.find("ramindex"); + BOOST_ASSERT(server_paths.end() != paths_iterator); + ram_index_path = paths_iterator->second; + paths_iterator = server_paths.find("fileindex"); + BOOST_ASSERT(server_paths.end() != paths_iterator); + file_index_path = paths_iterator->second; + paths_iterator = server_paths.find("nodesdata"); + BOOST_ASSERT(server_paths.end() != paths_iterator); + const boost::filesystem::path &nodes_data_path = paths_iterator->second; + paths_iterator = server_paths.find("edgesdata"); + BOOST_ASSERT(server_paths.end() != paths_iterator); + const boost::filesystem::path &edges_data_path = paths_iterator->second; + paths_iterator = server_paths.find("namesdata"); + BOOST_ASSERT(server_paths.end() != paths_iterator); + const boost::filesystem::path &names_data_path = paths_iterator->second; + paths_iterator = server_paths.find("geometries"); + BOOST_ASSERT(server_paths.end() != paths_iterator); + const boost::filesystem::path &geometries_path = paths_iterator->second; + + // load data + SimpleLogger().Write() << "loading graph data"; + AssertPathExists(hsgr_path); + LoadGraph(hsgr_path); + SimpleLogger().Write() << "loading edge information"; + AssertPathExists(nodes_data_path); + AssertPathExists(edges_data_path); + LoadNodeAndEdgeInformation(nodes_data_path, edges_data_path); + SimpleLogger().Write() << "loading geometries"; + AssertPathExists(geometries_path); + LoadGeometries(geometries_path); + SimpleLogger().Write() << "loading r-tree"; + AssertPathExists(ram_index_path); + AssertPathExists(file_index_path); + SimpleLogger().Write() << "loading timestamp"; + LoadTimestamp(timestamp_path); + SimpleLogger().Write() << "loading street names"; + AssertPathExists(names_data_path); + LoadStreetNames(names_data_path); + } + + // search graph access + unsigned GetNumberOfNodes() const final { return m_query_graph->GetNumberOfNodes(); } + + unsigned GetNumberOfEdges() const final { return m_query_graph->GetNumberOfEdges(); } + + unsigned GetOutDegree(const NodeID n) const final { return m_query_graph->GetOutDegree(n); } + + NodeID GetTarget(const EdgeID e) const final { return m_query_graph->GetTarget(e); } + + // EdgeDataT &GetEdgeData(const EdgeID e) final { return m_query_graph->GetEdgeData(e); } + + EdgeDataT &GetEdgeData(const EdgeID e) const final { return m_query_graph->GetEdgeData(e); } + + EdgeID BeginEdges(const NodeID n) const final { return m_query_graph->BeginEdges(n); } + + EdgeID EndEdges(const NodeID n) const final { return m_query_graph->EndEdges(n); } + + EdgeRange GetAdjacentEdgeRange(const NodeID node) const final + { + return m_query_graph->GetAdjacentEdgeRange(node); + }; + + // searches for a specific edge + EdgeID FindEdge(const NodeID from, const NodeID to) const final + { + return m_query_graph->FindEdge(from, to); + } + + EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const final + { + return m_query_graph->FindEdgeInEitherDirection(from, to); + } + + EdgeID FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const final + { + return m_query_graph->FindEdgeIndicateIfReverse(from, to, result); + } + + // node and edge information access + FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const final + { + return m_coordinate_list->at(id); + }; + + bool EdgeIsCompressed(const unsigned id) const { return m_edge_is_compressed.at(id); } + + TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const final + { + return m_turn_instruction_list.at(id); + } + + TravelMode GetTravelModeForEdgeID(const unsigned id) const { return m_travel_mode_list.at(id); } + + bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate, + FixedPointCoordinate &result, + const unsigned zoom_level = 18) final + { + if (!m_static_rtree.get()) + { + LoadRTree(); + } + + return m_static_rtree->LocateClosestEndPointForCoordinate(input_coordinate, result, + zoom_level); + } + + bool IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, + PhantomNode &resulting_phantom_node) final + { + std::vector resulting_phantom_node_vector; + auto result = IncrementalFindPhantomNodeForCoordinate(input_coordinate, + resulting_phantom_node_vector, 1); + if (result) + { + BOOST_ASSERT(!resulting_phantom_node_vector.empty()); + resulting_phantom_node = resulting_phantom_node_vector.front(); + } + return result; + } + + bool + IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, + std::vector &resulting_phantom_node_vector, + const unsigned number_of_results) final + { + if (!m_static_rtree.get()) + { + LoadRTree(); + } + + return m_static_rtree->IncrementalFindPhantomNodeForCoordinate( + input_coordinate, resulting_phantom_node_vector, number_of_results); + } + + unsigned GetCheckSum() const final { return m_check_sum; } + + unsigned GetNameIndexFromEdgeID(const unsigned id) const final + { + return m_name_ID_list.at(id); + }; + + void GetName(const unsigned name_id, std::string &result) const final + { + if (UINT_MAX == name_id) + { + result = ""; + return; + } + auto range = m_name_table.GetRange(name_id); + + result.clear(); + if (range.begin() != range.end()) + { + result.resize(range.back() - range.front() + 1); + std::copy(m_names_char_list.begin() + range.front(), + m_names_char_list.begin() + range.back() + 1, result.begin()); + } + } + + virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const final + { + return m_via_node_list.at(id); + } + + virtual void GetUncompressedGeometry(const unsigned id, + std::vector &result_nodes) const final + { + const unsigned begin = m_geometry_indices.at(id); + const unsigned end = m_geometry_indices.at(id + 1); + + result_nodes.clear(); + result_nodes.insert(result_nodes.begin(), m_geometry_list.begin() + begin, + m_geometry_list.begin() + end); + } + + std::string GetTimestamp() const final { return m_timestamp; } +}; + +#endif // INTERNAL_DATAFACADE_HPP diff --git a/server/data_structures/shared_barriers.hpp b/server/data_structures/shared_barriers.hpp new file mode 100644 index 000000000..2d7de7e74 --- /dev/null +++ b/server/data_structures/shared_barriers.hpp @@ -0,0 +1,60 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef SHARED_BARRIERS_HPP +#define SHARED_BARRIERS_HPP + +#include +#include + +struct SharedBarriers +{ + + SharedBarriers() + : pending_update_mutex(boost::interprocess::open_or_create, "pending_update"), + update_mutex(boost::interprocess::open_or_create, "update"), + query_mutex(boost::interprocess::open_or_create, "query"), + no_running_queries_condition(boost::interprocess::open_or_create, "no_running_queries"), + update_ongoing(false), number_of_queries(0) + { + } + + // Mutex to protect access to the boolean variable + boost::interprocess::named_mutex pending_update_mutex; + boost::interprocess::named_mutex update_mutex; + boost::interprocess::named_mutex query_mutex; + + // Condition that no update is running + boost::interprocess::named_condition no_running_queries_condition; + + // Is there an ongoing update? + bool update_ongoing; + // Is there any query? + int number_of_queries; +}; + +#endif // SHARED_BARRIERS_HPP diff --git a/server/data_structures/shared_datafacade.hpp b/server/data_structures/shared_datafacade.hpp new file mode 100644 index 000000000..11a295e27 --- /dev/null +++ b/server/data_structures/shared_datafacade.hpp @@ -0,0 +1,423 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef SHARED_DATAFACADE_HPP +#define SHARED_DATAFACADE_HPP + +// implements all data storage when shared memory _IS_ used + +#include "datafacade_base.hpp" +#include "shared_datatype.hpp" + +#include "../../data_structures/range_table.hpp" +#include "../../data_structures/static_graph.hpp" +#include "../../data_structures/static_rtree.hpp" +#include "../../Util/BoostFileSystemFix.h" +#include "../../Util/make_unique.hpp" +#include "../../Util/simple_logger.hpp" + +#include +#include + +template class SharedDataFacade : public BaseDataFacade +{ + + private: + typedef EdgeDataT EdgeData; + typedef BaseDataFacade super; + typedef StaticGraph QueryGraph; + typedef typename StaticGraph::NodeArrayEntry GraphNode; + typedef typename StaticGraph::EdgeArrayEntry GraphEdge; + typedef typename RangeTable<16, true>::BlockT NameIndexBlock; + typedef typename QueryGraph::InputEdge InputEdge; + typedef typename super::RTreeLeaf RTreeLeaf; + using SharedRTree = StaticRTree::vector, true>; + using TimeStampedRTreePair = std::pair>; + using RTreeNode = typename SharedRTree::TreeNode; + + SharedDataLayout *data_layout; + char *shared_memory; + SharedDataTimestamp *data_timestamp_ptr; + + SharedDataType CURRENT_LAYOUT; + SharedDataType CURRENT_DATA; + unsigned CURRENT_TIMESTAMP; + + unsigned m_check_sum; + std::unique_ptr m_query_graph; + std::unique_ptr m_layout_memory; + std::unique_ptr m_large_memory; + std::string m_timestamp; + + std::shared_ptr::vector> m_coordinate_list; + ShM::vector m_via_node_list; + ShM::vector m_name_ID_list; + ShM::vector m_turn_instruction_list; + ShM::vector m_travel_mode_list; + ShM::vector m_names_char_list; + ShM::vector m_name_begin_indices; + ShM::vector m_edge_is_compressed; + ShM::vector m_geometry_indices; + ShM::vector m_geometry_list; + + boost::thread_specific_ptr>> m_static_rtree; + boost::filesystem::path file_index_path; + + std::shared_ptr> m_name_table; + + void LoadChecksum() + { + m_check_sum = + *data_layout->GetBlockPtr(shared_memory, SharedDataLayout::HSGR_CHECKSUM); + SimpleLogger().Write() << "set checksum: " << m_check_sum; + } + + void LoadTimestamp() + { + char *timestamp_ptr = + data_layout->GetBlockPtr(shared_memory, SharedDataLayout::TIMESTAMP); + m_timestamp.resize(data_layout->GetBlockSize(SharedDataLayout::TIMESTAMP)); + std::copy(timestamp_ptr, + timestamp_ptr + data_layout->GetBlockSize(SharedDataLayout::TIMESTAMP), + m_timestamp.begin()); + } + + void LoadRTree() + { + BOOST_ASSERT_MSG(!m_coordinate_list->empty(), "coordinates must be loaded before r-tree"); + + RTreeNode *tree_ptr = + data_layout->GetBlockPtr(shared_memory, SharedDataLayout::R_SEARCH_TREE); + m_static_rtree.reset(new TimeStampedRTreePair( + CURRENT_TIMESTAMP, + osrm::make_unique( + tree_ptr, data_layout->num_entries[SharedDataLayout::R_SEARCH_TREE], + file_index_path, m_coordinate_list))); + } + + void LoadGraph() + { + GraphNode *graph_nodes_ptr = + data_layout->GetBlockPtr(shared_memory, SharedDataLayout::GRAPH_NODE_LIST); + + GraphEdge *graph_edges_ptr = + data_layout->GetBlockPtr(shared_memory, SharedDataLayout::GRAPH_EDGE_LIST); + + typename ShM::vector node_list( + graph_nodes_ptr, data_layout->num_entries[SharedDataLayout::GRAPH_NODE_LIST]); + typename ShM::vector edge_list( + graph_edges_ptr, data_layout->num_entries[SharedDataLayout::GRAPH_EDGE_LIST]); + m_query_graph.reset(new QueryGraph(node_list, edge_list)); + } + + void LoadNodeAndEdgeInformation() + { + + FixedPointCoordinate *coordinate_list_ptr = data_layout->GetBlockPtr( + shared_memory, SharedDataLayout::COORDINATE_LIST); + m_coordinate_list = osrm::make_unique::vector>( + coordinate_list_ptr, data_layout->num_entries[SharedDataLayout::COORDINATE_LIST]); + + TravelMode *travel_mode_list_ptr = + data_layout->GetBlockPtr(shared_memory, SharedDataLayout::TRAVEL_MODE); + typename ShM::vector travel_mode_list( + travel_mode_list_ptr, data_layout->num_entries[SharedDataLayout::TRAVEL_MODE]); + m_travel_mode_list.swap(travel_mode_list); + + TurnInstruction *turn_instruction_list_ptr = data_layout->GetBlockPtr( + shared_memory, SharedDataLayout::TURN_INSTRUCTION); + typename ShM::vector turn_instruction_list( + turn_instruction_list_ptr, + data_layout->num_entries[SharedDataLayout::TURN_INSTRUCTION]); + m_turn_instruction_list.swap(turn_instruction_list); + + unsigned *name_id_list_ptr = + data_layout->GetBlockPtr(shared_memory, SharedDataLayout::NAME_ID_LIST); + typename ShM::vector name_id_list( + name_id_list_ptr, data_layout->num_entries[SharedDataLayout::NAME_ID_LIST]); + m_name_ID_list.swap(name_id_list); + } + + void LoadViaNodeList() + { + NodeID *via_node_list_ptr = + data_layout->GetBlockPtr(shared_memory, SharedDataLayout::VIA_NODE_LIST); + typename ShM::vector via_node_list( + via_node_list_ptr, data_layout->num_entries[SharedDataLayout::VIA_NODE_LIST]); + m_via_node_list.swap(via_node_list); + } + + void LoadNames() + { + unsigned *offsets_ptr = + data_layout->GetBlockPtr(shared_memory, SharedDataLayout::NAME_OFFSETS); + NameIndexBlock *blocks_ptr = + data_layout->GetBlockPtr(shared_memory, SharedDataLayout::NAME_BLOCKS); + typename ShM::vector name_offsets( + offsets_ptr, data_layout->num_entries[SharedDataLayout::NAME_OFFSETS]); + typename ShM::vector name_blocks( + blocks_ptr, data_layout->num_entries[SharedDataLayout::NAME_BLOCKS]); + + char *names_list_ptr = + data_layout->GetBlockPtr(shared_memory, SharedDataLayout::NAME_CHAR_LIST); + typename ShM::vector names_char_list( + names_list_ptr, data_layout->num_entries[SharedDataLayout::NAME_CHAR_LIST]); + m_name_table = osrm::make_unique>( + name_offsets, name_blocks, static_cast(names_char_list.size())); + + m_names_char_list.swap(names_char_list); + } + + void LoadGeometries() + { + unsigned *geometries_compressed_ptr = data_layout->GetBlockPtr( + shared_memory, SharedDataLayout::GEOMETRIES_INDICATORS); + typename ShM::vector edge_is_compressed( + geometries_compressed_ptr, + data_layout->num_entries[SharedDataLayout::GEOMETRIES_INDICATORS]); + m_edge_is_compressed.swap(edge_is_compressed); + + unsigned *geometries_index_ptr = + data_layout->GetBlockPtr(shared_memory, SharedDataLayout::GEOMETRIES_INDEX); + typename ShM::vector geometry_begin_indices( + geometries_index_ptr, data_layout->num_entries[SharedDataLayout::GEOMETRIES_INDEX]); + m_geometry_indices.swap(geometry_begin_indices); + + unsigned *geometries_list_ptr = + data_layout->GetBlockPtr(shared_memory, SharedDataLayout::GEOMETRIES_LIST); + typename ShM::vector geometry_list( + geometries_list_ptr, data_layout->num_entries[SharedDataLayout::GEOMETRIES_LIST]); + m_geometry_list.swap(geometry_list); + } + + public: + virtual ~SharedDataFacade() {} + + SharedDataFacade() + { + data_timestamp_ptr = (SharedDataTimestamp *)SharedMemoryFactory::Get( + CURRENT_REGIONS, sizeof(SharedDataTimestamp), false, false)->Ptr(); + CURRENT_LAYOUT = LAYOUT_NONE; + CURRENT_DATA = DATA_NONE; + CURRENT_TIMESTAMP = 0; + + // load data + CheckAndReloadFacade(); + } + + void CheckAndReloadFacade() + { + if (CURRENT_LAYOUT != data_timestamp_ptr->layout || + CURRENT_DATA != data_timestamp_ptr->data || + CURRENT_TIMESTAMP != data_timestamp_ptr->timestamp) + { + // release the previous shared memory segments + SharedMemory::Remove(CURRENT_LAYOUT); + SharedMemory::Remove(CURRENT_DATA); + + CURRENT_LAYOUT = data_timestamp_ptr->layout; + CURRENT_DATA = data_timestamp_ptr->data; + CURRENT_TIMESTAMP = data_timestamp_ptr->timestamp; + + m_layout_memory.reset(SharedMemoryFactory::Get(CURRENT_LAYOUT)); + + data_layout = (SharedDataLayout *)(m_layout_memory->Ptr()); + + m_large_memory.reset(SharedMemoryFactory::Get(CURRENT_DATA)); + shared_memory = (char *)(m_large_memory->Ptr()); + + const char *file_index_ptr = + data_layout->GetBlockPtr(shared_memory, SharedDataLayout::FILE_INDEX_PATH); + file_index_path = boost::filesystem::path(file_index_ptr); + if (!boost::filesystem::exists(file_index_path)) + { + SimpleLogger().Write(logDEBUG) << "Leaf file name " << file_index_path.string(); + throw osrm::exception("Could not load leaf index file." + "Is any data loaded into shared memory?"); + } + + LoadGraph(); + LoadChecksum(); + LoadNodeAndEdgeInformation(); + LoadGeometries(); + LoadTimestamp(); + LoadViaNodeList(); + LoadNames(); + + data_layout->PrintInformation(); + + SimpleLogger().Write() << "number of geometries: " << m_coordinate_list->size(); + for (unsigned i = 0; i < m_coordinate_list->size(); ++i) + { + if (!GetCoordinateOfNode(i).is_valid()) + { + SimpleLogger().Write() << "coordinate " << i << " not valid"; + } + } + } + } + + // search graph access + unsigned GetNumberOfNodes() const final { return m_query_graph->GetNumberOfNodes(); } + + unsigned GetNumberOfEdges() const final { return m_query_graph->GetNumberOfEdges(); } + + unsigned GetOutDegree(const NodeID n) const final { return m_query_graph->GetOutDegree(n); } + + NodeID GetTarget(const EdgeID e) const final { return m_query_graph->GetTarget(e); } + + EdgeDataT &GetEdgeData(const EdgeID e) const final { return m_query_graph->GetEdgeData(e); } + + EdgeID BeginEdges(const NodeID n) const final { return m_query_graph->BeginEdges(n); } + + EdgeID EndEdges(const NodeID n) const final { return m_query_graph->EndEdges(n); } + + EdgeRange GetAdjacentEdgeRange(const NodeID node) const final + { + return m_query_graph->GetAdjacentEdgeRange(node); + }; + + // searches for a specific edge + EdgeID FindEdge(const NodeID from, const NodeID to) const final + { + return m_query_graph->FindEdge(from, to); + } + + EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const final + { + return m_query_graph->FindEdgeInEitherDirection(from, to); + } + + EdgeID FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const final + { + return m_query_graph->FindEdgeIndicateIfReverse(from, to, result); + } + + // node and edge information access + FixedPointCoordinate GetCoordinateOfNode(const NodeID id) const final + { + return m_coordinate_list->at(id); + }; + + virtual bool EdgeIsCompressed(const unsigned id) const final + { + return m_edge_is_compressed.at(id); + } + + virtual void GetUncompressedGeometry(const unsigned id, + std::vector &result_nodes) const final + { + const unsigned begin = m_geometry_indices.at(id); + const unsigned end = m_geometry_indices.at(id + 1); + + result_nodes.clear(); + result_nodes.insert(result_nodes.begin(), m_geometry_list.begin() + begin, + m_geometry_list.begin() + end); + } + + virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const final + { + return m_via_node_list.at(id); + } + + TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const final + { + return m_turn_instruction_list.at(id); + } + + TravelMode GetTravelModeForEdgeID(const unsigned id) const { return m_travel_mode_list.at(id); } + + bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate, + FixedPointCoordinate &result, + const unsigned zoom_level = 18) final + { + if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first) + { + LoadRTree(); + } + + return m_static_rtree->second->LocateClosestEndPointForCoordinate(input_coordinate, result, + zoom_level); + } + + bool IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, + PhantomNode &resulting_phantom_node) final + { + std::vector resulting_phantom_node_vector; + auto result = IncrementalFindPhantomNodeForCoordinate(input_coordinate, + resulting_phantom_node_vector, 1); + if (result) + { + BOOST_ASSERT(!resulting_phantom_node_vector.empty()); + resulting_phantom_node = resulting_phantom_node_vector.front(); + } + return result; + } + + bool + IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, + std::vector &resulting_phantom_node_vector, + const unsigned number_of_results) final + { + if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first) + { + LoadRTree(); + } + + return m_static_rtree->second->IncrementalFindPhantomNodeForCoordinate( + input_coordinate, resulting_phantom_node_vector, number_of_results); + } + + unsigned GetCheckSum() const final { return m_check_sum; } + + unsigned GetNameIndexFromEdgeID(const unsigned id) const final + { + return m_name_ID_list.at(id); + }; + + void GetName(const unsigned name_id, std::string &result) const final + { + if (UINT_MAX == name_id) + { + result = ""; + return; + } + auto range = m_name_table->GetRange(name_id); + + result.clear(); + if (range.begin() != range.end()) + { + result.resize(range.back() - range.front() + 1); + std::copy(m_names_char_list.begin() + range.front(), + m_names_char_list.begin() + range.back() + 1, result.begin()); + } + } + + std::string GetTimestamp() const final { return m_timestamp; } +}; + +#endif // SHARED_DATAFACADE_HPP diff --git a/server/data_structures/shared_datatype.hpp b/server/data_structures/shared_datatype.hpp new file mode 100644 index 000000000..9464ff015 --- /dev/null +++ b/server/data_structures/shared_datatype.hpp @@ -0,0 +1,227 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef SHARED_DATA_TYPE_HPP +#define SHARED_DATA_TYPE_HPP + +#include "../../Util/osrm_exception.hpp" +#include "../../Util/simple_logger.hpp" + +#include + +#include + +namespace +{ +// Added at the start and end of each block as sanity check +constexpr static const char CANARY[] = "OSRM"; +} + +struct SharedDataLayout +{ + enum BlockID + { + NAME_OFFSETS = 0, + NAME_BLOCKS, + NAME_CHAR_LIST, + NAME_ID_LIST, + VIA_NODE_LIST, + GRAPH_NODE_LIST, + GRAPH_EDGE_LIST, + COORDINATE_LIST, + TURN_INSTRUCTION, + TRAVEL_MODE, + R_SEARCH_TREE, + GEOMETRIES_INDEX, + GEOMETRIES_LIST, + GEOMETRIES_INDICATORS, + HSGR_CHECKSUM, + TIMESTAMP, + FILE_INDEX_PATH, + NUM_BLOCKS + }; + + std::array num_entries; + std::array entry_size; + + SharedDataLayout() : num_entries(), entry_size() {} + + void PrintInformation() const + { + SimpleLogger().Write(logDEBUG) << "-"; + SimpleLogger().Write(logDEBUG) + << "name_offsets_size: " << num_entries[NAME_OFFSETS]; + SimpleLogger().Write(logDEBUG) + << "name_blocks_size: " << num_entries[NAME_BLOCKS]; + SimpleLogger().Write(logDEBUG) + << "name_char_list_size: " << num_entries[NAME_CHAR_LIST]; + SimpleLogger().Write(logDEBUG) + << "name_id_list_size: " << num_entries[NAME_ID_LIST]; + SimpleLogger().Write(logDEBUG) + << "via_node_list_size: " << num_entries[VIA_NODE_LIST]; + SimpleLogger().Write(logDEBUG) + << "graph_node_list_size: " << num_entries[GRAPH_NODE_LIST]; + SimpleLogger().Write(logDEBUG) + << "graph_edge_list_size: " << num_entries[GRAPH_EDGE_LIST]; + SimpleLogger().Write(logDEBUG) << "timestamp_length: " << num_entries[TIMESTAMP]; + SimpleLogger().Write(logDEBUG) + << "coordinate_list_size: " << num_entries[COORDINATE_LIST]; + SimpleLogger().Write(logDEBUG) + << "turn_instruction_list_size: " << num_entries[TURN_INSTRUCTION]; + SimpleLogger().Write(logDEBUG) + << "travel_mode_list_size: " << num_entries[TRAVEL_MODE]; + SimpleLogger().Write(logDEBUG) + << "r_search_tree_size: " << num_entries[R_SEARCH_TREE]; + SimpleLogger().Write(logDEBUG) + << "geometries_indicators: " << num_entries[GEOMETRIES_INDICATORS] << "/" + << ((num_entries[GEOMETRIES_INDICATORS] / 8) + 1); + SimpleLogger().Write(logDEBUG) + << "geometries_index_list_size: " << num_entries[GEOMETRIES_INDEX]; + SimpleLogger().Write(logDEBUG) + << "geometries_list_size: " << num_entries[GEOMETRIES_LIST]; + SimpleLogger().Write(logDEBUG) + << "sizeof(checksum): " << entry_size[HSGR_CHECKSUM]; + + SimpleLogger().Write(logDEBUG) << "NAME_OFFSETS " + << ": " << GetBlockSize(NAME_OFFSETS); + SimpleLogger().Write(logDEBUG) << "NAME_BLOCKS " + << ": " << GetBlockSize(NAME_BLOCKS); + SimpleLogger().Write(logDEBUG) << "NAME_CHAR_LIST " + << ": " << GetBlockSize(NAME_CHAR_LIST); + SimpleLogger().Write(logDEBUG) << "NAME_ID_LIST " + << ": " << GetBlockSize(NAME_ID_LIST); + SimpleLogger().Write(logDEBUG) << "VIA_NODE_LIST " + << ": " << GetBlockSize(VIA_NODE_LIST); + SimpleLogger().Write(logDEBUG) << "GRAPH_NODE_LIST " + << ": " << GetBlockSize(GRAPH_NODE_LIST); + SimpleLogger().Write(logDEBUG) << "GRAPH_EDGE_LIST " + << ": " << GetBlockSize(GRAPH_EDGE_LIST); + SimpleLogger().Write(logDEBUG) << "COORDINATE_LIST " + << ": " << GetBlockSize(COORDINATE_LIST); + SimpleLogger().Write(logDEBUG) << "TURN_INSTRUCTION " + << ": " << GetBlockSize(TURN_INSTRUCTION); + SimpleLogger().Write(logDEBUG) << "TRAVEL_MODE " + << ": " << GetBlockSize(TRAVEL_MODE); + SimpleLogger().Write(logDEBUG) << "R_SEARCH_TREE " + << ": " << GetBlockSize(R_SEARCH_TREE); + SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDEX " + << ": " << GetBlockSize(GEOMETRIES_INDEX); + SimpleLogger().Write(logDEBUG) << "GEOMETRIES_LIST " + << ": " << GetBlockSize(GEOMETRIES_LIST); + SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDICATORS" + << ": " << GetBlockSize(GEOMETRIES_INDICATORS); + SimpleLogger().Write(logDEBUG) << "HSGR_CHECKSUM " + << ": " << GetBlockSize(HSGR_CHECKSUM); + SimpleLogger().Write(logDEBUG) << "TIMESTAMP " + << ": " << GetBlockSize(TIMESTAMP); + SimpleLogger().Write(logDEBUG) << "FILE_INDEX_PATH " + << ": " << GetBlockSize(FILE_INDEX_PATH); + } + + template inline void SetBlockSize(BlockID bid, uint64_t entries) + { + num_entries[bid] = entries; + entry_size[bid] = sizeof(T); + } + + inline uint64_t GetBlockSize(BlockID bid) const + { + // special encoding + if (bid == GEOMETRIES_INDICATORS) + { + return (num_entries[GEOMETRIES_INDICATORS] / 32 + 1) * + entry_size[GEOMETRIES_INDICATORS]; + } + + return num_entries[bid] * entry_size[bid]; + } + + inline uint64_t GetSizeOfLayout() const + { + return GetBlockOffset(NUM_BLOCKS) + NUM_BLOCKS * 2 * sizeof(CANARY); + } + + inline uint64_t GetBlockOffset(BlockID bid) const + { + uint64_t result = sizeof(CANARY); + for (auto i = 0; i < bid; i++) + { + result += GetBlockSize((BlockID)i) + 2 * sizeof(CANARY); + } + return result; + } + + template + inline T *GetBlockPtr(char *shared_memory, BlockID bid) + { + T *ptr = (T *)(shared_memory + GetBlockOffset(bid)); + if (WRITE_CANARY) + { + char *start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY); + char *end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid); + std::copy(CANARY, CANARY + sizeof(CANARY), start_canary_ptr); + std::copy(CANARY, CANARY + sizeof(CANARY), end_canary_ptr); + } + else + { + char *start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY); + char *end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid); + bool start_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), start_canary_ptr); + bool end_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), end_canary_ptr); + if (!start_canary_alive) + { + throw osrm::exception("Start canary of block corrupted."); + } + if (!end_canary_alive) + { + throw osrm::exception("End canary of block corrupted."); + } + } + + return ptr; + } +}; + +enum SharedDataType +{ + CURRENT_REGIONS, + LAYOUT_1, + DATA_1, + LAYOUT_2, + DATA_2, + LAYOUT_NONE, + DATA_NONE +}; + +struct SharedDataTimestamp +{ + SharedDataType layout; + SharedDataType data; + unsigned timestamp; +}; + +#endif /* SHARED_DATA_TYPE_HPP */ diff --git a/server/http/compression_type.hpp b/server/http/compression_type.hpp new file mode 100644 index 000000000..49163adab --- /dev/null +++ b/server/http/compression_type.hpp @@ -0,0 +1,42 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef COMPRESSION_TYPE_HPP +#define COMPRESSION_TYPE_HPP + +namespace http +{ + +enum compression_type +{ + no_compression, + gzip_rfc1952, + deflate_rfc1951 +}; +} + +#endif // COMPRESSION_TYPE_HPP diff --git a/server/http/header.hpp b/server/http/header.hpp new file mode 100644 index 000000000..7996be439 --- /dev/null +++ b/server/http/header.hpp @@ -0,0 +1,54 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef HEADER_HPP +#define HEADER_HPP + +#include +#include + +namespace http +{ +struct header +{ + // explicitly use default copy c'tor as adding move c'tor + header &operator=(const header &other) = default; + header(const std::string &name, const std::string &value) : name(name), value(value) {} + header(header &&other) : name(std::move(other.name)), value(std::move(other.value)) {} + + void clear() + { + name.clear(); + value.clear(); + } + + std::string name; + std::string value; +}; +} + +#endif // HEADER_HPP diff --git a/server/http/reply.cpp b/server/http/reply.cpp new file mode 100644 index 000000000..89b931b05 --- /dev/null +++ b/server/http/reply.cpp @@ -0,0 +1,130 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "reply.hpp" + +#include "../../Util/cast.hpp" + +namespace http +{ + +const char ok_html[] = ""; +const char bad_request_html[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}"; +const char internal_server_error_html[] = + "{\"status\": 500,\"status_message\":\"Internal Server Error\"}"; +const char seperators[] = {':', ' '}; +const char crlf[] = {'\r', '\n'}; +const std::string http_ok_string = "HTTP/1.0 200 OK\r\n"; +const std::string http_bad_request_string = "HTTP/1.0 400 Bad Request\r\n"; +const std::string http_internal_server_error_string = "HTTP/1.0 500 Internal Server Error\r\n"; + +void reply::set_size(const std::size_t size) +{ + for (header &h : headers) + { + if ("Content-Length" == h.name) + { + h.value = cast::integral_to_string(size); + } + } +} + +void reply::set_uncompressed_size() { set_size(content.size()); } + +std::vector reply::to_buffers() +{ + std::vector buffers; + buffers.push_back(status_to_buffer(status)); + for (const header &h : headers) + { + buffers.push_back(boost::asio::buffer(h.name)); + buffers.push_back(boost::asio::buffer(seperators)); + buffers.push_back(boost::asio::buffer(h.value)); + buffers.push_back(boost::asio::buffer(crlf)); + } + buffers.push_back(boost::asio::buffer(crlf)); + buffers.push_back(boost::asio::buffer(content)); + return buffers; +} + +std::vector reply::headers_to_buffers() +{ + std::vector buffers; + buffers.push_back(status_to_buffer(status)); + for (const header ¤t_header : headers) + { + buffers.push_back(boost::asio::buffer(current_header.name)); + buffers.push_back(boost::asio::buffer(seperators)); + buffers.push_back(boost::asio::buffer(current_header.value)); + buffers.push_back(boost::asio::buffer(crlf)); + } + buffers.push_back(boost::asio::buffer(crlf)); + return buffers; +} + +reply reply::stock_reply(const reply::status_type status) +{ + reply reply; + reply.status = status; + reply.content.clear(); + + const std::string status_string = reply.status_to_string(status); + reply.content.insert(reply.content.end(), status_string.begin(), status_string.end()); + reply.headers.emplace_back("Access-Control-Allow-Origin", "*"); + reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size())); + reply.headers.emplace_back("Content-Type", "text/html"); + return reply; +} + +std::string reply::status_to_string(const reply::status_type status) +{ + if (reply::ok == status) + { + return ok_html; + } + if (reply::bad_request == status) + { + return bad_request_html; + } + return internal_server_error_html; +} + +boost::asio::const_buffer reply::status_to_buffer(const reply::status_type status) +{ + if (reply::ok == status) + { + return boost::asio::buffer(http_ok_string); + } + if (reply::internal_server_error == status) + { + return boost::asio::buffer(http_internal_server_error_string); + } + return boost::asio::buffer(http_bad_request_string); +} + +reply::reply() : status(ok) {} +} diff --git a/server/http/reply.hpp b/server/http/reply.hpp new file mode 100644 index 000000000..a4b6cb69b --- /dev/null +++ b/server/http/reply.hpp @@ -0,0 +1,65 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef REPLY_HPP +#define REPLY_HPP + +#include "header.hpp" + +#include + +#include + +namespace http +{ +class reply +{ + public: + enum status_type + { + ok = 200, + bad_request = 400, + internal_server_error = 500 + } status; + + std::vector
headers; + std::vector to_buffers(); + std::vector headers_to_buffers(); + std::vector content; + static reply stock_reply(const status_type status); + void set_size(const std::size_t size); + void set_uncompressed_size(); + + reply(); + + private: + std::string status_to_string(reply::status_type status); + boost::asio::const_buffer status_to_buffer(reply::status_type status); +}; +} + +#endif // REPLY_HPP diff --git a/server/http/request.hpp b/server/http/request.hpp new file mode 100644 index 000000000..0ad622580 --- /dev/null +++ b/server/http/request.hpp @@ -0,0 +1,48 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef REQUEST_HPP +#define REQUEST_HPP + +#include + +#include + +namespace http +{ + +struct request +{ + std::string uri; + std::string referrer; + std::string agent; + boost::asio::ip::address endpoint; +}; + +} // namespace http + +#endif // REQUEST_HPP diff --git a/Server/RequestHandler.cpp b/server/request_handler.cpp similarity index 98% rename from Server/RequestHandler.cpp rename to server/request_handler.cpp index 1ff82e24e..ca95118a9 100644 --- a/Server/RequestHandler.cpp +++ b/server/request_handler.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,9 +25,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "RequestHandler.h" +#include "request_handler.hpp" -#include "APIGrammar.h" +#include "api_grammar.hpp" #include "http/reply.hpp" #include "http/request.hpp" diff --git a/Server/RequestHandler.h b/server/request_handler.hpp similarity index 92% rename from Server/RequestHandler.h rename to server/request_handler.hpp index 2f0fd878f..1965a79c0 100644 --- a/Server/RequestHandler.h +++ b/server/request_handler.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef REQUEST_HANDLER_H -#define REQUEST_HANDLER_H +#ifndef REQUEST_HANDLER_HPP +#define REQUEST_HANDLER_HPP #include @@ -56,4 +56,4 @@ class RequestHandler OSRM *routing_machine; }; -#endif // REQUEST_HANDLER_H +#endif // REQUEST_HANDLER_HPP diff --git a/Server/RequestParser.cpp b/server/request_parser.cpp similarity index 99% rename from Server/RequestParser.cpp rename to server/request_parser.cpp index 25bfddf67..258c89198 100644 --- a/Server/RequestParser.cpp +++ b/server/request_parser.cpp @@ -25,7 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "RequestParser.h" +#include "request_parser.hpp" #include "http/request.hpp" diff --git a/Server/RequestParser.h b/server/request_parser.hpp similarity index 96% rename from Server/RequestParser.h rename to server/request_parser.hpp index 0df106e68..c7a72071e 100644 --- a/Server/RequestParser.h +++ b/server/request_parser.hpp @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef REQUEST_PARSER_H -#define REQUEST_PARSER_H +#ifndef REQUEST_PARSER_HPP +#define REQUEST_PARSER_HPP #include "http/compression_type.hpp" #include "http/header.hpp" @@ -89,4 +89,4 @@ class RequestParser } // namespace http -#endif // REQUEST_PARSER_H +#endif // REQUEST_PARSER_HPP diff --git a/Server/Server.h b/server/server.hpp similarity index 97% rename from Server/Server.h rename to server/server.hpp index b3d618efe..ee9887e52 100644 --- a/Server/Server.h +++ b/server/server.hpp @@ -25,11 +25,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SERVER_H -#define SERVER_H +#ifndef SERVER_HPP +#define SERVER_HPP -#include "Connection.h" -#include "RequestHandler.h" +#include "connection.hpp" +#include "request_handler.hpp" #include "../Util/cast.hpp" #include "../Util/integer_range.hpp" @@ -116,4 +116,4 @@ class Server RequestHandler request_handler; }; -#endif // SERVER_H +#endif // SERVER_HPP diff --git a/tools/springclean.cpp b/tools/springclean.cpp index 7cf98e9e3..054133a58 100644 --- a/tools/springclean.cpp +++ b/tools/springclean.cpp @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "../data_structures/shared_memory_factory.hpp" -#include "../Server/data_structures/shared_datatype.hpp" +#include "../server/data_structures/shared_datatype.hpp" #include "../Util/git_sha.hpp" #include "../Util/simple_logger.hpp" diff --git a/tools/unlock_all_mutexes.cpp b/tools/unlock_all_mutexes.cpp index 78fa6dcbf..f68ec32a7 100644 --- a/tools/unlock_all_mutexes.cpp +++ b/tools/unlock_all_mutexes.cpp @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../Util/git_sha.hpp" #include "../Util/simple_logger.hpp" -#include "../Server/data_structures/shared_barriers.hpp" +#include "../server/data_structures/shared_barriers.hpp" #include From 6768ecc3fc59d9eb508d2a20ab70829d4692d714 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 12:52:55 +0100 Subject: [PATCH 130/360] rename variable to make name lookup not fail on gcc --- server/connection.cpp | 35 +++++++++++++++++++---------------- server/connection.hpp | 4 ++-- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/server/connection.cpp b/server/connection.cpp index 1dd5ae5f1..0f16f465f 100644 --- a/server/connection.cpp +++ b/server/connection.cpp @@ -67,14 +67,15 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t // no error detected, let's parse the request compression_type compression_type(no_compression); osrm::tribool result; - std::tie(result, compression_type) = RequestParser().parse( - request, incoming_data_buffer.data(), incoming_data_buffer.data() + bytes_transferred); + std::tie(result, compression_type) = + RequestParser().parse(current_request, incoming_data_buffer.data(), + incoming_data_buffer.data() + bytes_transferred); // the request has been parsed if (result == osrm::tribool::yes) { - request.endpoint = TCP_socket.remote_endpoint().address(); - request_handler.handle_request(request, reply); + current_request.endpoint = TCP_socket.remote_endpoint().address(); + request_handler.handle_request(current_request, current_reply); // Header compression_header; std::vector compressed_output; @@ -85,24 +86,26 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t { case deflate_rfc1951: // use deflate for compression - reply.headers.insert(reply.headers.begin(), {"Content-Encoding", "deflate"}); - compressed_output = compress_buffers(reply.content, compression_type); - reply.set_size(static_cast(compressed_output.size())); - output_buffer = reply.headers_to_buffers(); + current_reply.headers.insert(current_reply.headers.begin(), + {"Content-Encoding", "deflate"}); + compressed_output = compress_buffers(current_reply.content, compression_type); + current_reply.set_size(static_cast(compressed_output.size())); + output_buffer = current_reply.headers_to_buffers(); output_buffer.push_back(boost::asio::buffer(compressed_output)); break; case gzip_rfc1952: // use gzip for compression - reply.headers.insert(reply.headers.begin(), {"Content-Encoding", "gzip"}); - compressed_output = compress_buffers(reply.content, compression_type); - reply.set_size(static_cast(compressed_output.size())); - output_buffer = reply.headers_to_buffers(); + current_reply.headers.insert(current_reply.headers.begin(), + {"Content-Encoding", "gzip"}); + compressed_output = compress_buffers(current_reply.content, compression_type); + current_reply.set_size(static_cast(compressed_output.size())); + output_buffer = current_reply.headers_to_buffers(); output_buffer.push_back(boost::asio::buffer(compressed_output)); break; case no_compression: // don't use any compression - reply.set_uncompressed_size(); - output_buffer = reply.to_buffers(); + current_reply.set_uncompressed_size(); + output_buffer = current_reply.to_buffers(); break; } // write result to stream @@ -113,10 +116,10 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t } else if (result == osrm::tribool::no) { // request is not parseable - reply = reply::stock_reply(reply::bad_request); + current_reply = reply::stock_reply(reply::bad_request); boost::asio::async_write( - TCP_socket, reply.to_buffers(), + TCP_socket, current_reply.to_buffers(), strand.wrap(boost::bind(&Connection::handle_write, this->shared_from_this(), boost::asio::placeholders::error))); } diff --git a/server/connection.hpp b/server/connection.hpp index ad9335523..d549f6e44 100644 --- a/server/connection.hpp +++ b/server/connection.hpp @@ -83,8 +83,8 @@ class Connection : public std::enable_shared_from_this boost::asio::ip::tcp::socket TCP_socket; RequestHandler &request_handler; boost::array incoming_data_buffer; - request request; - reply reply; + request current_request; + reply current_reply; }; } // namespace http From 8318b3ba8333a4c279d5fd706603814b91909e88 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 13:01:33 +0100 Subject: [PATCH 131/360] rename variable to be more telling that it's not a type but a variable --- Server/Connection.cpp | 35 +++++++++++++++++++---------------- server/request_parser.cpp | 10 +++++----- server/request_parser.hpp | 2 +- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/Server/Connection.cpp b/Server/Connection.cpp index 1dd5ae5f1..0f16f465f 100644 --- a/Server/Connection.cpp +++ b/Server/Connection.cpp @@ -67,14 +67,15 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t // no error detected, let's parse the request compression_type compression_type(no_compression); osrm::tribool result; - std::tie(result, compression_type) = RequestParser().parse( - request, incoming_data_buffer.data(), incoming_data_buffer.data() + bytes_transferred); + std::tie(result, compression_type) = + RequestParser().parse(current_request, incoming_data_buffer.data(), + incoming_data_buffer.data() + bytes_transferred); // the request has been parsed if (result == osrm::tribool::yes) { - request.endpoint = TCP_socket.remote_endpoint().address(); - request_handler.handle_request(request, reply); + current_request.endpoint = TCP_socket.remote_endpoint().address(); + request_handler.handle_request(current_request, current_reply); // Header compression_header; std::vector compressed_output; @@ -85,24 +86,26 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t { case deflate_rfc1951: // use deflate for compression - reply.headers.insert(reply.headers.begin(), {"Content-Encoding", "deflate"}); - compressed_output = compress_buffers(reply.content, compression_type); - reply.set_size(static_cast(compressed_output.size())); - output_buffer = reply.headers_to_buffers(); + current_reply.headers.insert(current_reply.headers.begin(), + {"Content-Encoding", "deflate"}); + compressed_output = compress_buffers(current_reply.content, compression_type); + current_reply.set_size(static_cast(compressed_output.size())); + output_buffer = current_reply.headers_to_buffers(); output_buffer.push_back(boost::asio::buffer(compressed_output)); break; case gzip_rfc1952: // use gzip for compression - reply.headers.insert(reply.headers.begin(), {"Content-Encoding", "gzip"}); - compressed_output = compress_buffers(reply.content, compression_type); - reply.set_size(static_cast(compressed_output.size())); - output_buffer = reply.headers_to_buffers(); + current_reply.headers.insert(current_reply.headers.begin(), + {"Content-Encoding", "gzip"}); + compressed_output = compress_buffers(current_reply.content, compression_type); + current_reply.set_size(static_cast(compressed_output.size())); + output_buffer = current_reply.headers_to_buffers(); output_buffer.push_back(boost::asio::buffer(compressed_output)); break; case no_compression: // don't use any compression - reply.set_uncompressed_size(); - output_buffer = reply.to_buffers(); + current_reply.set_uncompressed_size(); + output_buffer = current_reply.to_buffers(); break; } // write result to stream @@ -113,10 +116,10 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t } else if (result == osrm::tribool::no) { // request is not parseable - reply = reply::stock_reply(reply::bad_request); + current_reply = reply::stock_reply(reply::bad_request); boost::asio::async_write( - TCP_socket, reply.to_buffers(), + TCP_socket, current_reply.to_buffers(), strand.wrap(boost::bind(&Connection::handle_write, this->shared_from_this(), boost::asio::placeholders::error))); } diff --git a/server/request_parser.cpp b/server/request_parser.cpp index 258c89198..833eb937c 100644 --- a/server/request_parser.cpp +++ b/server/request_parser.cpp @@ -35,7 +35,7 @@ namespace http { RequestParser::RequestParser() - : state(internal_state::method_start), header({"", ""}), compression_type(no_compression) + : state(internal_state::method_start), header({"", ""}), selected_compression(no_compression) { } @@ -47,11 +47,11 @@ RequestParser::parse(request ¤t_request, char *begin, char *end) osrm::tribool result = consume(current_request, *begin++); if (result != osrm::tribool::indeterminate) { - return std::make_tuple(result, compression_type); + return std::make_tuple(result, selected_compression); } } osrm::tribool result = osrm::tribool::indeterminate; - return std::make_tuple(result, compression_type); + return std::make_tuple(result, selected_compression); } osrm::tribool RequestParser::consume(request ¤t_request, const char input) @@ -180,11 +180,11 @@ osrm::tribool RequestParser::consume(request ¤t_request, const char input) /* giving gzip precedence over deflate */ if (boost::icontains(header.value, "deflate")) { - compression_type = deflate_rfc1951; + selected_compression = deflate_rfc1951; } if (boost::icontains(header.value, "gzip")) { - compression_type = gzip_rfc1952; + selected_compression = gzip_rfc1952; } } diff --git a/server/request_parser.hpp b/server/request_parser.hpp index c7a72071e..35786690e 100644 --- a/server/request_parser.hpp +++ b/server/request_parser.hpp @@ -84,7 +84,7 @@ class RequestParser } state; header header; - compression_type compression_type; + compression_type selected_compression; }; } // namespace http From 34bbd7dcaa770fa7097cbb7fbbf0fd67883c2cea Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 13:11:04 +0100 Subject: [PATCH 132/360] renaming yet another variable to fix gcc name lookup --- server/request_parser.cpp | 25 +++++++++++++------------ server/request_parser.hpp | 2 +- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/server/request_parser.cpp b/server/request_parser.cpp index 833eb937c..3f7fa8145 100644 --- a/server/request_parser.cpp +++ b/server/request_parser.cpp @@ -35,7 +35,8 @@ namespace http { RequestParser::RequestParser() - : state(internal_state::method_start), header({"", ""}), selected_compression(no_compression) + : state(internal_state::method_start), current_header({"", ""}), + selected_compression(no_compression) { } @@ -175,27 +176,27 @@ osrm::tribool RequestParser::consume(request ¤t_request, const char input) } return osrm::tribool::no; case internal_state::header_line_start: - if (boost::iequals(header.name, "Accept-Encoding")) + if (boost::iequals(current_header.name, "Accept-Encoding")) { /* giving gzip precedence over deflate */ - if (boost::icontains(header.value, "deflate")) + if (boost::icontains(current_header.value, "deflate")) { selected_compression = deflate_rfc1951; } - if (boost::icontains(header.value, "gzip")) + if (boost::icontains(current_header.value, "gzip")) { selected_compression = gzip_rfc1952; } } - if (boost::iequals(header.name, "Referer")) + if (boost::iequals(current_header.name, "Referer")) { - current_request.referrer = header.value; + current_request.referrer = current_header.value; } - if (boost::iequals(header.name, "User-Agent")) + if (boost::iequals(current_header.name, "User-Agent")) { - current_request.agent = header.value; + current_request.agent = current_header.value; } if (input == '\r') @@ -208,8 +209,8 @@ osrm::tribool RequestParser::consume(request ¤t_request, const char input) return osrm::tribool::no; } state = internal_state::header_name; - header.clear(); - header.name.push_back(input); + current_header.clear(); + current_header.name.push_back(input); return osrm::tribool::indeterminate; case internal_state::header_lws: if (input == '\r') @@ -237,7 +238,7 @@ osrm::tribool RequestParser::consume(request ¤t_request, const char input) { return osrm::tribool::no; } - header.name.push_back(input); + current_header.name.push_back(input); return osrm::tribool::indeterminate; case internal_state::space_before_header_value: if (input == ' ') @@ -256,7 +257,7 @@ osrm::tribool RequestParser::consume(request ¤t_request, const char input) { return osrm::tribool::no; } - header.value.push_back(input); + current_header.value.push_back(input); return osrm::tribool::indeterminate; case internal_state::expecting_newline_2: if (input == '\n') diff --git a/server/request_parser.hpp b/server/request_parser.hpp index 35786690e..045db8d17 100644 --- a/server/request_parser.hpp +++ b/server/request_parser.hpp @@ -83,7 +83,7 @@ class RequestParser expecting_newline_3 } state; - header header; + header current_header; compression_type selected_compression; }; From dd3b8469dd8028551e4e6171028b2bcf594a7126 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 13:17:18 +0100 Subject: [PATCH 133/360] renamed: Include/* include/* --- CMakeLists.txt | 4 +- Include/osrm/libosrm_config.hpp | 14 ++--- include/osrm/coordinate.hpp | 71 +++++++++++++++++++++++ include/osrm/json_container.hpp | 94 +++++++++++++++++++++++++++++++ include/osrm/libosrm_config.hpp | 48 ++++++++++++++++ include/osrm/route_parameters.hpp | 92 ++++++++++++++++++++++++++++++ include/osrm/server_paths.hpp | 38 +++++++++++++ 7 files changed, 350 insertions(+), 11 deletions(-) create mode 100644 include/osrm/coordinate.hpp create mode 100644 include/osrm/json_container.hpp create mode 100644 include/osrm/libosrm_config.hpp create mode 100644 include/osrm/route_parameters.hpp create mode 100644 include/osrm/server_paths.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d9a6906d..12324fb05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,7 @@ endif() OPTION(WITH_TOOLS "Build OSRM tools" OFF) OPTION(BUILD_TOOLS "Build OSRM tools" OFF) -include_directories(${CMAKE_SOURCE_DIR}/Include/) +include_directories(${CMAKE_SOURCE_DIR}/include/) include_directories(${CMAKE_SOURCE_DIR}/third_party/) include_directories(${CMAKE_SOURCE_DIR}/third_party/libosmium/include/) @@ -325,7 +325,7 @@ if(WITH_TOOLS OR BUILD_TOOLS) install(TARGETS osrm-springclean DESTINATION bin) endif() -file(GLOB InstallGlob Include/osrm/*.hpp Library/OSRM.h) +file(GLOB InstallGlob include/osrm/*.hpp Library/OSRM.h) file(GLOB VariantGlob third_party/variant/*.hpp) # Add RPATH info to executables so that when they are run after being installed diff --git a/Include/osrm/libosrm_config.hpp b/Include/osrm/libosrm_config.hpp index 078c28f8f..2f0edaf35 100644 --- a/Include/osrm/libosrm_config.hpp +++ b/Include/osrm/libosrm_config.hpp @@ -32,17 +32,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct libosrm_config { - libosrm_config(const libosrm_config&) = delete; - libosrm_config() - : max_locations_distance_table(100) - , use_shared_memory(false) - {} + libosrm_config(const libosrm_config &) = delete; + libosrm_config() : max_locations_distance_table(100), use_shared_memory(false) {} libosrm_config(const ServerPaths &paths, const bool flag, const int max) - : server_paths(paths) - , max_locations_distance_table(max) - , use_shared_memory(flag) - {} + : server_paths(paths), max_locations_distance_table(max), use_shared_memory(flag) + { + } ServerPaths server_paths; int max_locations_distance_table; diff --git a/include/osrm/coordinate.hpp b/include/osrm/coordinate.hpp new file mode 100644 index 000000000..546515d49 --- /dev/null +++ b/include/osrm/coordinate.hpp @@ -0,0 +1,71 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef COORDINATE_HPP_ +#define COORDINATE_HPP_ + +#include //for std::ostream +#include +#include + +namespace +{ +constexpr static const float COORDINATE_PRECISION = 1000000.f; +} + +struct FixedPointCoordinate +{ + int lat; + int lon; + + FixedPointCoordinate(); + FixedPointCoordinate(int lat, int lon); + + template + FixedPointCoordinate(const T &coordinate) + : lat(coordinate.lat), lon(coordinate.lon) + { + static_assert(std::is_same::value, + "coordinate types incompatible"); + static_assert(std::is_same::value, + "coordinate types incompatible"); + } + + bool is_valid() const; + bool operator==(const FixedPointCoordinate &other) const; + + float bearing(const FixedPointCoordinate &other) const; + void output(std::ostream &out) const; +}; + +inline std::ostream &operator<<(std::ostream &out_stream, FixedPointCoordinate const &coordinate) +{ + coordinate.output(out_stream); + return out_stream; +} + +#endif /* COORDINATE_HPP_ */ diff --git a/include/osrm/json_container.hpp b/include/osrm/json_container.hpp new file mode 100644 index 000000000..9bbbec433 --- /dev/null +++ b/include/osrm/json_container.hpp @@ -0,0 +1,94 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +// based on +// https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp + +#ifndef JSON_CONTAINER_H +#define JSON_CONTAINER_H + +#include + +#include +#include +#include +#include + +namespace JSON +{ + +struct Object; +struct Array; + +struct String +{ + String() {} + String(const char *value) : value(value) {} + String(const std::string &value) : value(value) {} + std::string value; +}; + +struct Number +{ + Number() {} + Number(double value) : value(static_cast(value)) {} + double value; +}; + +struct True +{ +}; + +struct False +{ +}; + +struct Null +{ +}; + +using Value = mapbox::util::variant, + mapbox::util::recursive_wrapper, + True, + False, + Null>; + +struct Object +{ + std::unordered_map values; +}; + +struct Array +{ + std::vector values; +}; + +} // namespace JSON + +#endif // JSON_CONTAINER_H diff --git a/include/osrm/libosrm_config.hpp b/include/osrm/libosrm_config.hpp new file mode 100644 index 000000000..2f0edaf35 --- /dev/null +++ b/include/osrm/libosrm_config.hpp @@ -0,0 +1,48 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef SERVER_CONFIG_HPP +#define SERVER_CONFIG_HPP + +#include + +struct libosrm_config +{ + libosrm_config(const libosrm_config &) = delete; + libosrm_config() : max_locations_distance_table(100), use_shared_memory(false) {} + + libosrm_config(const ServerPaths &paths, const bool flag, const int max) + : server_paths(paths), max_locations_distance_table(max), use_shared_memory(flag) + { + } + + ServerPaths server_paths; + int max_locations_distance_table; + bool use_shared_memory; +}; + +#endif // SERVER_CONFIG_HPP diff --git a/include/osrm/route_parameters.hpp b/include/osrm/route_parameters.hpp new file mode 100644 index 000000000..0a450d571 --- /dev/null +++ b/include/osrm/route_parameters.hpp @@ -0,0 +1,92 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef ROUTE_PARAMETERS_H +#define ROUTE_PARAMETERS_H + +#include + +#include + +#include +#include + +struct RouteParameters +{ + RouteParameters(); + + void setZoomLevel(const short level); + + void setNumberOfResults(const short number); + + void setAlternateRouteFlag(const bool flag); + + void setUTurn(const bool flag); + + void setAllUTurns(const bool flag); + + void setDeprecatedAPIFlag(const std::string &); + + void setChecksum(const unsigned check_sum); + + void setInstructionFlag(const bool flag); + + void setService(const std::string &service); + + void setOutputFormat(const std::string &format); + + void setJSONpParameter(const std::string ¶meter); + + void addHint(const std::string &hint); + + void setLanguage(const std::string &language); + + void setGeometryFlag(const bool flag); + + void setCompressionFlag(const bool flag); + + void addCoordinate(const boost::fusion::vector &coordinates); + + short zoom_level; + bool print_instructions; + bool alternate_route; + bool geometry; + bool compression; + bool deprecatedAPI; + bool uturn_default; + unsigned check_sum; + short num_results; + std::string service; + std::string output_format; + std::string jsonp_parameter; + std::string language; + std::vector hints; + std::vector uturns; + std::vector coordinates; +}; + +#endif // ROUTE_PARAMETERS_H diff --git a/include/osrm/server_paths.hpp b/include/osrm/server_paths.hpp new file mode 100644 index 000000000..52b60c7c4 --- /dev/null +++ b/include/osrm/server_paths.hpp @@ -0,0 +1,38 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef SERVER_PATH_H +#define SERVER_PATH_H + +#include + +#include +#include + +typedef std::unordered_map ServerPaths; + +#endif // SERVER_PATH_H From 1187f83ffdade459ada6e762f902e42c66b3a298 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 16:35:19 +0100 Subject: [PATCH 134/360] renamed: Library/*.h -> library/*.hpp --- CMakeLists.txt | 4 +- Library/OSRM_impl.cpp | 4 +- Library/OSRM.h => library/osrm.hpp | 6 +- library/osrm_impl.cpp | 178 +++++++++++++++++++ Library/OSRM_impl.h => library/osrm_impl.hpp | 11 +- routed.cpp | 2 +- server/request_handler.cpp | 2 +- tools/simpleclient.cpp | 2 +- 8 files changed, 195 insertions(+), 14 deletions(-) rename Library/OSRM.h => library/osrm.hpp (96%) create mode 100644 library/osrm_impl.cpp rename Library/OSRM_impl.h => library/osrm_impl.hpp (95%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 12324fb05..ccb2632bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,7 +76,7 @@ list(REMOVE_ITEM DatastructureGlob data_structures/Coordinate.cpp) file(GLOB CoordinateGlob data_structures/coordinate*.cpp) file(GLOB AlgorithmGlob algorithms/*.cpp) file(GLOB HttpGlob server/http/*.cpp) -file(GLOB LibOSRMGlob Library/*.cpp) +file(GLOB LibOSRMGlob library/*.cpp) file(GLOB DataStructureTestsGlob unit_tests/data_structures/*.cpp data_structures/hilbert_value.cpp) file(GLOB AlgorithmTestsGlob unit_tests/algorithms/*.cpp) @@ -325,7 +325,7 @@ if(WITH_TOOLS OR BUILD_TOOLS) install(TARGETS osrm-springclean DESTINATION bin) endif() -file(GLOB InstallGlob include/osrm/*.hpp Library/OSRM.h) +file(GLOB InstallGlob include/osrm/*.hpp library/osrm.hpp) file(GLOB VariantGlob third_party/variant/*.hpp) # Add RPATH info to executables so that when they are run after being installed diff --git a/Library/OSRM_impl.cpp b/Library/OSRM_impl.cpp index cbb33a904..ba3a8abb9 100644 --- a/Library/OSRM_impl.cpp +++ b/Library/OSRM_impl.cpp @@ -33,8 +33,8 @@ class named_mutex; } } -#include "OSRM_impl.h" -#include "OSRM.h" +#include "osrm_impl.hpp" +#include "osrm.hpp" #include "../plugins/distance_table.hpp" #include "../plugins/hello_world.hpp" diff --git a/Library/OSRM.h b/library/osrm.hpp similarity index 96% rename from Library/OSRM.h rename to library/osrm.hpp index 1f0acebfa..571297d06 100644 --- a/Library/OSRM.h +++ b/library/osrm.hpp @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef OSRM_H -#define OSRM_H +#ifndef OSRM_HPP +#define OSRM_HPP #include @@ -51,4 +51,4 @@ class OSRM int RunQuery(RouteParameters &route_parameters, JSON::Object &json_result); }; -#endif // OSRM_H +#endif // OSRM_HPP diff --git a/library/osrm_impl.cpp b/library/osrm_impl.cpp new file mode 100644 index 000000000..ba3a8abb9 --- /dev/null +++ b/library/osrm_impl.cpp @@ -0,0 +1,178 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +namespace boost +{ +namespace interprocess +{ +class named_mutex; +} +} + +#include "osrm_impl.hpp" +#include "osrm.hpp" + +#include "../plugins/distance_table.hpp" +#include "../plugins/hello_world.hpp" +#include "../plugins/locate.hpp" +#include "../plugins/nearest.hpp" +#include "../plugins/timestamp.hpp" +#include "../plugins/viaroute.hpp" +#include "../server/data_structures/datafacade_base.hpp" +#include "../server/data_structures/internal_datafacade.hpp" +#include "../server/data_structures/shared_barriers.hpp" +#include "../server/data_structures/shared_datafacade.hpp" +#include "../Util/make_unique.hpp" +#include "../Util/ProgramOptions.h" +#include "../Util/simple_logger.hpp" + +#include +#include +#include + +#include + +#include +#include +#include +#include + +OSRM_impl::OSRM_impl(libosrm_config &lib_config) +{ + if (lib_config.use_shared_memory) + { + barrier = osrm::make_unique(); + query_data_facade = new SharedDataFacade(); + } + else + { + // populate base path + populate_base_path(lib_config.server_paths); + query_data_facade = new InternalDataFacade(lib_config.server_paths); + } + + // The following plugins handle all requests. + RegisterPlugin(new DistanceTablePlugin>( + query_data_facade, lib_config.max_locations_distance_table)); + RegisterPlugin(new HelloWorldPlugin()); + RegisterPlugin(new LocatePlugin>(query_data_facade)); + RegisterPlugin(new NearestPlugin>(query_data_facade)); + RegisterPlugin(new TimestampPlugin>(query_data_facade)); + RegisterPlugin(new ViaRoutePlugin>(query_data_facade)); +} + +OSRM_impl::~OSRM_impl() +{ + delete query_data_facade; + for (PluginMap::value_type &plugin_pointer : plugin_map) + { + delete plugin_pointer.second; + } +} + +void OSRM_impl::RegisterPlugin(BasePlugin *plugin) +{ + SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor(); + if (plugin_map.find(plugin->GetDescriptor()) != plugin_map.end()) + { + delete plugin_map.find(plugin->GetDescriptor())->second; + } + plugin_map.emplace(plugin->GetDescriptor(), plugin); +} + +int OSRM_impl::RunQuery(RouteParameters &route_parameters, JSON::Object &json_result) +{ + const auto &plugin_iterator = plugin_map.find(route_parameters.service); + + if (plugin_map.end() == plugin_iterator) + { + return 400; + } + + increase_concurrent_query_count(); + plugin_iterator->second->HandleRequest(route_parameters, json_result); + decrease_concurrent_query_count(); + return 200; +} + +// decrease number of concurrent queries +void OSRM_impl::decrease_concurrent_query_count() +{ + if (!barrier) + { + return; + } + // lock query + boost::interprocess::scoped_lock query_lock( + barrier->query_mutex); + + // decrement query count + --(barrier->number_of_queries); + BOOST_ASSERT_MSG(0 <= barrier->number_of_queries, "invalid number of queries"); + + // notify all processes that were waiting for this condition + if (0 == barrier->number_of_queries) + { + barrier->no_running_queries_condition.notify_all(); + } +} + +// increase number of concurrent queries +void OSRM_impl::increase_concurrent_query_count() +{ + if (!barrier) + { + return; + } + + // lock update pending + boost::interprocess::scoped_lock pending_lock( + barrier->pending_update_mutex); + + // lock query + boost::interprocess::scoped_lock query_lock( + barrier->query_mutex); + + // unlock update pending + pending_lock.unlock(); + + // increment query count + ++(barrier->number_of_queries); + + (static_cast *>(query_data_facade)) + ->CheckAndReloadFacade(); +} + +// proxy code for compilation firewall +OSRM::OSRM(libosrm_config &lib_config) : OSRM_pimpl_(osrm::make_unique(lib_config)) {} + +OSRM::~OSRM() { OSRM_pimpl_.reset(); } + +int OSRM::RunQuery(RouteParameters &route_parameters, JSON::Object &json_result) +{ + return OSRM_pimpl_->RunQuery(route_parameters, json_result); +} diff --git a/Library/OSRM_impl.h b/library/osrm_impl.hpp similarity index 95% rename from Library/OSRM_impl.h rename to library/osrm_impl.hpp index 4568f47d3..8f12ba69c 100644 --- a/Library/OSRM_impl.h +++ b/library/osrm_impl.hpp @@ -25,11 +25,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef OSRM_IMPL_H -#define OSRM_IMPL_H +#ifndef OSRM_IMPL_HPP +#define OSRM_IMPL_HPP class BasePlugin; -namespace http { class Reply; } +namespace http +{ +class Reply; +} struct RouteParameters; #include "../data_structures/query_edge.hpp" @@ -69,4 +72,4 @@ class OSRM_impl void increase_concurrent_query_count(); }; -#endif // OSRM_IMPL_H +#endif // OSRM_IMPL_HPP diff --git a/routed.cpp b/routed.cpp index 96b20133f..962fe1eec 100644 --- a/routed.cpp +++ b/routed.cpp @@ -25,7 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "Library/OSRM.h" +#include "library/osrm.hpp" #include "server/server.hpp" #include "Util/git_sha.hpp" #include "Util/ProgramOptions.h" diff --git a/server/request_handler.cpp b/server/request_handler.cpp index ca95118a9..17a004338 100644 --- a/server/request_handler.cpp +++ b/server/request_handler.cpp @@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "http/reply.hpp" #include "http/request.hpp" -#include "../Library/OSRM.h" +#include "../library/osrm.hpp" #include "../Util/json_renderer.hpp" #include "../Util/simple_logger.hpp" #include "../Util/string_util.hpp" diff --git a/tools/simpleclient.cpp b/tools/simpleclient.cpp index 11b4f9a89..3200d9ea6 100644 --- a/tools/simpleclient.cpp +++ b/tools/simpleclient.cpp @@ -25,7 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "../Library/OSRM.h" +#include "../library/osrm.hpp" #include "../Util/git_sha.hpp" #include "../Util/json_renderer.hpp" #include "../Util/ProgramOptions.h" From c8041bacd672f4e0f66af7130738e9358989da0e Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 16:57:50 +0100 Subject: [PATCH 135/360] renamed: Util/IniFileUtil.h -> Util/ini_file.hpp --- Util/DataStoreOptions.h | 30 +++++++++++----------------- Util/ProgramOptions.h | 4 ++-- Util/{IniFileUtil.h => ini_file.hpp} | 26 +++++++++++++----------- extractor/extractor.cpp | 4 +++- extractor/extractor_options.cpp | 4 ++-- 5 files changed, 33 insertions(+), 35 deletions(-) rename Util/{IniFileUtil.h => ini_file.hpp} (74%) diff --git a/Util/DataStoreOptions.h b/Util/DataStoreOptions.h index 0ad3222fc..c1435e29b 100644 --- a/Util/DataStoreOptions.h +++ b/Util/DataStoreOptions.h @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BoostFileSystemFix.h" #include "git_sha.hpp" -#include "IniFileUtil.h" +#include "ini_file.hpp" #include "osrm_exception.hpp" #include "simple_logger.hpp" @@ -47,34 +47,29 @@ bool GenerateDataStoreOptions(const int argc, const char *argv[], ServerPaths &p { // declare a group of options that will be allowed only on command line boost::program_options::options_description generic_options("Options"); - generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message") - ("springclean,s", "Remove all regions in shared memory")("config,c", - boost::program_options::value(&paths["config"]) - ->default_value("server.ini"), + generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")( + "springclean,s", "Remove all regions in shared memory")( + "config,c", boost::program_options::value(&paths["config"]) + ->default_value("server.ini"), "Path to a configuration file"); // declare a group of options that will be allowed both on command line // as well as in a config file boost::program_options::options_description config_options("Configuration"); config_options.add_options()( - "hsgrdata", - boost::program_options::value(&paths["hsgrdata"]), + "hsgrdata", boost::program_options::value(&paths["hsgrdata"]), ".hsgr file")("nodesdata", boost::program_options::value(&paths["nodesdata"]), ".nodes file")( - "edgesdata", - boost::program_options::value(&paths["edgesdata"]), + "edgesdata", boost::program_options::value(&paths["edgesdata"]), ".edges file")("geometry", boost::program_options::value(&paths["geometry"]), ".geometry file")( - "ramindex", - boost::program_options::value(&paths["ramindex"]), + "ramindex", boost::program_options::value(&paths["ramindex"]), ".ramIndex file")( - "fileindex", - boost::program_options::value(&paths["fileindex"]), + "fileindex", boost::program_options::value(&paths["fileindex"]), ".fileIndex file")( - "namesdata", - boost::program_options::value(&paths["namesdata"]), + "namesdata", boost::program_options::value(&paths["namesdata"]), ".names file")("timestamp", boost::program_options::value(&paths["timestamp"]), ".timestamp file"); @@ -83,8 +78,7 @@ bool GenerateDataStoreOptions(const int argc, const char *argv[], ServerPaths &p // file, but will not be shown to the user boost::program_options::options_description hidden_options("Hidden options"); hidden_options.add_options()( - "base,b", - boost::program_options::value(&paths["base"]), + "base,b", boost::program_options::value(&paths["base"]), "base path to .osrm file"); // positional option @@ -157,7 +151,7 @@ bool GenerateDataStoreOptions(const int argc, const char *argv[], ServerPaths &p !option_variables.count("base")) { SimpleLogger().Write() << "Reading options from: " << path_iterator->second.string(); - std::string ini_file_contents = ReadIniFileAndLowerContents(path_iterator->second); + std::string ini_file_contents = read_file_lower_content(path_iterator->second); std::stringstream config_stream(ini_file_contents); boost::program_options::store(parse_config_file(config_stream, config_file_options), option_variables); diff --git a/Util/ProgramOptions.h b/Util/ProgramOptions.h index 0c350fc75..55ee99539 100644 --- a/Util/ProgramOptions.h +++ b/Util/ProgramOptions.h @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define PROGAM_OPTIONS_H #include "git_sha.hpp" -#include "IniFileUtil.h" +#include "ini_file.hpp" #include "osrm_exception.hpp" #include "simple_logger.hpp" @@ -244,7 +244,7 @@ inline unsigned GenerateServerProgramOptions(const int argc, !option_variables.count("base")) { SimpleLogger().Write() << "Reading options from: " << path_iterator->second.string(); - std::string ini_file_contents = ReadIniFileAndLowerContents(path_iterator->second); + std::string ini_file_contents = read_file_lower_content(path_iterator->second); std::stringstream config_stream(ini_file_contents); boost::program_options::store(parse_config_file(config_stream, config_file_options), option_variables); diff --git a/Util/IniFileUtil.h b/Util/ini_file.hpp similarity index 74% rename from Util/IniFileUtil.h rename to Util/ini_file.hpp index ea1d7a13b..20616257a 100644 --- a/Util/IniFileUtil.h +++ b/Util/ini_file.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,25 +25,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef INI_FILE_UTIL_H -#define INI_FILE_UTIL_H +#ifndef INI_FILE_HPP +#define INI_FILE_HPP #include #include -#include -#include +#include #include +namespace +{ + // support old capitalized option names by down-casing them with a regex replace -inline std::string ReadIniFileAndLowerContents(const boost::filesystem::path &path) +std::string read_file_lower_content(const boost::filesystem::path &path) { boost::filesystem::fstream config_stream(path); std::string ini_file_content((std::istreambuf_iterator(config_stream)), - std::istreambuf_iterator()); - boost::regex regex( "^([^=]*)" ); //match from start of line to '=' - std::string format( "\\L$1\\E" ); //replace with downcased substring - return boost::regex_replace( ini_file_content, regex, format ); + std::istreambuf_iterator()); + std::transform(std::begin(ini_file_content), std::end(ini_file_content), + std::begin(ini_file_content), ::tolower); + return ini_file_content; } - -#endif // INI_FILE_UTIL_H +} +#endif // INI_FILE_HPP diff --git a/extractor/extractor.cpp b/extractor/extractor.cpp index a4c31e04e..c4e7203f5 100644 --- a/extractor/extractor.cpp +++ b/extractor/extractor.cpp @@ -35,7 +35,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "scripting_environment.hpp" #include "../Util/git_sha.hpp" -#include "../Util/IniFileUtil.h" #include "../Util/make_unique.hpp" #include "../Util/simple_logger.hpp" #include "../Util/timing_util.hpp" @@ -46,6 +45,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include +#include + #include #include diff --git a/extractor/extractor_options.cpp b/extractor/extractor_options.cpp index 6514ef647..68a905a22 100644 --- a/extractor/extractor_options.cpp +++ b/extractor/extractor_options.cpp @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "extractor_options.hpp" #include "../Util/git_sha.hpp" -#include "../Util/IniFileUtil.h" +#include "../Util/ini_file.hpp" #include "../Util/simple_logger.hpp" #include @@ -108,7 +108,7 @@ ExtractorOptions::ParseArguments(int argc, char *argv[], ExtractorConfig &extrac SimpleLogger().Write() << "Reading options from: " << extractor_config.config_file_path.string(); std::string ini_file_contents = - ReadIniFileAndLowerContents(extractor_config.config_file_path); + read_file_lower_content(extractor_config.config_file_path); std::stringstream config_stream(ini_file_contents); boost::program_options::store(parse_config_file(config_stream, config_file_options), option_variables); From 0de6e4ccbb646aab4e6da496a1d94146c2f10637 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 17:06:10 +0100 Subject: [PATCH 136/360] renamed: Util/DataStoreOptions.h -> Util/datastore_options.hpp renamed: Util/ProgramOptions.h -> Util/routed_options.hpp --- Library/OSRM_impl.cpp | 2 +- Util/{DataStoreOptions.h => datastore_options.hpp} | 6 +++--- Util/{ProgramOptions.h => routed_options.hpp} | 6 +++--- datastore.cpp | 2 +- library/osrm_impl.cpp | 2 +- routed.cpp | 2 +- tools/simpleclient.cpp | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) rename Util/{DataStoreOptions.h => datastore_options.hpp} (99%) rename Util/{ProgramOptions.h => routed_options.hpp} (99%) diff --git a/Library/OSRM_impl.cpp b/Library/OSRM_impl.cpp index ba3a8abb9..aaf1e3da3 100644 --- a/Library/OSRM_impl.cpp +++ b/Library/OSRM_impl.cpp @@ -47,7 +47,7 @@ class named_mutex; #include "../server/data_structures/shared_barriers.hpp" #include "../server/data_structures/shared_datafacade.hpp" #include "../Util/make_unique.hpp" -#include "../Util/ProgramOptions.h" +#include "../Util/routed_options.hpp" #include "../Util/simple_logger.hpp" #include diff --git a/Util/DataStoreOptions.h b/Util/datastore_options.hpp similarity index 99% rename from Util/DataStoreOptions.h rename to Util/datastore_options.hpp index c1435e29b..dbc7fe87e 100644 --- a/Util/DataStoreOptions.h +++ b/Util/datastore_options.hpp @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DATA_STORE_OPTIONS_H -#define DATA_STORE_OPTIONS_H +#ifndef DATASTORE_OPTIONS_HPP +#define DATASTORE_OPTIONS_HPP #include "BoostFileSystemFix.h" #include "git_sha.hpp" @@ -270,4 +270,4 @@ bool GenerateDataStoreOptions(const int argc, const char *argv[], ServerPaths &p return true; } -#endif /* DATA_STORE_OPTIONS_H */ +#endif /* DATASTORE_OPTIONS_HPP */ diff --git a/Util/ProgramOptions.h b/Util/routed_options.hpp similarity index 99% rename from Util/ProgramOptions.h rename to Util/routed_options.hpp index 55ee99539..74e79b070 100644 --- a/Util/ProgramOptions.h +++ b/Util/routed_options.hpp @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef PROGAM_OPTIONS_H -#define PROGAM_OPTIONS_H +#ifndef ROUTED_OPTIONS_HPP +#define ROUTED_OPTIONS_HPP #include "git_sha.hpp" #include "ini_file.hpp" @@ -274,4 +274,4 @@ inline unsigned GenerateServerProgramOptions(const int argc, return INIT_OK_DO_NOT_START_ENGINE; } -#endif /* PROGRAM_OPTIONS_H */ +#endif // ROUTED_OPTIONS_HPP diff --git a/datastore.cpp b/datastore.cpp index d33f6f603..ce0a8c6b9 100644 --- a/datastore.cpp +++ b/datastore.cpp @@ -37,7 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "server/data_structures/shared_datatype.hpp" #include "server/data_structures/shared_barriers.hpp" #include "Util/BoostFileSystemFix.h" -#include "Util/DataStoreOptions.h" +#include "Util/datastore_options.hpp" #include "Util/simple_logger.hpp" #include "Util/osrm_exception.hpp" #include "Util/fingerprint.hpp" diff --git a/library/osrm_impl.cpp b/library/osrm_impl.cpp index ba3a8abb9..aaf1e3da3 100644 --- a/library/osrm_impl.cpp +++ b/library/osrm_impl.cpp @@ -47,7 +47,7 @@ class named_mutex; #include "../server/data_structures/shared_barriers.hpp" #include "../server/data_structures/shared_datafacade.hpp" #include "../Util/make_unique.hpp" -#include "../Util/ProgramOptions.h" +#include "../Util/routed_options.hpp" #include "../Util/simple_logger.hpp" #include diff --git a/routed.cpp b/routed.cpp index 962fe1eec..78f48cc82 100644 --- a/routed.cpp +++ b/routed.cpp @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "library/osrm.hpp" #include "server/server.hpp" #include "Util/git_sha.hpp" -#include "Util/ProgramOptions.h" +#include "Util/routed_options.hpp" #include "Util/simple_logger.hpp" #ifdef __linux__ diff --git a/tools/simpleclient.cpp b/tools/simpleclient.cpp index 3200d9ea6..8de120821 100644 --- a/tools/simpleclient.cpp +++ b/tools/simpleclient.cpp @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../library/osrm.hpp" #include "../Util/git_sha.hpp" #include "../Util/json_renderer.hpp" -#include "../Util/ProgramOptions.h" +#include "../Util/routed_options.hpp" #include "../Util/simple_logger.hpp" #include From 7be5502a12be19532fbcaa71d5cf712cddcd01c2 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 17:14:03 +0100 Subject: [PATCH 137/360] renamed: Util/BoostFileSystemFix.h -> Util/boost_filesystem_2_fix.hpp renamed: Util/TrigonometryTables.h -> Util/trigonometry_table.hpp --- .../data_structures/internal_datafacade.hpp | 2 +- Server/data_structures/shared_datafacade.hpp | 2 +- Util/TrigonometryTables.h | 790 ------------------ ...SystemFix.h => boost_filesystem_2_fix.hpp} | 0 Util/compute_angle.cpp | 2 +- Util/datastore_options.hpp | 2 +- Util/trigonometry_table.hpp | 448 ++++++++++ datastore.cpp | 2 +- .../data_structures/internal_datafacade.hpp | 2 +- server/data_structures/shared_datafacade.hpp | 2 +- 10 files changed, 455 insertions(+), 797 deletions(-) delete mode 100644 Util/TrigonometryTables.h rename Util/{BoostFileSystemFix.h => boost_filesystem_2_fix.hpp} (100%) create mode 100644 Util/trigonometry_table.hpp diff --git a/Server/data_structures/internal_datafacade.hpp b/Server/data_structures/internal_datafacade.hpp index a9949e383..f25185a1e 100644 --- a/Server/data_structures/internal_datafacade.hpp +++ b/Server/data_structures/internal_datafacade.hpp @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../data_structures/static_graph.hpp" #include "../../data_structures/static_rtree.hpp" #include "../../data_structures/range_table.hpp" -#include "../../Util/BoostFileSystemFix.h" +#include "../../Util/boost_filesystem_2_fix.hpp" #include "../../Util/graph_loader.hpp" #include "../../Util/simple_logger.hpp" diff --git a/Server/data_structures/shared_datafacade.hpp b/Server/data_structures/shared_datafacade.hpp index 11a295e27..1b038dc89 100644 --- a/Server/data_structures/shared_datafacade.hpp +++ b/Server/data_structures/shared_datafacade.hpp @@ -36,7 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../data_structures/range_table.hpp" #include "../../data_structures/static_graph.hpp" #include "../../data_structures/static_rtree.hpp" -#include "../../Util/BoostFileSystemFix.h" +#include "../../Util/boost_filesystem_2_fix.hpp" #include "../../Util/make_unique.hpp" #include "../../Util/simple_logger.hpp" diff --git a/Util/TrigonometryTables.h b/Util/TrigonometryTables.h deleted file mode 100644 index d14540482..000000000 --- a/Util/TrigonometryTables.h +++ /dev/null @@ -1,790 +0,0 @@ -/* - -Copyright (c) 2013, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TRIGONOMETRY_TABLES_H -#define TRIGONOMETRY_TABLES_H - -#include "../typedefs.h" -#include - -#include - -constexpr unsigned short atan_table[4096] = { -0x0000, 0x0014, 0x0028, 0x003d, 0x0051, 0x0065, -0x007a, 0x008e, 0x00a3, 0x00b7, 0x00cb, 0x00e0, -0x00f4, 0x0108, 0x011d, 0x0131, 0x0146, 0x015a, -0x016e, 0x0183, 0x0197, 0x01ab, 0x01c0, 0x01d4, -0x01e9, 0x01fd, 0x0211, 0x0226, 0x023a, 0x024e, -0x0263, 0x0277, 0x028c, 0x02a0, 0x02b4, 0x02c9, -0x02dd, 0x02f1, 0x0306, 0x031a, 0x032f, 0x0343, -0x0357, 0x036c, 0x0380, 0x0394, 0x03a9, 0x03bd, -0x03d2, 0x03e6, 0x03fa, 0x040f, 0x0423, 0x0437, -0x044c, 0x0460, 0x0475, 0x0489, 0x049d, 0x04b2, -0x04c6, 0x04da, 0x04ef, 0x0503, 0x0517, 0x052c, -0x0540, 0x0555, 0x0569, 0x057d, 0x0592, 0x05a6, -0x05ba, 0x05cf, 0x05e3, 0x05f8, 0x060c, 0x0620, -0x0635, 0x0649, 0x065d, 0x0672, 0x0686, 0x069b, -0x06af, 0x06c3, 0x06d8, 0x06ec, 0x0700, 0x0715, -0x0729, 0x073d, 0x0752, 0x0766, 0x077b, 0x078f, -0x07a3, 0x07b8, 0x07cc, 0x07e0, 0x07f5, 0x0809, -0x081d, 0x0832, 0x0846, 0x085b, 0x086f, 0x0883, -0x0898, 0x08ac, 0x08c0, 0x08d5, 0x08e9, 0x08fd, -0x0912, 0x0926, 0x093b, 0x094f, 0x0963, 0x0978, -0x098c, 0x09a0, 0x09b5, 0x09c9, 0x09dd, 0x09f2, -0x0a06, 0x0a1a, 0x0a2f, 0x0a43, 0x0a58, 0x0a6c, -0x0a80, 0x0a95, 0x0aa9, 0x0abd, 0x0ad2, 0x0ae6, -0x0afa, 0x0b0f, 0x0b23, 0x0b37, 0x0b4c, 0x0b60, -0x0b75, 0x0b89, 0x0b9d, 0x0bb2, 0x0bc6, 0x0bda, -0x0bef, 0x0c03, 0x0c17, 0x0c2c, 0x0c40, 0x0c54, -0x0c69, 0x0c7d, 0x0c91, 0x0ca6, 0x0cba, 0x0cce, -0x0ce3, 0x0cf7, 0x0d0b, 0x0d20, 0x0d34, 0x0d48, -0x0d5d, 0x0d71, 0x0d86, 0x0d9a, 0x0dae, 0x0dc3, -0x0dd7, 0x0deb, 0x0e00, 0x0e14, 0x0e28, 0x0e3d, -0x0e51, 0x0e65, 0x0e7a, 0x0e8e, 0x0ea2, 0x0eb7, -0x0ecb, 0x0edf, 0x0ef4, 0x0f08, 0x0f1c, 0x0f31, -0x0f45, 0x0f59, 0x0f6e, 0x0f82, 0x0f96, 0x0fab, -0x0fbf, 0x0fd3, 0x0fe8, 0x0ffc, 0x1010, 0x1025, -0x1039, 0x104d, 0x1062, 0x1076, 0x108a, 0x109e, -0x10b3, 0x10c7, 0x10db, 0x10f0, 0x1104, 0x1118, -0x112d, 0x1141, 0x1155, 0x116a, 0x117e, 0x1192, -0x11a7, 0x11bb, 0x11cf, 0x11e4, 0x11f8, 0x120c, -0x1221, 0x1235, 0x1249, 0x125d, 0x1272, 0x1286, -0x129a, 0x12af, 0x12c3, 0x12d7, 0x12ec, 0x1300, -0x1314, 0x1329, 0x133d, 0x1351, 0x1365, 0x137a, -0x138e, 0x13a2, 0x13b7, 0x13cb, 0x13df, 0x13f4, -0x1408, 0x141c, 0x1431, 0x1445, 0x1459, 0x146d, -0x1482, 0x1496, 0x14aa, 0x14bf, 0x14d3, 0x14e7, -0x14fb, 0x1510, 0x1524, 0x1538, 0x154d, 0x1561, -0x1575, 0x1589, 0x159e, 0x15b2, 0x15c6, 0x15db, -0x15ef, 0x1603, 0x1617, 0x162c, 0x1640, 0x1654, -0x1669, 0x167d, 0x1691, 0x16a5, 0x16ba, 0x16ce, -0x16e2, 0x16f7, 0x170b, 0x171f, 0x1733, 0x1748, -0x175c, 0x1770, 0x1784, 0x1799, 0x17ad, 0x17c1, -0x17d6, 0x17ea, 0x17fe, 0x1812, 0x1827, 0x183b, -0x184f, 0x1863, 0x1878, 0x188c, 0x18a0, 0x18b4, -0x18c9, 0x18dd, 0x18f1, 0x1905, 0x191a, 0x192e, -0x1942, 0x1957, 0x196b, 0x197f, 0x1993, 0x19a8, -0x19bc, 0x19d0, 0x19e4, 0x19f9, 0x1a0d, 0x1a21, -0x1a35, 0x1a49, 0x1a5e, 0x1a72, 0x1a86, 0x1a9a, -0x1aaf, 0x1ac3, 0x1ad7, 0x1aeb, 0x1b00, 0x1b14, -0x1b28, 0x1b3c, 0x1b51, 0x1b65, 0x1b79, 0x1b8d, -0x1ba2, 0x1bb6, 0x1bca, 0x1bde, 0x1bf2, 0x1c07, -0x1c1b, 0x1c2f, 0x1c43, 0x1c58, 0x1c6c, 0x1c80, -0x1c94, 0x1ca8, 0x1cbd, 0x1cd1, 0x1ce5, 0x1cf9, -0x1d0e, 0x1d22, 0x1d36, 0x1d4a, 0x1d5e, 0x1d73, -0x1d87, 0x1d9b, 0x1daf, 0x1dc3, 0x1dd8, 0x1dec, -0x1e00, 0x1e14, 0x1e28, 0x1e3d, 0x1e51, 0x1e65, -0x1e79, 0x1e8d, 0x1ea2, 0x1eb6, 0x1eca, 0x1ede, -0x1ef2, 0x1f07, 0x1f1b, 0x1f2f, 0x1f43, 0x1f57, -0x1f6c, 0x1f80, 0x1f94, 0x1fa8, 0x1fbc, 0x1fd1, -0x1fe5, 0x1ff9, 0x200d, 0x2021, 0x2035, 0x204a, -0x205e, 0x2072, 0x2086, 0x209a, 0x20ae, 0x20c3, -0x20d7, 0x20eb, 0x20ff, 0x2113, 0x2127, 0x213c, -0x2150, 0x2164, 0x2178, 0x218c, 0x21a0, 0x21b5, -0x21c9, 0x21dd, 0x21f1, 0x2205, 0x2219, 0x222e, -0x2242, 0x2256, 0x226a, 0x227e, 0x2292, 0x22a6, -0x22bb, 0x22cf, 0x22e3, 0x22f7, 0x230b, 0x231f, -0x2333, 0x2348, 0x235c, 0x2370, 0x2384, 0x2398, -0x23ac, 0x23c0, 0x23d5, 0x23e9, 0x23fd, 0x2411, -0x2425, 0x2439, 0x244d, 0x2461, 0x2476, 0x248a, -0x249e, 0x24b2, 0x24c6, 0x24da, 0x24ee, 0x2502, -0x2517, 0x252b, 0x253f, 0x2553, 0x2567, 0x257b, -0x258f, 0x25a3, 0x25b7, 0x25cb, 0x25e0, 0x25f4, -0x2608, 0x261c, 0x2630, 0x2644, 0x2658, 0x266c, -0x2680, 0x2694, 0x26a9, 0x26bd, 0x26d1, 0x26e5, -0x26f9, 0x270d, 0x2721, 0x2735, 0x2749, 0x275d, -0x2771, 0x2785, 0x279a, 0x27ae, 0x27c2, 0x27d6, -0x27ea, 0x27fe, 0x2812, 0x2826, 0x283a, 0x284e, -0x2862, 0x2876, 0x288a, 0x289e, 0x28b3, 0x28c7, -0x28db, 0x28ef, 0x2903, 0x2917, 0x292b, 0x293f, -0x2953, 0x2967, 0x297b, 0x298f, 0x29a3, 0x29b7, -0x29cb, 0x29df, 0x29f3, 0x2a07, 0x2a1b, 0x2a2f, -0x2a43, 0x2a58, 0x2a6c, 0x2a80, 0x2a94, 0x2aa8, -0x2abc, 0x2ad0, 0x2ae4, 0x2af8, 0x2b0c, 0x2b20, -0x2b34, 0x2b48, 0x2b5c, 0x2b70, 0x2b84, 0x2b98, -0x2bac, 0x2bc0, 0x2bd4, 0x2be8, 0x2bfc, 0x2c10, -0x2c24, 0x2c38, 0x2c4c, 0x2c60, 0x2c74, 0x2c88, -0x2c9c, 0x2cb0, 0x2cc4, 0x2cd8, 0x2cec, 0x2d00, -0x2d14, 0x2d28, 0x2d3c, 0x2d50, 0x2d64, 0x2d78, -0x2d8c, 0x2da0, 0x2db4, 0x2dc8, 0x2ddc, 0x2df0, -0x2e04, 0x2e18, 0x2e2c, 0x2e40, 0x2e54, 0x2e68, -0x2e7c, 0x2e90, 0x2ea3, 0x2eb7, 0x2ecb, 0x2edf, -0x2ef3, 0x2f07, 0x2f1b, 0x2f2f, 0x2f43, 0x2f57, -0x2f6b, 0x2f7f, 0x2f93, 0x2fa7, 0x2fbb, 0x2fcf, -0x2fe3, 0x2ff7, 0x300b, 0x301e, 0x3032, 0x3046, -0x305a, 0x306e, 0x3082, 0x3096, 0x30aa, 0x30be, -0x30d2, 0x30e6, 0x30fa, 0x310e, 0x3122, 0x3135, -0x3149, 0x315d, 0x3171, 0x3185, 0x3199, 0x31ad, -0x31c1, 0x31d5, 0x31e9, 0x31fd, 0x3210, 0x3224, -0x3238, 0x324c, 0x3260, 0x3274, 0x3288, 0x329c, -0x32b0, 0x32c3, 0x32d7, 0x32eb, 0x32ff, 0x3313, -0x3327, 0x333b, 0x334f, 0x3363, 0x3376, 0x338a, -0x339e, 0x33b2, 0x33c6, 0x33da, 0x33ee, 0x3401, -0x3415, 0x3429, 0x343d, 0x3451, 0x3465, 0x3479, -0x348c, 0x34a0, 0x34b4, 0x34c8, 0x34dc, 0x34f0, -0x3504, 0x3517, 0x352b, 0x353f, 0x3553, 0x3567, -0x357b, 0x358e, 0x35a2, 0x35b6, 0x35ca, 0x35de, -0x35f2, 0x3605, 0x3619, 0x362d, 0x3641, 0x3655, -0x3668, 0x367c, 0x3690, 0x36a4, 0x36b8, 0x36cb, -0x36df, 0x36f3, 0x3707, 0x371b, 0x372f, 0x3742, -0x3756, 0x376a, 0x377e, 0x3791, 0x37a5, 0x37b9, -0x37cd, 0x37e1, 0x37f4, 0x3808, 0x381c, 0x3830, -0x3844, 0x3857, 0x386b, 0x387f, 0x3893, 0x38a6, -0x38ba, 0x38ce, 0x38e2, 0x38f5, 0x3909, 0x391d, -0x3931, 0x3944, 0x3958, 0x396c, 0x3980, 0x3993, -0x39a7, 0x39bb, 0x39cf, 0x39e2, 0x39f6, 0x3a0a, -0x3a1e, 0x3a31, 0x3a45, 0x3a59, 0x3a6d, 0x3a80, -0x3a94, 0x3aa8, 0x3abb, 0x3acf, 0x3ae3, 0x3af7, -0x3b0a, 0x3b1e, 0x3b32, 0x3b45, 0x3b59, 0x3b6d, -0x3b81, 0x3b94, 0x3ba8, 0x3bbc, 0x3bcf, 0x3be3, -0x3bf7, 0x3c0b, 0x3c1e, 0x3c32, 0x3c46, 0x3c59, -0x3c6d, 0x3c81, 0x3c94, 0x3ca8, 0x3cbc, 0x3ccf, -0x3ce3, 0x3cf7, 0x3d0a, 0x3d1e, 0x3d32, 0x3d45, -0x3d59, 0x3d6d, 0x3d80, 0x3d94, 0x3da8, 0x3dbb, -0x3dcf, 0x3de3, 0x3df6, 0x3e0a, 0x3e1e, 0x3e31, -0x3e45, 0x3e59, 0x3e6c, 0x3e80, 0x3e93, 0x3ea7, -0x3ebb, 0x3ece, 0x3ee2, 0x3ef6, 0x3f09, 0x3f1d, -0x3f30, 0x3f44, 0x3f58, 0x3f6b, 0x3f7f, 0x3f93, -0x3fa6, 0x3fba, 0x3fcd, 0x3fe1, 0x3ff5, 0x4008, -0x401c, 0x402f, 0x4043, 0x4057, 0x406a, 0x407e, -0x4091, 0x40a5, 0x40b8, 0x40cc, 0x40e0, 0x40f3, -0x4107, 0x411a, 0x412e, 0x4142, 0x4155, 0x4169, -0x417c, 0x4190, 0x41a3, 0x41b7, 0x41ca, 0x41de, -0x41f2, 0x4205, 0x4219, 0x422c, 0x4240, 0x4253, -0x4267, 0x427a, 0x428e, 0x42a1, 0x42b5, 0x42c9, -0x42dc, 0x42f0, 0x4303, 0x4317, 0x432a, 0x433e, -0x4351, 0x4365, 0x4378, 0x438c, 0x439f, 0x43b3, -0x43c6, 0x43da, 0x43ed, 0x4401, 0x4414, 0x4428, -0x443b, 0x444f, 0x4462, 0x4476, 0x4489, 0x449d, -0x44b0, 0x44c4, 0x44d7, 0x44eb, 0x44fe, 0x4512, -0x4525, 0x4539, 0x454c, 0x4560, 0x4573, 0x4586, -0x459a, 0x45ad, 0x45c1, 0x45d4, 0x45e8, 0x45fb, -0x460f, 0x4622, 0x4636, 0x4649, 0x465c, 0x4670, -0x4683, 0x4697, 0x46aa, 0x46be, 0x46d1, 0x46e5, -0x46f8, 0x470b, 0x471f, 0x4732, 0x4746, 0x4759, -0x476c, 0x4780, 0x4793, 0x47a7, 0x47ba, 0x47cd, -0x47e1, 0x47f4, 0x4808, 0x481b, 0x482e, 0x4842, -0x4855, 0x4869, 0x487c, 0x488f, 0x48a3, 0x48b6, -0x48ca, 0x48dd, 0x48f0, 0x4904, 0x4917, 0x492a, -0x493e, 0x4951, 0x4965, 0x4978, 0x498b, 0x499f, -0x49b2, 0x49c5, 0x49d9, 0x49ec, 0x49ff, 0x4a13, -0x4a26, 0x4a39, 0x4a4d, 0x4a60, 0x4a73, 0x4a87, -0x4a9a, 0x4aad, 0x4ac1, 0x4ad4, 0x4ae7, 0x4afb, -0x4b0e, 0x4b21, 0x4b35, 0x4b48, 0x4b5b, 0x4b6f, -0x4b82, 0x4b95, 0x4ba8, 0x4bbc, 0x4bcf, 0x4be2, -0x4bf6, 0x4c09, 0x4c1c, 0x4c2f, 0x4c43, 0x4c56, -0x4c69, 0x4c7d, 0x4c90, 0x4ca3, 0x4cb6, 0x4cca, -0x4cdd, 0x4cf0, 0x4d03, 0x4d17, 0x4d2a, 0x4d3d, -0x4d50, 0x4d64, 0x4d77, 0x4d8a, 0x4d9d, 0x4db1, -0x4dc4, 0x4dd7, 0x4dea, 0x4dfe, 0x4e11, 0x4e24, -0x4e37, 0x4e4b, 0x4e5e, 0x4e71, 0x4e84, 0x4e97, -0x4eab, 0x4ebe, 0x4ed1, 0x4ee4, 0x4ef7, 0x4f0b, -0x4f1e, 0x4f31, 0x4f44, 0x4f57, 0x4f6b, 0x4f7e, -0x4f91, 0x4fa4, 0x4fb7, 0x4fcb, 0x4fde, 0x4ff1, -0x5004, 0x5017, 0x502a, 0x503e, 0x5051, 0x5064, -0x5077, 0x508a, 0x509d, 0x50b1, 0x50c4, 0x50d7, -0x50ea, 0x50fd, 0x5110, 0x5123, 0x5137, 0x514a, -0x515d, 0x5170, 0x5183, 0x5196, 0x51a9, 0x51bc, -0x51d0, 0x51e3, 0x51f6, 0x5209, 0x521c, 0x522f, -0x5242, 0x5255, 0x5268, 0x527c, 0x528f, 0x52a2, -0x52b5, 0x52c8, 0x52db, 0x52ee, 0x5301, 0x5314, -0x5327, 0x533a, 0x534e, 0x5361, 0x5374, 0x5387, -0x539a, 0x53ad, 0x53c0, 0x53d3, 0x53e6, 0x53f9, -0x540c, 0x541f, 0x5432, 0x5445, 0x5458, 0x546b, -0x547e, 0x5491, 0x54a5, 0x54b8, 0x54cb, 0x54de, -0x54f1, 0x5504, 0x5517, 0x552a, 0x553d, 0x5550, -0x5563, 0x5576, 0x5589, 0x559c, 0x55af, 0x55c2, -0x55d5, 0x55e8, 0x55fb, 0x560e, 0x5621, 0x5634, -0x5647, 0x565a, 0x566d, 0x5680, 0x5693, 0x56a6, -0x56b9, 0x56cb, 0x56de, 0x56f1, 0x5704, 0x5717, -0x572a, 0x573d, 0x5750, 0x5763, 0x5776, 0x5789, -0x579c, 0x57af, 0x57c2, 0x57d5, 0x57e8, 0x57fb, -0x580e, 0x5820, 0x5833, 0x5846, 0x5859, 0x586c, -0x587f, 0x5892, 0x58a5, 0x58b8, 0x58cb, 0x58de, -0x58f0, 0x5903, 0x5916, 0x5929, 0x593c, 0x594f, -0x5962, 0x5975, 0x5988, 0x599a, 0x59ad, 0x59c0, -0x59d3, 0x59e6, 0x59f9, 0x5a0c, 0x5a1f, 0x5a31, -0x5a44, 0x5a57, 0x5a6a, 0x5a7d, 0x5a90, 0x5aa2, -0x5ab5, 0x5ac8, 0x5adb, 0x5aee, 0x5b01, 0x5b13, -0x5b26, 0x5b39, 0x5b4c, 0x5b5f, 0x5b72, 0x5b84, -0x5b97, 0x5baa, 0x5bbd, 0x5bd0, 0x5be2, 0x5bf5, -0x5c08, 0x5c1b, 0x5c2e, 0x5c40, 0x5c53, 0x5c66, -0x5c79, 0x5c8c, 0x5c9e, 0x5cb1, 0x5cc4, 0x5cd7, -0x5ce9, 0x5cfc, 0x5d0f, 0x5d22, 0x5d34, 0x5d47, -0x5d5a, 0x5d6d, 0x5d7f, 0x5d92, 0x5da5, 0x5db8, -0x5dca, 0x5ddd, 0x5df0, 0x5e03, 0x5e15, 0x5e28, -0x5e3b, 0x5e4d, 0x5e60, 0x5e73, 0x5e86, 0x5e98, -0x5eab, 0x5ebe, 0x5ed0, 0x5ee3, 0x5ef6, 0x5f09, -0x5f1b, 0x5f2e, 0x5f41, 0x5f53, 0x5f66, 0x5f79, -0x5f8b, 0x5f9e, 0x5fb1, 0x5fc3, 0x5fd6, 0x5fe9, -0x5ffb, 0x600e, 0x6021, 0x6033, 0x6046, 0x6059, -0x606b, 0x607e, 0x6091, 0x60a3, 0x60b6, 0x60c8, -0x60db, 0x60ee, 0x6100, 0x6113, 0x6126, 0x6138, -0x614b, 0x615d, 0x6170, 0x6183, 0x6195, 0x61a8, -0x61ba, 0x61cd, 0x61e0, 0x61f2, 0x6205, 0x6217, -0x622a, 0x623d, 0x624f, 0x6262, 0x6274, 0x6287, -0x6299, 0x62ac, 0x62bf, 0x62d1, 0x62e4, 0x62f6, -0x6309, 0x631b, 0x632e, 0x6340, 0x6353, 0x6366, -0x6378, 0x638b, 0x639d, 0x63b0, 0x63c2, 0x63d5, -0x63e7, 0x63fa, 0x640c, 0x641f, 0x6431, 0x6444, -0x6456, 0x6469, 0x647b, 0x648e, 0x64a0, 0x64b3, -0x64c5, 0x64d8, 0x64ea, 0x64fd, 0x650f, 0x6522, -0x6534, 0x6547, 0x6559, 0x656c, 0x657e, 0x6591, -0x65a3, 0x65b5, 0x65c8, 0x65da, 0x65ed, 0x65ff, -0x6612, 0x6624, 0x6637, 0x6649, 0x665b, 0x666e, -0x6680, 0x6693, 0x66a5, 0x66b8, 0x66ca, 0x66dc, -0x66ef, 0x6701, 0x6714, 0x6726, 0x6738, 0x674b, -0x675d, 0x6770, 0x6782, 0x6794, 0x67a7, 0x67b9, -0x67cc, 0x67de, 0x67f0, 0x6803, 0x6815, 0x6827, -0x683a, 0x684c, 0x685e, 0x6871, 0x6883, 0x6896, -0x68a8, 0x68ba, 0x68cd, 0x68df, 0x68f1, 0x6904, -0x6916, 0x6928, 0x693b, 0x694d, 0x695f, 0x6972, -0x6984, 0x6996, 0x69a8, 0x69bb, 0x69cd, 0x69df, -0x69f2, 0x6a04, 0x6a16, 0x6a29, 0x6a3b, 0x6a4d, -0x6a5f, 0x6a72, 0x6a84, 0x6a96, 0x6aa9, 0x6abb, -0x6acd, 0x6adf, 0x6af2, 0x6b04, 0x6b16, 0x6b28, -0x6b3b, 0x6b4d, 0x6b5f, 0x6b71, 0x6b84, 0x6b96, -0x6ba8, 0x6bba, 0x6bcd, 0x6bdf, 0x6bf1, 0x6c03, -0x6c15, 0x6c28, 0x6c3a, 0x6c4c, 0x6c5e, 0x6c70, -0x6c83, 0x6c95, 0x6ca7, 0x6cb9, 0x6ccb, 0x6cde, -0x6cf0, 0x6d02, 0x6d14, 0x6d26, 0x6d39, 0x6d4b, -0x6d5d, 0x6d6f, 0x6d81, 0x6d93, 0x6da6, 0x6db8, -0x6dca, 0x6ddc, 0x6dee, 0x6e00, 0x6e12, 0x6e25, -0x6e37, 0x6e49, 0x6e5b, 0x6e6d, 0x6e7f, 0x6e91, -0x6ea3, 0x6eb6, 0x6ec8, 0x6eda, 0x6eec, 0x6efe, -0x6f10, 0x6f22, 0x6f34, 0x6f46, 0x6f58, 0x6f6b, -0x6f7d, 0x6f8f, 0x6fa1, 0x6fb3, 0x6fc5, 0x6fd7, -0x6fe9, 0x6ffb, 0x700d, 0x701f, 0x7031, 0x7043, -0x7055, 0x7068, 0x707a, 0x708c, 0x709e, 0x70b0, -0x70c2, 0x70d4, 0x70e6, 0x70f8, 0x710a, 0x711c, -0x712e, 0x7140, 0x7152, 0x7164, 0x7176, 0x7188, -0x719a, 0x71ac, 0x71be, 0x71d0, 0x71e2, 0x71f4, -0x7206, 0x7218, 0x722a, 0x723c, 0x724e, 0x7260, -0x7272, 0x7284, 0x7296, 0x72a8, 0x72ba, 0x72cc, -0x72dd, 0x72ef, 0x7301, 0x7313, 0x7325, 0x7337, -0x7349, 0x735b, 0x736d, 0x737f, 0x7391, 0x73a3, -0x73b5, 0x73c7, 0x73d8, 0x73ea, 0x73fc, 0x740e, -0x7420, 0x7432, 0x7444, 0x7456, 0x7468, 0x747a, -0x748b, 0x749d, 0x74af, 0x74c1, 0x74d3, 0x74e5, -0x74f7, 0x7509, 0x751a, 0x752c, 0x753e, 0x7550, -0x7562, 0x7574, 0x7585, 0x7597, 0x75a9, 0x75bb, -0x75cd, 0x75df, 0x75f0, 0x7602, 0x7614, 0x7626, -0x7638, 0x764a, 0x765b, 0x766d, 0x767f, 0x7691, -0x76a3, 0x76b4, 0x76c6, 0x76d8, 0x76ea, 0x76fb, -0x770d, 0x771f, 0x7731, 0x7743, 0x7754, 0x7766, -0x7778, 0x778a, 0x779b, 0x77ad, 0x77bf, 0x77d1, -0x77e2, 0x77f4, 0x7806, 0x7818, 0x7829, 0x783b, -0x784d, 0x785e, 0x7870, 0x7882, 0x7894, 0x78a5, -0x78b7, 0x78c9, 0x78da, 0x78ec, 0x78fe, 0x7910, -0x7921, 0x7933, 0x7945, 0x7956, 0x7968, 0x797a, -0x798b, 0x799d, 0x79af, 0x79c0, 0x79d2, 0x79e4, -0x79f5, 0x7a07, 0x7a19, 0x7a2a, 0x7a3c, 0x7a4e, -0x7a5f, 0x7a71, 0x7a82, 0x7a94, 0x7aa6, 0x7ab7, -0x7ac9, 0x7adb, 0x7aec, 0x7afe, 0x7b0f, 0x7b21, -0x7b33, 0x7b44, 0x7b56, 0x7b67, 0x7b79, 0x7b8b, -0x7b9c, 0x7bae, 0x7bbf, 0x7bd1, 0x7be2, 0x7bf4, -0x7c06, 0x7c17, 0x7c29, 0x7c3a, 0x7c4c, 0x7c5d, -0x7c6f, 0x7c81, 0x7c92, 0x7ca4, 0x7cb5, 0x7cc7, -0x7cd8, 0x7cea, 0x7cfb, 0x7d0d, 0x7d1e, 0x7d30, -0x7d41, 0x7d53, 0x7d64, 0x7d76, 0x7d87, 0x7d99, -0x7daa, 0x7dbc, 0x7dcd, 0x7ddf, 0x7df0, 0x7e02, -0x7e13, 0x7e25, 0x7e36, 0x7e48, 0x7e59, 0x7e6b, -0x7e7c, 0x7e8e, 0x7e9f, 0x7eb0, 0x7ec2, 0x7ed3, -0x7ee5, 0x7ef6, 0x7f08, 0x7f19, 0x7f2b, 0x7f3c, -0x7f4d, 0x7f5f, 0x7f70, 0x7f82, 0x7f93, 0x7fa4, -0x7fb6, 0x7fc7, 0x7fd9, 0x7fea, 0x7ffb, 0x800d, -0x801e, 0x8030, 0x8041, 0x8052, 0x8064, 0x8075, -0x8086, 0x8098, 0x80a9, 0x80bb, 0x80cc, 0x80dd, -0x80ef, 0x8100, 0x8111, 0x8123, 0x8134, 0x8145, -0x8157, 0x8168, 0x8179, 0x818b, 0x819c, 0x81ad, -0x81bf, 0x81d0, 0x81e1, 0x81f3, 0x8204, 0x8215, -0x8226, 0x8238, 0x8249, 0x825a, 0x826c, 0x827d, -0x828e, 0x829f, 0x82b1, 0x82c2, 0x82d3, 0x82e5, -0x82f6, 0x8307, 0x8318, 0x832a, 0x833b, 0x834c, -0x835d, 0x836f, 0x8380, 0x8391, 0x83a2, 0x83b3, -0x83c5, 0x83d6, 0x83e7, 0x83f8, 0x840a, 0x841b, -0x842c, 0x843d, 0x844e, 0x8460, 0x8471, 0x8482, -0x8493, 0x84a4, 0x84b6, 0x84c7, 0x84d8, 0x84e9, -0x84fa, 0x850b, 0x851d, 0x852e, 0x853f, 0x8550, -0x8561, 0x8572, 0x8584, 0x8595, 0x85a6, 0x85b7, -0x85c8, 0x85d9, 0x85ea, 0x85fb, 0x860d, 0x861e, -0x862f, 0x8640, 0x8651, 0x8662, 0x8673, 0x8684, -0x8695, 0x86a7, 0x86b8, 0x86c9, 0x86da, 0x86eb, -0x86fc, 0x870d, 0x871e, 0x872f, 0x8740, 0x8751, -0x8762, 0x8773, 0x8784, 0x8796, 0x87a7, 0x87b8, -0x87c9, 0x87da, 0x87eb, 0x87fc, 0x880d, 0x881e, -0x882f, 0x8840, 0x8851, 0x8862, 0x8873, 0x8884, -0x8895, 0x88a6, 0x88b7, 0x88c8, 0x88d9, 0x88ea, -0x88fb, 0x890c, 0x891d, 0x892e, 0x893f, 0x8950, -0x8961, 0x8972, 0x8983, 0x8994, 0x89a5, 0x89b6, -0x89c6, 0x89d7, 0x89e8, 0x89f9, 0x8a0a, 0x8a1b, -0x8a2c, 0x8a3d, 0x8a4e, 0x8a5f, 0x8a70, 0x8a81, -0x8a92, 0x8aa3, 0x8ab3, 0x8ac4, 0x8ad5, 0x8ae6, -0x8af7, 0x8b08, 0x8b19, 0x8b2a, 0x8b3b, 0x8b4b, -0x8b5c, 0x8b6d, 0x8b7e, 0x8b8f, 0x8ba0, 0x8bb1, -0x8bc1, 0x8bd2, 0x8be3, 0x8bf4, 0x8c05, 0x8c16, -0x8c27, 0x8c37, 0x8c48, 0x8c59, 0x8c6a, 0x8c7b, -0x8c8c, 0x8c9c, 0x8cad, 0x8cbe, 0x8ccf, 0x8ce0, -0x8cf0, 0x8d01, 0x8d12, 0x8d23, 0x8d34, 0x8d44, -0x8d55, 0x8d66, 0x8d77, 0x8d87, 0x8d98, 0x8da9, -0x8dba, 0x8dca, 0x8ddb, 0x8dec, 0x8dfd, 0x8e0d, -0x8e1e, 0x8e2f, 0x8e40, 0x8e50, 0x8e61, 0x8e72, -0x8e83, 0x8e93, 0x8ea4, 0x8eb5, 0x8ec5, 0x8ed6, -0x8ee7, 0x8ef8, 0x8f08, 0x8f19, 0x8f2a, 0x8f3a, -0x8f4b, 0x8f5c, 0x8f6c, 0x8f7d, 0x8f8e, 0x8f9e, -0x8faf, 0x8fc0, 0x8fd0, 0x8fe1, 0x8ff2, 0x9002, -0x9013, 0x9024, 0x9034, 0x9045, 0x9056, 0x9066, -0x9077, 0x9088, 0x9098, 0x90a9, 0x90b9, 0x90ca, -0x90db, 0x90eb, 0x90fc, 0x910c, 0x911d, 0x912e, -0x913e, 0x914f, 0x915f, 0x9170, 0x9181, 0x9191, -0x91a2, 0x91b2, 0x91c3, 0x91d3, 0x91e4, 0x91f5, -0x9205, 0x9216, 0x9226, 0x9237, 0x9247, 0x9258, -0x9268, 0x9279, 0x9289, 0x929a, 0x92aa, 0x92bb, -0x92cc, 0x92dc, 0x92ed, 0x92fd, 0x930e, 0x931e, -0x932f, 0x933f, 0x9350, 0x9360, 0x9370, 0x9381, -0x9391, 0x93a2, 0x93b2, 0x93c3, 0x93d3, 0x93e4, -0x93f4, 0x9405, 0x9415, 0x9426, 0x9436, 0x9447, -0x9457, 0x9467, 0x9478, 0x9488, 0x9499, 0x94a9, -0x94ba, 0x94ca, 0x94da, 0x94eb, 0x94fb, 0x950c, -0x951c, 0x952c, 0x953d, 0x954d, 0x955e, 0x956e, -0x957e, 0x958f, 0x959f, 0x95af, 0x95c0, 0x95d0, -0x95e1, 0x95f1, 0x9601, 0x9612, 0x9622, 0x9632, -0x9643, 0x9653, 0x9663, 0x9674, 0x9684, 0x9694, -0x96a5, 0x96b5, 0x96c5, 0x96d6, 0x96e6, 0x96f6, -0x9707, 0x9717, 0x9727, 0x9738, 0x9748, 0x9758, -0x9768, 0x9779, 0x9789, 0x9799, 0x97aa, 0x97ba, -0x97ca, 0x97da, 0x97eb, 0x97fb, 0x980b, 0x981b, -0x982c, 0x983c, 0x984c, 0x985c, 0x986d, 0x987d, -0x988d, 0x989d, 0x98ad, 0x98be, 0x98ce, 0x98de, -0x98ee, 0x98ff, 0x990f, 0x991f, 0x992f, 0x993f, -0x9950, 0x9960, 0x9970, 0x9980, 0x9990, 0x99a0, -0x99b1, 0x99c1, 0x99d1, 0x99e1, 0x99f1, 0x9a01, -0x9a12, 0x9a22, 0x9a32, 0x9a42, 0x9a52, 0x9a62, -0x9a72, 0x9a83, 0x9a93, 0x9aa3, 0x9ab3, 0x9ac3, -0x9ad3, 0x9ae3, 0x9af3, 0x9b04, 0x9b14, 0x9b24, -0x9b34, 0x9b44, 0x9b54, 0x9b64, 0x9b74, 0x9b84, -0x9b94, 0x9ba4, 0x9bb5, 0x9bc5, 0x9bd5, 0x9be5, -0x9bf5, 0x9c05, 0x9c15, 0x9c25, 0x9c35, 0x9c45, -0x9c55, 0x9c65, 0x9c75, 0x9c85, 0x9c95, 0x9ca5, -0x9cb5, 0x9cc5, 0x9cd5, 0x9ce5, 0x9cf5, 0x9d05, -0x9d15, 0x9d25, 0x9d35, 0x9d45, 0x9d55, 0x9d65, -0x9d75, 0x9d85, 0x9d95, 0x9da5, 0x9db5, 0x9dc5, -0x9dd5, 0x9de5, 0x9df5, 0x9e05, 0x9e15, 0x9e25, -0x9e35, 0x9e45, 0x9e55, 0x9e65, 0x9e74, 0x9e84, -0x9e94, 0x9ea4, 0x9eb4, 0x9ec4, 0x9ed4, 0x9ee4, -0x9ef4, 0x9f04, 0x9f14, 0x9f23, 0x9f33, 0x9f43, -0x9f53, 0x9f63, 0x9f73, 0x9f83, 0x9f93, 0x9fa3, -0x9fb2, 0x9fc2, 0x9fd2, 0x9fe2, 0x9ff2, 0xa002, -0xa012, 0xa021, 0xa031, 0xa041, 0xa051, 0xa061, -0xa071, 0xa080, 0xa090, 0xa0a0, 0xa0b0, 0xa0c0, -0xa0cf, 0xa0df, 0xa0ef, 0xa0ff, 0xa10f, 0xa11e, -0xa12e, 0xa13e, 0xa14e, 0xa15e, 0xa16d, 0xa17d, -0xa18d, 0xa19d, 0xa1ac, 0xa1bc, 0xa1cc, 0xa1dc, -0xa1eb, 0xa1fb, 0xa20b, 0xa21b, 0xa22a, 0xa23a, -0xa24a, 0xa25a, 0xa269, 0xa279, 0xa289, 0xa298, -0xa2a8, 0xa2b8, 0xa2c8, 0xa2d7, 0xa2e7, 0xa2f7, -0xa306, 0xa316, 0xa326, 0xa335, 0xa345, 0xa355, -0xa364, 0xa374, 0xa384, 0xa393, 0xa3a3, 0xa3b3, -0xa3c2, 0xa3d2, 0xa3e2, 0xa3f1, 0xa401, 0xa411, -0xa420, 0xa430, 0xa440, 0xa44f, 0xa45f, 0xa46e, -0xa47e, 0xa48e, 0xa49d, 0xa4ad, 0xa4bc, 0xa4cc, -0xa4dc, 0xa4eb, 0xa4fb, 0xa50a, 0xa51a, 0xa52a, -0xa539, 0xa549, 0xa558, 0xa568, 0xa577, 0xa587, -0xa597, 0xa5a6, 0xa5b6, 0xa5c5, 0xa5d5, 0xa5e4, -0xa5f4, 0xa603, 0xa613, 0xa622, 0xa632, 0xa641, -0xa651, 0xa660, 0xa670, 0xa67f, 0xa68f, 0xa69e, -0xa6ae, 0xa6bd, 0xa6cd, 0xa6dc, 0xa6ec, 0xa6fb, -0xa70b, 0xa71a, 0xa72a, 0xa739, 0xa749, 0xa758, -0xa768, 0xa777, 0xa787, 0xa796, 0xa7a5, 0xa7b5, -0xa7c4, 0xa7d4, 0xa7e3, 0xa7f3, 0xa802, 0xa812, -0xa821, 0xa830, 0xa840, 0xa84f, 0xa85f, 0xa86e, -0xa87d, 0xa88d, 0xa89c, 0xa8ac, 0xa8bb, 0xa8ca, -0xa8da, 0xa8e9, 0xa8f8, 0xa908, 0xa917, 0xa927, -0xa936, 0xa945, 0xa955, 0xa964, 0xa973, 0xa983, -0xa992, 0xa9a1, 0xa9b1, 0xa9c0, 0xa9cf, 0xa9df, -0xa9ee, 0xa9fd, 0xaa0d, 0xaa1c, 0xaa2b, 0xaa3b, -0xaa4a, 0xaa59, 0xaa69, 0xaa78, 0xaa87, 0xaa96, -0xaaa6, 0xaab5, 0xaac4, 0xaad4, 0xaae3, 0xaaf2, -0xab01, 0xab11, 0xab20, 0xab2f, 0xab3e, 0xab4e, -0xab5d, 0xab6c, 0xab7b, 0xab8b, 0xab9a, 0xaba9, -0xabb8, 0xabc7, 0xabd7, 0xabe6, 0xabf5, 0xac04, -0xac14, 0xac23, 0xac32, 0xac41, 0xac50, 0xac60, -0xac6f, 0xac7e, 0xac8d, 0xac9c, 0xacab, 0xacbb, -0xacca, 0xacd9, 0xace8, 0xacf7, 0xad06, 0xad16, -0xad25, 0xad34, 0xad43, 0xad52, 0xad61, 0xad70, -0xad80, 0xad8f, 0xad9e, 0xadad, 0xadbc, 0xadcb, -0xadda, 0xade9, 0xadf8, 0xae08, 0xae17, 0xae26, -0xae35, 0xae44, 0xae53, 0xae62, 0xae71, 0xae80, -0xae8f, 0xae9e, 0xaead, 0xaebd, 0xaecc, 0xaedb, -0xaeea, 0xaef9, 0xaf08, 0xaf17, 0xaf26, 0xaf35, -0xaf44, 0xaf53, 0xaf62, 0xaf71, 0xaf80, 0xaf8f, -0xaf9e, 0xafad, 0xafbc, 0xafcb, 0xafda, 0xafe9, -0xaff8, 0xb007, 0xb016, 0xb025, 0xb034, 0xb043, -0xb052, 0xb061, 0xb070, 0xb07f, 0xb08e, 0xb09d, -0xb0ac, 0xb0bb, 0xb0ca, 0xb0d9, 0xb0e8, 0xb0f6, -0xb105, 0xb114, 0xb123, 0xb132, 0xb141, 0xb150, -0xb15f, 0xb16e, 0xb17d, 0xb18c, 0xb19b, 0xb1aa, -0xb1b8, 0xb1c7, 0xb1d6, 0xb1e5, 0xb1f4, 0xb203, -0xb212, 0xb221, 0xb22f, 0xb23e, 0xb24d, 0xb25c, -0xb26b, 0xb27a, 0xb289, 0xb297, 0xb2a6, 0xb2b5, -0xb2c4, 0xb2d3, 0xb2e2, 0xb2f1, 0xb2ff, 0xb30e, -0xb31d, 0xb32c, 0xb33b, 0xb349, 0xb358, 0xb367, -0xb376, 0xb385, 0xb393, 0xb3a2, 0xb3b1, 0xb3c0, -0xb3cf, 0xb3dd, 0xb3ec, 0xb3fb, 0xb40a, 0xb418, -0xb427, 0xb436, 0xb445, 0xb453, 0xb462, 0xb471, -0xb480, 0xb48e, 0xb49d, 0xb4ac, 0xb4bb, 0xb4c9, -0xb4d8, 0xb4e7, 0xb4f6, 0xb504, 0xb513, 0xb522, -0xb530, 0xb53f, 0xb54e, 0xb55c, 0xb56b, 0xb57a, -0xb588, 0xb597, 0xb5a6, 0xb5b5, 0xb5c3, 0xb5d2, -0xb5e1, 0xb5ef, 0xb5fe, 0xb60d, 0xb61b, 0xb62a, -0xb638, 0xb647, 0xb656, 0xb664, 0xb673, 0xb682, -0xb690, 0xb69f, 0xb6ae, 0xb6bc, 0xb6cb, 0xb6d9, -0xb6e8, 0xb6f7, 0xb705, 0xb714, 0xb722, 0xb731, -0xb740, 0xb74e, 0xb75d, 0xb76b, 0xb77a, 0xb788, -0xb797, 0xb7a6, 0xb7b4, 0xb7c3, 0xb7d1, 0xb7e0, -0xb7ee, 0xb7fd, 0xb80b, 0xb81a, 0xb829, 0xb837, -0xb846, 0xb854, 0xb863, 0xb871, 0xb880, 0xb88e, -0xb89d, 0xb8ab, 0xb8ba, 0xb8c8, 0xb8d7, 0xb8e5, -0xb8f4, 0xb902, 0xb911, 0xb91f, 0xb92e, 0xb93c, -0xb94b, 0xb959, 0xb968, 0xb976, 0xb984, 0xb993, -0xb9a1, 0xb9b0, 0xb9be, 0xb9cd, 0xb9db, 0xb9ea, -0xb9f8, 0xba06, 0xba15, 0xba23, 0xba32, 0xba40, -0xba4f, 0xba5d, 0xba6b, 0xba7a, 0xba88, 0xba97, -0xbaa5, 0xbab3, 0xbac2, 0xbad0, 0xbade, 0xbaed, -0xbafb, 0xbb0a, 0xbb18, 0xbb26, 0xbb35, 0xbb43, -0xbb51, 0xbb60, 0xbb6e, 0xbb7c, 0xbb8b, 0xbb99, -0xbba8, 0xbbb6, 0xbbc4, 0xbbd3, 0xbbe1, 0xbbef, -0xbbfd, 0xbc0c, 0xbc1a, 0xbc28, 0xbc37, 0xbc45, -0xbc53, 0xbc62, 0xbc70, 0xbc7e, 0xbc8c, 0xbc9b, -0xbca9, 0xbcb7, 0xbcc6, 0xbcd4, 0xbce2, 0xbcf0, -0xbcff, 0xbd0d, 0xbd1b, 0xbd29, 0xbd38, 0xbd46, -0xbd54, 0xbd62, 0xbd71, 0xbd7f, 0xbd8d, 0xbd9b, -0xbdaa, 0xbdb8, 0xbdc6, 0xbdd4, 0xbde2, 0xbdf1, -0xbdff, 0xbe0d, 0xbe1b, 0xbe29, 0xbe38, 0xbe46, -0xbe54, 0xbe62, 0xbe70, 0xbe7f, 0xbe8d, 0xbe9b, -0xbea9, 0xbeb7, 0xbec5, 0xbed4, 0xbee2, 0xbef0, -0xbefe, 0xbf0c, 0xbf1a, 0xbf28, 0xbf37, 0xbf45, -0xbf53, 0xbf61, 0xbf6f, 0xbf7d, 0xbf8b, 0xbf99, -0xbfa7, 0xbfb6, 0xbfc4, 0xbfd2, 0xbfe0, 0xbfee, -0xbffc, 0xc00a, 0xc018, 0xc026, 0xc034, 0xc042, -0xc051, 0xc05f, 0xc06d, 0xc07b, 0xc089, 0xc097, -0xc0a5, 0xc0b3, 0xc0c1, 0xc0cf, 0xc0dd, 0xc0eb, -0xc0f9, 0xc107, 0xc115, 0xc123, 0xc131, 0xc13f, -0xc14d, 0xc15b, 0xc169, 0xc177, 0xc185, 0xc193, -0xc1a1, 0xc1af, 0xc1bd, 0xc1cb, 0xc1d9, 0xc1e7, -0xc1f5, 0xc203, 0xc211, 0xc21f, 0xc22d, 0xc23b, -0xc249, 0xc257, 0xc265, 0xc273, 0xc281, 0xc28f, -0xc29d, 0xc2ab, 0xc2b8, 0xc2c6, 0xc2d4, 0xc2e2, -0xc2f0, 0xc2fe, 0xc30c, 0xc31a, 0xc328, 0xc336, -0xc344, 0xc352, 0xc35f, 0xc36d, 0xc37b, 0xc389, -0xc397, 0xc3a5, 0xc3b3, 0xc3c1, 0xc3ce, 0xc3dc, -0xc3ea, 0xc3f8, 0xc406, 0xc414, 0xc422, 0xc42f, -0xc43d, 0xc44b, 0xc459, 0xc467, 0xc475, 0xc482, -0xc490, 0xc49e, 0xc4ac, 0xc4ba, 0xc4c7, 0xc4d5, -0xc4e3, 0xc4f1, 0xc4ff, 0xc50d, 0xc51a, 0xc528, -0xc536, 0xc544, 0xc551, 0xc55f, 0xc56d, 0xc57b, -0xc589, 0xc596, 0xc5a4, 0xc5b2, 0xc5c0, 0xc5cd, -0xc5db, 0xc5e9, 0xc5f7, 0xc604, 0xc612, 0xc620, -0xc62d, 0xc63b, 0xc649, 0xc657, 0xc664, 0xc672, -0xc680, 0xc68d, 0xc69b, 0xc6a9, 0xc6b7, 0xc6c4, -0xc6d2, 0xc6e0, 0xc6ed, 0xc6fb, 0xc709, 0xc716, -0xc724, 0xc732, 0xc73f, 0xc74d, 0xc75b, 0xc768, -0xc776, 0xc784, 0xc791, 0xc79f, 0xc7ad, 0xc7ba, -0xc7c8, 0xc7d6, 0xc7e3, 0xc7f1, 0xc7fe, 0xc80c, -0xc81a, 0xc827, 0xc835, 0xc842, 0xc850, 0xc85e, -0xc86b, 0xc879, 0xc886, 0xc894, 0xc8a2, 0xc8af, -0xc8bd, 0xc8ca, 0xc8d8, 0xc8e5, 0xc8f3, 0xc901, -0xc90e, 0xc91c, 0xc929, 0xc937, 0xc944, 0xc952, -0xc95f, 0xc96d, 0xc97b, 0xc988, 0xc996, 0xc9a3, -0xc9b1, 0xc9be, 0xc9cc, 0xc9d9, 0xc9e7, 0xc9f4, -0xca02, 0xca0f, 0xca1d, 0xca2a, 0xca38, 0xca45, -0xca53, 0xca60, 0xca6e, 0xca7b, 0xca89, 0xca96, -0xcaa4, 0xcab1, 0xcabe, 0xcacc, 0xcad9, 0xcae7, -0xcaf4, 0xcb02, 0xcb0f, 0xcb1d, 0xcb2a, 0xcb37, -0xcb45, 0xcb52, 0xcb60, 0xcb6d, 0xcb7b, 0xcb88, -0xcb95, 0xcba3, 0xcbb0, 0xcbbe, 0xcbcb, 0xcbd8, -0xcbe6, 0xcbf3, 0xcc01, 0xcc0e, 0xcc1b, 0xcc29, -0xcc36, 0xcc43, 0xcc51, 0xcc5e, 0xcc6c, 0xcc79, -0xcc86, 0xcc94, 0xcca1, 0xccae, 0xccbc, 0xccc9, -0xccd6, 0xcce4, 0xccf1, 0xccfe, 0xcd0c, 0xcd19, -0xcd26, 0xcd34, 0xcd41, 0xcd4e, 0xcd5b, 0xcd69, -0xcd76, 0xcd83, 0xcd91, 0xcd9e, 0xcdab, 0xcdb9, -0xcdc6, 0xcdd3, 0xcde0, 0xcdee, 0xcdfb, 0xce08, -0xce15, 0xce23, 0xce30, 0xce3d, 0xce4a, 0xce58, -0xce65, 0xce72, 0xce7f, 0xce8d, 0xce9a, 0xcea7, -0xceb4, 0xcec2, 0xcecf, 0xcedc, 0xcee9, 0xcef6, -0xcf04, 0xcf11, 0xcf1e, 0xcf2b, 0xcf38, 0xcf46, -0xcf53, 0xcf60, 0xcf6d, 0xcf7a, 0xcf87, 0xcf95, -0xcfa2, 0xcfaf, 0xcfbc, 0xcfc9, 0xcfd6, 0xcfe4, -0xcff1, 0xcffe, 0xd00b, 0xd018, 0xd025, 0xd032, -0xd040, 0xd04d, 0xd05a, 0xd067, 0xd074, 0xd081, -0xd08e, 0xd09b, 0xd0a9, 0xd0b6, 0xd0c3, 0xd0d0, -0xd0dd, 0xd0ea, 0xd0f7, 0xd104, 0xd111, 0xd11e, -0xd12b, 0xd139, 0xd146, 0xd153, 0xd160, 0xd16d, -0xd17a, 0xd187, 0xd194, 0xd1a1, 0xd1ae, 0xd1bb, -0xd1c8, 0xd1d5, 0xd1e2, 0xd1ef, 0xd1fc, 0xd209, -0xd216, 0xd223, 0xd230, 0xd23d, 0xd24a, 0xd257, -0xd264, 0xd271, 0xd27e, 0xd28b, 0xd298, 0xd2a5, -0xd2b2, 0xd2bf, 0xd2cc, 0xd2d9, 0xd2e6, 0xd2f3, -0xd300, 0xd30d, 0xd31a, 0xd327, 0xd334, 0xd341, -0xd34e, 0xd35b, 0xd368, 0xd375, 0xd382, 0xd38f, -0xd39c, 0xd3a8, 0xd3b5, 0xd3c2, 0xd3cf, 0xd3dc, -0xd3e9, 0xd3f6, 0xd403, 0xd410, 0xd41d, 0xd42a, -0xd436, 0xd443, 0xd450, 0xd45d, 0xd46a, 0xd477, -0xd484, 0xd491, 0xd49e, 0xd4aa, 0xd4b7, 0xd4c4, -0xd4d1, 0xd4de, 0xd4eb, 0xd4f8, 0xd504, 0xd511, -0xd51e, 0xd52b, 0xd538, 0xd545, 0xd551, 0xd55e, -0xd56b, 0xd578, 0xd585, 0xd591, 0xd59e, 0xd5ab, -0xd5b8, 0xd5c5, 0xd5d1, 0xd5de, 0xd5eb, 0xd5f8, -0xd605, 0xd611, 0xd61e, 0xd62b, 0xd638, 0xd645, -0xd651, 0xd65e, 0xd66b, 0xd678, 0xd684, 0xd691, -0xd69e, 0xd6ab, 0xd6b7, 0xd6c4, 0xd6d1, 0xd6de, -0xd6ea, 0xd6f7, 0xd704, 0xd710, 0xd71d, 0xd72a, -0xd737, 0xd743, 0xd750, 0xd75d, 0xd769, 0xd776, -0xd783, 0xd78f, 0xd79c, 0xd7a9, 0xd7b6, 0xd7c2, -0xd7cf, 0xd7dc, 0xd7e8, 0xd7f5, 0xd802, 0xd80e, -0xd81b, 0xd828, 0xd834, 0xd841, 0xd84e, 0xd85a, -0xd867, 0xd873, 0xd880, 0xd88d, 0xd899, 0xd8a6, -0xd8b3, 0xd8bf, 0xd8cc, 0xd8d8, 0xd8e5, 0xd8f2, -0xd8fe, 0xd90b, 0xd917, 0xd924, 0xd931, 0xd93d, -0xd94a, 0xd956, 0xd963, 0xd970, 0xd97c, 0xd989, -0xd995, 0xd9a2, 0xd9ae, 0xd9bb, 0xd9c8, 0xd9d4, -0xd9e1, 0xd9ed, 0xd9fa, 0xda06, 0xda13, 0xda1f, -0xda2c, 0xda38, 0xda45, 0xda51, 0xda5e, 0xda6a, -0xda77, 0xda84, 0xda90, 0xda9d, 0xdaa9, 0xdab6, -0xdac2, 0xdacf, 0xdadb, 0xdae7, 0xdaf4, 0xdb00, -0xdb0d, 0xdb19, 0xdb26, 0xdb32, 0xdb3f, 0xdb4b, -0xdb58, 0xdb64, 0xdb71, 0xdb7d, 0xdb8a, 0xdb96, -0xdba2, 0xdbaf, 0xdbbb, 0xdbc8, 0xdbd4, 0xdbe1, -0xdbed, 0xdbf9, 0xdc06, 0xdc12, 0xdc1f, 0xdc2b, -0xdc38, 0xdc44, 0xdc50, 0xdc5d, 0xdc69, 0xdc76, -0xdc82, 0xdc8e, 0xdc9b, 0xdca7, 0xdcb3, 0xdcc0, -0xdccc, 0xdcd9, 0xdce5, 0xdcf1, 0xdcfe, 0xdd0a, -0xdd16, 0xdd23, 0xdd2f, 0xdd3b, 0xdd48, 0xdd54, -0xdd60, 0xdd6d, 0xdd79, 0xdd85, 0xdd92, 0xdd9e, -0xddaa, 0xddb7, 0xddc3, 0xddcf, 0xdddc, 0xdde8, -0xddf4, 0xde01, 0xde0d, 0xde19, 0xde25, 0xde32, -0xde3e, 0xde4a, 0xde57, 0xde63, 0xde6f, 0xde7b, -0xde88, 0xde94, 0xdea0, 0xdeac, 0xdeb9, 0xdec5, -0xded1, 0xdedd, 0xdeea, 0xdef6, 0xdf02, 0xdf0e, -0xdf1b, 0xdf27, 0xdf33, 0xdf3f, 0xdf4c, 0xdf58, -0xdf64, 0xdf70, 0xdf7c, 0xdf89, 0xdf95, 0xdfa1, -0xdfad, 0xdfb9, 0xdfc6, 0xdfd2, 0xdfde, 0xdfea, -0xdff6, 0xe003, 0xe00f, 0xe01b, 0xe027, 0xe033, -0xe03f, 0xe04c, 0xe058, 0xe064, 0xe070, 0xe07c, -0xe088, 0xe094, 0xe0a1, 0xe0ad, 0xe0b9, 0xe0c5, -0xe0d1, 0xe0dd, 0xe0e9, 0xe0f5, 0xe102, 0xe10e, -0xe11a, 0xe126, 0xe132, 0xe13e, 0xe14a, 0xe156, -0xe162, 0xe16e, 0xe17b, 0xe187, 0xe193, 0xe19f, -0xe1ab, 0xe1b7, 0xe1c3, 0xe1cf, 0xe1db, 0xe1e7, -0xe1f3, 0xe1ff, 0xe20b, 0xe217, 0xe223, 0xe22f, -0xe23c, 0xe248, 0xe254, 0xe260, 0xe26c, 0xe278, -0xe284, 0xe290, 0xe29c, 0xe2a8, 0xe2b4, 0xe2c0, -0xe2cc, 0xe2d8, 0xe2e4, 0xe2f0, 0xe2fc, 0xe308, -0xe314, 0xe320, 0xe32c, 0xe338, 0xe344, 0xe350, -0xe35c, 0xe368, 0xe374, 0xe380, 0xe38b, 0xe397, -0xe3a3, 0xe3af, 0xe3bb, 0xe3c7, 0xe3d3, 0xe3df, -0xe3eb, 0xe3f7, 0xe403, 0xe40f, 0xe41b, 0xe427, -0xe433, 0xe43f, 0xe44a, 0xe456, 0xe462, 0xe46e, -0xe47a, 0xe486, 0xe492, 0xe49e, 0xe4aa, 0xe4b6, -0xe4c1, 0xe4cd, 0xe4d9, 0xe4e5, 0xe4f1, 0xe4fd, -0xe509, 0xe515, 0xe520, 0xe52c, 0xe538, 0xe544, -0xe550, 0xe55c, 0xe567, 0xe573, 0xe57f, 0xe58b, -0xe597, 0xe5a3, 0xe5af, 0xe5ba, 0xe5c6, 0xe5d2, -0xe5de, 0xe5ea, 0xe5f5, 0xe601, 0xe60d, 0xe619, -0xe625, 0xe630, 0xe63c, 0xe648, 0xe654, 0xe660, -0xe66b, 0xe677, 0xe683, 0xe68f, 0xe69a, 0xe6a6, -0xe6b2, 0xe6be, 0xe6ca, 0xe6d5, 0xe6e1, 0xe6ed, -0xe6f9, 0xe704, 0xe710, 0xe71c, 0xe727, 0xe733, -0xe73f, 0xe74b, 0xe756, 0xe762, 0xe76e, 0xe77a, -0xe785, 0xe791, 0xe79d, 0xe7a8, 0xe7b4, 0xe7c0, -0xe7cb, 0xe7d7, 0xe7e3, 0xe7ef, 0xe7fa, 0xe806, -0xe812, 0xe81d, 0xe829, 0xe835, 0xe840, 0xe84c, -0xe858, 0xe863, 0xe86f, 0xe87b, 0xe886, 0xe892, -0xe89e, 0xe8a9, 0xe8b5, 0xe8c0, 0xe8cc, 0xe8d8, -0xe8e3, 0xe8ef, 0xe8fb, 0xe906, 0xe912, 0xe91d, -0xe929, 0xe935, 0xe940, 0xe94c, 0xe958, 0xe963, -0xe96f, 0xe97a, 0xe986, 0xe991, 0xe99d, 0xe9a9, -0xe9b4, 0xe9c0, 0xe9cb, 0xe9d7, 0xe9e3, 0xe9ee, -0xe9fa, 0xea05, 0xea11, 0xea1c, 0xea28, 0xea33, -0xea3f, 0xea4a, 0xea56, 0xea62, 0xea6d, 0xea79, -0xea84, 0xea90, 0xea9b, 0xeaa7, 0xeab2, 0xeabe, -0xeac9, 0xead5, 0xeae0, 0xeaec, 0xeaf7, 0xeb03, -0xeb0e, 0xeb1a, 0xeb25, 0xeb31, 0xeb3c, 0xeb48, -0xeb53, 0xeb5f, 0xeb6a, 0xeb76, 0xeb81, 0xeb8d, -0xeb98, 0xeba3, 0xebaf, 0xebba, 0xebc6, 0xebd1, -0xebdd, 0xebe8, 0xebf4, 0xebff, 0xec0a, 0xec16, -0xec21, 0xec2d, 0xec38, 0xec44, 0xec4f, 0xec5a, -0xec66, 0xec71, 0xec7d, 0xec88, 0xec93, 0xec9f, -0xecaa, 0xecb6, 0xecc1, 0xeccc, 0xecd8, 0xece3, -0xecef, 0xecfa, 0xed05, 0xed11, 0xed1c, 0xed27, -0xed33, 0xed3e, 0xed4a, 0xed55, 0xed60, 0xed6c, -0xed77, 0xed82, 0xed8e, 0xed99, 0xeda4, 0xedb0, -0xedbb, 0xedc6, 0xedd2, 0xeddd, 0xede8, 0xedf4, -0xedff, 0xee0a, 0xee15, 0xee21, 0xee2c, 0xee37, -0xee43, 0xee4e, 0xee59, 0xee65, 0xee70, 0xee7b, -0xee86, 0xee92, 0xee9d, 0xeea8, 0xeeb3, 0xeebf, -0xeeca, 0xeed5, 0xeee1, 0xeeec, 0xeef7, 0xef02, -0xef0e, 0xef19, 0xef24, 0xef2f, 0xef3a, 0xef46, -0xef51, 0xef5c, 0xef67, 0xef73, 0xef7e, 0xef89, -0xef94, 0xef9f, 0xefab, 0xefb6, 0xefc1, 0xefcc, -0xefd7, 0xefe3, 0xefee, 0xeff9, 0xf004, 0xf00f, -0xf01b, 0xf026, 0xf031, 0xf03c, 0xf047, 0xf052, -0xf05e, 0xf069, 0xf074, 0xf07f, 0xf08a, 0xf095, -0xf0a1, 0xf0ac, 0xf0b7, 0xf0c2, 0xf0cd, 0xf0d8, -0xf0e3, 0xf0ef, 0xf0fa, 0xf105, 0xf110, 0xf11b, -0xf126, 0xf131, 0xf13c, 0xf147, 0xf153, 0xf15e, -0xf169, 0xf174, 0xf17f, 0xf18a, 0xf195, 0xf1a0, -0xf1ab, 0xf1b6, 0xf1c2, 0xf1cd, 0xf1d8, 0xf1e3, -0xf1ee, 0xf1f9, 0xf204, 0xf20f, 0xf21a, 0xf225, -0xf230, 0xf23b, 0xf246, 0xf251, 0xf25c, 0xf267, -0xf272, 0xf27d, 0xf288, 0xf293, 0xf29f, 0xf2aa, -0xf2b5, 0xf2c0, 0xf2cb, 0xf2d6, 0xf2e1, 0xf2ec, -0xf2f7, 0xf302, 0xf30d, 0xf318, 0xf323, 0xf32e, -0xf339, 0xf344, 0xf34f, 0xf35a, 0xf364, 0xf36f, -0xf37a, 0xf385, 0xf390, 0xf39b, 0xf3a6, 0xf3b1, -0xf3bc, 0xf3c7, 0xf3d2, 0xf3dd, 0xf3e8, 0xf3f3, -0xf3fe, 0xf409, 0xf414, 0xf41f, 0xf42a, 0xf435, -0xf43f, 0xf44a, 0xf455, 0xf460, 0xf46b, 0xf476, -0xf481, 0xf48c, 0xf497, 0xf4a2, 0xf4ad, 0xf4b7, -0xf4c2, 0xf4cd, 0xf4d8, 0xf4e3, 0xf4ee, 0xf4f9, -0xf504, 0xf50f, 0xf519, 0xf524, 0xf52f, 0xf53a, -0xf545, 0xf550, 0xf55b, 0xf565, 0xf570, 0xf57b, -0xf586, 0xf591, 0xf59c, 0xf5a6, 0xf5b1, 0xf5bc, -0xf5c7, 0xf5d2, 0xf5dd, 0xf5e7, 0xf5f2, 0xf5fd, -0xf608, 0xf613, 0xf61d, 0xf628, 0xf633, 0xf63e, -0xf649, 0xf653, 0xf65e, 0xf669, 0xf674, 0xf67f, -0xf689, 0xf694, 0xf69f, 0xf6aa, 0xf6b4, 0xf6bf, -0xf6ca, 0xf6d5, 0xf6e0, 0xf6ea, 0xf6f5, 0xf700, -0xf70b, 0xf715, 0xf720, 0xf72b, 0xf736, 0xf740, -0xf74b, 0xf756, 0xf760, 0xf76b, 0xf776, 0xf781, -0xf78b, 0xf796, 0xf7a1, 0xf7ab, 0xf7b6, 0xf7c1, -0xf7cc, 0xf7d6, 0xf7e1, 0xf7ec, 0xf7f6, 0xf801, -0xf80c, 0xf816, 0xf821, 0xf82c, 0xf836, 0xf841, -0xf84c, 0xf856, 0xf861, 0xf86c, 0xf876, 0xf881, -0xf88c, 0xf896, 0xf8a1, 0xf8ac, 0xf8b6, 0xf8c1, -0xf8cc, 0xf8d6, 0xf8e1, 0xf8ec, 0xf8f6, 0xf901, -0xf90b, 0xf916, 0xf921, 0xf92b, 0xf936, 0xf941, -0xf94b, 0xf956, 0xf960, 0xf96b, 0xf976, 0xf980, -0xf98b, 0xf995, 0xf9a0, 0xf9aa, 0xf9b5, 0xf9c0, -0xf9ca, 0xf9d5, 0xf9df, 0xf9ea, 0xf9f4, 0xf9ff, -0xfa0a, 0xfa14, 0xfa1f, 0xfa29, 0xfa34, 0xfa3e, -0xfa49, 0xfa53, 0xfa5e, 0xfa69, 0xfa73, 0xfa7e, -0xfa88, 0xfa93, 0xfa9d, 0xfaa8, 0xfab2, 0xfabd, -0xfac7, 0xfad2, 0xfadc, 0xfae7, 0xfaf1, 0xfafc, -0xfb06, 0xfb11, 0xfb1b, 0xfb26, 0xfb30, 0xfb3b, -0xfb45, 0xfb50, 0xfb5a, 0xfb65, 0xfb6f, 0xfb7a, -0xfb84, 0xfb8f, 0xfb99, 0xfba4, 0xfbae, 0xfbb8, -0xfbc3, 0xfbcd, 0xfbd8, 0xfbe2, 0xfbed, 0xfbf7, -0xfc02, 0xfc0c, 0xfc16, 0xfc21, 0xfc2b, 0xfc36, -0xfc40, 0xfc4b, 0xfc55, 0xfc5f, 0xfc6a, 0xfc74, -0xfc7f, 0xfc89, 0xfc93, 0xfc9e, 0xfca8, 0xfcb3, -0xfcbd, 0xfcc7, 0xfcd2, 0xfcdc, 0xfce7, 0xfcf1, -0xfcfb, 0xfd06, 0xfd10, 0xfd1a, 0xfd25, 0xfd2f, -0xfd3a, 0xfd44, 0xfd4e, 0xfd59, 0xfd63, 0xfd6d, -0xfd78, 0xfd82, 0xfd8c, 0xfd97, 0xfda1, 0xfdab, -0xfdb6, 0xfdc0, 0xfdca, 0xfdd5, 0xfddf, 0xfde9, -0xfdf4, 0xfdfe, 0xfe08, 0xfe13, 0xfe1d, 0xfe27, -0xfe32, 0xfe3c, 0xfe46, 0xfe50, 0xfe5b, 0xfe65, -0xfe6f, 0xfe7a, 0xfe84, 0xfe8e, 0xfe98, 0xfea3, -0xfead, 0xfeb7, 0xfec1, 0xfecc, 0xfed6, 0xfee0, -0xfeeb, 0xfef5, 0xfeff, 0xff09, 0xff14, 0xff1e, -0xff28, 0xff32, 0xff3c, 0xff47, 0xff51, 0xff5b, -0xff65, 0xff70, 0xff7a, 0xff84, 0xff8e, 0xff98, -0xffa3, 0xffad, 0xffb7, 0xffc1, 0xffcc, 0xffd6, -0xffe0, 0xffea, 0xfff4, 0xffff -}; - -// max value is pi/4 -constexpr double SCALING_FACTOR = 4. / M_PI * 0xFFFF; - -inline double atan2_lookup(double y, double x) -{ - if (std::abs(x) < std::numeric_limits::epsilon()) - { - if (y >= 0.) - { - return M_PI / 2.; - } - else - { - return -M_PI / 2.; - } - } - - unsigned octant = 0; - - if (x < 0.) - { - octant = 1; - x = -x; - } - if (y < 0.) - { - octant |= 2; - y = -y; - } - - double t = y / x; - if (t > 1.0) - { - octant |= 4; - t = 1.0 / t; - } - - double angle = atan_table[(unsigned)(t * 4095)] / SCALING_FACTOR; - - switch (octant) - { - case 0: - break; - case 1: - angle = M_PI - angle; - break; - case 2: - angle = -angle; - break; - case 3: - angle = -M_PI + angle; - break; - case 4: - angle = M_PI / 2.0 - angle; - break; - case 5: - angle = M_PI / 2.0 + angle; - break; - case 6: - angle = -M_PI / 2.0 + angle; - break; - case 7: - angle = -M_PI / 2.0 - angle; - break; - } - return angle; -} - -#endif // TRIGONOMETRY_TABLES_H diff --git a/Util/BoostFileSystemFix.h b/Util/boost_filesystem_2_fix.hpp similarity index 100% rename from Util/BoostFileSystemFix.h rename to Util/boost_filesystem_2_fix.hpp diff --git a/Util/compute_angle.cpp b/Util/compute_angle.cpp index 445b67f12..dd1989b80 100644 --- a/Util/compute_angle.cpp +++ b/Util/compute_angle.cpp @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "compute_angle.hpp" -#include "TrigonometryTables.h" +#include "trigonometry_table.hpp" #include "../Util/mercator.hpp" #include diff --git a/Util/datastore_options.hpp b/Util/datastore_options.hpp index dbc7fe87e..1992860b5 100644 --- a/Util/datastore_options.hpp +++ b/Util/datastore_options.hpp @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef DATASTORE_OPTIONS_HPP #define DATASTORE_OPTIONS_HPP -#include "BoostFileSystemFix.h" +#include "boost_filesystem_2_fix.hpp" #include "git_sha.hpp" #include "ini_file.hpp" #include "osrm_exception.hpp" diff --git a/Util/trigonometry_table.hpp b/Util/trigonometry_table.hpp new file mode 100644 index 000000000..ebcf7ba4d --- /dev/null +++ b/Util/trigonometry_table.hpp @@ -0,0 +1,448 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TRIGONOMETRY_TABLE_HPP +#define TRIGONOMETRY_TABLE_HPP + +#include "../typedefs.h" +#include + +#include + +constexpr unsigned short atan_table[4096] = { + 0x0000, 0x0014, 0x0028, 0x003d, 0x0051, 0x0065, 0x007a, 0x008e, 0x00a3, 0x00b7, 0x00cb, 0x00e0, + 0x00f4, 0x0108, 0x011d, 0x0131, 0x0146, 0x015a, 0x016e, 0x0183, 0x0197, 0x01ab, 0x01c0, 0x01d4, + 0x01e9, 0x01fd, 0x0211, 0x0226, 0x023a, 0x024e, 0x0263, 0x0277, 0x028c, 0x02a0, 0x02b4, 0x02c9, + 0x02dd, 0x02f1, 0x0306, 0x031a, 0x032f, 0x0343, 0x0357, 0x036c, 0x0380, 0x0394, 0x03a9, 0x03bd, + 0x03d2, 0x03e6, 0x03fa, 0x040f, 0x0423, 0x0437, 0x044c, 0x0460, 0x0475, 0x0489, 0x049d, 0x04b2, + 0x04c6, 0x04da, 0x04ef, 0x0503, 0x0517, 0x052c, 0x0540, 0x0555, 0x0569, 0x057d, 0x0592, 0x05a6, + 0x05ba, 0x05cf, 0x05e3, 0x05f8, 0x060c, 0x0620, 0x0635, 0x0649, 0x065d, 0x0672, 0x0686, 0x069b, + 0x06af, 0x06c3, 0x06d8, 0x06ec, 0x0700, 0x0715, 0x0729, 0x073d, 0x0752, 0x0766, 0x077b, 0x078f, + 0x07a3, 0x07b8, 0x07cc, 0x07e0, 0x07f5, 0x0809, 0x081d, 0x0832, 0x0846, 0x085b, 0x086f, 0x0883, + 0x0898, 0x08ac, 0x08c0, 0x08d5, 0x08e9, 0x08fd, 0x0912, 0x0926, 0x093b, 0x094f, 0x0963, 0x0978, + 0x098c, 0x09a0, 0x09b5, 0x09c9, 0x09dd, 0x09f2, 0x0a06, 0x0a1a, 0x0a2f, 0x0a43, 0x0a58, 0x0a6c, + 0x0a80, 0x0a95, 0x0aa9, 0x0abd, 0x0ad2, 0x0ae6, 0x0afa, 0x0b0f, 0x0b23, 0x0b37, 0x0b4c, 0x0b60, + 0x0b75, 0x0b89, 0x0b9d, 0x0bb2, 0x0bc6, 0x0bda, 0x0bef, 0x0c03, 0x0c17, 0x0c2c, 0x0c40, 0x0c54, + 0x0c69, 0x0c7d, 0x0c91, 0x0ca6, 0x0cba, 0x0cce, 0x0ce3, 0x0cf7, 0x0d0b, 0x0d20, 0x0d34, 0x0d48, + 0x0d5d, 0x0d71, 0x0d86, 0x0d9a, 0x0dae, 0x0dc3, 0x0dd7, 0x0deb, 0x0e00, 0x0e14, 0x0e28, 0x0e3d, + 0x0e51, 0x0e65, 0x0e7a, 0x0e8e, 0x0ea2, 0x0eb7, 0x0ecb, 0x0edf, 0x0ef4, 0x0f08, 0x0f1c, 0x0f31, + 0x0f45, 0x0f59, 0x0f6e, 0x0f82, 0x0f96, 0x0fab, 0x0fbf, 0x0fd3, 0x0fe8, 0x0ffc, 0x1010, 0x1025, + 0x1039, 0x104d, 0x1062, 0x1076, 0x108a, 0x109e, 0x10b3, 0x10c7, 0x10db, 0x10f0, 0x1104, 0x1118, + 0x112d, 0x1141, 0x1155, 0x116a, 0x117e, 0x1192, 0x11a7, 0x11bb, 0x11cf, 0x11e4, 0x11f8, 0x120c, + 0x1221, 0x1235, 0x1249, 0x125d, 0x1272, 0x1286, 0x129a, 0x12af, 0x12c3, 0x12d7, 0x12ec, 0x1300, + 0x1314, 0x1329, 0x133d, 0x1351, 0x1365, 0x137a, 0x138e, 0x13a2, 0x13b7, 0x13cb, 0x13df, 0x13f4, + 0x1408, 0x141c, 0x1431, 0x1445, 0x1459, 0x146d, 0x1482, 0x1496, 0x14aa, 0x14bf, 0x14d3, 0x14e7, + 0x14fb, 0x1510, 0x1524, 0x1538, 0x154d, 0x1561, 0x1575, 0x1589, 0x159e, 0x15b2, 0x15c6, 0x15db, + 0x15ef, 0x1603, 0x1617, 0x162c, 0x1640, 0x1654, 0x1669, 0x167d, 0x1691, 0x16a5, 0x16ba, 0x16ce, + 0x16e2, 0x16f7, 0x170b, 0x171f, 0x1733, 0x1748, 0x175c, 0x1770, 0x1784, 0x1799, 0x17ad, 0x17c1, + 0x17d6, 0x17ea, 0x17fe, 0x1812, 0x1827, 0x183b, 0x184f, 0x1863, 0x1878, 0x188c, 0x18a0, 0x18b4, + 0x18c9, 0x18dd, 0x18f1, 0x1905, 0x191a, 0x192e, 0x1942, 0x1957, 0x196b, 0x197f, 0x1993, 0x19a8, + 0x19bc, 0x19d0, 0x19e4, 0x19f9, 0x1a0d, 0x1a21, 0x1a35, 0x1a49, 0x1a5e, 0x1a72, 0x1a86, 0x1a9a, + 0x1aaf, 0x1ac3, 0x1ad7, 0x1aeb, 0x1b00, 0x1b14, 0x1b28, 0x1b3c, 0x1b51, 0x1b65, 0x1b79, 0x1b8d, + 0x1ba2, 0x1bb6, 0x1bca, 0x1bde, 0x1bf2, 0x1c07, 0x1c1b, 0x1c2f, 0x1c43, 0x1c58, 0x1c6c, 0x1c80, + 0x1c94, 0x1ca8, 0x1cbd, 0x1cd1, 0x1ce5, 0x1cf9, 0x1d0e, 0x1d22, 0x1d36, 0x1d4a, 0x1d5e, 0x1d73, + 0x1d87, 0x1d9b, 0x1daf, 0x1dc3, 0x1dd8, 0x1dec, 0x1e00, 0x1e14, 0x1e28, 0x1e3d, 0x1e51, 0x1e65, + 0x1e79, 0x1e8d, 0x1ea2, 0x1eb6, 0x1eca, 0x1ede, 0x1ef2, 0x1f07, 0x1f1b, 0x1f2f, 0x1f43, 0x1f57, + 0x1f6c, 0x1f80, 0x1f94, 0x1fa8, 0x1fbc, 0x1fd1, 0x1fe5, 0x1ff9, 0x200d, 0x2021, 0x2035, 0x204a, + 0x205e, 0x2072, 0x2086, 0x209a, 0x20ae, 0x20c3, 0x20d7, 0x20eb, 0x20ff, 0x2113, 0x2127, 0x213c, + 0x2150, 0x2164, 0x2178, 0x218c, 0x21a0, 0x21b5, 0x21c9, 0x21dd, 0x21f1, 0x2205, 0x2219, 0x222e, + 0x2242, 0x2256, 0x226a, 0x227e, 0x2292, 0x22a6, 0x22bb, 0x22cf, 0x22e3, 0x22f7, 0x230b, 0x231f, + 0x2333, 0x2348, 0x235c, 0x2370, 0x2384, 0x2398, 0x23ac, 0x23c0, 0x23d5, 0x23e9, 0x23fd, 0x2411, + 0x2425, 0x2439, 0x244d, 0x2461, 0x2476, 0x248a, 0x249e, 0x24b2, 0x24c6, 0x24da, 0x24ee, 0x2502, + 0x2517, 0x252b, 0x253f, 0x2553, 0x2567, 0x257b, 0x258f, 0x25a3, 0x25b7, 0x25cb, 0x25e0, 0x25f4, + 0x2608, 0x261c, 0x2630, 0x2644, 0x2658, 0x266c, 0x2680, 0x2694, 0x26a9, 0x26bd, 0x26d1, 0x26e5, + 0x26f9, 0x270d, 0x2721, 0x2735, 0x2749, 0x275d, 0x2771, 0x2785, 0x279a, 0x27ae, 0x27c2, 0x27d6, + 0x27ea, 0x27fe, 0x2812, 0x2826, 0x283a, 0x284e, 0x2862, 0x2876, 0x288a, 0x289e, 0x28b3, 0x28c7, + 0x28db, 0x28ef, 0x2903, 0x2917, 0x292b, 0x293f, 0x2953, 0x2967, 0x297b, 0x298f, 0x29a3, 0x29b7, + 0x29cb, 0x29df, 0x29f3, 0x2a07, 0x2a1b, 0x2a2f, 0x2a43, 0x2a58, 0x2a6c, 0x2a80, 0x2a94, 0x2aa8, + 0x2abc, 0x2ad0, 0x2ae4, 0x2af8, 0x2b0c, 0x2b20, 0x2b34, 0x2b48, 0x2b5c, 0x2b70, 0x2b84, 0x2b98, + 0x2bac, 0x2bc0, 0x2bd4, 0x2be8, 0x2bfc, 0x2c10, 0x2c24, 0x2c38, 0x2c4c, 0x2c60, 0x2c74, 0x2c88, + 0x2c9c, 0x2cb0, 0x2cc4, 0x2cd8, 0x2cec, 0x2d00, 0x2d14, 0x2d28, 0x2d3c, 0x2d50, 0x2d64, 0x2d78, + 0x2d8c, 0x2da0, 0x2db4, 0x2dc8, 0x2ddc, 0x2df0, 0x2e04, 0x2e18, 0x2e2c, 0x2e40, 0x2e54, 0x2e68, + 0x2e7c, 0x2e90, 0x2ea3, 0x2eb7, 0x2ecb, 0x2edf, 0x2ef3, 0x2f07, 0x2f1b, 0x2f2f, 0x2f43, 0x2f57, + 0x2f6b, 0x2f7f, 0x2f93, 0x2fa7, 0x2fbb, 0x2fcf, 0x2fe3, 0x2ff7, 0x300b, 0x301e, 0x3032, 0x3046, + 0x305a, 0x306e, 0x3082, 0x3096, 0x30aa, 0x30be, 0x30d2, 0x30e6, 0x30fa, 0x310e, 0x3122, 0x3135, + 0x3149, 0x315d, 0x3171, 0x3185, 0x3199, 0x31ad, 0x31c1, 0x31d5, 0x31e9, 0x31fd, 0x3210, 0x3224, + 0x3238, 0x324c, 0x3260, 0x3274, 0x3288, 0x329c, 0x32b0, 0x32c3, 0x32d7, 0x32eb, 0x32ff, 0x3313, + 0x3327, 0x333b, 0x334f, 0x3363, 0x3376, 0x338a, 0x339e, 0x33b2, 0x33c6, 0x33da, 0x33ee, 0x3401, + 0x3415, 0x3429, 0x343d, 0x3451, 0x3465, 0x3479, 0x348c, 0x34a0, 0x34b4, 0x34c8, 0x34dc, 0x34f0, + 0x3504, 0x3517, 0x352b, 0x353f, 0x3553, 0x3567, 0x357b, 0x358e, 0x35a2, 0x35b6, 0x35ca, 0x35de, + 0x35f2, 0x3605, 0x3619, 0x362d, 0x3641, 0x3655, 0x3668, 0x367c, 0x3690, 0x36a4, 0x36b8, 0x36cb, + 0x36df, 0x36f3, 0x3707, 0x371b, 0x372f, 0x3742, 0x3756, 0x376a, 0x377e, 0x3791, 0x37a5, 0x37b9, + 0x37cd, 0x37e1, 0x37f4, 0x3808, 0x381c, 0x3830, 0x3844, 0x3857, 0x386b, 0x387f, 0x3893, 0x38a6, + 0x38ba, 0x38ce, 0x38e2, 0x38f5, 0x3909, 0x391d, 0x3931, 0x3944, 0x3958, 0x396c, 0x3980, 0x3993, + 0x39a7, 0x39bb, 0x39cf, 0x39e2, 0x39f6, 0x3a0a, 0x3a1e, 0x3a31, 0x3a45, 0x3a59, 0x3a6d, 0x3a80, + 0x3a94, 0x3aa8, 0x3abb, 0x3acf, 0x3ae3, 0x3af7, 0x3b0a, 0x3b1e, 0x3b32, 0x3b45, 0x3b59, 0x3b6d, + 0x3b81, 0x3b94, 0x3ba8, 0x3bbc, 0x3bcf, 0x3be3, 0x3bf7, 0x3c0b, 0x3c1e, 0x3c32, 0x3c46, 0x3c59, + 0x3c6d, 0x3c81, 0x3c94, 0x3ca8, 0x3cbc, 0x3ccf, 0x3ce3, 0x3cf7, 0x3d0a, 0x3d1e, 0x3d32, 0x3d45, + 0x3d59, 0x3d6d, 0x3d80, 0x3d94, 0x3da8, 0x3dbb, 0x3dcf, 0x3de3, 0x3df6, 0x3e0a, 0x3e1e, 0x3e31, + 0x3e45, 0x3e59, 0x3e6c, 0x3e80, 0x3e93, 0x3ea7, 0x3ebb, 0x3ece, 0x3ee2, 0x3ef6, 0x3f09, 0x3f1d, + 0x3f30, 0x3f44, 0x3f58, 0x3f6b, 0x3f7f, 0x3f93, 0x3fa6, 0x3fba, 0x3fcd, 0x3fe1, 0x3ff5, 0x4008, + 0x401c, 0x402f, 0x4043, 0x4057, 0x406a, 0x407e, 0x4091, 0x40a5, 0x40b8, 0x40cc, 0x40e0, 0x40f3, + 0x4107, 0x411a, 0x412e, 0x4142, 0x4155, 0x4169, 0x417c, 0x4190, 0x41a3, 0x41b7, 0x41ca, 0x41de, + 0x41f2, 0x4205, 0x4219, 0x422c, 0x4240, 0x4253, 0x4267, 0x427a, 0x428e, 0x42a1, 0x42b5, 0x42c9, + 0x42dc, 0x42f0, 0x4303, 0x4317, 0x432a, 0x433e, 0x4351, 0x4365, 0x4378, 0x438c, 0x439f, 0x43b3, + 0x43c6, 0x43da, 0x43ed, 0x4401, 0x4414, 0x4428, 0x443b, 0x444f, 0x4462, 0x4476, 0x4489, 0x449d, + 0x44b0, 0x44c4, 0x44d7, 0x44eb, 0x44fe, 0x4512, 0x4525, 0x4539, 0x454c, 0x4560, 0x4573, 0x4586, + 0x459a, 0x45ad, 0x45c1, 0x45d4, 0x45e8, 0x45fb, 0x460f, 0x4622, 0x4636, 0x4649, 0x465c, 0x4670, + 0x4683, 0x4697, 0x46aa, 0x46be, 0x46d1, 0x46e5, 0x46f8, 0x470b, 0x471f, 0x4732, 0x4746, 0x4759, + 0x476c, 0x4780, 0x4793, 0x47a7, 0x47ba, 0x47cd, 0x47e1, 0x47f4, 0x4808, 0x481b, 0x482e, 0x4842, + 0x4855, 0x4869, 0x487c, 0x488f, 0x48a3, 0x48b6, 0x48ca, 0x48dd, 0x48f0, 0x4904, 0x4917, 0x492a, + 0x493e, 0x4951, 0x4965, 0x4978, 0x498b, 0x499f, 0x49b2, 0x49c5, 0x49d9, 0x49ec, 0x49ff, 0x4a13, + 0x4a26, 0x4a39, 0x4a4d, 0x4a60, 0x4a73, 0x4a87, 0x4a9a, 0x4aad, 0x4ac1, 0x4ad4, 0x4ae7, 0x4afb, + 0x4b0e, 0x4b21, 0x4b35, 0x4b48, 0x4b5b, 0x4b6f, 0x4b82, 0x4b95, 0x4ba8, 0x4bbc, 0x4bcf, 0x4be2, + 0x4bf6, 0x4c09, 0x4c1c, 0x4c2f, 0x4c43, 0x4c56, 0x4c69, 0x4c7d, 0x4c90, 0x4ca3, 0x4cb6, 0x4cca, + 0x4cdd, 0x4cf0, 0x4d03, 0x4d17, 0x4d2a, 0x4d3d, 0x4d50, 0x4d64, 0x4d77, 0x4d8a, 0x4d9d, 0x4db1, + 0x4dc4, 0x4dd7, 0x4dea, 0x4dfe, 0x4e11, 0x4e24, 0x4e37, 0x4e4b, 0x4e5e, 0x4e71, 0x4e84, 0x4e97, + 0x4eab, 0x4ebe, 0x4ed1, 0x4ee4, 0x4ef7, 0x4f0b, 0x4f1e, 0x4f31, 0x4f44, 0x4f57, 0x4f6b, 0x4f7e, + 0x4f91, 0x4fa4, 0x4fb7, 0x4fcb, 0x4fde, 0x4ff1, 0x5004, 0x5017, 0x502a, 0x503e, 0x5051, 0x5064, + 0x5077, 0x508a, 0x509d, 0x50b1, 0x50c4, 0x50d7, 0x50ea, 0x50fd, 0x5110, 0x5123, 0x5137, 0x514a, + 0x515d, 0x5170, 0x5183, 0x5196, 0x51a9, 0x51bc, 0x51d0, 0x51e3, 0x51f6, 0x5209, 0x521c, 0x522f, + 0x5242, 0x5255, 0x5268, 0x527c, 0x528f, 0x52a2, 0x52b5, 0x52c8, 0x52db, 0x52ee, 0x5301, 0x5314, + 0x5327, 0x533a, 0x534e, 0x5361, 0x5374, 0x5387, 0x539a, 0x53ad, 0x53c0, 0x53d3, 0x53e6, 0x53f9, + 0x540c, 0x541f, 0x5432, 0x5445, 0x5458, 0x546b, 0x547e, 0x5491, 0x54a5, 0x54b8, 0x54cb, 0x54de, + 0x54f1, 0x5504, 0x5517, 0x552a, 0x553d, 0x5550, 0x5563, 0x5576, 0x5589, 0x559c, 0x55af, 0x55c2, + 0x55d5, 0x55e8, 0x55fb, 0x560e, 0x5621, 0x5634, 0x5647, 0x565a, 0x566d, 0x5680, 0x5693, 0x56a6, + 0x56b9, 0x56cb, 0x56de, 0x56f1, 0x5704, 0x5717, 0x572a, 0x573d, 0x5750, 0x5763, 0x5776, 0x5789, + 0x579c, 0x57af, 0x57c2, 0x57d5, 0x57e8, 0x57fb, 0x580e, 0x5820, 0x5833, 0x5846, 0x5859, 0x586c, + 0x587f, 0x5892, 0x58a5, 0x58b8, 0x58cb, 0x58de, 0x58f0, 0x5903, 0x5916, 0x5929, 0x593c, 0x594f, + 0x5962, 0x5975, 0x5988, 0x599a, 0x59ad, 0x59c0, 0x59d3, 0x59e6, 0x59f9, 0x5a0c, 0x5a1f, 0x5a31, + 0x5a44, 0x5a57, 0x5a6a, 0x5a7d, 0x5a90, 0x5aa2, 0x5ab5, 0x5ac8, 0x5adb, 0x5aee, 0x5b01, 0x5b13, + 0x5b26, 0x5b39, 0x5b4c, 0x5b5f, 0x5b72, 0x5b84, 0x5b97, 0x5baa, 0x5bbd, 0x5bd0, 0x5be2, 0x5bf5, + 0x5c08, 0x5c1b, 0x5c2e, 0x5c40, 0x5c53, 0x5c66, 0x5c79, 0x5c8c, 0x5c9e, 0x5cb1, 0x5cc4, 0x5cd7, + 0x5ce9, 0x5cfc, 0x5d0f, 0x5d22, 0x5d34, 0x5d47, 0x5d5a, 0x5d6d, 0x5d7f, 0x5d92, 0x5da5, 0x5db8, + 0x5dca, 0x5ddd, 0x5df0, 0x5e03, 0x5e15, 0x5e28, 0x5e3b, 0x5e4d, 0x5e60, 0x5e73, 0x5e86, 0x5e98, + 0x5eab, 0x5ebe, 0x5ed0, 0x5ee3, 0x5ef6, 0x5f09, 0x5f1b, 0x5f2e, 0x5f41, 0x5f53, 0x5f66, 0x5f79, + 0x5f8b, 0x5f9e, 0x5fb1, 0x5fc3, 0x5fd6, 0x5fe9, 0x5ffb, 0x600e, 0x6021, 0x6033, 0x6046, 0x6059, + 0x606b, 0x607e, 0x6091, 0x60a3, 0x60b6, 0x60c8, 0x60db, 0x60ee, 0x6100, 0x6113, 0x6126, 0x6138, + 0x614b, 0x615d, 0x6170, 0x6183, 0x6195, 0x61a8, 0x61ba, 0x61cd, 0x61e0, 0x61f2, 0x6205, 0x6217, + 0x622a, 0x623d, 0x624f, 0x6262, 0x6274, 0x6287, 0x6299, 0x62ac, 0x62bf, 0x62d1, 0x62e4, 0x62f6, + 0x6309, 0x631b, 0x632e, 0x6340, 0x6353, 0x6366, 0x6378, 0x638b, 0x639d, 0x63b0, 0x63c2, 0x63d5, + 0x63e7, 0x63fa, 0x640c, 0x641f, 0x6431, 0x6444, 0x6456, 0x6469, 0x647b, 0x648e, 0x64a0, 0x64b3, + 0x64c5, 0x64d8, 0x64ea, 0x64fd, 0x650f, 0x6522, 0x6534, 0x6547, 0x6559, 0x656c, 0x657e, 0x6591, + 0x65a3, 0x65b5, 0x65c8, 0x65da, 0x65ed, 0x65ff, 0x6612, 0x6624, 0x6637, 0x6649, 0x665b, 0x666e, + 0x6680, 0x6693, 0x66a5, 0x66b8, 0x66ca, 0x66dc, 0x66ef, 0x6701, 0x6714, 0x6726, 0x6738, 0x674b, + 0x675d, 0x6770, 0x6782, 0x6794, 0x67a7, 0x67b9, 0x67cc, 0x67de, 0x67f0, 0x6803, 0x6815, 0x6827, + 0x683a, 0x684c, 0x685e, 0x6871, 0x6883, 0x6896, 0x68a8, 0x68ba, 0x68cd, 0x68df, 0x68f1, 0x6904, + 0x6916, 0x6928, 0x693b, 0x694d, 0x695f, 0x6972, 0x6984, 0x6996, 0x69a8, 0x69bb, 0x69cd, 0x69df, + 0x69f2, 0x6a04, 0x6a16, 0x6a29, 0x6a3b, 0x6a4d, 0x6a5f, 0x6a72, 0x6a84, 0x6a96, 0x6aa9, 0x6abb, + 0x6acd, 0x6adf, 0x6af2, 0x6b04, 0x6b16, 0x6b28, 0x6b3b, 0x6b4d, 0x6b5f, 0x6b71, 0x6b84, 0x6b96, + 0x6ba8, 0x6bba, 0x6bcd, 0x6bdf, 0x6bf1, 0x6c03, 0x6c15, 0x6c28, 0x6c3a, 0x6c4c, 0x6c5e, 0x6c70, + 0x6c83, 0x6c95, 0x6ca7, 0x6cb9, 0x6ccb, 0x6cde, 0x6cf0, 0x6d02, 0x6d14, 0x6d26, 0x6d39, 0x6d4b, + 0x6d5d, 0x6d6f, 0x6d81, 0x6d93, 0x6da6, 0x6db8, 0x6dca, 0x6ddc, 0x6dee, 0x6e00, 0x6e12, 0x6e25, + 0x6e37, 0x6e49, 0x6e5b, 0x6e6d, 0x6e7f, 0x6e91, 0x6ea3, 0x6eb6, 0x6ec8, 0x6eda, 0x6eec, 0x6efe, + 0x6f10, 0x6f22, 0x6f34, 0x6f46, 0x6f58, 0x6f6b, 0x6f7d, 0x6f8f, 0x6fa1, 0x6fb3, 0x6fc5, 0x6fd7, + 0x6fe9, 0x6ffb, 0x700d, 0x701f, 0x7031, 0x7043, 0x7055, 0x7068, 0x707a, 0x708c, 0x709e, 0x70b0, + 0x70c2, 0x70d4, 0x70e6, 0x70f8, 0x710a, 0x711c, 0x712e, 0x7140, 0x7152, 0x7164, 0x7176, 0x7188, + 0x719a, 0x71ac, 0x71be, 0x71d0, 0x71e2, 0x71f4, 0x7206, 0x7218, 0x722a, 0x723c, 0x724e, 0x7260, + 0x7272, 0x7284, 0x7296, 0x72a8, 0x72ba, 0x72cc, 0x72dd, 0x72ef, 0x7301, 0x7313, 0x7325, 0x7337, + 0x7349, 0x735b, 0x736d, 0x737f, 0x7391, 0x73a3, 0x73b5, 0x73c7, 0x73d8, 0x73ea, 0x73fc, 0x740e, + 0x7420, 0x7432, 0x7444, 0x7456, 0x7468, 0x747a, 0x748b, 0x749d, 0x74af, 0x74c1, 0x74d3, 0x74e5, + 0x74f7, 0x7509, 0x751a, 0x752c, 0x753e, 0x7550, 0x7562, 0x7574, 0x7585, 0x7597, 0x75a9, 0x75bb, + 0x75cd, 0x75df, 0x75f0, 0x7602, 0x7614, 0x7626, 0x7638, 0x764a, 0x765b, 0x766d, 0x767f, 0x7691, + 0x76a3, 0x76b4, 0x76c6, 0x76d8, 0x76ea, 0x76fb, 0x770d, 0x771f, 0x7731, 0x7743, 0x7754, 0x7766, + 0x7778, 0x778a, 0x779b, 0x77ad, 0x77bf, 0x77d1, 0x77e2, 0x77f4, 0x7806, 0x7818, 0x7829, 0x783b, + 0x784d, 0x785e, 0x7870, 0x7882, 0x7894, 0x78a5, 0x78b7, 0x78c9, 0x78da, 0x78ec, 0x78fe, 0x7910, + 0x7921, 0x7933, 0x7945, 0x7956, 0x7968, 0x797a, 0x798b, 0x799d, 0x79af, 0x79c0, 0x79d2, 0x79e4, + 0x79f5, 0x7a07, 0x7a19, 0x7a2a, 0x7a3c, 0x7a4e, 0x7a5f, 0x7a71, 0x7a82, 0x7a94, 0x7aa6, 0x7ab7, + 0x7ac9, 0x7adb, 0x7aec, 0x7afe, 0x7b0f, 0x7b21, 0x7b33, 0x7b44, 0x7b56, 0x7b67, 0x7b79, 0x7b8b, + 0x7b9c, 0x7bae, 0x7bbf, 0x7bd1, 0x7be2, 0x7bf4, 0x7c06, 0x7c17, 0x7c29, 0x7c3a, 0x7c4c, 0x7c5d, + 0x7c6f, 0x7c81, 0x7c92, 0x7ca4, 0x7cb5, 0x7cc7, 0x7cd8, 0x7cea, 0x7cfb, 0x7d0d, 0x7d1e, 0x7d30, + 0x7d41, 0x7d53, 0x7d64, 0x7d76, 0x7d87, 0x7d99, 0x7daa, 0x7dbc, 0x7dcd, 0x7ddf, 0x7df0, 0x7e02, + 0x7e13, 0x7e25, 0x7e36, 0x7e48, 0x7e59, 0x7e6b, 0x7e7c, 0x7e8e, 0x7e9f, 0x7eb0, 0x7ec2, 0x7ed3, + 0x7ee5, 0x7ef6, 0x7f08, 0x7f19, 0x7f2b, 0x7f3c, 0x7f4d, 0x7f5f, 0x7f70, 0x7f82, 0x7f93, 0x7fa4, + 0x7fb6, 0x7fc7, 0x7fd9, 0x7fea, 0x7ffb, 0x800d, 0x801e, 0x8030, 0x8041, 0x8052, 0x8064, 0x8075, + 0x8086, 0x8098, 0x80a9, 0x80bb, 0x80cc, 0x80dd, 0x80ef, 0x8100, 0x8111, 0x8123, 0x8134, 0x8145, + 0x8157, 0x8168, 0x8179, 0x818b, 0x819c, 0x81ad, 0x81bf, 0x81d0, 0x81e1, 0x81f3, 0x8204, 0x8215, + 0x8226, 0x8238, 0x8249, 0x825a, 0x826c, 0x827d, 0x828e, 0x829f, 0x82b1, 0x82c2, 0x82d3, 0x82e5, + 0x82f6, 0x8307, 0x8318, 0x832a, 0x833b, 0x834c, 0x835d, 0x836f, 0x8380, 0x8391, 0x83a2, 0x83b3, + 0x83c5, 0x83d6, 0x83e7, 0x83f8, 0x840a, 0x841b, 0x842c, 0x843d, 0x844e, 0x8460, 0x8471, 0x8482, + 0x8493, 0x84a4, 0x84b6, 0x84c7, 0x84d8, 0x84e9, 0x84fa, 0x850b, 0x851d, 0x852e, 0x853f, 0x8550, + 0x8561, 0x8572, 0x8584, 0x8595, 0x85a6, 0x85b7, 0x85c8, 0x85d9, 0x85ea, 0x85fb, 0x860d, 0x861e, + 0x862f, 0x8640, 0x8651, 0x8662, 0x8673, 0x8684, 0x8695, 0x86a7, 0x86b8, 0x86c9, 0x86da, 0x86eb, + 0x86fc, 0x870d, 0x871e, 0x872f, 0x8740, 0x8751, 0x8762, 0x8773, 0x8784, 0x8796, 0x87a7, 0x87b8, + 0x87c9, 0x87da, 0x87eb, 0x87fc, 0x880d, 0x881e, 0x882f, 0x8840, 0x8851, 0x8862, 0x8873, 0x8884, + 0x8895, 0x88a6, 0x88b7, 0x88c8, 0x88d9, 0x88ea, 0x88fb, 0x890c, 0x891d, 0x892e, 0x893f, 0x8950, + 0x8961, 0x8972, 0x8983, 0x8994, 0x89a5, 0x89b6, 0x89c6, 0x89d7, 0x89e8, 0x89f9, 0x8a0a, 0x8a1b, + 0x8a2c, 0x8a3d, 0x8a4e, 0x8a5f, 0x8a70, 0x8a81, 0x8a92, 0x8aa3, 0x8ab3, 0x8ac4, 0x8ad5, 0x8ae6, + 0x8af7, 0x8b08, 0x8b19, 0x8b2a, 0x8b3b, 0x8b4b, 0x8b5c, 0x8b6d, 0x8b7e, 0x8b8f, 0x8ba0, 0x8bb1, + 0x8bc1, 0x8bd2, 0x8be3, 0x8bf4, 0x8c05, 0x8c16, 0x8c27, 0x8c37, 0x8c48, 0x8c59, 0x8c6a, 0x8c7b, + 0x8c8c, 0x8c9c, 0x8cad, 0x8cbe, 0x8ccf, 0x8ce0, 0x8cf0, 0x8d01, 0x8d12, 0x8d23, 0x8d34, 0x8d44, + 0x8d55, 0x8d66, 0x8d77, 0x8d87, 0x8d98, 0x8da9, 0x8dba, 0x8dca, 0x8ddb, 0x8dec, 0x8dfd, 0x8e0d, + 0x8e1e, 0x8e2f, 0x8e40, 0x8e50, 0x8e61, 0x8e72, 0x8e83, 0x8e93, 0x8ea4, 0x8eb5, 0x8ec5, 0x8ed6, + 0x8ee7, 0x8ef8, 0x8f08, 0x8f19, 0x8f2a, 0x8f3a, 0x8f4b, 0x8f5c, 0x8f6c, 0x8f7d, 0x8f8e, 0x8f9e, + 0x8faf, 0x8fc0, 0x8fd0, 0x8fe1, 0x8ff2, 0x9002, 0x9013, 0x9024, 0x9034, 0x9045, 0x9056, 0x9066, + 0x9077, 0x9088, 0x9098, 0x90a9, 0x90b9, 0x90ca, 0x90db, 0x90eb, 0x90fc, 0x910c, 0x911d, 0x912e, + 0x913e, 0x914f, 0x915f, 0x9170, 0x9181, 0x9191, 0x91a2, 0x91b2, 0x91c3, 0x91d3, 0x91e4, 0x91f5, + 0x9205, 0x9216, 0x9226, 0x9237, 0x9247, 0x9258, 0x9268, 0x9279, 0x9289, 0x929a, 0x92aa, 0x92bb, + 0x92cc, 0x92dc, 0x92ed, 0x92fd, 0x930e, 0x931e, 0x932f, 0x933f, 0x9350, 0x9360, 0x9370, 0x9381, + 0x9391, 0x93a2, 0x93b2, 0x93c3, 0x93d3, 0x93e4, 0x93f4, 0x9405, 0x9415, 0x9426, 0x9436, 0x9447, + 0x9457, 0x9467, 0x9478, 0x9488, 0x9499, 0x94a9, 0x94ba, 0x94ca, 0x94da, 0x94eb, 0x94fb, 0x950c, + 0x951c, 0x952c, 0x953d, 0x954d, 0x955e, 0x956e, 0x957e, 0x958f, 0x959f, 0x95af, 0x95c0, 0x95d0, + 0x95e1, 0x95f1, 0x9601, 0x9612, 0x9622, 0x9632, 0x9643, 0x9653, 0x9663, 0x9674, 0x9684, 0x9694, + 0x96a5, 0x96b5, 0x96c5, 0x96d6, 0x96e6, 0x96f6, 0x9707, 0x9717, 0x9727, 0x9738, 0x9748, 0x9758, + 0x9768, 0x9779, 0x9789, 0x9799, 0x97aa, 0x97ba, 0x97ca, 0x97da, 0x97eb, 0x97fb, 0x980b, 0x981b, + 0x982c, 0x983c, 0x984c, 0x985c, 0x986d, 0x987d, 0x988d, 0x989d, 0x98ad, 0x98be, 0x98ce, 0x98de, + 0x98ee, 0x98ff, 0x990f, 0x991f, 0x992f, 0x993f, 0x9950, 0x9960, 0x9970, 0x9980, 0x9990, 0x99a0, + 0x99b1, 0x99c1, 0x99d1, 0x99e1, 0x99f1, 0x9a01, 0x9a12, 0x9a22, 0x9a32, 0x9a42, 0x9a52, 0x9a62, + 0x9a72, 0x9a83, 0x9a93, 0x9aa3, 0x9ab3, 0x9ac3, 0x9ad3, 0x9ae3, 0x9af3, 0x9b04, 0x9b14, 0x9b24, + 0x9b34, 0x9b44, 0x9b54, 0x9b64, 0x9b74, 0x9b84, 0x9b94, 0x9ba4, 0x9bb5, 0x9bc5, 0x9bd5, 0x9be5, + 0x9bf5, 0x9c05, 0x9c15, 0x9c25, 0x9c35, 0x9c45, 0x9c55, 0x9c65, 0x9c75, 0x9c85, 0x9c95, 0x9ca5, + 0x9cb5, 0x9cc5, 0x9cd5, 0x9ce5, 0x9cf5, 0x9d05, 0x9d15, 0x9d25, 0x9d35, 0x9d45, 0x9d55, 0x9d65, + 0x9d75, 0x9d85, 0x9d95, 0x9da5, 0x9db5, 0x9dc5, 0x9dd5, 0x9de5, 0x9df5, 0x9e05, 0x9e15, 0x9e25, + 0x9e35, 0x9e45, 0x9e55, 0x9e65, 0x9e74, 0x9e84, 0x9e94, 0x9ea4, 0x9eb4, 0x9ec4, 0x9ed4, 0x9ee4, + 0x9ef4, 0x9f04, 0x9f14, 0x9f23, 0x9f33, 0x9f43, 0x9f53, 0x9f63, 0x9f73, 0x9f83, 0x9f93, 0x9fa3, + 0x9fb2, 0x9fc2, 0x9fd2, 0x9fe2, 0x9ff2, 0xa002, 0xa012, 0xa021, 0xa031, 0xa041, 0xa051, 0xa061, + 0xa071, 0xa080, 0xa090, 0xa0a0, 0xa0b0, 0xa0c0, 0xa0cf, 0xa0df, 0xa0ef, 0xa0ff, 0xa10f, 0xa11e, + 0xa12e, 0xa13e, 0xa14e, 0xa15e, 0xa16d, 0xa17d, 0xa18d, 0xa19d, 0xa1ac, 0xa1bc, 0xa1cc, 0xa1dc, + 0xa1eb, 0xa1fb, 0xa20b, 0xa21b, 0xa22a, 0xa23a, 0xa24a, 0xa25a, 0xa269, 0xa279, 0xa289, 0xa298, + 0xa2a8, 0xa2b8, 0xa2c8, 0xa2d7, 0xa2e7, 0xa2f7, 0xa306, 0xa316, 0xa326, 0xa335, 0xa345, 0xa355, + 0xa364, 0xa374, 0xa384, 0xa393, 0xa3a3, 0xa3b3, 0xa3c2, 0xa3d2, 0xa3e2, 0xa3f1, 0xa401, 0xa411, + 0xa420, 0xa430, 0xa440, 0xa44f, 0xa45f, 0xa46e, 0xa47e, 0xa48e, 0xa49d, 0xa4ad, 0xa4bc, 0xa4cc, + 0xa4dc, 0xa4eb, 0xa4fb, 0xa50a, 0xa51a, 0xa52a, 0xa539, 0xa549, 0xa558, 0xa568, 0xa577, 0xa587, + 0xa597, 0xa5a6, 0xa5b6, 0xa5c5, 0xa5d5, 0xa5e4, 0xa5f4, 0xa603, 0xa613, 0xa622, 0xa632, 0xa641, + 0xa651, 0xa660, 0xa670, 0xa67f, 0xa68f, 0xa69e, 0xa6ae, 0xa6bd, 0xa6cd, 0xa6dc, 0xa6ec, 0xa6fb, + 0xa70b, 0xa71a, 0xa72a, 0xa739, 0xa749, 0xa758, 0xa768, 0xa777, 0xa787, 0xa796, 0xa7a5, 0xa7b5, + 0xa7c4, 0xa7d4, 0xa7e3, 0xa7f3, 0xa802, 0xa812, 0xa821, 0xa830, 0xa840, 0xa84f, 0xa85f, 0xa86e, + 0xa87d, 0xa88d, 0xa89c, 0xa8ac, 0xa8bb, 0xa8ca, 0xa8da, 0xa8e9, 0xa8f8, 0xa908, 0xa917, 0xa927, + 0xa936, 0xa945, 0xa955, 0xa964, 0xa973, 0xa983, 0xa992, 0xa9a1, 0xa9b1, 0xa9c0, 0xa9cf, 0xa9df, + 0xa9ee, 0xa9fd, 0xaa0d, 0xaa1c, 0xaa2b, 0xaa3b, 0xaa4a, 0xaa59, 0xaa69, 0xaa78, 0xaa87, 0xaa96, + 0xaaa6, 0xaab5, 0xaac4, 0xaad4, 0xaae3, 0xaaf2, 0xab01, 0xab11, 0xab20, 0xab2f, 0xab3e, 0xab4e, + 0xab5d, 0xab6c, 0xab7b, 0xab8b, 0xab9a, 0xaba9, 0xabb8, 0xabc7, 0xabd7, 0xabe6, 0xabf5, 0xac04, + 0xac14, 0xac23, 0xac32, 0xac41, 0xac50, 0xac60, 0xac6f, 0xac7e, 0xac8d, 0xac9c, 0xacab, 0xacbb, + 0xacca, 0xacd9, 0xace8, 0xacf7, 0xad06, 0xad16, 0xad25, 0xad34, 0xad43, 0xad52, 0xad61, 0xad70, + 0xad80, 0xad8f, 0xad9e, 0xadad, 0xadbc, 0xadcb, 0xadda, 0xade9, 0xadf8, 0xae08, 0xae17, 0xae26, + 0xae35, 0xae44, 0xae53, 0xae62, 0xae71, 0xae80, 0xae8f, 0xae9e, 0xaead, 0xaebd, 0xaecc, 0xaedb, + 0xaeea, 0xaef9, 0xaf08, 0xaf17, 0xaf26, 0xaf35, 0xaf44, 0xaf53, 0xaf62, 0xaf71, 0xaf80, 0xaf8f, + 0xaf9e, 0xafad, 0xafbc, 0xafcb, 0xafda, 0xafe9, 0xaff8, 0xb007, 0xb016, 0xb025, 0xb034, 0xb043, + 0xb052, 0xb061, 0xb070, 0xb07f, 0xb08e, 0xb09d, 0xb0ac, 0xb0bb, 0xb0ca, 0xb0d9, 0xb0e8, 0xb0f6, + 0xb105, 0xb114, 0xb123, 0xb132, 0xb141, 0xb150, 0xb15f, 0xb16e, 0xb17d, 0xb18c, 0xb19b, 0xb1aa, + 0xb1b8, 0xb1c7, 0xb1d6, 0xb1e5, 0xb1f4, 0xb203, 0xb212, 0xb221, 0xb22f, 0xb23e, 0xb24d, 0xb25c, + 0xb26b, 0xb27a, 0xb289, 0xb297, 0xb2a6, 0xb2b5, 0xb2c4, 0xb2d3, 0xb2e2, 0xb2f1, 0xb2ff, 0xb30e, + 0xb31d, 0xb32c, 0xb33b, 0xb349, 0xb358, 0xb367, 0xb376, 0xb385, 0xb393, 0xb3a2, 0xb3b1, 0xb3c0, + 0xb3cf, 0xb3dd, 0xb3ec, 0xb3fb, 0xb40a, 0xb418, 0xb427, 0xb436, 0xb445, 0xb453, 0xb462, 0xb471, + 0xb480, 0xb48e, 0xb49d, 0xb4ac, 0xb4bb, 0xb4c9, 0xb4d8, 0xb4e7, 0xb4f6, 0xb504, 0xb513, 0xb522, + 0xb530, 0xb53f, 0xb54e, 0xb55c, 0xb56b, 0xb57a, 0xb588, 0xb597, 0xb5a6, 0xb5b5, 0xb5c3, 0xb5d2, + 0xb5e1, 0xb5ef, 0xb5fe, 0xb60d, 0xb61b, 0xb62a, 0xb638, 0xb647, 0xb656, 0xb664, 0xb673, 0xb682, + 0xb690, 0xb69f, 0xb6ae, 0xb6bc, 0xb6cb, 0xb6d9, 0xb6e8, 0xb6f7, 0xb705, 0xb714, 0xb722, 0xb731, + 0xb740, 0xb74e, 0xb75d, 0xb76b, 0xb77a, 0xb788, 0xb797, 0xb7a6, 0xb7b4, 0xb7c3, 0xb7d1, 0xb7e0, + 0xb7ee, 0xb7fd, 0xb80b, 0xb81a, 0xb829, 0xb837, 0xb846, 0xb854, 0xb863, 0xb871, 0xb880, 0xb88e, + 0xb89d, 0xb8ab, 0xb8ba, 0xb8c8, 0xb8d7, 0xb8e5, 0xb8f4, 0xb902, 0xb911, 0xb91f, 0xb92e, 0xb93c, + 0xb94b, 0xb959, 0xb968, 0xb976, 0xb984, 0xb993, 0xb9a1, 0xb9b0, 0xb9be, 0xb9cd, 0xb9db, 0xb9ea, + 0xb9f8, 0xba06, 0xba15, 0xba23, 0xba32, 0xba40, 0xba4f, 0xba5d, 0xba6b, 0xba7a, 0xba88, 0xba97, + 0xbaa5, 0xbab3, 0xbac2, 0xbad0, 0xbade, 0xbaed, 0xbafb, 0xbb0a, 0xbb18, 0xbb26, 0xbb35, 0xbb43, + 0xbb51, 0xbb60, 0xbb6e, 0xbb7c, 0xbb8b, 0xbb99, 0xbba8, 0xbbb6, 0xbbc4, 0xbbd3, 0xbbe1, 0xbbef, + 0xbbfd, 0xbc0c, 0xbc1a, 0xbc28, 0xbc37, 0xbc45, 0xbc53, 0xbc62, 0xbc70, 0xbc7e, 0xbc8c, 0xbc9b, + 0xbca9, 0xbcb7, 0xbcc6, 0xbcd4, 0xbce2, 0xbcf0, 0xbcff, 0xbd0d, 0xbd1b, 0xbd29, 0xbd38, 0xbd46, + 0xbd54, 0xbd62, 0xbd71, 0xbd7f, 0xbd8d, 0xbd9b, 0xbdaa, 0xbdb8, 0xbdc6, 0xbdd4, 0xbde2, 0xbdf1, + 0xbdff, 0xbe0d, 0xbe1b, 0xbe29, 0xbe38, 0xbe46, 0xbe54, 0xbe62, 0xbe70, 0xbe7f, 0xbe8d, 0xbe9b, + 0xbea9, 0xbeb7, 0xbec5, 0xbed4, 0xbee2, 0xbef0, 0xbefe, 0xbf0c, 0xbf1a, 0xbf28, 0xbf37, 0xbf45, + 0xbf53, 0xbf61, 0xbf6f, 0xbf7d, 0xbf8b, 0xbf99, 0xbfa7, 0xbfb6, 0xbfc4, 0xbfd2, 0xbfe0, 0xbfee, + 0xbffc, 0xc00a, 0xc018, 0xc026, 0xc034, 0xc042, 0xc051, 0xc05f, 0xc06d, 0xc07b, 0xc089, 0xc097, + 0xc0a5, 0xc0b3, 0xc0c1, 0xc0cf, 0xc0dd, 0xc0eb, 0xc0f9, 0xc107, 0xc115, 0xc123, 0xc131, 0xc13f, + 0xc14d, 0xc15b, 0xc169, 0xc177, 0xc185, 0xc193, 0xc1a1, 0xc1af, 0xc1bd, 0xc1cb, 0xc1d9, 0xc1e7, + 0xc1f5, 0xc203, 0xc211, 0xc21f, 0xc22d, 0xc23b, 0xc249, 0xc257, 0xc265, 0xc273, 0xc281, 0xc28f, + 0xc29d, 0xc2ab, 0xc2b8, 0xc2c6, 0xc2d4, 0xc2e2, 0xc2f0, 0xc2fe, 0xc30c, 0xc31a, 0xc328, 0xc336, + 0xc344, 0xc352, 0xc35f, 0xc36d, 0xc37b, 0xc389, 0xc397, 0xc3a5, 0xc3b3, 0xc3c1, 0xc3ce, 0xc3dc, + 0xc3ea, 0xc3f8, 0xc406, 0xc414, 0xc422, 0xc42f, 0xc43d, 0xc44b, 0xc459, 0xc467, 0xc475, 0xc482, + 0xc490, 0xc49e, 0xc4ac, 0xc4ba, 0xc4c7, 0xc4d5, 0xc4e3, 0xc4f1, 0xc4ff, 0xc50d, 0xc51a, 0xc528, + 0xc536, 0xc544, 0xc551, 0xc55f, 0xc56d, 0xc57b, 0xc589, 0xc596, 0xc5a4, 0xc5b2, 0xc5c0, 0xc5cd, + 0xc5db, 0xc5e9, 0xc5f7, 0xc604, 0xc612, 0xc620, 0xc62d, 0xc63b, 0xc649, 0xc657, 0xc664, 0xc672, + 0xc680, 0xc68d, 0xc69b, 0xc6a9, 0xc6b7, 0xc6c4, 0xc6d2, 0xc6e0, 0xc6ed, 0xc6fb, 0xc709, 0xc716, + 0xc724, 0xc732, 0xc73f, 0xc74d, 0xc75b, 0xc768, 0xc776, 0xc784, 0xc791, 0xc79f, 0xc7ad, 0xc7ba, + 0xc7c8, 0xc7d6, 0xc7e3, 0xc7f1, 0xc7fe, 0xc80c, 0xc81a, 0xc827, 0xc835, 0xc842, 0xc850, 0xc85e, + 0xc86b, 0xc879, 0xc886, 0xc894, 0xc8a2, 0xc8af, 0xc8bd, 0xc8ca, 0xc8d8, 0xc8e5, 0xc8f3, 0xc901, + 0xc90e, 0xc91c, 0xc929, 0xc937, 0xc944, 0xc952, 0xc95f, 0xc96d, 0xc97b, 0xc988, 0xc996, 0xc9a3, + 0xc9b1, 0xc9be, 0xc9cc, 0xc9d9, 0xc9e7, 0xc9f4, 0xca02, 0xca0f, 0xca1d, 0xca2a, 0xca38, 0xca45, + 0xca53, 0xca60, 0xca6e, 0xca7b, 0xca89, 0xca96, 0xcaa4, 0xcab1, 0xcabe, 0xcacc, 0xcad9, 0xcae7, + 0xcaf4, 0xcb02, 0xcb0f, 0xcb1d, 0xcb2a, 0xcb37, 0xcb45, 0xcb52, 0xcb60, 0xcb6d, 0xcb7b, 0xcb88, + 0xcb95, 0xcba3, 0xcbb0, 0xcbbe, 0xcbcb, 0xcbd8, 0xcbe6, 0xcbf3, 0xcc01, 0xcc0e, 0xcc1b, 0xcc29, + 0xcc36, 0xcc43, 0xcc51, 0xcc5e, 0xcc6c, 0xcc79, 0xcc86, 0xcc94, 0xcca1, 0xccae, 0xccbc, 0xccc9, + 0xccd6, 0xcce4, 0xccf1, 0xccfe, 0xcd0c, 0xcd19, 0xcd26, 0xcd34, 0xcd41, 0xcd4e, 0xcd5b, 0xcd69, + 0xcd76, 0xcd83, 0xcd91, 0xcd9e, 0xcdab, 0xcdb9, 0xcdc6, 0xcdd3, 0xcde0, 0xcdee, 0xcdfb, 0xce08, + 0xce15, 0xce23, 0xce30, 0xce3d, 0xce4a, 0xce58, 0xce65, 0xce72, 0xce7f, 0xce8d, 0xce9a, 0xcea7, + 0xceb4, 0xcec2, 0xcecf, 0xcedc, 0xcee9, 0xcef6, 0xcf04, 0xcf11, 0xcf1e, 0xcf2b, 0xcf38, 0xcf46, + 0xcf53, 0xcf60, 0xcf6d, 0xcf7a, 0xcf87, 0xcf95, 0xcfa2, 0xcfaf, 0xcfbc, 0xcfc9, 0xcfd6, 0xcfe4, + 0xcff1, 0xcffe, 0xd00b, 0xd018, 0xd025, 0xd032, 0xd040, 0xd04d, 0xd05a, 0xd067, 0xd074, 0xd081, + 0xd08e, 0xd09b, 0xd0a9, 0xd0b6, 0xd0c3, 0xd0d0, 0xd0dd, 0xd0ea, 0xd0f7, 0xd104, 0xd111, 0xd11e, + 0xd12b, 0xd139, 0xd146, 0xd153, 0xd160, 0xd16d, 0xd17a, 0xd187, 0xd194, 0xd1a1, 0xd1ae, 0xd1bb, + 0xd1c8, 0xd1d5, 0xd1e2, 0xd1ef, 0xd1fc, 0xd209, 0xd216, 0xd223, 0xd230, 0xd23d, 0xd24a, 0xd257, + 0xd264, 0xd271, 0xd27e, 0xd28b, 0xd298, 0xd2a5, 0xd2b2, 0xd2bf, 0xd2cc, 0xd2d9, 0xd2e6, 0xd2f3, + 0xd300, 0xd30d, 0xd31a, 0xd327, 0xd334, 0xd341, 0xd34e, 0xd35b, 0xd368, 0xd375, 0xd382, 0xd38f, + 0xd39c, 0xd3a8, 0xd3b5, 0xd3c2, 0xd3cf, 0xd3dc, 0xd3e9, 0xd3f6, 0xd403, 0xd410, 0xd41d, 0xd42a, + 0xd436, 0xd443, 0xd450, 0xd45d, 0xd46a, 0xd477, 0xd484, 0xd491, 0xd49e, 0xd4aa, 0xd4b7, 0xd4c4, + 0xd4d1, 0xd4de, 0xd4eb, 0xd4f8, 0xd504, 0xd511, 0xd51e, 0xd52b, 0xd538, 0xd545, 0xd551, 0xd55e, + 0xd56b, 0xd578, 0xd585, 0xd591, 0xd59e, 0xd5ab, 0xd5b8, 0xd5c5, 0xd5d1, 0xd5de, 0xd5eb, 0xd5f8, + 0xd605, 0xd611, 0xd61e, 0xd62b, 0xd638, 0xd645, 0xd651, 0xd65e, 0xd66b, 0xd678, 0xd684, 0xd691, + 0xd69e, 0xd6ab, 0xd6b7, 0xd6c4, 0xd6d1, 0xd6de, 0xd6ea, 0xd6f7, 0xd704, 0xd710, 0xd71d, 0xd72a, + 0xd737, 0xd743, 0xd750, 0xd75d, 0xd769, 0xd776, 0xd783, 0xd78f, 0xd79c, 0xd7a9, 0xd7b6, 0xd7c2, + 0xd7cf, 0xd7dc, 0xd7e8, 0xd7f5, 0xd802, 0xd80e, 0xd81b, 0xd828, 0xd834, 0xd841, 0xd84e, 0xd85a, + 0xd867, 0xd873, 0xd880, 0xd88d, 0xd899, 0xd8a6, 0xd8b3, 0xd8bf, 0xd8cc, 0xd8d8, 0xd8e5, 0xd8f2, + 0xd8fe, 0xd90b, 0xd917, 0xd924, 0xd931, 0xd93d, 0xd94a, 0xd956, 0xd963, 0xd970, 0xd97c, 0xd989, + 0xd995, 0xd9a2, 0xd9ae, 0xd9bb, 0xd9c8, 0xd9d4, 0xd9e1, 0xd9ed, 0xd9fa, 0xda06, 0xda13, 0xda1f, + 0xda2c, 0xda38, 0xda45, 0xda51, 0xda5e, 0xda6a, 0xda77, 0xda84, 0xda90, 0xda9d, 0xdaa9, 0xdab6, + 0xdac2, 0xdacf, 0xdadb, 0xdae7, 0xdaf4, 0xdb00, 0xdb0d, 0xdb19, 0xdb26, 0xdb32, 0xdb3f, 0xdb4b, + 0xdb58, 0xdb64, 0xdb71, 0xdb7d, 0xdb8a, 0xdb96, 0xdba2, 0xdbaf, 0xdbbb, 0xdbc8, 0xdbd4, 0xdbe1, + 0xdbed, 0xdbf9, 0xdc06, 0xdc12, 0xdc1f, 0xdc2b, 0xdc38, 0xdc44, 0xdc50, 0xdc5d, 0xdc69, 0xdc76, + 0xdc82, 0xdc8e, 0xdc9b, 0xdca7, 0xdcb3, 0xdcc0, 0xdccc, 0xdcd9, 0xdce5, 0xdcf1, 0xdcfe, 0xdd0a, + 0xdd16, 0xdd23, 0xdd2f, 0xdd3b, 0xdd48, 0xdd54, 0xdd60, 0xdd6d, 0xdd79, 0xdd85, 0xdd92, 0xdd9e, + 0xddaa, 0xddb7, 0xddc3, 0xddcf, 0xdddc, 0xdde8, 0xddf4, 0xde01, 0xde0d, 0xde19, 0xde25, 0xde32, + 0xde3e, 0xde4a, 0xde57, 0xde63, 0xde6f, 0xde7b, 0xde88, 0xde94, 0xdea0, 0xdeac, 0xdeb9, 0xdec5, + 0xded1, 0xdedd, 0xdeea, 0xdef6, 0xdf02, 0xdf0e, 0xdf1b, 0xdf27, 0xdf33, 0xdf3f, 0xdf4c, 0xdf58, + 0xdf64, 0xdf70, 0xdf7c, 0xdf89, 0xdf95, 0xdfa1, 0xdfad, 0xdfb9, 0xdfc6, 0xdfd2, 0xdfde, 0xdfea, + 0xdff6, 0xe003, 0xe00f, 0xe01b, 0xe027, 0xe033, 0xe03f, 0xe04c, 0xe058, 0xe064, 0xe070, 0xe07c, + 0xe088, 0xe094, 0xe0a1, 0xe0ad, 0xe0b9, 0xe0c5, 0xe0d1, 0xe0dd, 0xe0e9, 0xe0f5, 0xe102, 0xe10e, + 0xe11a, 0xe126, 0xe132, 0xe13e, 0xe14a, 0xe156, 0xe162, 0xe16e, 0xe17b, 0xe187, 0xe193, 0xe19f, + 0xe1ab, 0xe1b7, 0xe1c3, 0xe1cf, 0xe1db, 0xe1e7, 0xe1f3, 0xe1ff, 0xe20b, 0xe217, 0xe223, 0xe22f, + 0xe23c, 0xe248, 0xe254, 0xe260, 0xe26c, 0xe278, 0xe284, 0xe290, 0xe29c, 0xe2a8, 0xe2b4, 0xe2c0, + 0xe2cc, 0xe2d8, 0xe2e4, 0xe2f0, 0xe2fc, 0xe308, 0xe314, 0xe320, 0xe32c, 0xe338, 0xe344, 0xe350, + 0xe35c, 0xe368, 0xe374, 0xe380, 0xe38b, 0xe397, 0xe3a3, 0xe3af, 0xe3bb, 0xe3c7, 0xe3d3, 0xe3df, + 0xe3eb, 0xe3f7, 0xe403, 0xe40f, 0xe41b, 0xe427, 0xe433, 0xe43f, 0xe44a, 0xe456, 0xe462, 0xe46e, + 0xe47a, 0xe486, 0xe492, 0xe49e, 0xe4aa, 0xe4b6, 0xe4c1, 0xe4cd, 0xe4d9, 0xe4e5, 0xe4f1, 0xe4fd, + 0xe509, 0xe515, 0xe520, 0xe52c, 0xe538, 0xe544, 0xe550, 0xe55c, 0xe567, 0xe573, 0xe57f, 0xe58b, + 0xe597, 0xe5a3, 0xe5af, 0xe5ba, 0xe5c6, 0xe5d2, 0xe5de, 0xe5ea, 0xe5f5, 0xe601, 0xe60d, 0xe619, + 0xe625, 0xe630, 0xe63c, 0xe648, 0xe654, 0xe660, 0xe66b, 0xe677, 0xe683, 0xe68f, 0xe69a, 0xe6a6, + 0xe6b2, 0xe6be, 0xe6ca, 0xe6d5, 0xe6e1, 0xe6ed, 0xe6f9, 0xe704, 0xe710, 0xe71c, 0xe727, 0xe733, + 0xe73f, 0xe74b, 0xe756, 0xe762, 0xe76e, 0xe77a, 0xe785, 0xe791, 0xe79d, 0xe7a8, 0xe7b4, 0xe7c0, + 0xe7cb, 0xe7d7, 0xe7e3, 0xe7ef, 0xe7fa, 0xe806, 0xe812, 0xe81d, 0xe829, 0xe835, 0xe840, 0xe84c, + 0xe858, 0xe863, 0xe86f, 0xe87b, 0xe886, 0xe892, 0xe89e, 0xe8a9, 0xe8b5, 0xe8c0, 0xe8cc, 0xe8d8, + 0xe8e3, 0xe8ef, 0xe8fb, 0xe906, 0xe912, 0xe91d, 0xe929, 0xe935, 0xe940, 0xe94c, 0xe958, 0xe963, + 0xe96f, 0xe97a, 0xe986, 0xe991, 0xe99d, 0xe9a9, 0xe9b4, 0xe9c0, 0xe9cb, 0xe9d7, 0xe9e3, 0xe9ee, + 0xe9fa, 0xea05, 0xea11, 0xea1c, 0xea28, 0xea33, 0xea3f, 0xea4a, 0xea56, 0xea62, 0xea6d, 0xea79, + 0xea84, 0xea90, 0xea9b, 0xeaa7, 0xeab2, 0xeabe, 0xeac9, 0xead5, 0xeae0, 0xeaec, 0xeaf7, 0xeb03, + 0xeb0e, 0xeb1a, 0xeb25, 0xeb31, 0xeb3c, 0xeb48, 0xeb53, 0xeb5f, 0xeb6a, 0xeb76, 0xeb81, 0xeb8d, + 0xeb98, 0xeba3, 0xebaf, 0xebba, 0xebc6, 0xebd1, 0xebdd, 0xebe8, 0xebf4, 0xebff, 0xec0a, 0xec16, + 0xec21, 0xec2d, 0xec38, 0xec44, 0xec4f, 0xec5a, 0xec66, 0xec71, 0xec7d, 0xec88, 0xec93, 0xec9f, + 0xecaa, 0xecb6, 0xecc1, 0xeccc, 0xecd8, 0xece3, 0xecef, 0xecfa, 0xed05, 0xed11, 0xed1c, 0xed27, + 0xed33, 0xed3e, 0xed4a, 0xed55, 0xed60, 0xed6c, 0xed77, 0xed82, 0xed8e, 0xed99, 0xeda4, 0xedb0, + 0xedbb, 0xedc6, 0xedd2, 0xeddd, 0xede8, 0xedf4, 0xedff, 0xee0a, 0xee15, 0xee21, 0xee2c, 0xee37, + 0xee43, 0xee4e, 0xee59, 0xee65, 0xee70, 0xee7b, 0xee86, 0xee92, 0xee9d, 0xeea8, 0xeeb3, 0xeebf, + 0xeeca, 0xeed5, 0xeee1, 0xeeec, 0xeef7, 0xef02, 0xef0e, 0xef19, 0xef24, 0xef2f, 0xef3a, 0xef46, + 0xef51, 0xef5c, 0xef67, 0xef73, 0xef7e, 0xef89, 0xef94, 0xef9f, 0xefab, 0xefb6, 0xefc1, 0xefcc, + 0xefd7, 0xefe3, 0xefee, 0xeff9, 0xf004, 0xf00f, 0xf01b, 0xf026, 0xf031, 0xf03c, 0xf047, 0xf052, + 0xf05e, 0xf069, 0xf074, 0xf07f, 0xf08a, 0xf095, 0xf0a1, 0xf0ac, 0xf0b7, 0xf0c2, 0xf0cd, 0xf0d8, + 0xf0e3, 0xf0ef, 0xf0fa, 0xf105, 0xf110, 0xf11b, 0xf126, 0xf131, 0xf13c, 0xf147, 0xf153, 0xf15e, + 0xf169, 0xf174, 0xf17f, 0xf18a, 0xf195, 0xf1a0, 0xf1ab, 0xf1b6, 0xf1c2, 0xf1cd, 0xf1d8, 0xf1e3, + 0xf1ee, 0xf1f9, 0xf204, 0xf20f, 0xf21a, 0xf225, 0xf230, 0xf23b, 0xf246, 0xf251, 0xf25c, 0xf267, + 0xf272, 0xf27d, 0xf288, 0xf293, 0xf29f, 0xf2aa, 0xf2b5, 0xf2c0, 0xf2cb, 0xf2d6, 0xf2e1, 0xf2ec, + 0xf2f7, 0xf302, 0xf30d, 0xf318, 0xf323, 0xf32e, 0xf339, 0xf344, 0xf34f, 0xf35a, 0xf364, 0xf36f, + 0xf37a, 0xf385, 0xf390, 0xf39b, 0xf3a6, 0xf3b1, 0xf3bc, 0xf3c7, 0xf3d2, 0xf3dd, 0xf3e8, 0xf3f3, + 0xf3fe, 0xf409, 0xf414, 0xf41f, 0xf42a, 0xf435, 0xf43f, 0xf44a, 0xf455, 0xf460, 0xf46b, 0xf476, + 0xf481, 0xf48c, 0xf497, 0xf4a2, 0xf4ad, 0xf4b7, 0xf4c2, 0xf4cd, 0xf4d8, 0xf4e3, 0xf4ee, 0xf4f9, + 0xf504, 0xf50f, 0xf519, 0xf524, 0xf52f, 0xf53a, 0xf545, 0xf550, 0xf55b, 0xf565, 0xf570, 0xf57b, + 0xf586, 0xf591, 0xf59c, 0xf5a6, 0xf5b1, 0xf5bc, 0xf5c7, 0xf5d2, 0xf5dd, 0xf5e7, 0xf5f2, 0xf5fd, + 0xf608, 0xf613, 0xf61d, 0xf628, 0xf633, 0xf63e, 0xf649, 0xf653, 0xf65e, 0xf669, 0xf674, 0xf67f, + 0xf689, 0xf694, 0xf69f, 0xf6aa, 0xf6b4, 0xf6bf, 0xf6ca, 0xf6d5, 0xf6e0, 0xf6ea, 0xf6f5, 0xf700, + 0xf70b, 0xf715, 0xf720, 0xf72b, 0xf736, 0xf740, 0xf74b, 0xf756, 0xf760, 0xf76b, 0xf776, 0xf781, + 0xf78b, 0xf796, 0xf7a1, 0xf7ab, 0xf7b6, 0xf7c1, 0xf7cc, 0xf7d6, 0xf7e1, 0xf7ec, 0xf7f6, 0xf801, + 0xf80c, 0xf816, 0xf821, 0xf82c, 0xf836, 0xf841, 0xf84c, 0xf856, 0xf861, 0xf86c, 0xf876, 0xf881, + 0xf88c, 0xf896, 0xf8a1, 0xf8ac, 0xf8b6, 0xf8c1, 0xf8cc, 0xf8d6, 0xf8e1, 0xf8ec, 0xf8f6, 0xf901, + 0xf90b, 0xf916, 0xf921, 0xf92b, 0xf936, 0xf941, 0xf94b, 0xf956, 0xf960, 0xf96b, 0xf976, 0xf980, + 0xf98b, 0xf995, 0xf9a0, 0xf9aa, 0xf9b5, 0xf9c0, 0xf9ca, 0xf9d5, 0xf9df, 0xf9ea, 0xf9f4, 0xf9ff, + 0xfa0a, 0xfa14, 0xfa1f, 0xfa29, 0xfa34, 0xfa3e, 0xfa49, 0xfa53, 0xfa5e, 0xfa69, 0xfa73, 0xfa7e, + 0xfa88, 0xfa93, 0xfa9d, 0xfaa8, 0xfab2, 0xfabd, 0xfac7, 0xfad2, 0xfadc, 0xfae7, 0xfaf1, 0xfafc, + 0xfb06, 0xfb11, 0xfb1b, 0xfb26, 0xfb30, 0xfb3b, 0xfb45, 0xfb50, 0xfb5a, 0xfb65, 0xfb6f, 0xfb7a, + 0xfb84, 0xfb8f, 0xfb99, 0xfba4, 0xfbae, 0xfbb8, 0xfbc3, 0xfbcd, 0xfbd8, 0xfbe2, 0xfbed, 0xfbf7, + 0xfc02, 0xfc0c, 0xfc16, 0xfc21, 0xfc2b, 0xfc36, 0xfc40, 0xfc4b, 0xfc55, 0xfc5f, 0xfc6a, 0xfc74, + 0xfc7f, 0xfc89, 0xfc93, 0xfc9e, 0xfca8, 0xfcb3, 0xfcbd, 0xfcc7, 0xfcd2, 0xfcdc, 0xfce7, 0xfcf1, + 0xfcfb, 0xfd06, 0xfd10, 0xfd1a, 0xfd25, 0xfd2f, 0xfd3a, 0xfd44, 0xfd4e, 0xfd59, 0xfd63, 0xfd6d, + 0xfd78, 0xfd82, 0xfd8c, 0xfd97, 0xfda1, 0xfdab, 0xfdb6, 0xfdc0, 0xfdca, 0xfdd5, 0xfddf, 0xfde9, + 0xfdf4, 0xfdfe, 0xfe08, 0xfe13, 0xfe1d, 0xfe27, 0xfe32, 0xfe3c, 0xfe46, 0xfe50, 0xfe5b, 0xfe65, + 0xfe6f, 0xfe7a, 0xfe84, 0xfe8e, 0xfe98, 0xfea3, 0xfead, 0xfeb7, 0xfec1, 0xfecc, 0xfed6, 0xfee0, + 0xfeeb, 0xfef5, 0xfeff, 0xff09, 0xff14, 0xff1e, 0xff28, 0xff32, 0xff3c, 0xff47, 0xff51, 0xff5b, + 0xff65, 0xff70, 0xff7a, 0xff84, 0xff8e, 0xff98, 0xffa3, 0xffad, 0xffb7, 0xffc1, 0xffcc, 0xffd6, + 0xffe0, 0xffea, 0xfff4, 0xffff}; + +// max value is pi/4 +constexpr double SCALING_FACTOR = 4. / M_PI * 0xFFFF; + +inline double atan2_lookup(double y, double x) +{ + if (std::abs(x) < std::numeric_limits::epsilon()) + { + if (y >= 0.) + { + return M_PI / 2.; + } + else + { + return -M_PI / 2.; + } + } + + unsigned octant = 0; + + if (x < 0.) + { + octant = 1; + x = -x; + } + if (y < 0.) + { + octant |= 2; + y = -y; + } + + double t = y / x; + if (t > 1.0) + { + octant |= 4; + t = 1.0 / t; + } + + double angle = atan_table[(unsigned)(t * 4095)] / SCALING_FACTOR; + + switch (octant) + { + case 0: + break; + case 1: + angle = M_PI - angle; + break; + case 2: + angle = -angle; + break; + case 3: + angle = -M_PI + angle; + break; + case 4: + angle = M_PI / 2.0 - angle; + break; + case 5: + angle = M_PI / 2.0 + angle; + break; + case 6: + angle = -M_PI / 2.0 + angle; + break; + case 7: + angle = -M_PI / 2.0 - angle; + break; + } + return angle; +} + +#endif // TRIGONOMETRY_TABLE_HPP diff --git a/datastore.cpp b/datastore.cpp index ce0a8c6b9..bcb1d8b43 100644 --- a/datastore.cpp +++ b/datastore.cpp @@ -36,7 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "server/data_structures/datafacade_base.hpp" #include "server/data_structures/shared_datatype.hpp" #include "server/data_structures/shared_barriers.hpp" -#include "Util/BoostFileSystemFix.h" +#include "Util/boost_filesystem_2_fix.hpp" #include "Util/datastore_options.hpp" #include "Util/simple_logger.hpp" #include "Util/osrm_exception.hpp" diff --git a/server/data_structures/internal_datafacade.hpp b/server/data_structures/internal_datafacade.hpp index a9949e383..f25185a1e 100644 --- a/server/data_structures/internal_datafacade.hpp +++ b/server/data_structures/internal_datafacade.hpp @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../data_structures/static_graph.hpp" #include "../../data_structures/static_rtree.hpp" #include "../../data_structures/range_table.hpp" -#include "../../Util/BoostFileSystemFix.h" +#include "../../Util/boost_filesystem_2_fix.hpp" #include "../../Util/graph_loader.hpp" #include "../../Util/simple_logger.hpp" diff --git a/server/data_structures/shared_datafacade.hpp b/server/data_structures/shared_datafacade.hpp index 11a295e27..1b038dc89 100644 --- a/server/data_structures/shared_datafacade.hpp +++ b/server/data_structures/shared_datafacade.hpp @@ -36,7 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../data_structures/range_table.hpp" #include "../../data_structures/static_graph.hpp" #include "../../data_structures/static_rtree.hpp" -#include "../../Util/BoostFileSystemFix.h" +#include "../../Util/boost_filesystem_2_fix.hpp" #include "../../Util/make_unique.hpp" #include "../../Util/simple_logger.hpp" From 203e3ef0773a5400b804c2783efbe5852b5bc3aa Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 17:16:50 +0100 Subject: [PATCH 138/360] fix test after header file rename --- benchmarks/static_rtree.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/benchmarks/static_rtree.cpp b/benchmarks/static_rtree.cpp index 83a94ae9b..e7095e9f6 100644 --- a/benchmarks/static_rtree.cpp +++ b/benchmarks/static_rtree.cpp @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/query_node.hpp" #include "../data_structures/shared_memory_vector_wrapper.hpp" #include "../data_structures/static_rtree.hpp" -#include "../Util/BoostFileSystemFix.h" +#include "../Util/boost_filesystem_2_fix.hpp" #include "../data_structures/edge_based_node.hpp" #include @@ -88,11 +88,9 @@ void Benchmark(BenchStaticRTree &rtree, unsigned num_queries) for (const auto &q : queries) { phantom_node_vector.clear(); - rtree.IncrementalFindPhantomNodeForCoordinate( - q, phantom_node_vector, 3, num_results); + rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 3, num_results); phantom_node_vector.clear(); - rtree.IncrementalFindPhantomNodeForCoordinate( - q, phantom_node_vector, 17, num_results); + rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 17, num_results); } TIMER_STOP(query_phantom); @@ -130,8 +128,7 @@ void Benchmark(BenchStaticRTree &rtree, unsigned num_queries) } TIMER_STOP(query_node); - std::cout << "Took " << TIMER_MSEC(query_node) << " msec for " << num_queries - << " queries." + std::cout << "Took " << TIMER_MSEC(query_node) << " msec for " << num_queries << " queries." << "\n"; std::cout << TIMER_MSEC(query_node) / ((double)num_queries) << " msec/query." << "\n"; @@ -147,11 +144,9 @@ void Benchmark(BenchStaticRTree &rtree, unsigned num_queries) for (const auto &q : queries) { phantom_node_vector.clear(); - rtree.IncrementalFindPhantomNodeForCoordinate( - q, phantom_node_vector, 3, num_results); + rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 3, num_results); phantom_node_vector.clear(); - rtree.IncrementalFindPhantomNodeForCoordinate( - q, phantom_node_vector, 17, num_results); + rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 17, num_results); } TIMER_STOP(query_phantom); From b20b7e65bf2f8bdf50d8c0462f20bed499aebb58 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 17:44:46 +0100 Subject: [PATCH 139/360] renamed: Util/* -> util/* --- CMakeLists.txt | 24 +- Library/OSRM_impl.cpp | 6 +- Server/Http/Reply.cpp | 2 +- Server/data_structures/datafacade_base.hpp | 6 +- .../data_structures/internal_datafacade.hpp | 6 +- Server/data_structures/shared_datafacade.hpp | 6 +- Server/data_structures/shared_datatype.hpp | 4 +- Server/http/reply.cpp | 2 +- Util/cast.hpp | 11 +- Util/compute_angle.cpp | 2 +- Util/container.hpp | 13 +- Util/fingerprint.hpp | 2 +- Util/git_sha.hpp | 2 +- Util/graph_loader.hpp | 44 +- Util/json_renderer.hpp | 3 +- Util/make_unique.hpp | 2 +- Util/osrm_exception.cpp | 20 +- Util/range_algorithms.hpp | 12 +- Util/simple_logger.cpp | 10 +- Util/std_hash.hpp | 23 +- Util/timing_util.hpp | 34 +- Util/xml_renderer.hpp | 25 +- algorithms/douglas_peucker.cpp | 2 +- algorithms/object_encoder.hpp | 13 +- algorithms/tiny_components.hpp | 52 +- benchmarks/static_rtree.cpp | 4 +- cmake/FingerPrint-Config.cmake | 6 +- contractor/contractor.hpp | 200 ++++---- contractor/edge_based_graph_factory.cpp | 10 +- contractor/geometry_compressor.cpp | 38 +- contractor/processing_chain.cpp | 18 +- data_structures/coordinate.cpp | 4 +- data_structures/coordinate_calculation.cpp | 4 +- data_structures/deallocating_vector.hpp | 20 +- data_structures/dynamic_graph.hpp | 19 +- data_structures/node_based_graph.hpp | 48 +- data_structures/range_table.hpp | 81 ++-- data_structures/restriction_map.hpp | 30 +- data_structures/shared_memory_factory.hpp | 53 ++- data_structures/static_graph.hpp | 13 +- data_structures/static_rtree.hpp | 408 ++++++++-------- datastore.cpp | 10 +- descriptors/description_factory.cpp | 4 +- descriptors/gpx_descriptor.hpp | 2 +- descriptors/json_descriptor.hpp | 12 +- extract.cpp | 2 +- extractor/extraction_containers.cpp | 6 +- extractor/extraction_containers.hpp | 2 +- extractor/extraction_helper_functions.hpp | 4 +- extractor/extractor.cpp | 8 +- extractor/extractor_callbacks.cpp | 6 +- extractor/extractor_options.cpp | 6 +- extractor/restriction_parser.cpp | 6 +- extractor/scripting_environment.cpp | 6 +- library/osrm_impl.cpp | 6 +- plugins/distance_table.hpp | 29 +- plugins/hello_world.hpp | 18 +- plugins/locate.hpp | 15 +- plugins/nearest.hpp | 18 +- plugins/timestamp.hpp | 4 +- plugins/viaroute.hpp | 10 +- routed.cpp | 6 +- routing_algorithms/alternative_path.hpp | 138 ++---- routing_algorithms/routing_base.hpp | 46 +- routing_algorithms/shortest_path.hpp | 119 +++-- server/Http/Reply.cpp | 2 +- server/data_structures/datafacade_base.hpp | 6 +- .../data_structures/internal_datafacade.hpp | 6 +- server/data_structures/shared_datafacade.hpp | 6 +- server/data_structures/shared_datatype.hpp | 4 +- server/http/reply.cpp | 2 +- server/request_handler.cpp | 8 +- server/server.hpp | 6 +- tools/check-hsgr.cpp | 20 +- tools/components.cpp | 63 ++- tools/io-benchmark.cpp | 22 +- tools/simpleclient.cpp | 8 +- tools/springclean.cpp | 4 +- tools/unlock_all_mutexes.cpp | 4 +- unit_tests/data_structures/static_rtree.cpp | 2 +- util/bearing.cpp | 65 +++ util/bearing.hpp | 38 ++ util/boost_filesystem_2_fix.hpp | 144 ++++++ util/cast.hpp | 185 ++++++++ util/compute_angle.cpp | 54 +++ util/compute_angle.hpp | 42 ++ util/container.hpp | 85 ++++ util/datastore_options.hpp | 273 +++++++++++ util/fingerprint.cpp.in | 103 ++++ util/fingerprint.hpp | 59 +++ util/floating_point.hpp | 44 ++ util/git_sha.cpp.in | 31 ++ util/git_sha.hpp | 33 ++ util/graph_loader.hpp | 320 +++++++++++++ util/ini_file.hpp | 51 ++ util/integer_range.hpp | 70 +++ util/iterator_range.hpp | 72 +++ util/json_renderer.hpp | 184 +++++++ util/lua_util.hpp | 66 +++ util/make_unique.hpp | 57 +++ util/mercator.cpp | 40 ++ util/mercator.hpp | 38 ++ util/osrm_exception.cpp | 43 ++ util/osrm_exception.hpp | 51 ++ util/range_algorithms.hpp | 42 ++ util/routed_options.hpp | 277 +++++++++++ util/simple_logger.cpp | 135 ++++++ util/simple_logger.hpp | 74 +++ util/std_hash.hpp | 72 +++ util/string_util.hpp | 150 ++++++ util/timing_util.hpp | 90 ++++ util/trigonometry_table.hpp | 448 ++++++++++++++++++ util/xml_renderer.hpp | 140 ++++++ 113 files changed, 4533 insertions(+), 971 deletions(-) create mode 100644 util/bearing.cpp create mode 100644 util/bearing.hpp create mode 100644 util/boost_filesystem_2_fix.hpp create mode 100644 util/cast.hpp create mode 100644 util/compute_angle.cpp create mode 100644 util/compute_angle.hpp create mode 100644 util/container.hpp create mode 100644 util/datastore_options.hpp create mode 100644 util/fingerprint.cpp.in create mode 100644 util/fingerprint.hpp create mode 100644 util/floating_point.hpp create mode 100644 util/git_sha.cpp.in create mode 100644 util/git_sha.hpp create mode 100644 util/graph_loader.hpp create mode 100644 util/ini_file.hpp create mode 100644 util/integer_range.hpp create mode 100644 util/iterator_range.hpp create mode 100644 util/json_renderer.hpp create mode 100644 util/lua_util.hpp create mode 100644 util/make_unique.hpp create mode 100644 util/mercator.cpp create mode 100644 util/mercator.hpp create mode 100644 util/osrm_exception.cpp create mode 100644 util/osrm_exception.hpp create mode 100644 util/range_algorithms.hpp create mode 100644 util/routed_options.hpp create mode 100644 util/simple_logger.cpp create mode 100644 util/simple_logger.hpp create mode 100644 util/std_hash.hpp create mode 100644 util/string_util.hpp create mode 100644 util/timing_util.hpp create mode 100644 util/trigonometry_table.hpp create mode 100644 util/xml_renderer.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ccb2632bc..f01518799 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,44 +34,44 @@ include_directories(${CMAKE_SOURCE_DIR}/include/) include_directories(${CMAKE_SOURCE_DIR}/third_party/) include_directories(${CMAKE_SOURCE_DIR}/third_party/libosmium/include/) -add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/fingerprint.cpp fingerprint.cpp.alwaysbuild +add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/util/fingerprint.cpp fingerprint.cpp.alwaysbuild COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FingerPrint-Config.cmake DEPENDS - ${CMAKE_SOURCE_DIR}/Util/fingerprint.cpp.in + ${CMAKE_SOURCE_DIR}/util/fingerprint.cpp.in COMMENT "Configuring fingerprint.cpp" VERBATIM) -add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/fingerprint.cpp) +add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_SOURCE_DIR}/util/fingerprint.cpp) add_custom_target(tests DEPENDS datastructure-tests algorithm-tests) add_custom_target(benchmarks DEPENDS rtree-bench) set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread unit_test_framework) configure_file( - ${CMAKE_SOURCE_DIR}/Util/git_sha.cpp.in - ${CMAKE_SOURCE_DIR}/Util/git_sha.cpp + ${CMAKE_SOURCE_DIR}/util/git_sha.cpp.in + ${CMAKE_SOURCE_DIR}/util/git_sha.cpp ) file(GLOB ExtractorGlob extractor/*.cpp) file(GLOB ImporterGlob data_structures/import_edge.cpp data_structures/external_memory_node.cpp) add_library(IMPORT OBJECT ${ImporterGlob}) -add_library(LOGGER OBJECT Util/simple_logger.cpp) +add_library(LOGGER OBJECT util/simple_logger.cpp) add_library(PHANTOMNODE OBJECT data_structures/phantom_node.cpp) -add_library(EXCEPTION OBJECT Util/osrm_exception.cpp) -add_library(MERCATOR OBJECT Util/mercator.cpp) +add_library(EXCEPTION OBJECT util/osrm_exception.cpp) +add_library(MERCATOR OBJECT util/mercator.cpp) set(ExtractorSources extract.cpp ${ExtractorGlob}) add_executable(osrm-extract ${ExtractorSources} $ $ $ $ $ $ $) add_library(RESTRICTION OBJECT data_structures/restriction_map.cpp) -file(GLOB PrepareGlob contractor/*.cpp data_structures/hilbert_value.cpp Util/compute_angle.cpp {RestrictionMapGlob}) +file(GLOB PrepareGlob contractor/*.cpp data_structures/hilbert_value.cpp util/compute_angle.cpp {RestrictionMapGlob}) set(PrepareSources prepare.cpp ${PrepareGlob}) add_executable(osrm-prepare ${PrepareSources} $ $ $ $ $ $ $ $) file(GLOB ServerGlob server/*.cpp) file(GLOB DescriptorGlob descriptors/*.cpp) -file(GLOB DatastructureGlob data_structures/search_engine_data.cpp data_structures/route_parameters.cpp Util/bearing.cpp) +file(GLOB DatastructureGlob data_structures/search_engine_data.cpp data_structures/route_parameters.cpp util/bearing.cpp) list(REMOVE_ITEM DatastructureGlob data_structures/Coordinate.cpp) file(GLOB CoordinateGlob data_structures/coordinate*.cpp) file(GLOB AlgorithmGlob algorithms/*.cpp) @@ -91,8 +91,8 @@ set( ) add_library(COORDINATE OBJECT ${CoordinateGlob}) -add_library(FINGERPRINT OBJECT Util/fingerprint.cpp) -add_library(GITDESCRIPTION OBJECT Util/git_sha.cpp) +add_library(FINGERPRINT OBJECT util/fingerprint.cpp) +add_library(GITDESCRIPTION OBJECT util/git_sha.cpp) add_library(OSRM ${OSRMSources} $ $ $ $ $ $ $) add_dependencies(FINGERPRINT FingerPrintConfigure) diff --git a/Library/OSRM_impl.cpp b/Library/OSRM_impl.cpp index aaf1e3da3..aea85a44c 100644 --- a/Library/OSRM_impl.cpp +++ b/Library/OSRM_impl.cpp @@ -46,9 +46,9 @@ class named_mutex; #include "../server/data_structures/internal_datafacade.hpp" #include "../server/data_structures/shared_barriers.hpp" #include "../server/data_structures/shared_datafacade.hpp" -#include "../Util/make_unique.hpp" -#include "../Util/routed_options.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/make_unique.hpp" +#include "../util/routed_options.hpp" +#include "../util/simple_logger.hpp" #include #include diff --git a/Server/Http/Reply.cpp b/Server/Http/Reply.cpp index 89b931b05..2642e2be2 100644 --- a/Server/Http/Reply.cpp +++ b/Server/Http/Reply.cpp @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "reply.hpp" -#include "../../Util/cast.hpp" +#include "../../util/cast.hpp" namespace http { diff --git a/Server/data_structures/datafacade_base.hpp b/Server/data_structures/datafacade_base.hpp index 2de79f915..0dbeef4b6 100644 --- a/Server/data_structures/datafacade_base.hpp +++ b/Server/data_structures/datafacade_base.hpp @@ -34,9 +34,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../data_structures/external_memory_node.hpp" #include "../../data_structures/phantom_node.hpp" #include "../../data_structures/turn_instructions.hpp" -#include "../../Util/integer_range.hpp" -#include "../../Util/osrm_exception.hpp" -#include "../../Util/string_util.hpp" +#include "../../util/integer_range.hpp" +#include "../../util/osrm_exception.hpp" +#include "../../util/string_util.hpp" #include "../../typedefs.h" #include diff --git a/Server/data_structures/internal_datafacade.hpp b/Server/data_structures/internal_datafacade.hpp index f25185a1e..8a481c5c5 100644 --- a/Server/data_structures/internal_datafacade.hpp +++ b/Server/data_structures/internal_datafacade.hpp @@ -39,9 +39,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../data_structures/static_graph.hpp" #include "../../data_structures/static_rtree.hpp" #include "../../data_structures/range_table.hpp" -#include "../../Util/boost_filesystem_2_fix.hpp" -#include "../../Util/graph_loader.hpp" -#include "../../Util/simple_logger.hpp" +#include "../../util/boost_filesystem_2_fix.hpp" +#include "../../util/graph_loader.hpp" +#include "../../util/simple_logger.hpp" #include #include diff --git a/Server/data_structures/shared_datafacade.hpp b/Server/data_structures/shared_datafacade.hpp index 1b038dc89..b6a144174 100644 --- a/Server/data_structures/shared_datafacade.hpp +++ b/Server/data_structures/shared_datafacade.hpp @@ -36,9 +36,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../data_structures/range_table.hpp" #include "../../data_structures/static_graph.hpp" #include "../../data_structures/static_rtree.hpp" -#include "../../Util/boost_filesystem_2_fix.hpp" -#include "../../Util/make_unique.hpp" -#include "../../Util/simple_logger.hpp" +#include "../../util/boost_filesystem_2_fix.hpp" +#include "../../util/make_unique.hpp" +#include "../../util/simple_logger.hpp" #include #include diff --git a/Server/data_structures/shared_datatype.hpp b/Server/data_structures/shared_datatype.hpp index 9464ff015..0c0b23910 100644 --- a/Server/data_structures/shared_datatype.hpp +++ b/Server/data_structures/shared_datatype.hpp @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef SHARED_DATA_TYPE_HPP #define SHARED_DATA_TYPE_HPP -#include "../../Util/osrm_exception.hpp" -#include "../../Util/simple_logger.hpp" +#include "../../util/osrm_exception.hpp" +#include "../../util/simple_logger.hpp" #include diff --git a/Server/http/reply.cpp b/Server/http/reply.cpp index 89b931b05..2642e2be2 100644 --- a/Server/http/reply.cpp +++ b/Server/http/reply.cpp @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "reply.hpp" -#include "../../Util/cast.hpp" +#include "../../util/cast.hpp" namespace http { diff --git a/Util/cast.hpp b/Util/cast.hpp index 9d09761b1..e28b9ff84 100644 --- a/Util/cast.hpp +++ b/Util/cast.hpp @@ -38,7 +38,8 @@ struct cast { // convert scoped enums to integers template - static auto enum_to_underlying(Enumeration const value) -> typename std::underlying_type::type + static auto enum_to_underlying(Enumeration const value) -> + typename std::underlying_type::type { return static_cast::type>(value); } @@ -145,10 +146,7 @@ struct cast template struct scientific_policy : boost::spirit::karma::real_policies { // we want the numbers always to be in fixed format - static int floatfield(T) - { - return boost::spirit::karma::real_policies::fmtflags::fixed; - } + static int floatfield(T) { return boost::spirit::karma::real_policies::fmtflags::fixed; } static unsigned int precision(T) { return 6; } }; typedef boost::spirit::karma::real_generator> science_type; @@ -174,8 +172,7 @@ struct cast return output; } - static void double_with_two_digits_to_string(const double value, - std::string &output) + static void double_with_two_digits_to_string(const double value, std::string &output) { // The largest 32-bit integer is 4294967295, that is 10 chars // On the safe side, add 1 for sign, and 1 for trailing zero diff --git a/Util/compute_angle.cpp b/Util/compute_angle.cpp index dd1989b80..e83b67b75 100644 --- a/Util/compute_angle.cpp +++ b/Util/compute_angle.cpp @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "compute_angle.hpp" #include "trigonometry_table.hpp" -#include "../Util/mercator.hpp" +#include "../util/mercator.hpp" #include diff --git a/Util/container.hpp b/Util/container.hpp index 343ebe9ba..a35d56a6d 100644 --- a/Util/container.hpp +++ b/Util/container.hpp @@ -37,7 +37,8 @@ namespace osrm template void sort_unique_resize(std::vector &vector) { std::sort(vector.begin(), vector.end()); - const auto number_of_unique_elements = std::unique(vector.begin(), vector.end()) - vector.begin(); + const auto number_of_unique_elements = + std::unique(vector.begin(), vector.end()) - vector.begin(); vector.resize(number_of_unique_elements); } @@ -47,9 +48,11 @@ template void sort_unique_resize(std::vector &vector) // vector.shrink_to_fit(); // } -// template inline void remove_consecutive_duplicates_from_vector(std::vector &vector) +// template inline void remove_consecutive_duplicates_from_vector(std::vector +// &vector) // { -// const auto number_of_unique_elements = std::unique(vector.begin(), vector.end()) - vector.begin(); +// const auto number_of_unique_elements = std::unique(vector.begin(), vector.end()) - +// vector.begin(); // vector.resize(number_of_unique_elements); // } @@ -67,7 +70,8 @@ Function for_each_pair(ForwardIterator begin, ForwardIterator end, Function func while (next != end) { function(*begin, *next); - begin = std::next(begin); next = std::next(next); + begin = std::next(begin); + next = std::next(next); } return function; } @@ -77,6 +81,5 @@ Function for_each_pair(ContainerT &container, Function function) { return for_each_pair(std::begin(container), std::end(container), function); } - } #endif /* CONTAINER_HPP_ */ diff --git a/Util/fingerprint.hpp b/Util/fingerprint.hpp index 43a811deb..494a877ab 100644 --- a/Util/fingerprint.hpp +++ b/Util/fingerprint.hpp @@ -35,7 +35,7 @@ class FingerPrint { public: FingerPrint(); - FingerPrint(const FingerPrint&) = delete; + FingerPrint(const FingerPrint &) = delete; ~FingerPrint(); const boost::uuids::uuid &GetFingerPrint() const; bool IsMagicNumberOK() const; diff --git a/Util/git_sha.hpp b/Util/git_sha.hpp index d1f18a661..9e55deff3 100644 --- a/Util/git_sha.hpp +++ b/Util/git_sha.hpp @@ -30,4 +30,4 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. extern char g_GIT_DESCRIPTION[]; -#endif //GIT_SHA_HPP +#endif // GIT_SHA_HPP diff --git a/Util/graph_loader.hpp b/Util/graph_loader.hpp index 6c40ee7c7..44f628034 100644 --- a/Util/graph_loader.hpp +++ b/Util/graph_loader.hpp @@ -28,13 +28,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef GRAPH_LOADER_HPP #define GRAPH_LOADER_HPP +#include "fingerprint.hpp" #include "osrm_exception.hpp" +#include "simple_logger.hpp" #include "../data_structures/external_memory_node.hpp" #include "../data_structures/import_edge.hpp" #include "../data_structures/query_node.hpp" #include "../data_structures/restriction.hpp" -#include "../Util/fingerprint.hpp" -#include "../Util/simple_logger.hpp" #include "../typedefs.h" #include @@ -80,7 +80,8 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, for (NodeID i = 0; i < n; ++i) { input_stream.read((char *)¤t_node, sizeof(ExternalMemoryNode)); - int_to_ext_node_id_map->emplace_back(current_node.lat, current_node.lon, current_node.node_id); + int_to_ext_node_id_map->emplace_back(current_node.lat, current_node.lon, + current_node.node_id); ext_to_int_id_map.emplace(current_node.node_id, i); if (current_node.barrier) { @@ -102,7 +103,8 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, auto internal_id_iter = ext_to_int_id_map.find(current_restriction.from.node); if (internal_id_iter == ext_to_int_id_map.end()) { - SimpleLogger().Write(logDEBUG) << "Unmapped from node " << current_restriction.from.node << " of restriction"; + SimpleLogger().Write(logDEBUG) << "Unmapped from node " << current_restriction.from.node + << " of restriction"; continue; } current_restriction.from.node = internal_id_iter->second; @@ -110,7 +112,8 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, internal_id_iter = ext_to_int_id_map.find(current_restriction.via.node); if (internal_id_iter == ext_to_int_id_map.end()) { - SimpleLogger().Write(logDEBUG) << "Unmapped via node " << current_restriction.via.node << " of restriction"; + SimpleLogger().Write(logDEBUG) << "Unmapped via node " << current_restriction.via.node + << " of restriction"; continue; } @@ -119,7 +122,8 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, internal_id_iter = ext_to_int_id_map.find(current_restriction.to.node); if (internal_id_iter == ext_to_int_id_map.end()) { - SimpleLogger().Write(logDEBUG) << "Unmapped to node " << current_restriction.to.node << " of restriction"; + SimpleLogger().Write(logDEBUG) << "Unmapped to node " << current_restriction.to.node + << " of restriction"; continue; } current_restriction.to.node = internal_id_iter->second; @@ -195,17 +199,8 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, std::swap(forward, backward); } - edge_list.emplace_back(source, - target, - nameID, - weight, - forward, - backward, - is_roundabout, - ignore_in_grid, - is_access_restricted, - travel_mode, - is_split); + edge_list.emplace_back(source, target, nameID, weight, forward, backward, is_roundabout, + ignore_in_grid, is_access_restricted, travel_mode, is_split); } ext_to_int_id_map.clear(); @@ -216,9 +211,8 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, if ((edge_list[i - 1].target == edge_list[i].target) && (edge_list[i - 1].source == edge_list[i].source)) { - const bool edge_flags_equivalent = - (edge_list[i - 1].forward == edge_list[i].forward) && - (edge_list[i - 1].backward == edge_list[i].backward); + const bool edge_flags_equivalent = (edge_list[i - 1].forward == edge_list[i].forward) && + (edge_list[i - 1].backward == edge_list[i].backward); const bool edge_flags_are_superset1 = (edge_list[i - 1].forward && edge_list[i - 1].backward) && (edge_list[i].forward != edge_list[i].backward); @@ -263,11 +257,11 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, } } } - const auto new_end_iter = std::remove_if(edge_list.begin(), edge_list.end(), [] (const EdgeT &edge) - { - return edge.source == SPECIAL_NODEID || - edge.target == SPECIAL_NODEID; - }); + const auto new_end_iter = + std::remove_if(edge_list.begin(), edge_list.end(), [](const EdgeT &edge) + { + return edge.source == SPECIAL_NODEID || edge.target == SPECIAL_NODEID; + }); edge_list.erase(new_end_iter, edge_list.end()); // remove excess candidates. edge_list.shrink_to_fit(); SimpleLogger().Write() << "Graph loaded ok and has " << edge_list.size() << " edges"; diff --git a/Util/json_renderer.hpp b/Util/json_renderer.hpp index a5fc239bb..adb7c544e 100644 --- a/Util/json_renderer.hpp +++ b/Util/json_renderer.hpp @@ -35,7 +35,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -namespace JSON { +namespace JSON +{ struct Renderer : mapbox::util::static_visitor<> { diff --git a/Util/make_unique.hpp b/Util/make_unique.hpp index 07786feaa..b88145d17 100644 --- a/Util/make_unique.hpp +++ b/Util/make_unique.hpp @@ -54,4 +54,4 @@ template typename std::enable_if::value != 0, void>::type make_unique(Types &&...) = delete; } -#endif //MAKE_UNIQUE_H_ +#endif // MAKE_UNIQUE_H_ diff --git a/Util/osrm_exception.cpp b/Util/osrm_exception.cpp index ebdac6db1..e6b7986e3 100644 --- a/Util/osrm_exception.cpp +++ b/Util/osrm_exception.cpp @@ -29,15 +29,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace osrm { - // This function exists to 'anchor' the class, and stop the compiler from - // copying vtable and RTTI info into every object file that includes - // this header. (Caught by -Wweak-vtables under Clang.) +// This function exists to 'anchor' the class, and stop the compiler from +// copying vtable and RTTI info into every object file that includes +// this header. (Caught by -Wweak-vtables under Clang.) - // More information from the LLVM Coding Standards: - // If a class is defined in a header file and has a vtable (either it has - // virtual methods or it derives from classes with virtual methods), it must - // always have at least one out-of-line virtual method in the class. Without - // this, the compiler will copy the vtable and RTTI into every .o file that - // #includes the header, bloating .o file sizes and increasing link times. - void exception::anchor() const { } +// More information from the LLVM Coding Standards: +// If a class is defined in a header file and has a vtable (either it has +// virtual methods or it derives from classes with virtual methods), it must +// always have at least one out-of-line virtual method in the class. Without +// this, the compiler will copy the vtable and RTTI into every .o file that +// #includes the header, bloating .o file sizes and increasing link times. +void exception::anchor() const {} } diff --git a/Util/range_algorithms.hpp b/Util/range_algorithms.hpp index 208236e6c..5aafd8e17 100644 --- a/Util/range_algorithms.hpp +++ b/Util/range_algorithms.hpp @@ -23,20 +23,20 @@ or see http://www.gnu.org/licenses/agpl.txt. #include -namespace osrm { +namespace osrm +{ -template -auto max_element(const Container & c) -> decltype(std::max_element(c.begin(), c.end())) +template +auto max_element(const Container &c) -> decltype(std::max_element(c.begin(), c.end())) { return std::max_element(c.begin(), c.end()); } -template -auto max_element(const Container & c) -> decltype(std::max_element(c.cbegin(), c.cend())) +template +auto max_element(const Container &c) -> decltype(std::max_element(c.cbegin(), c.cend())) { return std::max_element(c.cbegin(), c.cend()); } - } #endif // RANGE_ALGORITHMS_HPP diff --git a/Util/simple_logger.cpp b/Util/simple_logger.cpp index dbbf34808..5d8821233 100644 --- a/Util/simple_logger.cpp +++ b/Util/simple_logger.cpp @@ -47,10 +47,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace { -static const char COL_RESET[] { "\x1b[0m"}; -static const char RED[] { "\x1b[31m"}; +static const char COL_RESET[]{"\x1b[0m"}; +static const char RED[]{"\x1b[31m"}; #ifndef NDEBUG -static const char YELLOW[] { "\x1b[33m"}; +static const char YELLOW[]{"\x1b[33m"}; #endif // static const char GREEN[] { "\x1b[32m"}; // static const char BLUE[] { "\x1b[34m"}; @@ -95,7 +95,7 @@ std::ostringstream &SimpleLogger::Write(LogLevel lvl) os << "debug"; #endif break; - default: //logINFO: + default: // logINFO: os << "info"; break; } @@ -127,7 +127,7 @@ SimpleLogger::~SimpleLogger() << std::endl; #endif break; - default: //logINFO: + default: // logINFO: std::cout << os.str() << (is_terminal ? COL_RESET : "") << std::endl; break; } diff --git a/Util/std_hash.hpp b/Util/std_hash.hpp index 59c4ad9b4..8b4af3dd8 100644 --- a/Util/std_hash.hpp +++ b/Util/std_hash.hpp @@ -33,29 +33,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // this is largely inspired by boost's hash combine as can be found in // "The C++ Standard Library" 2nd Edition. Nicolai M. Josuttis. 2012. -namespace { +namespace +{ -template -void hash_combine(std::size_t &seed, const T& val) +template void hash_combine(std::size_t &seed, const T &val) { seed ^= std::hash()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } -template -void hash_val(std::size_t &seed, const T& val) +template void hash_val(std::size_t &seed, const T &val) { hash_combine(seed, val); } + +template +void hash_val(std::size_t &seed, const T &val, const Types &... args) { hash_combine(seed, val); + hash_val(seed, args...); } -template -void hash_val(std::size_t &seed, const T& val, const Types& ... args) -{ - hash_combine(seed, val); - hash_val(seed, args ...); -} - -template -std::size_t hash_val(const Types&... args) +template std::size_t hash_val(const Types &... args) { std::size_t seed = 0; hash_val(seed, args...); diff --git a/Util/timing_util.hpp b/Util/timing_util.hpp index 1bbea472a..2279bd083 100644 --- a/Util/timing_util.hpp +++ b/Util/timing_util.hpp @@ -42,39 +42,49 @@ struct GlobalTimer class GlobalTimerFactory { -public: - static GlobalTimerFactory& get() + public: + static GlobalTimerFactory &get() { static GlobalTimerFactory instance; return instance; } - GlobalTimer& getGlobalTimer(const std::string& name) + GlobalTimer &getGlobalTimer(const std::string &name) { std::lock_guard lock(map_mutex); return timer_map[name]; } -private: + private: std::mutex map_mutex; std::unordered_map timer_map; }; -#define GLOBAL_TIMER_AQUIRE(_X) auto& _X##_global_timer = GlobalTimerFactory::get().getGlobalTimer(#_X) +#define GLOBAL_TIMER_AQUIRE(_X) \ + auto &_X##_global_timer = GlobalTimerFactory::get().getGlobalTimer(#_X) #define GLOBAL_TIMER_RESET(_X) _X##_global_timer.time = 0 #define GLOBAL_TIMER_START(_X) TIMER_START(_X) -#define GLOBAL_TIMER_STOP(_X) TIMER_STOP(_X); _X##_global_timer.time += TIMER_NSEC(_X) +#define GLOBAL_TIMER_STOP(_X) \ + TIMER_STOP(_X); \ + _X##_global_timer.time += TIMER_NSEC(_X) #define GLOBAL_TIMER_NSEC(_X) static_cast(_X##_global_timer.time) #define GLOBAL_TIMER_USEC(_X) (_X##_global_timer.time / 1000.0) #define GLOBAL_TIMER_MSEC(_X) (_X##_global_timer.time / 1000.0 / 1000.0) -#define GLOBAL_TIMER_SEC(_X) (_X##_global_timer.time / 1000.0 / 1000.0 / 1000.0) +#define GLOBAL_TIMER_SEC(_X) (_X##_global_timer.time / 1000.0 / 1000.0 / 1000.0) #define TIMER_START(_X) auto _X##_start = std::chrono::steady_clock::now(), _X##_stop = _X##_start #define TIMER_STOP(_X) _X##_stop = std::chrono::steady_clock::now() -#define TIMER_NSEC(_X) std::chrono::duration_cast(_X##_stop - _X##_start).count() -#define TIMER_USEC(_X) std::chrono::duration_cast(_X##_stop - _X##_start).count() -#define TIMER_MSEC(_X) (0.000001*std::chrono::duration_cast(_X##_stop - _X##_start).count()) -#define TIMER_SEC(_X) (0.000001*std::chrono::duration_cast(_X##_stop - _X##_start).count()) -#define TIMER_MIN(_X) std::chrono::duration_cast(_X##_stop - _X##_start).count() +#define TIMER_NSEC(_X) \ + std::chrono::duration_cast(_X##_stop - _X##_start).count() +#define TIMER_USEC(_X) \ + std::chrono::duration_cast(_X##_stop - _X##_start).count() +#define TIMER_MSEC(_X) \ + (0.000001 * \ + std::chrono::duration_cast(_X##_stop - _X##_start).count()) +#define TIMER_SEC(_X) \ + (0.000001 * \ + std::chrono::duration_cast(_X##_stop - _X##_start).count()) +#define TIMER_MIN(_X) \ + std::chrono::duration_cast(_X##_stop - _X##_start).count() #endif // TIMING_UTIL_HPP diff --git a/Util/xml_renderer.hpp b/Util/xml_renderer.hpp index 4f08cddbe..bbf2287e1 100644 --- a/Util/xml_renderer.hpp +++ b/Util/xml_renderer.hpp @@ -32,7 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -namespace JSON { +namespace JSON +{ struct XMLToArrayRenderer : mapbox::util::static_visitor<> { @@ -66,7 +67,6 @@ struct XMLToArrayRenderer : mapbox::util::static_visitor<> out.push_back(' '); out.insert(out.end(), ++(*iterator).first.begin(), (*iterator).first.end()); out.push_back('='); - } mapbox::util::apply_visitor(XMLToArrayRenderer(out), (*iterator).second); if (iterator->first.at(0) != '_') @@ -111,29 +111,28 @@ struct XMLToArrayRenderer : mapbox::util::static_visitor<> std::vector &out; }; -template -inline void xml_render(std::vector &out, const JSONObject &object) +template inline void xml_render(std::vector &out, const JSONObject &object) { Value value = object; mapbox::util::apply_visitor(XMLToArrayRenderer(out), value); } -template -inline void gpx_render(std::vector &out, const JSONObject &object) +template inline void gpx_render(std::vector &out, const JSONObject &object) { // add header - const std::string header {"Data (c) OpenStreetMap contributors (ODbL)"}; + const std::string header{ + "Data (c) OpenStreetMap contributors (ODbL)"}; out.insert(out.end(), header.begin(), header.end()); xml_render(out, object); - const std::string footer {""}; + const std::string footer{""}; out.insert(out.end(), footer.begin(), footer.end()); } } // namespace JSON diff --git a/algorithms/douglas_peucker.cpp b/algorithms/douglas_peucker.cpp index fabea1810..3de89da4e 100644 --- a/algorithms/douglas_peucker.cpp +++ b/algorithms/douglas_peucker.cpp @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "douglas_peucker.hpp" #include "../data_structures/segment_information.hpp" -#include "../Util/integer_range.hpp" +#include "../util/integer_range.hpp" #include #include diff --git a/algorithms/object_encoder.hpp b/algorithms/object_encoder.hpp index af6e0d9ca..5a1e75309 100644 --- a/algorithms/object_encoder.hpp +++ b/algorithms/object_encoder.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef OBJECT_ENCODER_HPP #define OBJECT_ENCODER_HPP -#include "../Util/string_util.hpp" +#include "../util/string_util.hpp" #include #include @@ -49,8 +49,7 @@ struct ObjectEncoder 8, 6>; - template - static void EncodeToBase64(const ObjectT &object, std::string &encoded) + template static void EncodeToBase64(const ObjectT &object, std::string &encoded) { const char *char_ptr_to_object = (const char *)&object; std::vector data(sizeof(object)); @@ -71,8 +70,7 @@ struct ObjectEncoder replaceAll(encoded, "/", "_"); } - template - static void DecodeFromBase64(const std::string &input, ObjectT &object) + template static void DecodeFromBase64(const std::string &input, ObjectT &object) { try { @@ -81,8 +79,7 @@ struct ObjectEncoder replaceAll(encoded, "-", "+"); replaceAll(encoded, "_", "/"); - std::copy(binary_t(encoded.begin()), - binary_t(encoded.begin() + encoded.length() - 1), + std::copy(binary_t(encoded.begin()), binary_t(encoded.begin() + encoded.length() - 1), (char *)&object); } catch (...) diff --git a/algorithms/tiny_components.hpp b/algorithms/tiny_components.hpp index 04f380a1b..5354fc785 100644 --- a/algorithms/tiny_components.hpp +++ b/algorithms/tiny_components.hpp @@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/restriction_map.hpp" #include "../data_structures/turn_instructions.hpp" -#include "../Util/integer_range.hpp" -#include "../Util/simple_logger.hpp" -#include "../Util/std_hash.hpp" -#include "../Util/timing_util.hpp" +#include "../util/integer_range.hpp" +#include "../util/simple_logger.hpp" +#include "../util/std_hash.hpp" +#include "../util/timing_util.hpp" #include @@ -48,7 +48,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include - #include #include @@ -57,8 +56,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -template -class TarjanSCC +template class TarjanSCC { struct TarjanStackFrame { @@ -83,13 +81,12 @@ class TarjanSCC std::size_t size_one_counter; public: - template + template TarjanSCC(std::shared_ptr graph, const RestrictionMap &restrictions, const ContainerT &barrier_node_list) - : components_index(graph->GetNumberOfNodes(), SPECIAL_NODEID), - m_node_based_graph(graph), m_restriction_map(restrictions), - size_one_counter(0) + : components_index(graph->GetNumberOfNodes(), SPECIAL_NODEID), m_node_based_graph(graph), + m_restriction_map(restrictions), size_one_counter(0) { barrier_node_set.insert(std::begin(barrier_node_list), std::end(barrier_node_list)); BOOST_ASSERT(m_node_based_graph->GetNumberOfNodes() > 0); @@ -107,8 +104,9 @@ class TarjanSCC unsigned component_index = 0, size_of_current_component = 0; int index = 0; const NodeID last_node = m_node_based_graph->GetNumberOfNodes(); - std::vector processing_node_before_recursion(m_node_based_graph->GetNumberOfNodes(), true); - for(const NodeID node : osrm::irange(0u, last_node)) + std::vector processing_node_before_recursion(m_node_based_graph->GetNumberOfNodes(), + true); + for (const NodeID node : osrm::irange(0u, last_node)) { if (SPECIAL_NODEID == components_index[node]) { @@ -150,13 +148,11 @@ class TarjanSCC const auto vprime = m_node_based_graph->GetTarget(current_edge); // Traverse outgoing edges - if (barrier_node_set.find(v) != barrier_node_set.end() && - u != vprime) + if (barrier_node_set.find(v) != barrier_node_set.end() && u != vprime) { // continue; } - if (to_node_of_only_restriction != std::numeric_limits::max() && vprime == to_node_of_only_restriction) { @@ -219,35 +215,25 @@ class TarjanSCC } TIMER_STOP(SCC_RUN); - SimpleLogger().Write() << "SCC run took: " << TIMER_MSEC(SCC_RUN)/1000. << "s"; + SimpleLogger().Write() << "SCC run took: " << TIMER_MSEC(SCC_RUN) / 1000. << "s"; - size_one_counter = std::count_if(component_size_vector.begin(), - component_size_vector.end(), + size_one_counter = std::count_if(component_size_vector.begin(), component_size_vector.end(), [](unsigned value) { - return 1 == value; - }); + return 1 == value; + }); } - std::size_t get_number_of_components() const - { - return component_size_vector.size(); - } + std::size_t get_number_of_components() const { return component_size_vector.size(); } - unsigned get_size_one_count() const - { - return size_one_counter; - } + unsigned get_size_one_count() const { return size_one_counter; } unsigned get_component_size(const NodeID node) const { return component_size_vector[components_index[node]]; } - unsigned get_component_id(const NodeID node) const - { - return components_index[node]; - } + unsigned get_component_id(const NodeID node) const { return components_index[node]; } }; #endif /* TINY_COMPONENTS_HPP */ diff --git a/benchmarks/static_rtree.cpp b/benchmarks/static_rtree.cpp index e7095e9f6..7d2ae9f55 100644 --- a/benchmarks/static_rtree.cpp +++ b/benchmarks/static_rtree.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/query_node.hpp" #include "../data_structures/shared_memory_vector_wrapper.hpp" #include "../data_structures/static_rtree.hpp" -#include "../Util/boost_filesystem_2_fix.hpp" +#include "../util/boost_filesystem_2_fix.hpp" #include "../data_structures/edge_based_node.hpp" #include diff --git a/cmake/FingerPrint-Config.cmake b/cmake/FingerPrint-Config.cmake index 9ea843519..fe710ac63 100644 --- a/cmake/FingerPrint-Config.cmake +++ b/cmake/FingerPrint-Config.cmake @@ -1,10 +1,10 @@ -set(OLDFILE ${SOURCE_DIR}/Util/fingerprint.cpp) +set(OLDFILE ${SOURCE_DIR}/util/fingerprint.cpp) if (EXISTS ${OLDFILE}) file(REMOVE_RECURSE ${OLDFILE}) endif() file(MD5 ${SOURCE_DIR}/prepare.cpp MD5PREPARE) file(MD5 ${SOURCE_DIR}/data_structures/static_rtree.hpp MD5RTREE) -file(MD5 ${SOURCE_DIR}/Util/graph_loader.hpp MD5GRAPH) +file(MD5 ${SOURCE_DIR}/util/graph_loader.hpp MD5GRAPH) file(MD5 ${SOURCE_DIR}/server/data_structures/internal_datafacade.hpp MD5OBJECTS) -CONFIGURE_FILE( ${SOURCE_DIR}/Util/fingerprint.cpp.in ${SOURCE_DIR}/Util/fingerprint.cpp ) +CONFIGURE_FILE( ${SOURCE_DIR}/util/fingerprint.cpp.in ${SOURCE_DIR}/util/fingerprint.cpp ) diff --git a/contractor/contractor.hpp b/contractor/contractor.hpp index c8c107cdb..ccfabbc8f 100644 --- a/contractor/contractor.hpp +++ b/contractor/contractor.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -35,9 +35,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/query_edge.hpp" #include "../data_structures/xor_fast_hash.hpp" #include "../data_structures/xor_fast_hash_storage.hpp" -#include "../Util/integer_range.hpp" -#include "../Util/simple_logger.hpp" -#include "../Util/timing_util.hpp" +#include "../util/integer_range.hpp" +#include "../util/simple_logger.hpp" +#include "../util/timing_util.hpp" #include "../typedefs.h" #include @@ -92,9 +92,11 @@ class Contractor }; using ContractorGraph = DynamicGraph; - // using ContractorHeap = BinaryHeap + // using ContractorHeap = BinaryHeap // >; - using ContractorHeap = BinaryHeap>; + using ContractorHeap = + BinaryHeap>; using ContractorEdge = ContractorGraph::InputEdge; struct ContractorThreadData @@ -131,15 +133,14 @@ class Contractor bool is_independent : 1; }; - struct ThreadDataContainer { - explicit ThreadDataContainer(int number_of_nodes) : number_of_nodes(number_of_nodes) {} + explicit ThreadDataContainer(int number_of_nodes) : number_of_nodes(number_of_nodes) {} - inline ContractorThreadData* getThreadData() + inline ContractorThreadData *getThreadData() { bool exists = false; - auto& ref = data.local(exists); + auto &ref = data.local(exists); if (!exists) { ref = std::make_shared(number_of_nodes); @@ -149,7 +150,8 @@ class Contractor } int number_of_nodes; - using EnumerableThreadData = tbb::enumerable_thread_specific>; + using EnumerableThreadData = + tbb::enumerable_thread_specific>; EnumerableThreadData data; }; @@ -162,29 +164,25 @@ class Contractor const auto dend = input_edge_list.dend(); for (auto diter = input_edge_list.dbegin(); diter != dend; ++diter) { - BOOST_ASSERT_MSG(static_cast(std::max(diter->weight, 1)) > 0, "edge distance < 1"); + BOOST_ASSERT_MSG(static_cast(std::max(diter->weight, 1)) > 0, + "edge distance < 1"); #ifndef NDEBUG if (static_cast(std::max(diter->weight, 1)) > 24 * 60 * 60 * 10) { - SimpleLogger().Write(logWARNING) << "Edge weight large -> " - << static_cast(std::max(diter->weight, 1)); + SimpleLogger().Write(logWARNING) + << "Edge weight large -> " + << static_cast(std::max(diter->weight, 1)); } #endif edges.emplace_back(diter->source, diter->target, - static_cast(std::max(diter->weight, 1)), - 1, - diter->edge_id, - false, - diter->forward ? true : false, - diter->backward ? true : false); + static_cast(std::max(diter->weight, 1)), 1, + diter->edge_id, false, diter->forward ? true : false, + diter->backward ? true : false); edges.emplace_back(diter->target, diter->source, - static_cast(std::max(diter->weight, 1)), - 1, - diter->edge_id, - false, - diter->backward ? true : false, - diter->forward ? true : false); + static_cast(std::max(diter->weight, 1)), 1, + diter->edge_id, false, diter->backward ? true : false, + diter->forward ? true : false); } // clear input vector input_edge_list.clear(); @@ -282,20 +280,20 @@ class Contractor std::cout << "contractor finished initalization" << std::endl; } - ~Contractor() { } + ~Contractor() {} void Run() { // for the preperation we can use a big grain size, which is much faster (probably cache) - constexpr size_t InitGrainSize = 100000; - constexpr size_t PQGrainSize = 100000; + constexpr size_t InitGrainSize = 100000; + constexpr size_t PQGrainSize = 100000; // auto_partitioner will automatically increase the blocksize if we have // a lot of data. It is *important* for the last loop iterations // (which have a very small dataset) that it is devisible. constexpr size_t IndependentGrainSize = 1; - constexpr size_t ContractGrainSize = 1; - constexpr size_t NeighboursGrainSize = 1; - constexpr size_t DeleteGrainSize = 1; + constexpr size_t ContractGrainSize = 1; + constexpr size_t NeighboursGrainSize = 1; + constexpr size_t DeleteGrainSize = 1; const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes(); Percent p(number_of_nodes); @@ -307,30 +305,28 @@ class Contractor std::vector node_priorities(number_of_nodes); std::vector node_data(number_of_nodes); - // initialize priorities in parallel tbb::parallel_for(tbb::blocked_range(0, number_of_nodes, InitGrainSize), - [&remaining_nodes](const tbb::blocked_range& range) - { - for (int x = range.begin(); x != range.end(); ++x) - { - remaining_nodes[x].id = x; - } - } - ); - + [&remaining_nodes](const tbb::blocked_range &range) + { + for (int x = range.begin(); x != range.end(); ++x) + { + remaining_nodes[x].id = x; + } + }); std::cout << "initializing elimination PQ ..." << std::flush; tbb::parallel_for(tbb::blocked_range(0, number_of_nodes, PQGrainSize), - [this, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range& range) - { - ContractorThreadData *data = thread_data_list.getThreadData(); - for (int x = range.begin(); x != range.end(); ++x) - { - node_priorities[x] = this->EvaluateNodePriority(data, &node_data[x], x); - } - } - ); + [this, &node_priorities, &node_data, &thread_data_list]( + const tbb::blocked_range &range) + { + ContractorThreadData *data = thread_data_list.getThreadData(); + for (int x = range.begin(); x != range.end(); ++x) + { + node_priorities[x] = + this->EvaluateNodePriority(data, &node_data[x], x); + } + }); std::cout << "ok" << std::endl << "preprocessing " << number_of_nodes << " nodes ..." << std::flush; @@ -368,7 +364,8 @@ class Contractor remaining_nodes[new_node_id].id = new_node_id; } // walk over all nodes - for (const auto i : osrm::irange(0, contractor_graph->GetNumberOfNodes())) + for (const auto i : + osrm::irange(0, contractor_graph->GetNumberOfNodes())) { const NodeID source = i; for (auto current_edge : contractor_graph->GetAdjacentEdgeRange(source)) @@ -384,11 +381,9 @@ class Contractor { // node is not yet contracted. // add (renumbered) outgoing edges to new DynamicGraph. - ContractorEdge new_edge = { - new_node_id_from_orig_id_map[source], - new_node_id_from_orig_id_map[target], - data - }; + ContractorEdge new_edge = {new_node_id_from_orig_id_map[source], + new_node_id_from_orig_id_map[target], + data}; new_edge.data.is_original_via_node_ID = true; BOOST_ASSERT_MSG(UINT_MAX != new_node_id_from_orig_id_map[source], @@ -427,28 +422,30 @@ class Contractor const int last = (int)remaining_nodes.size(); tbb::parallel_for(tbb::blocked_range(0, last, IndependentGrainSize), - [this, &node_priorities, &remaining_nodes, &thread_data_list](const tbb::blocked_range& range) - { - ContractorThreadData *data = thread_data_list.getThreadData(); - // determine independent node set - for (int i = range.begin(); i != range.end(); ++i) - { - const NodeID node = remaining_nodes[i].id; - remaining_nodes[i].is_independent = - this->IsNodeIndependent(node_priorities, data, node); - } - } - ); + [this, &node_priorities, &remaining_nodes, &thread_data_list]( + const tbb::blocked_range &range) + { + ContractorThreadData *data = thread_data_list.getThreadData(); + // determine independent node set + for (int i = range.begin(); i != range.end(); ++i) + { + const NodeID node = remaining_nodes[i].id; + remaining_nodes[i].is_independent = + this->IsNodeIndependent(node_priorities, data, node); + } + }); - const auto first = stable_partition(remaining_nodes.begin(), - remaining_nodes.end(), + const auto first = stable_partition(remaining_nodes.begin(), remaining_nodes.end(), [](RemainingNodeData node_data) - { return !node_data.is_independent; }); + { + return !node_data.is_independent; + }); const int first_independent_node = static_cast(first - remaining_nodes.begin()); // contract independent nodes - tbb::parallel_for(tbb::blocked_range(first_independent_node, last, ContractGrainSize), - [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range& range) + tbb::parallel_for( + tbb::blocked_range(first_independent_node, last, ContractGrainSize), + [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range &range) { ContractorThreadData *data = thread_data_list.getThreadData(); for (int position = range.begin(); position != range.end(); ++position) @@ -456,19 +453,18 @@ class Contractor const NodeID x = remaining_nodes[position].id; this->ContractNode(data, x); } - } - ); + }); // make sure we really sort each block - tbb::parallel_for(thread_data_list.data.range(), - [&](const ThreadDataContainer::EnumerableThreadData::range_type& range) + tbb::parallel_for( + thread_data_list.data.range(), + [&](const ThreadDataContainer::EnumerableThreadData::range_type &range) { - for (auto& data : range) - std::sort(data->inserted_edges.begin(), - data->inserted_edges.end()); - } - ); - tbb::parallel_for(tbb::blocked_range(first_independent_node, last, DeleteGrainSize), - [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range& range) + for (auto &data : range) + std::sort(data->inserted_edges.begin(), data->inserted_edges.end()); + }); + tbb::parallel_for( + tbb::blocked_range(first_independent_node, last, DeleteGrainSize), + [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range &range) { ContractorThreadData *data = thread_data_list.getThreadData(); for (int position = range.begin(); position != range.end(); ++position) @@ -476,15 +472,15 @@ class Contractor const NodeID x = remaining_nodes[position].id; this->DeleteIncomingEdges(data, x); } - } - ); + }); // insert new edges - for (auto& data : thread_data_list.data) + for (auto &data : thread_data_list.data) { for (const ContractorEdge &edge : data->inserted_edges) { - const EdgeID current_edge_ID = contractor_graph->FindEdge(edge.source, edge.target); + const EdgeID current_edge_ID = + contractor_graph->FindEdge(edge.source, edge.target); if (current_edge_ID < contractor_graph->EndEdges(edge.source)) { ContractorGraph::EdgeData ¤t_data = @@ -503,8 +499,10 @@ class Contractor data->inserted_edges.clear(); } - tbb::parallel_for(tbb::blocked_range(first_independent_node, last, NeighboursGrainSize), - [this, &remaining_nodes, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range& range) + tbb::parallel_for( + tbb::blocked_range(first_independent_node, last, NeighboursGrainSize), + [this, &remaining_nodes, &node_priorities, &node_data, &thread_data_list]( + const tbb::blocked_range &range) { ContractorThreadData *data = thread_data_list.getThreadData(); for (int position = range.begin(); position != range.end(); ++position) @@ -512,8 +510,7 @@ class Contractor NodeID x = remaining_nodes[position].id; this->UpdateNodeNeighbours(node_priorities, node_data, data, x); } - } - ); + }); // remove contracted nodes from the pool number_of_contracted_nodes += last - first_independent_node; @@ -774,17 +771,11 @@ class Contractor { inserted_edges.emplace_back(source, target, path_distance, out_data.originalEdges + in_data.originalEdges, - node, - true, - true, - false); + node, true, true, false); inserted_edges.emplace_back(target, source, path_distance, out_data.originalEdges + in_data.originalEdges, - node, - true, - false, - true); + node, true, false, true); } } } @@ -883,10 +874,9 @@ class Contractor return true; } - inline bool IsNodeIndependent( - const std::vector &priorities, - ContractorThreadData *const data, - NodeID node) const + inline bool IsNodeIndependent(const std::vector &priorities, + ContractorThreadData *const data, + NodeID node) const { const float priority = priorities[node]; diff --git a/contractor/edge_based_graph_factory.cpp b/contractor/edge_based_graph_factory.cpp index 692bf2aa2..4f50b77b5 100644 --- a/contractor/edge_based_graph_factory.cpp +++ b/contractor/edge_based_graph_factory.cpp @@ -28,11 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "edge_based_graph_factory.hpp" #include "../algorithms/tiny_components.hpp" #include "../data_structures/percent.hpp" -#include "../Util/compute_angle.hpp" -#include "../Util/integer_range.hpp" -#include "../Util/lua_util.hpp" -#include "../Util/simple_logger.hpp" -#include "../Util/timing_util.hpp" +#include "../util/compute_angle.hpp" +#include "../util/integer_range.hpp" +#include "../util/lua_util.hpp" +#include "../util/simple_logger.hpp" +#include "../util/timing_util.hpp" #include diff --git a/contractor/geometry_compressor.cpp b/contractor/geometry_compressor.cpp index 9458c4415..5af89c297 100644 --- a/contractor/geometry_compressor.cpp +++ b/contractor/geometry_compressor.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "geometry_compressor.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/simple_logger.hpp" #include #include @@ -174,8 +174,8 @@ void GeometryCompressor::CompressEdge(const EdgeID edge_id_1, m_compressed_geometries[list_to_remove_index]; // found an existing list, append it to the list of edge_id_1 - edge_bucket_list1.insert( - edge_bucket_list1.end(), edge_bucket_list2.begin(), edge_bucket_list2.end()); + edge_bucket_list1.insert(edge_bucket_list1.end(), edge_bucket_list2.begin(), + edge_bucket_list2.end()); // remove the list of edge_id_2 m_edge_id_to_list_index_map.erase(edge_id_2); @@ -211,9 +211,8 @@ void GeometryCompressor::PrintStatistics() const "\n compressed edges: " << compressed_edges << "\n compressed geometries: " << compressed_geometries << "\n longest chain length: " << longest_chain_length - << "\n cmpr ratio: " - << ((float)compressed_edges / - std::max(compressed_geometries, (uint64_t)1)) + << "\n cmpr ratio: " << ((float)compressed_edges / + std::max(compressed_geometries, (uint64_t)1)) << "\n avg chain length: " << (float)compressed_geometries / std::max((uint64_t)1, compressed_edges); @@ -226,16 +225,15 @@ GeometryCompressor::GetBucketReference(const EdgeID edge_id) const return m_compressed_geometries.at(index); } - NodeID GeometryCompressor::GetFirstNodeIDOfBucket(const EdgeID edge_id) const - { - const auto &bucket = GetBucketReference(edge_id); - BOOST_ASSERT(bucket.size() >= 2); - return bucket[1].first; - } - NodeID GeometryCompressor::GetLastNodeIDOfBucket(const EdgeID edge_id) const - { - const auto &bucket = GetBucketReference(edge_id); - BOOST_ASSERT(bucket.size() >= 2); - return bucket[bucket.size()-2].first; - } - +NodeID GeometryCompressor::GetFirstNodeIDOfBucket(const EdgeID edge_id) const +{ + const auto &bucket = GetBucketReference(edge_id); + BOOST_ASSERT(bucket.size() >= 2); + return bucket[1].first; +} +NodeID GeometryCompressor::GetLastNodeIDOfBucket(const EdgeID edge_id) const +{ + const auto &bucket = GetBucketReference(edge_id); + BOOST_ASSERT(bucket.size() >= 2); + return bucket[bucket.size() - 2].first; +} diff --git a/contractor/processing_chain.cpp b/contractor/processing_chain.cpp index 46c12d0dd..ccff7fd09 100644 --- a/contractor/processing_chain.cpp +++ b/contractor/processing_chain.cpp @@ -34,15 +34,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/static_rtree.hpp" #include "../data_structures/restriction_map.hpp" -#include "../Util/git_sha.hpp" -#include "../Util/graph_loader.hpp" -#include "../Util/integer_range.hpp" -#include "../Util/lua_util.hpp" -#include "../Util/make_unique.hpp" -#include "../Util/osrm_exception.hpp" -#include "../Util/simple_logger.hpp" -#include "../Util/string_util.hpp" -#include "../Util/timing_util.hpp" +#include "../util/git_sha.hpp" +#include "../util/graph_loader.hpp" +#include "../util/integer_range.hpp" +#include "../util/lua_util.hpp" +#include "../util/make_unique.hpp" +#include "../util/osrm_exception.hpp" +#include "../util/simple_logger.hpp" +#include "../util/string_util.hpp" +#include "../util/timing_util.hpp" #include "../typedefs.h" #include diff --git a/data_structures/coordinate.cpp b/data_structures/coordinate.cpp index 031fafdce..bbe4f18ff 100644 --- a/data_structures/coordinate.cpp +++ b/data_structures/coordinate.cpp @@ -27,9 +27,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "coordinate_calculation.hpp" -#include "../Util/mercator.hpp" +#include "../util/mercator.hpp" #ifndef NDEBUG -#include "../Util/simple_logger.hpp" +#include "../util/simple_logger.hpp" #endif #include #include diff --git a/data_structures/coordinate_calculation.cpp b/data_structures/coordinate_calculation.cpp index 4ca281115..326a87981 100644 --- a/data_structures/coordinate_calculation.cpp +++ b/data_structures/coordinate_calculation.cpp @@ -27,8 +27,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "coordinate_calculation.hpp" -#include "../Util/mercator.hpp" -#include "../Util/string_util.hpp" +#include "../util/mercator.hpp" +#include "../util/string_util.hpp" #include diff --git a/data_structures/deallocating_vector.hpp b/data_structures/deallocating_vector.hpp index e2f82cfb0..5ea2a81ce 100644 --- a/data_structures/deallocating_vector.hpp +++ b/data_structures/deallocating_vector.hpp @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef DEALLOCATING_VECTOR_HPP #define DEALLOCATING_VECTOR_HPP -#include "../Util/integer_range.hpp" +#include "../util/integer_range.hpp" #include @@ -171,7 +171,10 @@ class DeallocatingVector // this forward-only iterator deallocates all buckets that have been visited using deallocation_iterator = DeallocatingVectorRemoveIterator; - DeallocatingVector() : current_size(0) { bucket_list.emplace_back(new ElementT[ELEMENTS_PER_BLOCK]); } + DeallocatingVector() : current_size(0) + { + bucket_list.emplace_back(new ElementT[ELEMENTS_PER_BLOCK]); + } ~DeallocatingVector() { clear(); } @@ -192,7 +195,8 @@ class DeallocatingVector bucket = nullptr; } } - bucket_list.clear(); bucket_list.shrink_to_fit(); + bucket_list.clear(); + bucket_list.shrink_to_fit(); current_size = 0; } @@ -222,7 +226,7 @@ class DeallocatingVector ++current_size; } - void reserve(const std::size_t) const { /* don't do anything */ } + void reserve(const std::size_t) const { /* don't do anything */} void resize(const std::size_t new_size) { @@ -234,9 +238,10 @@ class DeallocatingVector } } else - { // down-size + { // down-size const std::size_t number_of_necessary_buckets = 1 + (new_size / ELEMENTS_PER_BLOCK); - for (const auto bucket_index : osrm::irange(number_of_necessary_buckets, bucket_list.size())) + for (const auto bucket_index : + osrm::irange(number_of_necessary_buckets, bucket_list.size())) { if (nullptr != bucket_list[bucket_index]) { @@ -291,8 +296,7 @@ class DeallocatingVector return (bucket_list[_bucket][_index]); } - template - void append(InputIterator first, const InputIterator last) + template void append(InputIterator first, const InputIterator last) { InputIterator position = first; while (position != last) diff --git a/data_structures/dynamic_graph.hpp b/data_structures/dynamic_graph.hpp index 7244d1e9c..4a666c136 100644 --- a/data_structures/dynamic_graph.hpp +++ b/data_structures/dynamic_graph.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define DYNAMICGRAPH_HPP #include "deallocating_vector.hpp" -#include "../Util/integer_range.hpp" +#include "../util/integer_range.hpp" #include @@ -55,10 +55,17 @@ template class DynamicGraph NodeIterator target; EdgeDataT data; - InputEdge() : source(std::numeric_limits::max()), target(std::numeric_limits::max()) { } + InputEdge() + : source(std::numeric_limits::max()), + target(std::numeric_limits::max()) + { + } - template - InputEdge(NodeIterator source, NodeIterator target, Ts &&...data) : source(source), target(target), data(std::forward(data)...) { } + template + InputEdge(NodeIterator source, NodeIterator target, Ts &&... data) + : source(source), target(target), data(std::forward(data)...) + { + } bool operator<(const InputEdge &right) const { @@ -106,7 +113,7 @@ template class DynamicGraph for (const auto node : osrm::irange(0u, number_of_nodes)) { for (const auto i : osrm::irange(node_list[node].firstEdge, - node_list[node].firstEdge + node_list[node].edges)) + node_list[node].firstEdge + node_list[node].edges)) { edge_list[i].target = graph[edge].target; edge_list[i].data = graph[edge].data; diff --git a/data_structures/node_based_graph.hpp b/data_structures/node_based_graph.hpp index 8fe7b7550..49dba2c08 100644 --- a/data_structures/node_based_graph.hpp +++ b/data_structures/node_based_graph.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "dynamic_graph.hpp" #include "import_edge.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/simple_logger.hpp" #include @@ -40,9 +40,9 @@ struct NodeBasedEdgeData { NodeBasedEdgeData() : distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID), - nameID(std::numeric_limits::max()), - isAccessRestricted(false), shortcut(false), forward(false), backward(false), - roundabout(false), ignore_in_grid(false), travel_mode(TRAVEL_MODE_INACCESSIBLE) + nameID(std::numeric_limits::max()), isAccessRestricted(false), shortcut(false), + forward(false), backward(false), roundabout(false), ignore_in_grid(false), + travel_mode(TRAVEL_MODE_INACCESSIBLE) { } @@ -85,7 +85,8 @@ using SimpleNodeBasedDynamicGraph = DynamicGraph; inline std::shared_ptr NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector &input_edge_list) { - static_assert(sizeof(NodeBasedEdgeData) == 16, "changing node based edge data size changes memory consumption"); + static_assert(sizeof(NodeBasedEdgeData) == 16, + "changing node based edge data size changes memory consumption"); DeallocatingVector edges_list; NodeBasedDynamicGraph::InputEdge edge; @@ -134,7 +135,7 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector::max(); + forward_edge.data.distance = reverse_edge.data.distance = std::numeric_limits::max(); // remove parallel edges - while (i < edges_list.size() && edges_list[i].source == source && edges_list[i].target == target) + while (i < edges_list.size() && edges_list[i].source == source && + edges_list[i].target == target) { if (edges_list[i].data.forward) { @@ -189,17 +190,20 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector(static_cast(number_of_nodes), edges_list); + auto graph = std::make_shared( + static_cast(number_of_nodes), edges_list); return graph; } -template +template inline std::shared_ptr SimpleNodeBasedDynamicGraphFromEdges(int number_of_nodes, std::vector &input_edge_list) { - static_assert(sizeof(NodeBasedEdgeData) == 16, "changing node based edge data size changes memory consumption"); + static_assert(sizeof(NodeBasedEdgeData) == 16, + "changing node based edge data size changes memory consumption"); tbb::parallel_sort(input_edge_list.begin(), input_edge_list.end()); DeallocatingVector edges_list; @@ -218,10 +222,10 @@ SimpleNodeBasedDynamicGraphFromEdges(int number_of_nodes, std::vector(number_of_nodes, edges_list); return graph; diff --git a/data_structures/range_table.hpp b/data_structures/range_table.hpp index eef268b9d..ec0167231 100644 --- a/data_structures/range_table.hpp +++ b/data_structures/range_table.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef RANGE_TABLE_HPP #define RANGE_TABLE_HPP -#include "../Util/integer_range.hpp" +#include "../util/integer_range.hpp" #include "shared_memory_factory.hpp" #include "shared_memory_vector_wrapper.hpp" @@ -41,13 +41,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * and otherwise the compiler gets confused. */ -template class RangeTable; +template class RangeTable; -template -std::ostream& operator<<(std::ostream &out, const RangeTable &table); +template +std::ostream &operator<<(std::ostream &out, const RangeTable &table); -template -std::istream& operator>>(std::istream &in, RangeTable &table); +template +std::istream &operator>>(std::istream &in, RangeTable &table); /** * Stores adjacent ranges in a compressed format. @@ -58,33 +58,34 @@ std::istream& operator>>(std::istream &in, RangeTable -class RangeTable +template class RangeTable { -public: - + public: using BlockT = std::array; using BlockContainerT = typename ShM::vector; using OffsetContainerT = typename ShM::vector; using RangeT = osrm::range; - friend std::ostream& operator<< <>(std::ostream &out, const RangeTable &table); - friend std::istream& operator>> <>(std::istream &in, RangeTable &table); + friend std::ostream &operator<<<>(std::ostream &out, const RangeTable &table); + friend std::istream &operator>><>(std::istream &in, RangeTable &table); RangeTable() : sum_lengths(0) {} // for loading from shared memory - explicit RangeTable(OffsetContainerT& external_offsets, BlockContainerT& external_blocks, const unsigned sum_lengths) - : sum_lengths(sum_lengths) + explicit RangeTable(OffsetContainerT &external_offsets, + BlockContainerT &external_blocks, + const unsigned sum_lengths) + : sum_lengths(sum_lengths) { block_offsets.swap(external_offsets); diff_blocks.swap(external_blocks); } // construct table from length vector - explicit RangeTable(const std::vector& lengths) + explicit RangeTable(const std::vector &lengths) { - const unsigned number_of_blocks = [&lengths]() { + const unsigned number_of_blocks = [&lengths]() + { unsigned num = (lengths.size() + 1) / (BLOCK_SIZE + 1); if ((lengths.size() + 1) % (BLOCK_SIZE + 1) != 0) { @@ -116,8 +117,8 @@ public: block_sum += last_length; } - BOOST_ASSERT((block_idx == 0 && block_offsets[block_counter] == lengths_prefix_sum) - || lengths_prefix_sum == (block_offsets[block_counter]+block_sum)); + BOOST_ASSERT((block_idx == 0 && block_offsets[block_counter] == lengths_prefix_sum) || + lengths_prefix_sum == (block_offsets[block_counter] + block_sum)); // block is full if (BLOCK_SIZE == block_idx) @@ -136,7 +137,7 @@ public: } // Last block can't be finished because we didn't add the sentinel - BOOST_ASSERT (block_counter == (number_of_blocks - 1)); + BOOST_ASSERT(block_counter == (number_of_blocks - 1)); // one block missing: starts with guard value if (0 == block_idx) @@ -155,7 +156,8 @@ public: } diff_blocks.push_back(block); - BOOST_ASSERT(diff_blocks.size() == number_of_blocks && block_offsets.size() == number_of_blocks); + BOOST_ASSERT(diff_blocks.size() == number_of_blocks && + block_offsets.size() == number_of_blocks); sum_lengths = lengths_prefix_sum; } @@ -172,7 +174,7 @@ public: unsigned begin_idx = 0; unsigned end_idx = 0; begin_idx = block_offsets[block_idx]; - const BlockT& block = diff_blocks[block_idx]; + const BlockT &block = diff_blocks[block_idx]; if (internal_idx > 0) { begin_idx += PrefixSumAtIndex(internal_idx - 1, block); @@ -195,9 +197,9 @@ public: return osrm::irange(begin_idx, end_idx); } -private: - inline unsigned PrefixSumAtIndex(int index, const BlockT& block) const; + private: + inline unsigned PrefixSumAtIndex(int index, const BlockT &block) const; // contains offset for each differential block OffsetContainerT block_offsets; @@ -206,8 +208,9 @@ private: unsigned sum_lengths; }; -template -unsigned RangeTable::PrefixSumAtIndex(int index, const BlockT& block) const +template +unsigned RangeTable::PrefixSumAtIndex(int index, + const BlockT &block) const { // this loop looks inefficent, but a modern compiler // will emit nice SIMD here, at least for sensible block sizes. (I checked.) @@ -220,39 +223,39 @@ unsigned RangeTable::PrefixSumAtIndex(int index, return sum; } -template -std::ostream& operator<<(std::ostream &out, const RangeTable &table) +template +std::ostream &operator<<(std::ostream &out, const RangeTable &table) { // write number of block const unsigned number_of_blocks = table.diff_blocks.size(); - out.write((char *) &number_of_blocks, sizeof(unsigned)); + out.write((char *)&number_of_blocks, sizeof(unsigned)); // write total length - out.write((char *) &table.sum_lengths, sizeof(unsigned)); + out.write((char *)&table.sum_lengths, sizeof(unsigned)); // write block offsets - out.write((char *) table.block_offsets.data(), sizeof(unsigned) * table.block_offsets.size()); + out.write((char *)table.block_offsets.data(), sizeof(unsigned) * table.block_offsets.size()); // write blocks - out.write((char *) table.diff_blocks.data(), BLOCK_SIZE * table.diff_blocks.size()); + out.write((char *)table.diff_blocks.data(), BLOCK_SIZE * table.diff_blocks.size()); return out; } -template -std::istream& operator>>(std::istream &in, RangeTable &table) +template +std::istream &operator>>(std::istream &in, RangeTable &table) { // read number of block unsigned number_of_blocks; - in.read((char *) &number_of_blocks, sizeof(unsigned)); + in.read((char *)&number_of_blocks, sizeof(unsigned)); // read total length - in.read((char *) &table.sum_lengths, sizeof(unsigned)); + in.read((char *)&table.sum_lengths, sizeof(unsigned)); table.block_offsets.resize(number_of_blocks); table.diff_blocks.resize(number_of_blocks); // read block offsets - in.read((char *) table.block_offsets.data(), sizeof(unsigned) * number_of_blocks); + in.read((char *)table.block_offsets.data(), sizeof(unsigned) * number_of_blocks); // read blocks - in.read((char *) table.diff_blocks.data(), BLOCK_SIZE * number_of_blocks); + in.read((char *)table.diff_blocks.data(), BLOCK_SIZE * number_of_blocks); return in; } -#endif //RANGE_TABLE_HPP +#endif // RANGE_TABLE_HPP diff --git a/data_structures/restriction_map.hpp b/data_structures/restriction_map.hpp index 41eb17a8c..a11b987f2 100644 --- a/data_structures/restriction_map.hpp +++ b/data_structures/restriction_map.hpp @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define RESTRICTION_MAP_HPP #include "restriction.hpp" -#include "../Util/std_hash.hpp" +#include "../util/std_hash.hpp" #include "../typedefs.h" #include @@ -44,9 +44,7 @@ struct RestrictionSource NodeID start_node; NodeID via_node; - RestrictionSource(NodeID start, NodeID via) : start_node(start), via_node(via) - { - } + RestrictionSource(NodeID start, NodeID via) : start_node(start), via_node(via) {} friend inline bool operator==(const RestrictionSource &lhs, const RestrictionSource &rhs) { @@ -59,9 +57,7 @@ struct RestrictionTarget NodeID target_node; bool is_only; - explicit RestrictionTarget(NodeID target, bool only) : target_node(target), is_only(only) - { - } + explicit RestrictionTarget(NodeID target, bool only) : target_node(target), is_only(only) {} friend inline bool operator==(const RestrictionTarget &lhs, const RestrictionTarget &rhs) { @@ -98,7 +94,7 @@ class RestrictionMap RestrictionMap(const std::vector &restriction_list); // Replace end v with w in each turn restriction containing u as via node - template + template void FixupArrivingTurnRestriction(const NodeID node_u, const NodeID node_v, const NodeID node_w, @@ -148,24 +144,18 @@ class RestrictionMap bool IsViaNode(const NodeID node) const; - // Replaces start edge (v, w) with (u, w). Only start node changes. - void FixupStartingTurnRestriction(const NodeID node_u, - const NodeID node_v, - const NodeID node_w); + void + FixupStartingTurnRestriction(const NodeID node_u, const NodeID node_v, const NodeID node_w); // Check if edge (u, v) is the start of any turn restriction. // If so returns id of first target node. NodeID CheckForEmanatingIsOnlyTurn(const NodeID node_u, const NodeID node_v) const; // Checks if turn is actually a turn restriction. - bool CheckIfTurnIsRestricted(const NodeID node_u, - const NodeID node_v, - const NodeID node_w) const; + bool + CheckIfTurnIsRestricted(const NodeID node_u, const NodeID node_v, const NodeID node_w) const; - std::size_t size() - { - return m_count; - } + std::size_t size() { return m_count; } private: // check of node is the start of any restriction @@ -182,4 +172,4 @@ class RestrictionMap std::unordered_set m_no_turn_via_node_set; }; -#endif //RESTRICTION_MAP_HPP +#endif // RESTRICTION_MAP_HPP diff --git a/data_structures/shared_memory_factory.hpp b/data_structures/shared_memory_factory.hpp index dc714a68b..56e458ff1 100644 --- a/data_structures/shared_memory_factory.hpp +++ b/data_structures/shared_memory_factory.hpp @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef SHARED_MEMORY_FACTORY_HPP #define SHARED_MEMORY_FACTORY_HPP -#include "../Util/osrm_exception.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/osrm_exception.hpp" +#include "../util/simple_logger.hpp" #include #include @@ -123,8 +123,8 @@ class SharedMemory { Remove(key); } - shm = boost::interprocess::xsi_shared_memory( - boost::interprocess::open_or_create, key, size); + shm = boost::interprocess::xsi_shared_memory(boost::interprocess::open_or_create, key, + size); #ifdef __linux__ if (-1 == shmctl(shm.get_shmid(), SHM_LOCK, 0)) { @@ -150,7 +150,10 @@ class SharedMemory boost::interprocess::xsi_key key(lock_file().string().c_str(), id); result = RegionExists(key); } - catch (...) { result = false; } + catch (...) + { + result = false; + } return result; } @@ -165,8 +168,14 @@ class SharedMemory static bool RegionExists(const boost::interprocess::xsi_key &key) { bool result = true; - try { boost::interprocess::xsi_shared_memory shm(boost::interprocess::open_only, key); } - catch (...) { result = false; } + try + { + boost::interprocess::xsi_shared_memory shm(boost::interprocess::open_only, key); + } + catch (...) + { + result = false; + } return result; } @@ -198,12 +207,12 @@ class SharedMemory // Windows - specific code class SharedMemory { - SharedMemory(const SharedMemory&) = delete; + SharedMemory(const SharedMemory &) = delete; // Remove shared memory on destruction class shm_remove { private: - shm_remove(const shm_remove&) = delete; + shm_remove(const shm_remove &) = delete; char *m_shmid; bool m_initialized; @@ -242,8 +251,7 @@ class SharedMemory if (0 == size) { // read_only shm = boost::interprocess::shared_memory_object( - boost::interprocess::open_only, - key, + boost::interprocess::open_only, key, read_write ? boost::interprocess::read_write : boost::interprocess::read_only); region = boost::interprocess::mapped_region( shm, read_write ? boost::interprocess::read_write : boost::interprocess::read_only); @@ -255,8 +263,8 @@ class SharedMemory { Remove(key); } - shm = boost::interprocess::shared_memory_object( - boost::interprocess::open_or_create, key, boost::interprocess::read_write); + shm = boost::interprocess::shared_memory_object(boost::interprocess::open_or_create, + key, boost::interprocess::read_write); shm.truncate(size); region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write); @@ -274,7 +282,10 @@ class SharedMemory build_key(id, k); result = RegionExists(k); } - catch (...) { result = false; } + catch (...) + { + result = false; + } return result; } @@ -286,20 +297,20 @@ class SharedMemory } private: - static void build_key(int id, char *key) - { - sprintf(key, "%s.%d", "osrm.lock", id); - } + static void build_key(int id, char *key) { sprintf(key, "%s.%d", "osrm.lock", id); } static bool RegionExists(const char *key) { bool result = true; try { - boost::interprocess::shared_memory_object shm( - boost::interprocess::open_only, key, boost::interprocess::read_write); + boost::interprocess::shared_memory_object shm(boost::interprocess::open_only, key, + boost::interprocess::read_write); + } + catch (...) + { + result = false; } - catch (...) { result = false; } return result; } diff --git a/data_structures/static_graph.hpp b/data_structures/static_graph.hpp index 05d65eeee..1358027f7 100644 --- a/data_structures/static_graph.hpp +++ b/data_structures/static_graph.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "percent.hpp" #include "shared_memory_vector_wrapper.hpp" -#include "../Util/integer_range.hpp" +#include "../util/integer_range.hpp" #include "../typedefs.h" #include @@ -57,8 +57,11 @@ template class StaticGraph NodeIterator target; EdgeDataT data; - template - InputEdge(NodeIterator source, NodeIterator target, Ts &&...data) : source(source), target(target), data(std::forward(data)...) { } + template + InputEdge(NodeIterator source, NodeIterator target, Ts &&... data) + : source(source), target(target), data(std::forward(data)...) + { + } bool operator<(const InputEdge &right) const { if (source != right.source) @@ -94,7 +97,7 @@ template class StaticGraph node_array.resize(number_of_nodes + 1); EdgeIterator edge = 0; EdgeIterator position = 0; - for (const auto node : osrm::irange(0u, number_of_nodes+1)) + for (const auto node : osrm::irange(0u, number_of_nodes + 1)) { EdgeIterator last_edge = edge; while (edge < number_of_edges && graph[edge].source == node) diff --git a/data_structures/static_rtree.hpp b/data_structures/static_rtree.hpp index 8ab7fe4c1..5eaf64768 100644 --- a/data_structures/static_rtree.hpp +++ b/data_structures/static_rtree.hpp @@ -37,12 +37,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "shared_memory_vector_wrapper.hpp" #include "upper_bound.hpp" -#include "../Util/floating_point.hpp" -#include "../Util/integer_range.hpp" -#include "../Util/mercator.hpp" -#include "../Util/osrm_exception.hpp" -#include "../Util/simple_logger.hpp" -#include "../Util/timing_util.hpp" +#include "../util/floating_point.hpp" +#include "../util/integer_range.hpp" +#include "../util/mercator.hpp" +#include "../util/osrm_exception.hpp" +#include "../util/simple_logger.hpp" +#include "../util/timing_util.hpp" #include "../typedefs.h" #include @@ -69,8 +69,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. template , bool UseSharedMemory = false, - uint32_t BRANCHING_FACTOR=64, - uint32_t LEAF_NODE_SIZE=1024> + uint32_t BRANCHING_FACTOR = 64, + uint32_t LEAF_NODE_SIZE = 1024> class StaticRTree { public: @@ -87,19 +87,15 @@ class StaticRTree { for (uint32_t i = 0; i < element_count; ++i) { - min_lon = std::min(min_lon, - std::min(coordinate_list.at(objects[i].u).lon, - coordinate_list.at(objects[i].v).lon)); - max_lon = std::max(max_lon, - std::max(coordinate_list.at(objects[i].u).lon, - coordinate_list.at(objects[i].v).lon)); + min_lon = std::min(min_lon, std::min(coordinate_list.at(objects[i].u).lon, + coordinate_list.at(objects[i].v).lon)); + max_lon = std::max(max_lon, std::max(coordinate_list.at(objects[i].u).lon, + coordinate_list.at(objects[i].v).lon)); - min_lat = std::min(min_lat, - std::min(coordinate_list.at(objects[i].u).lat, - coordinate_list.at(objects[i].v).lat)); - max_lat = std::max(max_lat, - std::max(coordinate_list.at(objects[i].u).lat, - coordinate_list.at(objects[i].v).lat)); + min_lat = std::min(min_lat, std::min(coordinate_list.at(objects[i].u).lat, + coordinate_list.at(objects[i].v).lat)); + max_lat = std::max(max_lat, std::max(coordinate_list.at(objects[i].u).lat, + coordinate_list.at(objects[i].v).lat)); } BOOST_ASSERT(min_lat != std::numeric_limits::min()); BOOST_ASSERT(min_lon != std::numeric_limits::min()); @@ -150,58 +146,66 @@ class StaticRTree enum Direction { - INVALID = 0, - NORTH = 1, - SOUTH = 2, - EAST = 4, + INVALID = 0, + NORTH = 1, + SOUTH = 2, + EAST = 4, NORTH_EAST = 5, SOUTH_EAST = 6, - WEST = 8, + WEST = 8, NORTH_WEST = 9, SOUTH_WEST = 10 }; Direction d = INVALID; if (location.lat > max_lat) - d = (Direction) (d | NORTH); + d = (Direction)(d | NORTH); else if (location.lat < min_lat) - d = (Direction) (d | SOUTH); + d = (Direction)(d | SOUTH); if (location.lon > max_lon) - d = (Direction) (d | EAST); + d = (Direction)(d | EAST); else if (location.lon < min_lon) - d = (Direction) (d | WEST); + d = (Direction)(d | WEST); BOOST_ASSERT(d != INVALID); float min_dist = std::numeric_limits::max(); switch (d) { - case NORTH: - min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(max_lat, location.lon)); - break; - case SOUTH: - min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(min_lat, location.lon)); - break; - case WEST: - min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(location.lat, min_lon)); - break; - case EAST: - min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(location.lat, max_lon)); - break; - case NORTH_EAST: - min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(max_lat, max_lon)); - break; - case NORTH_WEST: - min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(max_lat, min_lon)); - break; - case SOUTH_EAST: - min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(min_lat, max_lon)); - break; - case SOUTH_WEST: - min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(min_lat, min_lon)); - break; - default: - break; + case NORTH: + min_dist = coordinate_calculation::euclidean_distance( + location, FixedPointCoordinate(max_lat, location.lon)); + break; + case SOUTH: + min_dist = coordinate_calculation::euclidean_distance( + location, FixedPointCoordinate(min_lat, location.lon)); + break; + case WEST: + min_dist = coordinate_calculation::euclidean_distance( + location, FixedPointCoordinate(location.lat, min_lon)); + break; + case EAST: + min_dist = coordinate_calculation::euclidean_distance( + location, FixedPointCoordinate(location.lat, max_lon)); + break; + case NORTH_EAST: + min_dist = coordinate_calculation::euclidean_distance( + location, FixedPointCoordinate(max_lat, max_lon)); + break; + case NORTH_WEST: + min_dist = coordinate_calculation::euclidean_distance( + location, FixedPointCoordinate(max_lat, min_lon)); + break; + case SOUTH_EAST: + min_dist = coordinate_calculation::euclidean_distance( + location, FixedPointCoordinate(min_lat, max_lon)); + break; + case SOUTH_WEST: + min_dist = coordinate_calculation::euclidean_distance( + location, FixedPointCoordinate(min_lat, min_lon)); + break; + default: + break; } BOOST_ASSERT(min_dist != std::numeric_limits::max()); @@ -220,15 +224,13 @@ class StaticRTree min_max_dist = std::min( min_max_dist, - std::max( - coordinate_calculation::euclidean_distance(location, upper_left), - coordinate_calculation::euclidean_distance(location, upper_right))); + std::max(coordinate_calculation::euclidean_distance(location, upper_left), + coordinate_calculation::euclidean_distance(location, upper_right))); min_max_dist = std::min( min_max_dist, - std::max( - coordinate_calculation::euclidean_distance(location, upper_right), - coordinate_calculation::euclidean_distance(location, lower_right))); + std::max(coordinate_calculation::euclidean_distance(location, upper_right), + coordinate_calculation::euclidean_distance(location, lower_right))); min_max_dist = std::min( min_max_dist, @@ -378,7 +380,8 @@ class StaticRTree FixedPointCoordinate(coordinate_list.at(current_element.v).lat, coordinate_list.at(current_element.v).lon)); current_centroid.lat = - COORDINATE_PRECISION * mercator::lat2y(current_centroid.lat / COORDINATE_PRECISION); + COORDINATE_PRECISION * + mercator::lat2y(current_centroid.lat / COORDINATE_PRECISION); current_wrapper.m_hilbert_value = get_hilbert_number(current_centroid); } @@ -416,8 +419,8 @@ class StaticRTree } // generate tree node that resemble the objects in leaf and store it for next level - InitializeMBRectangle(current_node.minimum_bounding_rectangle, - current_leaf.objects, current_leaf.object_count, coordinate_list); + InitializeMBRectangle(current_node.minimum_bounding_rectangle, current_leaf.objects, + current_leaf.object_count, coordinate_list); current_node.child_is_on_disk = true; current_node.children[0] = tree_nodes_in_level.size(); tree_nodes_in_level.emplace_back(current_node); @@ -440,8 +443,7 @@ class StaticRTree TreeNode parent_node; // pack BRANCHING_FACTOR elements into tree_nodes each for (uint32_t current_child_node_index = 0; - BRANCHING_FACTOR > current_child_node_index; - ++current_child_node_index) + BRANCHING_FACTOR > current_child_node_index; ++current_child_node_index) { if (processed_tree_nodes_in_level < tree_nodes_in_level.size()) { @@ -474,17 +476,17 @@ class StaticRTree tbb::parallel_for(tbb::blocked_range(0, search_tree_size), [this, &search_tree_size](const tbb::blocked_range &range) { - for (uint32_t i = range.begin(); i != range.end(); ++i) - { - TreeNode ¤t_tree_node = this->m_search_tree[i]; - for (uint32_t j = 0; j < current_tree_node.child_count; ++j) - { - const uint32_t old_id = current_tree_node.children[j]; - const uint32_t new_id = search_tree_size - old_id - 1; - current_tree_node.children[j] = new_id; - } - } - }); + for (uint32_t i = range.begin(); i != range.end(); ++i) + { + TreeNode ¤t_tree_node = this->m_search_tree[i]; + for (uint32_t j = 0; j < current_tree_node.child_count; ++j) + { + const uint32_t old_id = current_tree_node.children[j]; + const uint32_t new_id = search_tree_size - old_id - 1; + current_tree_node.children[j] = new_id; + } + } + }); // open tree file boost::filesystem::ofstream tree_node_file(tree_node_filename, std::ios::binary); @@ -606,12 +608,10 @@ class StaticRTree continue; } - float current_minimum_distance = - coordinate_calculation::euclidean_distance( - input_coordinate.lat, - input_coordinate.lon, - m_coordinate_list->at(current_edge.u).lat, - m_coordinate_list->at(current_edge.u).lon); + float current_minimum_distance = coordinate_calculation::euclidean_distance( + input_coordinate.lat, input_coordinate.lon, + m_coordinate_list->at(current_edge.u).lat, + m_coordinate_list->at(current_edge.u).lon); if (current_minimum_distance < min_dist) { // found a new minimum @@ -619,12 +619,10 @@ class StaticRTree result_coordinate = m_coordinate_list->at(current_edge.u); } - current_minimum_distance = - coordinate_calculation::euclidean_distance( - input_coordinate.lat, - input_coordinate.lon, - m_coordinate_list->at(current_edge.v).lat, - m_coordinate_list->at(current_edge.v).lon); + current_minimum_distance = coordinate_calculation::euclidean_distance( + input_coordinate.lat, input_coordinate.lon, + m_coordinate_list->at(current_edge.v).lat, + m_coordinate_list->at(current_edge.v).lon); if (current_minimum_distance < min_dist) { @@ -636,27 +634,23 @@ class StaticRTree } else { - min_max_dist = ExploreTreeNode(current_tree_node, - input_coordinate, - min_dist, - min_max_dist, - traversal_queue); + min_max_dist = ExploreTreeNode(current_tree_node, input_coordinate, min_dist, + min_max_dist, traversal_queue); } } } return result_coordinate.is_valid(); } - // implementation of the Hjaltason/Samet query [3], a BFS traversal of the tree // - searches for k elements nearest elements // - continues to find the k+1st element from a big component if k elements // come from tiny components - bool - IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, - std::vector &result_phantom_node_vector, - const unsigned max_number_of_phantom_nodes, - const unsigned max_checked_elements = 4*LEAF_NODE_SIZE) + bool IncrementalFindPhantomNodeForCoordinate( + const FixedPointCoordinate &input_coordinate, + std::vector &result_phantom_node_vector, + const unsigned max_number_of_phantom_nodes, + const unsigned max_checked_elements = 4 * LEAF_NODE_SIZE) { unsigned inspected_elements = 0; unsigned number_of_elements_from_big_cc = 0; @@ -664,9 +658,9 @@ class StaticRTree unsigned pruned_elements = 0; - std::pair projected_coordinate = - { mercator::lat2y(input_coordinate.lat / COORDINATE_PRECISION), - input_coordinate.lon / COORDINATE_PRECISION }; + std::pair projected_coordinate = { + mercator::lat2y(input_coordinate.lat / COORDINATE_PRECISION), + input_coordinate.lon / COORDINATE_PRECISION}; // upper bound pruning technique upper_bound pruning_bound(max_number_of_phantom_nodes); @@ -682,7 +676,8 @@ class StaticRTree if (current_query_node.node.template is()) { // current object is a tree node - const TreeNode & current_tree_node = current_query_node.node.template get(); + const TreeNode ¤t_tree_node = + current_query_node.node.template get(); if (current_tree_node.child_is_on_disk) { LeafNode current_leaf_node; @@ -692,11 +687,10 @@ class StaticRTree for (const auto i : osrm::irange(0u, current_leaf_node.object_count)) { const auto ¤t_edge = current_leaf_node.objects[i]; - const float current_perpendicular_distance = - coordinate_calculation::perpendicular_distance_from_projected_coordinate( + const float current_perpendicular_distance = coordinate_calculation:: + perpendicular_distance_from_projected_coordinate( m_coordinate_list->at(current_edge.u), - m_coordinate_list->at(current_edge.v), - input_coordinate, + m_coordinate_list->at(current_edge.v), input_coordinate, projected_coordinate); // distance must be non-negative BOOST_ASSERT(0.f <= current_perpendicular_distance); @@ -706,7 +700,9 @@ class StaticRTree { pruning_bound.insert(current_perpendicular_distance); traversal_queue.emplace(current_perpendicular_distance, current_edge); - } else { + } + else + { ++pruned_elements; } } @@ -718,8 +714,10 @@ class StaticRTree { const int32_t child_id = current_tree_node.children[i]; const TreeNode &child_tree_node = m_search_tree[child_id]; - const RectangleT &child_rectangle = child_tree_node.minimum_bounding_rectangle; - const float lower_bound_to_element = child_rectangle.GetMinDist(input_coordinate); + const RectangleT &child_rectangle = + child_tree_node.minimum_bounding_rectangle; + const float lower_bound_to_element = + child_rectangle.GetMinDist(input_coordinate); BOOST_ASSERT(0.f <= lower_bound_to_element); traversal_queue.emplace(lower_bound_to_element, child_tree_node); @@ -730,7 +728,8 @@ class StaticRTree { // current object is a leaf node ++inspected_elements; // inspecting an actual road segment - const EdgeDataT & current_segment = current_query_node.node.template get(); + const EdgeDataT ¤t_segment = + current_query_node.node.template get(); // continue searching for the first segment from a big component if (number_of_elements_from_big_cc == 0 && @@ -744,29 +743,20 @@ class StaticRTree float current_ratio = 0.f; FixedPointCoordinate foot_point_coordinate_on_segment; // const float current_perpendicular_distance = - coordinate_calculation::perpendicular_distance_from_projected_coordinate( - m_coordinate_list->at(current_segment.u), - m_coordinate_list->at(current_segment.v), - input_coordinate, - projected_coordinate, - foot_point_coordinate_on_segment, - current_ratio); + coordinate_calculation::perpendicular_distance_from_projected_coordinate( + m_coordinate_list->at(current_segment.u), + m_coordinate_list->at(current_segment.v), input_coordinate, + projected_coordinate, foot_point_coordinate_on_segment, current_ratio); // store phantom node in result vector result_phantom_node_vector.emplace_back( current_segment.forward_edge_based_node_id, - current_segment.reverse_edge_based_node_id, - current_segment.name_id, - current_segment.forward_weight, - current_segment.reverse_weight, - current_segment.forward_offset, - current_segment.reverse_offset, - current_segment.packed_geometry_id, - current_segment.component_id, - foot_point_coordinate_on_segment, - current_segment.fwd_segment_position, - current_segment.forward_travel_mode, - current_segment.backward_travel_mode); + current_segment.reverse_edge_based_node_id, current_segment.name_id, + current_segment.forward_weight, current_segment.reverse_weight, + current_segment.forward_offset, current_segment.reverse_offset, + current_segment.packed_geometry_id, current_segment.component_id, + foot_point_coordinate_on_segment, current_segment.fwd_segment_position, + current_segment.forward_travel_mode, current_segment.backward_travel_mode); // Hack to fix rounding errors and wandering via nodes. FixUpRoundingIssue(input_coordinate, result_phantom_node_vector.back()); @@ -787,16 +777,20 @@ class StaticRTree } // stop the search by flushing the queue - if ((result_phantom_node_vector.size() >= max_number_of_phantom_nodes && number_of_elements_from_big_cc > 0) || + if ((result_phantom_node_vector.size() >= max_number_of_phantom_nodes && + number_of_elements_from_big_cc > 0) || inspected_elements >= max_checked_elements) { traversal_queue = std::priority_queue{}; } } - // SimpleLogger().Write() << "result_phantom_node_vector.size(): " << result_phantom_node_vector.size(); + // SimpleLogger().Write() << "result_phantom_node_vector.size(): " << + // result_phantom_node_vector.size(); // SimpleLogger().Write() << "max_number_of_phantom_nodes: " << max_number_of_phantom_nodes; - // SimpleLogger().Write() << "number_of_elements_from_big_cc: " << number_of_elements_from_big_cc; - // SimpleLogger().Write() << "number_of_elements_from_tiny_cc: " << number_of_elements_from_tiny_cc; + // SimpleLogger().Write() << "number_of_elements_from_big_cc: " << + // number_of_elements_from_big_cc; + // SimpleLogger().Write() << "number_of_elements_from_tiny_cc: " << + // number_of_elements_from_tiny_cc; // SimpleLogger().Write() << "inspected_elements: " << inspected_elements; // SimpleLogger().Write() << "max_checked_elements: " << max_checked_elements; // SimpleLogger().Write() << "pruned_elements: " << pruned_elements; @@ -805,13 +799,14 @@ class StaticRTree } // implementation of the Hjaltason/Samet query [3], a BFS traversal of the tree - bool - IncrementalFindPhantomNodeForCoordinateWithDistance(const FixedPointCoordinate &input_coordinate, - std::vector> &result_phantom_node_vector, - const unsigned number_of_results, - const unsigned max_checked_segments = 4*LEAF_NODE_SIZE) + bool IncrementalFindPhantomNodeForCoordinateWithDistance( + const FixedPointCoordinate &input_coordinate, + std::vector> &result_phantom_node_vector, + const unsigned number_of_results, + const unsigned max_checked_segments = 4 * LEAF_NODE_SIZE) { - std::vector min_found_distances(number_of_results, std::numeric_limits::max()); + std::vector min_found_distances(number_of_results, + std::numeric_limits::max()); unsigned number_of_results_found_in_big_cc = 0; unsigned number_of_results_found_in_tiny_cc = 0; @@ -827,7 +822,7 @@ class StaticRTree const IncrementalQueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop(); - const float current_min_dist = min_found_distances[number_of_results-1]; + const float current_min_dist = min_found_distances[number_of_results - 1]; if (current_query_node.min_dist > current_min_dist) { @@ -836,7 +831,8 @@ class StaticRTree if (current_query_node.RepresentsTreeNode()) { - const TreeNode & current_tree_node = current_query_node.node.template get(); + const TreeNode ¤t_tree_node = + current_query_node.node.template get(); if (current_tree_node.child_is_on_disk) { LeafNode current_leaf_node; @@ -848,8 +844,7 @@ class StaticRTree const float current_perpendicular_distance = coordinate_calculation::perpendicular_distance( m_coordinate_list->at(current_edge.u), - m_coordinate_list->at(current_edge.v), - input_coordinate); + m_coordinate_list->at(current_edge.v), input_coordinate); // distance must be non-negative BOOST_ASSERT(0. <= current_perpendicular_distance); @@ -866,8 +861,10 @@ class StaticRTree { const int32_t child_id = current_tree_node.children[i]; const TreeNode &child_tree_node = m_search_tree[child_id]; - const RectangleT &child_rectangle = child_tree_node.minimum_bounding_rectangle; - const float lower_bound_to_element = child_rectangle.GetMinDist(input_coordinate); + const RectangleT &child_rectangle = + child_tree_node.minimum_bounding_rectangle; + const float lower_bound_to_element = + child_rectangle.GetMinDist(input_coordinate); // TODO - enough elements found, i.e. nearest distance > maximum distance? // ie. some measure of 'confidence of accuracy' @@ -878,23 +875,27 @@ class StaticRTree traversal_queue.emplace(lower_bound_to_element, child_tree_node); } } - // SimpleLogger().Write(logDEBUG) << "added " << current_tree_node.child_count << " mbrs into queue of " << traversal_queue.size(); + // SimpleLogger().Write(logDEBUG) << "added " << current_tree_node.child_count + // << " mbrs into queue of " << traversal_queue.size(); } } else { ++inspected_segments; // inspecting an actual road segment - const EdgeDataT & current_segment = current_query_node.node.template get(); + const EdgeDataT ¤t_segment = + current_query_node.node.template get(); // don't collect too many results from small components - if (number_of_results_found_in_big_cc == number_of_results && !current_segment.is_in_tiny_cc) + if (number_of_results_found_in_big_cc == number_of_results && + !current_segment.is_in_tiny_cc) { continue; } // don't collect too many results from big components - if (number_of_results_found_in_tiny_cc == number_of_results && current_segment.is_in_tiny_cc) + if (number_of_results_found_in_tiny_cc == number_of_results && + current_segment.is_in_tiny_cc) { continue; } @@ -905,10 +906,8 @@ class StaticRTree const float current_perpendicular_distance = coordinate_calculation::perpendicular_distance( m_coordinate_list->at(current_segment.u), - m_coordinate_list->at(current_segment.v), - input_coordinate, - foot_point_coordinate_on_segment, - current_ratio); + m_coordinate_list->at(current_segment.v), input_coordinate, + foot_point_coordinate_on_segment, current_ratio); BOOST_ASSERT(0. <= current_perpendicular_distance); @@ -918,16 +917,11 @@ class StaticRTree // store phantom node in result vector result_phantom_node_vector.emplace_back( current_segment.forward_edge_based_node_id, - current_segment.reverse_edge_based_node_id, - current_segment.name_id, - current_segment.forward_weight, - current_segment.reverse_weight, - current_segment.forward_offset, - current_segment.reverse_offset, - current_segment.packed_geometry_id, - foot_point_coordinate_on_segment, - current_segment.fwd_segment_position, - current_perpendicular_distance); + current_segment.reverse_edge_based_node_id, current_segment.name_id, + current_segment.forward_weight, current_segment.reverse_weight, + current_segment.forward_offset, current_segment.reverse_offset, + current_segment.packed_geometry_id, foot_point_coordinate_on_segment, + current_segment.fwd_segment_position, current_perpendicular_distance); // Hack to fix rounding errors and wandering via nodes. FixUpRoundingIssue(input_coordinate, result_phantom_node_vector.back()); @@ -944,17 +938,22 @@ class StaticRTree else { // found an element in a large component - min_found_distances[number_of_results_found_in_big_cc] = current_perpendicular_distance; + min_found_distances[number_of_results_found_in_big_cc] = + current_perpendicular_distance; ++number_of_results_found_in_big_cc; - // SimpleLogger().Write(logDEBUG) << std::setprecision(8) << foot_point_coordinate_on_segment << " at " << current_perpendicular_distance; + // SimpleLogger().Write(logDEBUG) << std::setprecision(8) << + // foot_point_coordinate_on_segment << " at " << + // current_perpendicular_distance; } } } // TODO add indicator to prune if maxdist > threshold - if (number_of_results == number_of_results_found_in_big_cc || inspected_segments >= max_checked_segments) + if (number_of_results == number_of_results_found_in_big_cc || + inspected_segments >= max_checked_segments) { - // SimpleLogger().Write(logDEBUG) << "flushing queue of " << traversal_queue.size() << " elements"; + // SimpleLogger().Write(logDEBUG) << "flushing queue of " << traversal_queue.size() + // << " elements"; // work-around for traversal_queue.clear(); traversal_queue = std::priority_queue{}; } @@ -963,8 +962,6 @@ class StaticRTree return !result_phantom_node_vector.empty(); } - - bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, PhantomNode &result_phantom_node, const unsigned zoom_level) @@ -1005,9 +1002,7 @@ class StaticRTree const float current_perpendicular_distance = coordinate_calculation::perpendicular_distance( m_coordinate_list->at(current_edge.u), - m_coordinate_list->at(current_edge.v), - input_coordinate, - nearest, + m_coordinate_list->at(current_edge.v), input_coordinate, nearest, current_ratio); BOOST_ASSERT(0. <= current_perpendicular_distance); @@ -1035,11 +1030,8 @@ class StaticRTree } else { - min_max_dist = ExploreTreeNode(current_tree_node, - input_coordinate, - min_dist, - min_max_dist, - traversal_queue); + min_max_dist = ExploreTreeNode(current_tree_node, input_coordinate, min_dist, + min_max_dist, traversal_queue); } } } @@ -1056,8 +1048,7 @@ class StaticRTree } private: - - inline void SetForwardAndReverseWeightsOnPhantomNode(const EdgeDataT & nearest_edge, + inline void SetForwardAndReverseWeightsOnPhantomNode(const EdgeDataT &nearest_edge, PhantomNode &result_phantom_node) const { const float distance_1 = coordinate_calculation::euclidean_distance( @@ -1069,32 +1060,34 @@ class StaticRTree using TreeWeightType = decltype(result_phantom_node.forward_weight); static_assert(std::is_same::value, - "forward and reverse weight type in tree must be the same"); + "forward and reverse weight type in tree must be the same"); if (SPECIAL_NODEID != result_phantom_node.forward_node_id) { - const auto new_weight = static_cast(result_phantom_node.forward_weight * ratio); + const auto new_weight = + static_cast(result_phantom_node.forward_weight * ratio); result_phantom_node.forward_weight = new_weight; } if (SPECIAL_NODEID != result_phantom_node.reverse_node_id) { - const auto new_weight = static_cast(result_phantom_node.reverse_weight * (1.f-ratio)); + const auto new_weight = + static_cast(result_phantom_node.reverse_weight * (1.f - ratio)); result_phantom_node.reverse_weight = new_weight; } } // fixup locations if too close to inputs inline void FixUpRoundingIssue(const FixedPointCoordinate &input_coordinate, - PhantomNode &result_phantom_node) const + PhantomNode &result_phantom_node) const { - if (1 == std::abs(input_coordinate.lon - result_phantom_node.location.lon)) - { - result_phantom_node.location.lon = input_coordinate.lon; - } - if (1 == std::abs(input_coordinate.lat - result_phantom_node.location.lat)) - { - result_phantom_node.location.lat = input_coordinate.lat; - } + if (1 == std::abs(input_coordinate.lon - result_phantom_node.location.lon)) + { + result_phantom_node.location.lon = input_coordinate.lon; + } + if (1 == std::abs(input_coordinate.lat - result_phantom_node.location.lat)) + { + result_phantom_node.location.lat = input_coordinate.lat; + } } template @@ -1140,8 +1133,7 @@ class StaticRTree } const uint64_t seek_pos = sizeof(uint64_t) + leaf_id * sizeof(LeafNode); leaves_stream.seekg(seek_pos); - BOOST_ASSERT_MSG(leaves_stream.good(), - "Seeking to position in leaf file failed."); + BOOST_ASSERT_MSG(leaves_stream.good(), "Seeking to position in leaf file failed."); leaves_stream.read((char *)&result_node, sizeof(LeafNode)); BOOST_ASSERT_MSG(leaves_stream.good(), "Reading from leaf file failed."); } @@ -1154,26 +1146,26 @@ class StaticRTree return (a == b && c == d) || (a == c && b == d) || (a == d && b == c); } - inline void InitializeMBRectangle(RectangleT& rectangle, + inline void InitializeMBRectangle(RectangleT &rectangle, const std::array &objects, const uint32_t element_count, const std::vector &coordinate_list) { for (uint32_t i = 0; i < element_count; ++i) { - rectangle.min_lon = std::min(rectangle.min_lon, - std::min(coordinate_list.at(objects[i].u).lon, - coordinate_list.at(objects[i].v).lon)); - rectangle.max_lon = std::max(rectangle.max_lon, - std::max(coordinate_list.at(objects[i].u).lon, - coordinate_list.at(objects[i].v).lon)); + rectangle.min_lon = + std::min(rectangle.min_lon, std::min(coordinate_list.at(objects[i].u).lon, + coordinate_list.at(objects[i].v).lon)); + rectangle.max_lon = + std::max(rectangle.max_lon, std::max(coordinate_list.at(objects[i].u).lon, + coordinate_list.at(objects[i].v).lon)); - rectangle.min_lat = std::min(rectangle.min_lat, - std::min(coordinate_list.at(objects[i].u).lat, - coordinate_list.at(objects[i].v).lat)); - rectangle.max_lat = std::max(rectangle.max_lat, - std::max(coordinate_list.at(objects[i].u).lat, - coordinate_list.at(objects[i].v).lat)); + rectangle.min_lat = + std::min(rectangle.min_lat, std::min(coordinate_list.at(objects[i].u).lat, + coordinate_list.at(objects[i].v).lat)); + rectangle.max_lat = + std::max(rectangle.max_lat, std::max(coordinate_list.at(objects[i].u).lat, + coordinate_list.at(objects[i].v).lat)); } BOOST_ASSERT(rectangle.min_lat != std::numeric_limits::min()); BOOST_ASSERT(rectangle.min_lon != std::numeric_limits::min()); diff --git a/datastore.cpp b/datastore.cpp index bcb1d8b43..e701b4e89 100644 --- a/datastore.cpp +++ b/datastore.cpp @@ -36,11 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "server/data_structures/datafacade_base.hpp" #include "server/data_structures/shared_datatype.hpp" #include "server/data_structures/shared_barriers.hpp" -#include "Util/boost_filesystem_2_fix.hpp" -#include "Util/datastore_options.hpp" -#include "Util/simple_logger.hpp" -#include "Util/osrm_exception.hpp" -#include "Util/fingerprint.hpp" +#include "util/boost_filesystem_2_fix.hpp" +#include "util/datastore_options.hpp" +#include "util/simple_logger.hpp" +#include "util/osrm_exception.hpp" +#include "util/fingerprint.hpp" #include "typedefs.h" #include diff --git a/descriptors/description_factory.cpp b/descriptors/description_factory.cpp index 5c19c34e5..034dc88ae 100644 --- a/descriptors/description_factory.cpp +++ b/descriptors/description_factory.cpp @@ -31,8 +31,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/coordinate_calculation.hpp" #include "../data_structures/internal_route_result.hpp" #include "../data_structures/turn_instructions.hpp" -#include "../Util/container.hpp" -#include "../Util/integer_range.hpp" +#include "../util/container.hpp" +#include "../util/integer_range.hpp" #include "../typedefs.h" DescriptionFactory::DescriptionFactory() : entire_length(0) { via_indices.push_back(0); } diff --git a/descriptors/gpx_descriptor.hpp b/descriptors/gpx_descriptor.hpp index a6af9f8dc..bff2733e7 100644 --- a/descriptors/gpx_descriptor.hpp +++ b/descriptors/gpx_descriptor.hpp @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define GPX_DESCRIPTOR_HPP #include "descriptor_base.hpp" -#include "../Util/xml_renderer.hpp" +#include "../util/xml_renderer.hpp" #include diff --git a/descriptors/json_descriptor.hpp b/descriptors/json_descriptor.hpp index 79d4a3d1e..aceca1927 100644 --- a/descriptors/json_descriptor.hpp +++ b/descriptors/json_descriptor.hpp @@ -34,12 +34,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../algorithms/route_name_extraction.hpp" #include "../data_structures/segment_information.hpp" #include "../data_structures/turn_instructions.hpp" -#include "../Util/bearing.hpp" -#include "../Util/integer_range.hpp" -#include "../Util/json_renderer.hpp" -#include "../Util/simple_logger.hpp" -#include "../Util/string_util.hpp" -#include "../Util/timing_util.hpp" +#include "../util/bearing.hpp" +#include "../util/integer_range.hpp" +#include "../util/json_renderer.hpp" +#include "../util/simple_logger.hpp" +#include "../util/string_util.hpp" +#include "../util/timing_util.hpp" #include diff --git a/extract.cpp b/extract.cpp index 9f496f115..b37518444 100644 --- a/extract.cpp +++ b/extract.cpp @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "extractor/extractor.hpp" #include "extractor/extractor_options.hpp" -#include "Util/simple_logger.hpp" +#include "util/simple_logger.hpp" int main(int argc, char *argv[]) { diff --git a/extractor/extraction_containers.cpp b/extractor/extraction_containers.cpp index 387f01d97..e40959d62 100644 --- a/extractor/extraction_containers.cpp +++ b/extractor/extraction_containers.cpp @@ -32,9 +32,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/node_id.hpp" #include "../data_structures/range_table.hpp" -#include "../Util/osrm_exception.hpp" -#include "../Util/simple_logger.hpp" -#include "../Util/timing_util.hpp" +#include "../util/osrm_exception.hpp" +#include "../util/simple_logger.hpp" +#include "../util/timing_util.hpp" #include #include diff --git a/extractor/extraction_containers.hpp b/extractor/extraction_containers.hpp index 588dcabb0..ec5b620ea 100644 --- a/extractor/extraction_containers.hpp +++ b/extractor/extraction_containers.hpp @@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "first_and_last_segment_of_way.hpp" #include "../data_structures/external_memory_node.hpp" #include "../data_structures/restriction.hpp" -#include "../Util/fingerprint.hpp" +#include "../util/fingerprint.hpp" #include diff --git a/extractor/extraction_helper_functions.hpp b/extractor/extraction_helper_functions.hpp index d2a73c9c9..ef840212b 100644 --- a/extractor/extraction_helper_functions.hpp +++ b/extractor/extraction_helper_functions.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef EXTRACTION_HELPER_FUNCTIONS_HPP #define EXTRACTION_HELPER_FUNCTIONS_HPP -#include "../Util/cast.hpp" +#include "../util/cast.hpp" #include #include diff --git a/extractor/extractor.cpp b/extractor/extractor.cpp index c4e7203f5..326a43e23 100644 --- a/extractor/extractor.cpp +++ b/extractor/extractor.cpp @@ -34,10 +34,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "restriction_parser.hpp" #include "scripting_environment.hpp" -#include "../Util/git_sha.hpp" -#include "../Util/make_unique.hpp" -#include "../Util/simple_logger.hpp" -#include "../Util/timing_util.hpp" +#include "../util/git_sha.hpp" +#include "../util/make_unique.hpp" +#include "../util/simple_logger.hpp" +#include "../util/timing_util.hpp" #include "../typedefs.h" diff --git a/extractor/extractor_callbacks.cpp b/extractor/extractor_callbacks.cpp index 361c7e5ce..2770cd918 100644 --- a/extractor/extractor_callbacks.cpp +++ b/extractor/extractor_callbacks.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -32,8 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/external_memory_node.hpp" #include "../data_structures/restriction.hpp" -#include "../Util/container.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/container.hpp" +#include "../util/simple_logger.hpp" #include diff --git a/extractor/extractor_options.cpp b/extractor/extractor_options.cpp index 68a905a22..12ac458fc 100644 --- a/extractor/extractor_options.cpp +++ b/extractor/extractor_options.cpp @@ -27,9 +27,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "extractor_options.hpp" -#include "../Util/git_sha.hpp" -#include "../Util/ini_file.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/git_sha.hpp" +#include "../util/ini_file.hpp" +#include "../util/simple_logger.hpp" #include #include diff --git a/extractor/restriction_parser.cpp b/extractor/restriction_parser.cpp index 3cd53ffff..de73dda5f 100644 --- a/extractor/restriction_parser.cpp +++ b/extractor/restriction_parser.cpp @@ -30,9 +30,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "scripting_environment.hpp" #include "../data_structures/external_memory_node.hpp" -#include "../Util/lua_util.hpp" -#include "../Util/osrm_exception.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/lua_util.hpp" +#include "../util/osrm_exception.hpp" +#include "../util/simple_logger.hpp" #include #include diff --git a/extractor/scripting_environment.cpp b/extractor/scripting_environment.cpp index d50161c12..45e4d0226 100644 --- a/extractor/scripting_environment.cpp +++ b/extractor/scripting_environment.cpp @@ -31,9 +31,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "extraction_node.hpp" #include "extraction_way.hpp" #include "../data_structures/external_memory_node.hpp" -#include "../Util/lua_util.hpp" -#include "../Util/osrm_exception.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/lua_util.hpp" +#include "../util/osrm_exception.hpp" +#include "../util/simple_logger.hpp" #include "../typedefs.h" #include diff --git a/library/osrm_impl.cpp b/library/osrm_impl.cpp index aaf1e3da3..aea85a44c 100644 --- a/library/osrm_impl.cpp +++ b/library/osrm_impl.cpp @@ -46,9 +46,9 @@ class named_mutex; #include "../server/data_structures/internal_datafacade.hpp" #include "../server/data_structures/shared_barriers.hpp" #include "../server/data_structures/shared_datafacade.hpp" -#include "../Util/make_unique.hpp" -#include "../Util/routed_options.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/make_unique.hpp" +#include "../util/routed_options.hpp" +#include "../util/simple_logger.hpp" #include #include diff --git a/plugins/distance_table.hpp b/plugins/distance_table.hpp index e5ca5da5c..b7483f16f 100644 --- a/plugins/distance_table.hpp +++ b/plugins/distance_table.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DISTANCE_TABLE_PLUGIN_H -#define DISTANCE_TABLE_PLUGIN_H +#ifndef DISTANCE_TABLE_HPP +#define DISTANCE_TABLE_HPP #include "plugin_base.hpp" @@ -34,10 +34,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/query_edge.hpp" #include "../data_structures/search_engine.hpp" #include "../descriptors/descriptor_base.hpp" -#include "../Util/json_renderer.hpp" -#include "../Util/make_unique.hpp" -#include "../Util/string_util.hpp" -#include "../Util/timing_util.hpp" +#include "../util/json_renderer.hpp" +#include "../util/make_unique.hpp" +#include "../util/string_util.hpp" +#include "../util/timing_util.hpp" #include @@ -56,8 +56,9 @@ template class DistanceTablePlugin final : public BasePlugin int max_locations_distance_table; public: - explicit DistanceTablePlugin(DataFacadeT *facade, const int max_locations_distance_table) : - max_locations_distance_table(max_locations_distance_table), descriptor_string("table"), facade(facade) + explicit DistanceTablePlugin(DataFacadeT *facade, const int max_locations_distance_table) + : max_locations_distance_table(max_locations_distance_table), descriptor_string("table"), + facade(facade) { search_engine_ptr = osrm::make_unique>(facade); } @@ -74,8 +75,9 @@ template class DistanceTablePlugin final : public BasePlugin } const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); - unsigned max_locations = std::min(static_cast(max_locations_distance_table), - static_cast(route_parameters.coordinates.size())); + unsigned max_locations = + std::min(static_cast(max_locations_distance_table), + static_cast(route_parameters.coordinates.size())); PhantomNodeArray phantom_node_vector(max_locations); for (const auto i : osrm::irange(0u, max_locations)) @@ -92,8 +94,7 @@ template class DistanceTablePlugin final : public BasePlugin } } facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i], - phantom_node_vector[i], - 1); + phantom_node_vector[i], 1); BOOST_ASSERT(phantom_node_vector[i].front().is_valid(facade->GetNumberOfNodes())); } @@ -128,4 +129,4 @@ template class DistanceTablePlugin final : public BasePlugin DataFacadeT *facade; }; -#endif // DISTANCE_TABLE_PLUGIN_H +#endif // DISTANCE_TABLE_HPP diff --git a/plugins/hello_world.hpp b/plugins/hello_world.hpp index d0f1e9092..97c03095b 100644 --- a/plugins/hello_world.hpp +++ b/plugins/hello_world.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,13 +25,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef HELLO_WORLD_PLUGIN_H -#define HELLO_WORLD_PLUGIN_H +#ifndef HELLO_WORLD_HPP +#define HELLO_WORLD_HPP #include "plugin_base.hpp" -#include "../Util/cast.hpp" -#include "../Util/json_renderer.hpp" +#include "../util/cast.hpp" +#include "../util/json_renderer.hpp" #include @@ -77,8 +77,10 @@ class HelloWorldPlugin final : public BasePlugin JSON::Object json_location; JSON::Array json_coordinates; - json_coordinates.values.push_back(static_cast(coordinate.lat / COORDINATE_PRECISION)); - json_coordinates.values.push_back(static_cast(coordinate.lon / COORDINATE_PRECISION)); + json_coordinates.values.push_back( + static_cast(coordinate.lat / COORDINATE_PRECISION)); + json_coordinates.values.push_back( + static_cast(coordinate.lon / COORDINATE_PRECISION)); json_location.values[cast::integral_to_string(counter)] = json_coordinates; json_locations.values.push_back(json_location); ++counter; @@ -101,4 +103,4 @@ class HelloWorldPlugin final : public BasePlugin std::string descriptor_string; }; -#endif // HELLO_WORLD_PLUGIN_H +#endif // HELLO_WORLD_HPP diff --git a/plugins/locate.hpp b/plugins/locate.hpp index 7092da9b0..262935a67 100644 --- a/plugins/locate.hpp +++ b/plugins/locate.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,13 +25,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef LOCATE_PLUGIN_H -#define LOCATE_PLUGIN_H +#ifndef LOCATE_HPP +#define LOCATE_HPP #include "plugin_base.hpp" -#include "../Util/json_renderer.hpp" -#include "../Util/string_util.hpp" +#include "../util/json_renderer.hpp" +#include "../util/string_util.hpp" #include @@ -47,7 +47,8 @@ template class LocatePlugin final : public BasePlugin int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final { // check number of parameters - if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().is_valid()) + if (route_parameters.coordinates.empty() || + !route_parameters.coordinates.front().is_valid()) { return 400; } @@ -74,4 +75,4 @@ template class LocatePlugin final : public BasePlugin DataFacadeT *facade; }; -#endif /* LOCATE_PLUGIN_H */ +#endif /* LOCATE_HPP */ diff --git a/plugins/nearest.hpp b/plugins/nearest.hpp index 33bed1333..9add3040b 100644 --- a/plugins/nearest.hpp +++ b/plugins/nearest.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,14 +25,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef NEAREST_PLUGIN_H -#define NEAREST_PLUGIN_H +#ifndef NEAREST_HPP +#define NEAREST_HPP #include "plugin_base.hpp" #include "../data_structures/phantom_node.hpp" -#include "../Util/integer_range.hpp" -#include "../Util/json_renderer.hpp" +#include "../util/integer_range.hpp" +#include "../util/json_renderer.hpp" #include @@ -52,7 +52,8 @@ template class NearestPlugin final : public BasePlugin int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final { // check number of parameters - if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().is_valid()) + if (route_parameters.coordinates.empty() || + !route_parameters.coordinates.front().is_valid()) { return 400; } @@ -76,7 +77,8 @@ template class NearestPlugin final : public BasePlugin JSON::Array results; auto vector_length = phantom_node_vector.size(); - for (const auto i : osrm::irange(0, std::min(number_of_results, vector_length))) + for (const auto i : + osrm::irange(0, std::min(number_of_results, vector_length))) { JSON::Array json_coordinate; JSON::Object result; @@ -113,4 +115,4 @@ template class NearestPlugin final : public BasePlugin std::string descriptor_string; }; -#endif /* NEAREST_PLUGIN_H */ +#endif /* NEAREST_HPP */ diff --git a/plugins/timestamp.hpp b/plugins/timestamp.hpp index 181efbf7b..b86174a50 100644 --- a/plugins/timestamp.hpp +++ b/plugins/timestamp.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "plugin_base.hpp" -#include "../Util/json_renderer.hpp" +#include "../util/json_renderer.hpp" #include diff --git a/plugins/viaroute.hpp b/plugins/viaroute.hpp index bf6891163..b253baa1c 100644 --- a/plugins/viaroute.hpp +++ b/plugins/viaroute.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -35,10 +35,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../descriptors/descriptor_base.hpp" #include "../descriptors/gpx_descriptor.hpp" #include "../descriptors/json_descriptor.hpp" -#include "../Util/integer_range.hpp" -#include "../Util/json_renderer.hpp" -#include "../Util/make_unique.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/integer_range.hpp" +#include "../util/json_renderer.hpp" +#include "../util/make_unique.hpp" +#include "../util/simple_logger.hpp" #include diff --git a/routed.cpp b/routed.cpp index 78f48cc82..a5ba4906d 100644 --- a/routed.cpp +++ b/routed.cpp @@ -27,9 +27,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "library/osrm.hpp" #include "server/server.hpp" -#include "Util/git_sha.hpp" -#include "Util/routed_options.hpp" -#include "Util/simple_logger.hpp" +#include "util/git_sha.hpp" +#include "util/routed_options.hpp" +#include "util/simple_logger.hpp" #ifdef __linux__ #include diff --git a/routing_algorithms/alternative_path.hpp b/routing_algorithms/alternative_path.hpp index ae1f62338..e3a81251b 100644 --- a/routing_algorithms/alternative_path.hpp +++ b/routing_algorithms/alternative_path.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -30,8 +30,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "routing_base.hpp" #include "../data_structures/search_engine_data.hpp" -#include "../Util/integer_range.hpp" -#include "../Util/container.hpp" +#include "../util/integer_range.hpp" +#include "../util/container.hpp" #include @@ -44,7 +44,8 @@ const double VIAPATH_ALPHA = 0.10; const double VIAPATH_EPSILON = 0.15; // alternative at most 15% longer const double VIAPATH_GAMMA = 0.75; // alternative shares at most 75% with the shortest. -template class AlternativeRouting final : private BasicRoutingInterface +template +class AlternativeRouting final : private BasicRoutingInterface { using super = BasicRoutingInterface; using EdgeData = typename DataFacadeT::EdgeData; @@ -148,22 +149,16 @@ template class AlternativeRouting final : private BasicRouti { if (0 < forward_heap1.Size()) { - AlternativeRoutingStep(forward_heap1, - reverse_heap1, - &middle_node, + AlternativeRoutingStep(forward_heap1, reverse_heap1, &middle_node, &upper_bound_to_shortest_path_distance, - via_node_candidate_list, - forward_search_space, + via_node_candidate_list, forward_search_space, min_edge_offset); } if (0 < reverse_heap1.Size()) { - AlternativeRoutingStep(reverse_heap1, - forward_heap1, - &middle_node, + AlternativeRoutingStep(reverse_heap1, forward_heap1, &middle_node, &upper_bound_to_shortest_path_distance, - via_node_candidate_list, - reverse_search_space, + via_node_candidate_list, reverse_search_space, min_edge_offset); } } @@ -274,19 +269,16 @@ template class AlternativeRouting final : private BasicRouti std::vector &packed_shortest_path = packed_forward_path; std::reverse(packed_shortest_path.begin(), packed_shortest_path.end()); packed_shortest_path.emplace_back(middle_node); - packed_shortest_path.insert( - packed_shortest_path.end(), packed_reverse_path.begin(), packed_reverse_path.end()); + packed_shortest_path.insert(packed_shortest_path.end(), packed_reverse_path.begin(), + packed_reverse_path.end()); std::vector ranked_candidates_list; // prioritizing via nodes for deep inspection for (const NodeID node : preselected_node_list) { int length_of_via_path = 0, sharing_of_via_path = 0; - ComputeLengthAndSharingOfViaPath(node, - &length_of_via_path, - &sharing_of_via_path, - packed_shortest_path, - min_edge_offset); + ComputeLengthAndSharingOfViaPath(node, &length_of_via_path, &sharing_of_via_path, + packed_shortest_path, min_edge_offset); const int maximum_allowed_sharing = static_cast(upper_bound_to_shortest_path_distance * VIAPATH_GAMMA); if (sharing_of_via_path <= maximum_allowed_sharing && @@ -302,16 +294,10 @@ template class AlternativeRouting final : private BasicRouti NodeID s_v_middle = SPECIAL_NODEID, v_t_middle = SPECIAL_NODEID; for (const RankedCandidateNode &candidate : ranked_candidates_list) { - if (ViaNodeCandidatePassesTTest(forward_heap1, - reverse_heap1, - forward_heap2, - reverse_heap2, - candidate, - upper_bound_to_shortest_path_distance, - &length_of_via_path, - &s_v_middle, - &v_t_middle, - min_edge_offset)) + if (ViaNodeCandidatePassesTTest( + forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, candidate, + upper_bound_to_shortest_path_distance, &length_of_via_path, &s_v_middle, + &v_t_middle, min_edge_offset)) { // select first admissable selected_via_node = candidate.node; @@ -343,13 +329,8 @@ template class AlternativeRouting final : private BasicRouti { std::vector packed_alternate_path; // retrieve alternate path - RetrievePackedAlternatePath(forward_heap1, - reverse_heap1, - forward_heap2, - reverse_heap2, - s_v_middle, - v_t_middle, - packed_alternate_path); + RetrievePackedAlternatePath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, + s_v_middle, v_t_middle, packed_alternate_path); raw_route_data.alt_source_traversed_in_reverse.push_back(( packed_alternate_path.front() != phantom_node_pair.source_phantom.forward_node_id)); @@ -357,8 +338,8 @@ template class AlternativeRouting final : private BasicRouti (packed_alternate_path.back() != phantom_node_pair.target_phantom.forward_node_id)); // unpack the alternate path - super::UnpackPath( - packed_alternate_path, phantom_node_pair, raw_route_data.unpacked_alternative); + super::UnpackPath(packed_alternate_path, phantom_node_pair, + raw_route_data.unpacked_alternative); raw_route_data.alternative_path_length = length_of_via_path; } @@ -384,8 +365,8 @@ template class AlternativeRouting final : private BasicRouti packed_path.pop_back(); // remove middle node. It's in both half-paths // fetch patched path [v,t] - super::RetrievePackedPathFromHeap( - forward_heap2, reverse_heap1, v_t_middle, packed_v_t_path); + super::RetrievePackedPathFromHeap(forward_heap2, reverse_heap1, v_t_middle, + packed_v_t_path); packed_path.insert(packed_path.end(), packed_v_t_path.begin(), packed_v_t_path.end()); } @@ -420,12 +401,8 @@ template class AlternativeRouting final : private BasicRouti // compute path by reusing forward search from s while (!new_reverse_heap.Empty()) { - super::RoutingStep(new_reverse_heap, - existing_forward_heap, - &s_v_middle, - &upper_bound_s_v_path_length, - min_edge_offset, - false); + super::RoutingStep(new_reverse_heap, existing_forward_heap, &s_v_middle, + &upper_bound_s_v_path_length, min_edge_offset, false); } // compute path by reusing backward search from node t NodeID v_t_middle = SPECIAL_NODEID; @@ -433,12 +410,8 @@ template class AlternativeRouting final : private BasicRouti new_forward_heap.Insert(via_node, 0, via_node); while (!new_forward_heap.Empty()) { - super::RoutingStep(new_forward_heap, - existing_reverse_heap, - &v_t_middle, - &upper_bound_of_v_t_path_length, - min_edge_offset, - true); + super::RoutingStep(new_forward_heap, existing_reverse_heap, &v_t_middle, + &upper_bound_of_v_t_path_length, min_edge_offset, true); } *real_length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length; @@ -448,10 +421,10 @@ template class AlternativeRouting final : private BasicRouti } // retrieve packed paths - super::RetrievePackedPathFromHeap( - existing_forward_heap, new_reverse_heap, s_v_middle, packed_s_v_path); - super::RetrievePackedPathFromHeap( - new_forward_heap, existing_reverse_heap, v_t_middle, packed_v_t_path); + super::RetrievePackedPathFromHeap(existing_forward_heap, new_reverse_heap, s_v_middle, + packed_s_v_path); + super::RetrievePackedPathFromHeap(new_forward_heap, existing_reverse_heap, v_t_middle, + packed_v_t_path); // partial unpacking, compute sharing // First partially unpack s-->v until paths deviate, note length of common path. @@ -484,12 +457,11 @@ template class AlternativeRouting final : private BasicRouti const int64_t packed_path_length = std::min(partially_unpacked_via_path.size(), partially_unpacked_shortest_path.size()) - 1; - for (int64_t current_node = 0; - (current_node < packed_path_length) && - (partially_unpacked_via_path[current_node] == - partially_unpacked_shortest_path[current_node] && - partially_unpacked_via_path[current_node + 1] == - partially_unpacked_shortest_path[current_node + 1]); + for (int64_t current_node = 0; (current_node < packed_path_length) && + (partially_unpacked_via_path[current_node] == + partially_unpacked_shortest_path[current_node] && + partially_unpacked_via_path[current_node + 1] == + partially_unpacked_shortest_path[current_node + 1]); ++current_node) { EdgeID selected_edge = @@ -517,8 +489,7 @@ template class AlternativeRouting final : private BasicRouti if (packed_v_t_path[via_path_index] == packed_shortest_path[shortest_path_index]) { super::UnpackEdge(packed_v_t_path[via_path_index - 1], - packed_v_t_path[via_path_index], - partially_unpacked_via_path); + packed_v_t_path[via_path_index], partially_unpacked_via_path); super::UnpackEdge(packed_shortest_path[shortest_path_index - 1], packed_shortest_path[shortest_path_index], partially_unpacked_shortest_path); @@ -696,12 +667,8 @@ template class AlternativeRouting final : private BasicRouti new_reverse_heap.Insert(candidate.node, 0, candidate.node); while (new_reverse_heap.Size() > 0) { - super::RoutingStep(new_reverse_heap, - existing_forward_heap, - s_v_middle, - &upper_bound_s_v_path_length, - min_edge_offset, - false); + super::RoutingStep(new_reverse_heap, existing_forward_heap, s_v_middle, + &upper_bound_s_v_path_length, min_edge_offset, false); } if (INVALID_EDGE_WEIGHT == upper_bound_s_v_path_length) @@ -715,12 +682,8 @@ template class AlternativeRouting final : private BasicRouti new_forward_heap.Insert(candidate.node, 0, candidate.node); while (new_forward_heap.Size() > 0) { - super::RoutingStep(new_forward_heap, - existing_reverse_heap, - v_t_middle, - &upper_bound_of_v_t_path_length, - min_edge_offset, - true); + super::RoutingStep(new_forward_heap, existing_reverse_heap, v_t_middle, + &upper_bound_of_v_t_path_length, min_edge_offset, true); } if (INVALID_EDGE_WEIGHT == upper_bound_of_v_t_path_length) @@ -731,11 +694,11 @@ template class AlternativeRouting final : private BasicRouti *length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length; // retrieve packed paths - super::RetrievePackedPathFromHeap( - existing_forward_heap, new_reverse_heap, *s_v_middle, packed_s_v_path); + super::RetrievePackedPathFromHeap(existing_forward_heap, new_reverse_heap, *s_v_middle, + packed_s_v_path); - super::RetrievePackedPathFromHeap( - new_forward_heap, existing_reverse_heap, *v_t_middle, packed_v_t_path); + super::RetrievePackedPathFromHeap(new_forward_heap, existing_reverse_heap, *v_t_middle, + packed_v_t_path); NodeID s_P = *s_v_middle, t_P = *v_t_middle; if (SPECIAL_NODEID == s_P) @@ -815,8 +778,7 @@ template class AlternativeRouting final : private BasicRouti // Traverse path s-->v BOOST_ASSERT(!packed_v_t_path.empty()); for (unsigned i = 0, packed_path_length = static_cast(packed_v_t_path.size() - 1); - (i < packed_path_length) && unpack_stack.empty(); - ++i) + (i < packed_path_length) && unpack_stack.empty(); ++i) { const EdgeID edgeID = facade->FindEdgeInEitherDirection(packed_v_t_path[i], packed_v_t_path[i + 1]); @@ -888,13 +850,13 @@ template class AlternativeRouting final : private BasicRouti { if (!forward_heap3.Empty()) { - super::RoutingStep( - forward_heap3, reverse_heap3, &middle, &upper_bound, min_edge_offset, true); + super::RoutingStep(forward_heap3, reverse_heap3, &middle, &upper_bound, + min_edge_offset, true); } if (!reverse_heap3.Empty()) { - super::RoutingStep( - reverse_heap3, forward_heap3, &middle, &upper_bound, min_edge_offset, false); + super::RoutingStep(reverse_heap3, forward_heap3, &middle, &upper_bound, + min_edge_offset, false); } } return (upper_bound <= t_test_path_length); diff --git a/routing_algorithms/routing_base.hpp b/routing_algorithms/routing_base.hpp index a120d9717..67dd2f5a8 100644 --- a/routing_algorithms/routing_base.hpp +++ b/routing_algorithms/routing_base.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/internal_route_result.hpp" #include "../data_structures/search_engine_data.hpp" #include "../data_structures/turn_instructions.hpp" -// #include "../Util/simple_logger.hpp" +// #include "../util/simple_logger.hpp" #include @@ -56,7 +56,7 @@ template class BasicRoutingInterface BasicRoutingInterface() = delete; BasicRoutingInterface(const BasicRoutingInterface &) = delete; explicit BasicRoutingInterface(DataFacadeT *facade) : facade(facade) {} - virtual ~BasicRoutingInterface() {}; + virtual ~BasicRoutingInterface(){}; inline void RoutingStep(SearchEngineData::QueryHeap &forward_heap, SearchEngineData::QueryHeap &reverse_heap, @@ -69,7 +69,8 @@ template class BasicRoutingInterface const int distance = forward_heap.GetKey(node); // const NodeID parentnode = forward_heap.GetData(node).parent; - // SimpleLogger().Write() << (forward_direction ? "[fwd] " : "[rev] ") << "settled edge (" << parentnode << "," << node << "), dist: " << distance; + // SimpleLogger().Write() << (forward_direction ? "[fwd] " : "[rev] ") << "settled edge (" + // << parentnode << "," << node << "), dist: " << distance; if (reverse_heap.WasInserted(node)) { @@ -80,9 +81,11 @@ template class BasicRoutingInterface { *middle_node_id = node; *upper_bound = new_distance; - // SimpleLogger().Write() << "accepted middle node " << node << " at distance " << new_distance; - // } else { - // SimpleLogger().Write() << "discared middle node " << node << " at distance " << new_distance; + // SimpleLogger().Write() << "accepted middle node " << node << " at + // distance " << new_distance; + // } else { + // SimpleLogger().Write() << "discared middle node " << node << " at + // distance " << new_distance; } } } @@ -228,15 +231,11 @@ template class BasicRoutingInterface const TurnInstruction turn_instruction = facade->GetTurnInstructionForEdgeID(ed.id); const TravelMode travel_mode = facade->GetTravelModeForEdgeID(ed.id); - if (!facade->EdgeIsCompressed(ed.id)) { BOOST_ASSERT(!facade->EdgeIsCompressed(ed.id)); - unpacked_path.emplace_back(facade->GetGeometryIndexForEdgeID(ed.id), - name_index, - turn_instruction, - ed.distance, - travel_mode); + unpacked_path.emplace_back(facade->GetGeometryIndexForEdgeID(ed.id), name_index, + turn_instruction, ed.distance, travel_mode); } else { @@ -257,7 +256,8 @@ template class BasicRoutingInterface BOOST_ASSERT(start_index <= end_index); for (std::size_t i = start_index; i < end_index; ++i) { - unpacked_path.emplace_back(id_vector[i], name_index, TurnInstruction::NoTurn, 0, travel_mode); + unpacked_path.emplace_back(id_vector[i], name_index, + TurnInstruction::NoTurn, 0, travel_mode); } unpacked_path.back().turn_instruction = turn_instruction; unpacked_path.back().segment_duration = ed.distance; @@ -294,18 +294,19 @@ template class BasicRoutingInterface if (start_index > end_index) { - start_index = std::min(start_index, id_vector.size()-1); + start_index = std::min(start_index, id_vector.size() - 1); } for (std::size_t i = start_index; i != end_index; (start_index < end_index ? ++i : --i)) { BOOST_ASSERT(i < id_vector.size()); - BOOST_ASSERT(phantom_node_pair.target_phantom.forward_travel_mode>0 ); - unpacked_path.emplace_back(PathData{id_vector[i], - phantom_node_pair.target_phantom.name_id, - TurnInstruction::NoTurn, - 0, - phantom_node_pair.target_phantom.forward_travel_mode}); + BOOST_ASSERT(phantom_node_pair.target_phantom.forward_travel_mode > 0); + unpacked_path.emplace_back( + PathData{id_vector[i], + phantom_node_pair.target_phantom.name_id, + TurnInstruction::NoTurn, + 0, + phantom_node_pair.target_phantom.forward_travel_mode}); } } @@ -367,7 +368,8 @@ template class BasicRoutingInterface } } } - BOOST_ASSERT_MSG(edge_weight != std::numeric_limits::max(), "edge weight invalid"); + BOOST_ASSERT_MSG(edge_weight != std::numeric_limits::max(), + "edge weight invalid"); const EdgeData &ed = facade->GetEdgeData(smaller_edge_id); if (ed.shortcut) diff --git a/routing_algorithms/shortest_path.hpp b/routing_algorithms/shortest_path.hpp index f09d2cff6..8282aa25f 100644 --- a/routing_algorithms/shortest_path.hpp +++ b/routing_algorithms/shortest_path.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -32,10 +32,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "routing_base.hpp" #include "../data_structures/search_engine_data.hpp" -#include "../Util/integer_range.hpp" +#include "../util/integer_range.hpp" #include "../typedefs.h" -template class ShortestPathRouting final : public BasicRoutingInterface +template +class ShortestPathRouting final : public BasicRoutingInterface { using super = BasicRoutingInterface; using QueryHeap = SearchEngineData::QueryHeap; @@ -88,7 +89,8 @@ template class ShortestPathRouting final : public BasicRouti middle1 = SPECIAL_NODEID; middle2 = SPECIAL_NODEID; - const bool allow_u_turn = current_leg > 0 && uturn_indicators.size() > current_leg && uturn_indicators[current_leg-1]; + const bool allow_u_turn = current_leg > 0 && uturn_indicators.size() > current_leg && + uturn_indicators[current_leg - 1]; EdgeWeight min_edge_offset = 0; // insert new starting nodes into forward heap, adjusted by previous distances. @@ -97,35 +99,58 @@ template class ShortestPathRouting final : public BasicRouti { forward_heap1.Insert( phantom_node_pair.source_phantom.forward_node_id, - (allow_u_turn ? 0 : distance1) - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), + (allow_u_turn ? 0 : distance1) - + phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), phantom_node_pair.source_phantom.forward_node_id); - min_edge_offset = std::min(min_edge_offset, (allow_u_turn ? 0 : distance1) - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset()); - // SimpleLogger().Write(logDEBUG) << "fwd-a2 insert: " << phantom_node_pair.source_phantom.forward_node_id << ", w: " << (allow_u_turn ? 0 : distance1) - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(); + min_edge_offset = + std::min(min_edge_offset, + (allow_u_turn ? 0 : distance1) - + phantom_node_pair.source_phantom.GetForwardWeightPlusOffset()); + // SimpleLogger().Write(logDEBUG) << "fwd-a2 insert: " << + // phantom_node_pair.source_phantom.forward_node_id << ", w: " << (allow_u_turn ? 0 + // : distance1) - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(); forward_heap2.Insert( phantom_node_pair.source_phantom.forward_node_id, - (allow_u_turn ? 0 : distance1) - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), + (allow_u_turn ? 0 : distance1) - + phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), phantom_node_pair.source_phantom.forward_node_id); - min_edge_offset = std::min(min_edge_offset, (allow_u_turn ? 0 : distance1) - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset()); - // SimpleLogger().Write(logDEBUG) << "fwd-b2 insert: " << phantom_node_pair.source_phantom.forward_node_id << ", w: " << (allow_u_turn ? 0 : distance1) - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(); - + min_edge_offset = + std::min(min_edge_offset, + (allow_u_turn ? 0 : distance1) - + phantom_node_pair.source_phantom.GetForwardWeightPlusOffset()); + // SimpleLogger().Write(logDEBUG) << "fwd-b2 insert: " << + // phantom_node_pair.source_phantom.forward_node_id << ", w: " << (allow_u_turn ? 0 + // : distance1) - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(); } if ((allow_u_turn || search_from_2nd_node) && phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID) { forward_heap1.Insert( phantom_node_pair.source_phantom.reverse_node_id, - (allow_u_turn ? 0 : distance2) - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), + (allow_u_turn ? 0 : distance2) - + phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), phantom_node_pair.source_phantom.reverse_node_id); - min_edge_offset = std::min(min_edge_offset, (allow_u_turn ? 0 : distance2) - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()); - // SimpleLogger().Write(logDEBUG) << "fwd-a2 insert: " << phantom_node_pair.source_phantom.reverse_node_id << - // ", w: " << (allow_u_turn ? 0 : distance2) - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(); + min_edge_offset = + std::min(min_edge_offset, + (allow_u_turn ? 0 : distance2) - + phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()); + // SimpleLogger().Write(logDEBUG) << "fwd-a2 insert: " << + // phantom_node_pair.source_phantom.reverse_node_id << + // ", w: " << (allow_u_turn ? 0 : distance2) - + // phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(); forward_heap2.Insert( phantom_node_pair.source_phantom.reverse_node_id, - (allow_u_turn ? 0 : distance2) - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), + (allow_u_turn ? 0 : distance2) - + phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), phantom_node_pair.source_phantom.reverse_node_id); - min_edge_offset = std::min(min_edge_offset, (allow_u_turn ? 0 : distance2) - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()); - // SimpleLogger().Write(logDEBUG) << "fwd-b2 insert: " << phantom_node_pair.source_phantom.reverse_node_id << - // ", w: " << (allow_u_turn ? 0 : distance2) - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(); + min_edge_offset = + std::min(min_edge_offset, + (allow_u_turn ? 0 : distance2) - + phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()); + // SimpleLogger().Write(logDEBUG) << "fwd-b2 insert: " << + // phantom_node_pair.source_phantom.reverse_node_id << + // ", w: " << (allow_u_turn ? 0 : distance2) - + // phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(); } // insert new backward nodes into backward heap, unadjusted. @@ -134,17 +159,21 @@ template class ShortestPathRouting final : public BasicRouti reverse_heap1.Insert(phantom_node_pair.target_phantom.forward_node_id, phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(), phantom_node_pair.target_phantom.forward_node_id); - // SimpleLogger().Write(logDEBUG) << "rev-a insert: " << phantom_node_pair.target_phantom.forward_node_id << - // ", w: " << phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(); - } + // SimpleLogger().Write(logDEBUG) << "rev-a insert: " << + // phantom_node_pair.target_phantom.forward_node_id << + // ", w: " << + // phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(); + } if (phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID) { reverse_heap2.Insert(phantom_node_pair.target_phantom.reverse_node_id, phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(), phantom_node_pair.target_phantom.reverse_node_id); - // SimpleLogger().Write(logDEBUG) << "rev-a insert: " << phantom_node_pair.target_phantom.reverse_node_id << - // ", w: " << phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(); + // SimpleLogger().Write(logDEBUG) << "rev-a insert: " << + // phantom_node_pair.target_phantom.reverse_node_id << + // ", w: " << + // phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(); } // run two-Target Dijkstra routing step. @@ -152,13 +181,13 @@ template class ShortestPathRouting final : public BasicRouti { if (!forward_heap1.Empty()) { - super::RoutingStep( - forward_heap1, reverse_heap1, &middle1, &local_upper_bound1, min_edge_offset, true); + super::RoutingStep(forward_heap1, reverse_heap1, &middle1, &local_upper_bound1, + min_edge_offset, true); } if (!reverse_heap1.Empty()) { - super::RoutingStep( - reverse_heap1, forward_heap1, &middle1, &local_upper_bound1, min_edge_offset, false); + super::RoutingStep(reverse_heap1, forward_heap1, &middle1, &local_upper_bound1, + min_edge_offset, false); } } @@ -168,13 +197,13 @@ template class ShortestPathRouting final : public BasicRouti { if (!forward_heap2.Empty()) { - super::RoutingStep( - forward_heap2, reverse_heap2, &middle2, &local_upper_bound2, min_edge_offset, true); + super::RoutingStep(forward_heap2, reverse_heap2, &middle2, + &local_upper_bound2, min_edge_offset, true); } if (!reverse_heap2.Empty()) { - super::RoutingStep( - reverse_heap2, forward_heap2, &middle2, &local_upper_bound2, min_edge_offset, false); + super::RoutingStep(reverse_heap2, forward_heap2, &middle2, + &local_upper_bound2, min_edge_offset, false); } } } @@ -200,7 +229,8 @@ template class ShortestPathRouting final : public BasicRouti } // Was at most one of the two paths not found? - BOOST_ASSERT_MSG((INVALID_EDGE_WEIGHT != distance1 || INVALID_EDGE_WEIGHT != distance2), "no path found"); + BOOST_ASSERT_MSG((INVALID_EDGE_WEIGHT != distance1 || INVALID_EDGE_WEIGHT != distance2), + "no path found"); // Unpack paths if they exist std::vector temporary_packed_leg1; @@ -211,18 +241,19 @@ template class ShortestPathRouting final : public BasicRouti if (INVALID_EDGE_WEIGHT != local_upper_bound1) { - super::RetrievePackedPathFromHeap( - forward_heap1, reverse_heap1, middle1, temporary_packed_leg1); + super::RetrievePackedPathFromHeap(forward_heap1, reverse_heap1, middle1, + temporary_packed_leg1); } if (INVALID_EDGE_WEIGHT != local_upper_bound2) { - super::RetrievePackedPathFromHeap( - forward_heap2, reverse_heap2, middle2, temporary_packed_leg2); + super::RetrievePackedPathFromHeap(forward_heap2, reverse_heap2, middle2, + temporary_packed_leg2); } // if one of the paths was not found, replace it with the other one. - if ((allow_u_turn && local_upper_bound1 > local_upper_bound2) || temporary_packed_leg1.empty()) + if ((allow_u_turn && local_upper_bound1 > local_upper_bound2) || + temporary_packed_leg1.empty()) { temporary_packed_leg1.clear(); temporary_packed_leg1.insert(temporary_packed_leg1.end(), @@ -230,7 +261,8 @@ template class ShortestPathRouting final : public BasicRouti temporary_packed_leg2.end()); local_upper_bound1 = local_upper_bound2; } - if ((allow_u_turn && local_upper_bound2 > local_upper_bound1) || temporary_packed_leg2.empty()) + if ((allow_u_turn && local_upper_bound2 > local_upper_bound1) || + temporary_packed_leg2.empty()) { temporary_packed_leg2.clear(); temporary_packed_leg2.insert(temporary_packed_leg2.end(), @@ -287,7 +319,8 @@ template class ShortestPathRouting final : public BasicRouti temporary_packed_leg2.end()); BOOST_ASSERT(packed_legs2[current_leg].size() == temporary_packed_leg2.size()); - if (!allow_u_turn && (packed_legs1[current_leg].back() == packed_legs2[current_leg].back()) && + if (!allow_u_turn && + (packed_legs1[current_leg].back() == packed_legs2[current_leg].back()) && phantom_node_pair.target_phantom.is_bidirected()) { const NodeID last_node_id = packed_legs2[current_leg].back(); @@ -324,9 +357,11 @@ template class ShortestPathRouting final : public BasicRouti raw_route_data.unpacked_path_segments[index]); raw_route_data.source_traversed_in_reverse.push_back( - (packed_legs1[index].front() != phantom_nodes_vector[index].source_phantom.forward_node_id)); + (packed_legs1[index].front() != + phantom_nodes_vector[index].source_phantom.forward_node_id)); raw_route_data.target_traversed_in_reverse.push_back( - (packed_legs1[index].back() != phantom_nodes_vector[index].target_phantom.forward_node_id)); + (packed_legs1[index].back() != + phantom_nodes_vector[index].target_phantom.forward_node_id)); } raw_route_data.shortest_path_length = std::min(distance1, distance2); } diff --git a/server/Http/Reply.cpp b/server/Http/Reply.cpp index 89b931b05..2642e2be2 100644 --- a/server/Http/Reply.cpp +++ b/server/Http/Reply.cpp @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "reply.hpp" -#include "../../Util/cast.hpp" +#include "../../util/cast.hpp" namespace http { diff --git a/server/data_structures/datafacade_base.hpp b/server/data_structures/datafacade_base.hpp index 2de79f915..0dbeef4b6 100644 --- a/server/data_structures/datafacade_base.hpp +++ b/server/data_structures/datafacade_base.hpp @@ -34,9 +34,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../data_structures/external_memory_node.hpp" #include "../../data_structures/phantom_node.hpp" #include "../../data_structures/turn_instructions.hpp" -#include "../../Util/integer_range.hpp" -#include "../../Util/osrm_exception.hpp" -#include "../../Util/string_util.hpp" +#include "../../util/integer_range.hpp" +#include "../../util/osrm_exception.hpp" +#include "../../util/string_util.hpp" #include "../../typedefs.h" #include diff --git a/server/data_structures/internal_datafacade.hpp b/server/data_structures/internal_datafacade.hpp index f25185a1e..8a481c5c5 100644 --- a/server/data_structures/internal_datafacade.hpp +++ b/server/data_structures/internal_datafacade.hpp @@ -39,9 +39,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../data_structures/static_graph.hpp" #include "../../data_structures/static_rtree.hpp" #include "../../data_structures/range_table.hpp" -#include "../../Util/boost_filesystem_2_fix.hpp" -#include "../../Util/graph_loader.hpp" -#include "../../Util/simple_logger.hpp" +#include "../../util/boost_filesystem_2_fix.hpp" +#include "../../util/graph_loader.hpp" +#include "../../util/simple_logger.hpp" #include #include diff --git a/server/data_structures/shared_datafacade.hpp b/server/data_structures/shared_datafacade.hpp index 1b038dc89..b6a144174 100644 --- a/server/data_structures/shared_datafacade.hpp +++ b/server/data_structures/shared_datafacade.hpp @@ -36,9 +36,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../data_structures/range_table.hpp" #include "../../data_structures/static_graph.hpp" #include "../../data_structures/static_rtree.hpp" -#include "../../Util/boost_filesystem_2_fix.hpp" -#include "../../Util/make_unique.hpp" -#include "../../Util/simple_logger.hpp" +#include "../../util/boost_filesystem_2_fix.hpp" +#include "../../util/make_unique.hpp" +#include "../../util/simple_logger.hpp" #include #include diff --git a/server/data_structures/shared_datatype.hpp b/server/data_structures/shared_datatype.hpp index 9464ff015..0c0b23910 100644 --- a/server/data_structures/shared_datatype.hpp +++ b/server/data_structures/shared_datatype.hpp @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef SHARED_DATA_TYPE_HPP #define SHARED_DATA_TYPE_HPP -#include "../../Util/osrm_exception.hpp" -#include "../../Util/simple_logger.hpp" +#include "../../util/osrm_exception.hpp" +#include "../../util/simple_logger.hpp" #include diff --git a/server/http/reply.cpp b/server/http/reply.cpp index 89b931b05..2642e2be2 100644 --- a/server/http/reply.cpp +++ b/server/http/reply.cpp @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "reply.hpp" -#include "../../Util/cast.hpp" +#include "../../util/cast.hpp" namespace http { diff --git a/server/request_handler.cpp b/server/request_handler.cpp index 17a004338..464ba5b94 100644 --- a/server/request_handler.cpp +++ b/server/request_handler.cpp @@ -32,10 +32,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "http/request.hpp" #include "../library/osrm.hpp" -#include "../Util/json_renderer.hpp" -#include "../Util/simple_logger.hpp" -#include "../Util/string_util.hpp" -#include "../Util/xml_renderer.hpp" +#include "../util/json_renderer.hpp" +#include "../util/simple_logger.hpp" +#include "../util/string_util.hpp" +#include "../util/xml_renderer.hpp" #include "../typedefs.h" #include diff --git a/server/server.hpp b/server/server.hpp index ee9887e52..46a87d23a 100644 --- a/server/server.hpp +++ b/server/server.hpp @@ -31,9 +31,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "connection.hpp" #include "request_handler.hpp" -#include "../Util/cast.hpp" -#include "../Util/integer_range.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/cast.hpp" +#include "../util/integer_range.hpp" +#include "../util/simple_logger.hpp" #include #include diff --git a/tools/check-hsgr.cpp b/tools/check-hsgr.cpp index 9173dc4f7..be2f973c7 100644 --- a/tools/check-hsgr.cpp +++ b/tools/check-hsgr.cpp @@ -27,10 +27,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/percent.hpp" #include "../data_structures/query_edge.hpp" #include "../data_structures/static_graph.hpp" -#include "../Util/integer_range.hpp" -#include "../Util/graph_loader.hpp" -#include "../Util/simple_logger.hpp" -#include "../Util/osrm_exception.hpp" +#include "../util/integer_range.hpp" +#include "../util/graph_loader.hpp" +#include "../util/simple_logger.hpp" +#include "../util/osrm_exception.hpp" #include #include @@ -86,17 +86,17 @@ int main(int argc, char *argv[]) if (SPECIAL_EDGEID == edge_id_1) { throw osrm::exception("cannot find first segment of edge (" + - std::to_string(node_u) + "," + std::to_string(data.id) + - "," + std::to_string(node_v) + "), eid: " + - std::to_string(eid)); + std::to_string(node_u) + "," + std::to_string(data.id) + + "," + std::to_string(node_v) + "), eid: " + + std::to_string(eid)); } const EdgeID edge_id_2 = m_query_graph->FindEdgeInEitherDirection(data.id, node_v); if (SPECIAL_EDGEID == edge_id_2) { throw osrm::exception("cannot find second segment of edge (" + - std::to_string(node_u) + "," + std::to_string(data.id) + - "," + std::to_string(node_v) + "), eid: " + - std::to_string(eid)); + std::to_string(node_u) + "," + std::to_string(data.id) + + "," + std::to_string(node_v) + "), eid: " + + std::to_string(eid)); } } progress.printStatus(node_u); diff --git a/tools/components.cpp b/tools/components.cpp index f7308d724..733c8ff84 100644 --- a/tools/components.cpp +++ b/tools/components.cpp @@ -29,15 +29,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../algorithms/tiny_components.hpp" #include "../data_structures/static_graph.hpp" #include "../data_structures/coordinate_calculation.hpp" -#include "../Util/fingerprint.hpp" -#include "../Util/graph_loader.hpp" -#include "../Util/make_unique.hpp" -#include "../Util/osrm_exception.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/fingerprint.hpp" +#include "../util/graph_loader.hpp" +#include "../util/make_unique.hpp" +#include "../util/osrm_exception.hpp" +#include "../util/simple_logger.hpp" #include -#if defined(__APPLE__) || defined (_WIN32) +#if defined(__APPLE__) || defined(_WIN32) #include #include #else @@ -52,7 +52,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -namespace { +namespace +{ struct TarjanEdgeData { @@ -129,15 +130,11 @@ int main(int argc, char *argv[]) // load graph data std::vector edge_list; - const NodeID number_of_nodes = readBinaryOSRMGraphFromStream(input_stream, - edge_list, - bollard_node_list, - traffic_lights_list, - &coordinate_list, - restriction_list); + const NodeID number_of_nodes = + readBinaryOSRMGraphFromStream(input_stream, edge_list, bollard_node_list, + traffic_lights_list, &coordinate_list, restriction_list); input_stream.close(); - BOOST_ASSERT_MSG(restriction_list.size() == usable_restrictions, "size of restriction_list changed"); @@ -159,17 +156,15 @@ int main(int argc, char *argv[]) if (input_edge.forward) { - graph_edge_list.emplace_back(input_edge.source, - input_edge.target, - (std::max)((int)input_edge.weight, 1), - input_edge.name_id); + graph_edge_list.emplace_back(input_edge.source, input_edge.target, + (std::max)((int)input_edge.weight, 1), + input_edge.name_id); } if (input_edge.backward) { - graph_edge_list.emplace_back(input_edge.target, - input_edge.source, - (std::max)((int)input_edge.weight, 1), - input_edge.name_id); + graph_edge_list.emplace_back(input_edge.target, input_edge.source, + (std::max)((int)input_edge.weight, 1), + input_edge.name_id); } } edge_list.clear(); @@ -185,12 +180,11 @@ int main(int argc, char *argv[]) SimpleLogger().Write() << "Starting SCC graph traversal"; RestrictionMap restriction_map(restriction_list); - auto tarjan = osrm::make_unique>(graph, - restriction_map, - bollard_node_list); + auto tarjan = + osrm::make_unique>(graph, restriction_map, bollard_node_list); tarjan->run(); SimpleLogger().Write() << "identified: " << tarjan->get_number_of_components() - << " many components"; + << " many components"; SimpleLogger().Write() << "identified " << tarjan->get_size_one_count() << " size 1 SCCs"; // output @@ -229,7 +223,8 @@ int main(int argc, char *argv[]) throw osrm::exception("Layer creation failed."); } TIMER_STOP(SCC_RUN_SETUP); - SimpleLogger().Write() << "shapefile setup took " << TIMER_MSEC(SCC_RUN_SETUP)/1000. << "s"; + SimpleLogger().Write() << "shapefile setup took " << TIMER_MSEC(SCC_RUN_SETUP) / 1000. + << "s"; uint64_t total_network_distance = 0; p.reinit(graph->GetNumberOfNodes()); @@ -245,18 +240,15 @@ int main(int argc, char *argv[]) { total_network_distance += 100 * coordinate_calculation::euclidean_distance( - coordinate_list[source].lat, - coordinate_list[source].lon, - coordinate_list[target].lat, - coordinate_list[target].lon); + coordinate_list[source].lat, coordinate_list[source].lon, + coordinate_list[target].lat, coordinate_list[target].lon); BOOST_ASSERT(current_edge != SPECIAL_EDGEID); BOOST_ASSERT(source != SPECIAL_NODEID); BOOST_ASSERT(target != SPECIAL_NODEID); - const unsigned size_of_containing_component = - std::min(tarjan->get_component_size(source), - tarjan->get_component_size(target)); + const unsigned size_of_containing_component = std::min( + tarjan->get_component_size(source), tarjan->get_component_size(target)); // edges that end on bollard nodes may actually be in two distinct components if (size_of_containing_component < 1000) @@ -282,7 +274,8 @@ int main(int argc, char *argv[]) OGRSpatialReference::DestroySpatialReference(poSRS); OGRDataSource::DestroyDataSource(poDS); TIMER_STOP(SCC_OUTPUT); - SimpleLogger().Write() << "generating output took: " << TIMER_MSEC(SCC_OUTPUT)/1000. << "s"; + SimpleLogger().Write() << "generating output took: " << TIMER_MSEC(SCC_OUTPUT) / 1000. + << "s"; SimpleLogger().Write() << "total network distance: " << (uint64_t)total_network_distance / 100 / 1000. << " km"; diff --git a/tools/io-benchmark.cpp b/tools/io-benchmark.cpp index c6da3ad44..277bd2ad1 100644 --- a/tools/io-benchmark.cpp +++ b/tools/io-benchmark.cpp @@ -25,10 +25,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "../Util/git_sha.hpp" -#include "../Util/osrm_exception.hpp" -#include "../Util/simple_logger.hpp" -#include "../Util/timing_util.hpp" +#include "../util/git_sha.hpp" +#include "../util/osrm_exception.hpp" +#include "../util/simple_logger.hpp" +#include "../util/timing_util.hpp" #include #include @@ -63,8 +63,8 @@ void RunStatistics(std::vector &timings_vector, Statistics &stats) double primary_sum = std::accumulate(timings_vector.begin(), timings_vector.end(), 0.0); stats.mean = primary_sum / timings_vector.size(); - double primary_sq_sum = std::inner_product( - timings_vector.begin(), timings_vector.end(), timings_vector.begin(), 0.0); + double primary_sq_sum = std::inner_product(timings_vector.begin(), timings_vector.end(), + timings_vector.begin(), 0.0); stats.dev = std::sqrt(primary_sq_sum / timings_vector.size() - (stats.mean * stats.mean)); } @@ -72,12 +72,12 @@ int main(int argc, char *argv[]) { #ifdef __FreeBSD__ - SimpleLogger().Write() << "Not supported on FreeBSD"; - return 0; + SimpleLogger().Write() << "Not supported on FreeBSD"; + return 0; #endif #ifdef _WIN32 - SimpleLogger().Write() << "Not supported on Windows"; - return 0; + SimpleLogger().Write() << "Not supported on Windows"; + return 0; #else LogPolicy::GetInstance().Unmute(); @@ -206,7 +206,7 @@ int main(int argc, char *argv[]) std::uniform_int_distribution uniform_dist(0, number_of_blocks - 1); for (unsigned i = 0; i < 1000; ++i) { - unsigned block_to_read =uniform_dist(e1); + unsigned block_to_read = uniform_dist(e1); off_t current_offset = block_to_read * 4096; TIMER_START(random_access); #ifdef __APPLE__ diff --git a/tools/simpleclient.cpp b/tools/simpleclient.cpp index 8de120821..2567b9319 100644 --- a/tools/simpleclient.cpp +++ b/tools/simpleclient.cpp @@ -26,10 +26,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "../library/osrm.hpp" -#include "../Util/git_sha.hpp" -#include "../Util/json_renderer.hpp" -#include "../Util/routed_options.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/git_sha.hpp" +#include "../util/json_renderer.hpp" +#include "../util/routed_options.hpp" +#include "../util/simple_logger.hpp" #include #include diff --git a/tools/springclean.cpp b/tools/springclean.cpp index 054133a58..cb4559c1c 100644 --- a/tools/springclean.cpp +++ b/tools/springclean.cpp @@ -29,8 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/shared_memory_factory.hpp" #include "../server/data_structures/shared_datatype.hpp" -#include "../Util/git_sha.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/git_sha.hpp" +#include "../util/simple_logger.hpp" void delete_region(const SharedDataType region) { diff --git a/tools/unlock_all_mutexes.cpp b/tools/unlock_all_mutexes.cpp index f68ec32a7..9a279ee1e 100644 --- a/tools/unlock_all_mutexes.cpp +++ b/tools/unlock_all_mutexes.cpp @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "../Util/git_sha.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/git_sha.hpp" +#include "../util/simple_logger.hpp" #include "../server/data_structures/shared_barriers.hpp" #include diff --git a/unit_tests/data_structures/static_rtree.cpp b/unit_tests/data_structures/static_rtree.cpp index 1e2676b4e..44912a6f6 100644 --- a/unit_tests/data_structures/static_rtree.cpp +++ b/unit_tests/data_structures/static_rtree.cpp @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../data_structures/static_rtree.hpp" #include "../../data_structures/query_node.hpp" #include "../../data_structures/edge_based_node.hpp" -#include "../../Util/floating_point.hpp" +#include "../../util/floating_point.hpp" #include "../../typedefs.h" #include diff --git a/util/bearing.cpp b/util/bearing.cpp new file mode 100644 index 000000000..92c47e6b8 --- /dev/null +++ b/util/bearing.cpp @@ -0,0 +1,65 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "bearing.hpp" + +std::string bearing::get(const double heading) +{ + if (heading <= 22.5) + { + return "N"; + } + if (heading <= 67.5) + { + return "NE"; + } + if (heading <= 112.5) + { + return "E"; + } + if (heading <= 157.5) + { + return "SE"; + } + if (heading <= 202.5) + { + return "S"; + } + if (heading <= 247.5) + { + return "SW"; + } + if (heading <= 292.5) + { + return "W"; + } + if (heading <= 337.5) + { + return "NW"; + } + return "N"; +} diff --git a/util/bearing.hpp b/util/bearing.hpp new file mode 100644 index 000000000..0066e9e02 --- /dev/null +++ b/util/bearing.hpp @@ -0,0 +1,38 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef BEARING_HPP +#define BEARING_HPP + +#include + +struct bearing +{ + static std::string get(const double heading); +}; + +#endif // BEARING_HPP diff --git a/util/boost_filesystem_2_fix.hpp b/util/boost_filesystem_2_fix.hpp new file mode 100644 index 000000000..aeab380b2 --- /dev/null +++ b/util/boost_filesystem_2_fix.hpp @@ -0,0 +1,144 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef BOOST_FILE_SYSTEM_FIX_H +#define BOOST_FILE_SYSTEM_FIX_H + +#include "osrm_exception.hpp" + +// #include +#include +// #include + +// This is one big workaround for latest boost renaming woes. + +#if BOOST_FILESYSTEM_VERSION < 3 +#warning Boost Installation with Filesystem3 missing, activating workaround +#include +#endif + +namespace boost +{ +namespace filesystem +{ + +// Validator for boost::filesystem::path, that verifies that the file +// exists. The validate() function must be defined in the same namespace +// as the target type, (boost::filesystem::path in this case), otherwise +// it is not called +// inline void validate( +// boost::any & v, +// const std::vector & values, +// boost::filesystem::path *, +// int +// ) { +// boost::program_options::validators::check_first_occurrence(v); +// const std::string & input_string = +// boost::program_options::validators::get_single_string(values); +// if(boost::filesystem::is_regular_file(input_string)) { +// v = boost::any(boost::filesystem::path(input_string)); +// } else { +// throw osrm::exception(input_string + " not found"); +// } +// } + +// adapted from: +// http://stackoverflow.com/questions/1746136/how-do-i-normalize-a-pathname-using-boostfilesystem +inline boost::filesystem::path +portable_canonical(const boost::filesystem::path &relative_path, + const boost::filesystem::path ¤t_path = boost::filesystem::current_path()) +{ + const boost::filesystem::path absolute_path = + boost::filesystem::absolute(relative_path, current_path); + + boost::filesystem::path canonical_path; + for (auto path_iterator = absolute_path.begin(); path_iterator != absolute_path.end(); + ++path_iterator) + { + if (".." == path_iterator->string()) + { + // /a/b/.. is not necessarily /a if b is a symbolic link + if (boost::filesystem::is_symlink(canonical_path)) + { + canonical_path /= *path_iterator; + } + else if (".." == canonical_path.filename()) + { + // /a/b/../.. is not /a/b/.. under most circumstances + // We can end up with ..s in our result because of symbolic links + canonical_path /= *path_iterator; + } + else + { + // Otherwise it should be safe to resolve the parent + canonical_path = canonical_path.parent_path(); + } + } + else if ("." == path_iterator->string()) + { + // Ignore + } + else + { + // Just cat other path entries + canonical_path /= *path_iterator; + } + } + BOOST_ASSERT(canonical_path.is_absolute()); + BOOST_ASSERT(boost::filesystem::exists(canonical_path)); + return canonical_path; +} + +#if BOOST_FILESYSTEM_VERSION < 3 + +inline path temp_directory_path() +{ + char *buffer; + buffer = tmpnam(nullptr); + + return path(buffer); +} + +inline path unique_path(const path &) { return temp_directory_path(); } + +#endif +} +} + +#ifndef BOOST_FILESYSTEM_VERSION +#define BOOST_FILESYSTEM_VERSION 3 +#endif + +inline void AssertPathExists(const boost::filesystem::path &path) +{ + if (!boost::filesystem::is_regular_file(path)) + { + throw osrm::exception(path.string() + " not found."); + } +} + +#endif /* BOOST_FILE_SYSTEM_FIX_H */ diff --git a/util/cast.hpp b/util/cast.hpp new file mode 100644 index 000000000..e28b9ff84 --- /dev/null +++ b/util/cast.hpp @@ -0,0 +1,185 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef CAST_HPP +#define CAST_HPP + +#include +#include + +#include +#include + +struct cast +{ + // convert scoped enums to integers + template + static auto enum_to_underlying(Enumeration const value) -> + typename std::underlying_type::type + { + return static_cast::type>(value); + } + + template + static typename std::enable_if::value, std::string>::type + integral_to_string(const Number value) + { + std::string output; + std::back_insert_iterator sink(output); + + if (8 == sizeof(Number)) + { + boost::spirit::karma::generate(sink, boost::spirit::karma::long_long, value); + } + else + { + if (std::is_signed::value) + { + boost::spirit::karma::generate(sink, boost::spirit::karma::int_, value); + } + else + { + boost::spirit::karma::generate(sink, boost::spirit::karma::uint_, value); + } + } + return output; + } + + static int string_to_int(const std::string &input) + { + auto first_digit = input.begin(); + // Delete any trailing white-spaces + while (first_digit != input.end() && std::isspace(*first_digit)) + { + ++first_digit; + } + int value = 0; + boost::spirit::qi::parse(first_digit, input.end(), boost::spirit::int_, value); + return value; + } + + static unsigned string_to_uint(const std::string &input) + { + auto first_digit = input.begin(); + // Delete any trailing white-spaces + while (first_digit != input.end() && (std::isspace(*first_digit) || '-' == *first_digit)) + { + ++first_digit; + } + unsigned value = 0; + boost::spirit::qi::parse(first_digit, input.end(), boost::spirit::uint_, value); + return value; + } + + static uint64_t string_to_uint64(const std::string &input) + { + auto first_digit = input.begin(); + // Delete any trailing white-spaces + while (first_digit != input.end() && std::isspace(*first_digit)) + { + ++first_digit; + } + uint64_t value = 0; + boost::spirit::qi::parse(first_digit, input.end(), boost::spirit::long_long, value); + return value; + } + + // source: http://tinodidriksen.com/2011/05/28/cpp-convert-string-to-double-speed/ + static double string_to_double(const char *p) + { + double r = 0.0; + bool neg = false; + if (*p == '-') + { + neg = true; + ++p; + } + while (*p >= '0' && *p <= '9') + { + r = (r * 10.0) + (*p - '0'); + ++p; + } + if (*p == '.') + { + double f = 0.0; + int n = 0; + ++p; + while (*p >= '0' && *p <= '9') + { + f = (f * 10.0) + (*p - '0'); + ++p; + ++n; + } + r += f / std::pow(10.0, n); + } + if (neg) + { + r = -r; + } + return r; + } + + template struct scientific_policy : boost::spirit::karma::real_policies + { + // we want the numbers always to be in fixed format + static int floatfield(T) { return boost::spirit::karma::real_policies::fmtflags::fixed; } + static unsigned int precision(T) { return 6; } + }; + typedef boost::spirit::karma::real_generator> science_type; + + static std::string double_fixed_to_string(const double value) + { + std::string output; + std::back_insert_iterator sink(output); + boost::spirit::karma::generate(sink, science_type(), value); + if (output.size() >= 2 && output[output.size() - 2] == '.' && + output[output.size() - 1] == '0') + { + output.resize(output.size() - 2); + } + return output; + } + + static std::string double_to_string(const double value) + { + std::string output; + std::back_insert_iterator sink(output); + boost::spirit::karma::generate(sink, value); + return output; + } + + static void double_with_two_digits_to_string(const double value, std::string &output) + { + // The largest 32-bit integer is 4294967295, that is 10 chars + // On the safe side, add 1 for sign, and 1 for trailing zero + char buffer[12]; + sprintf(buffer, "%g", value); + output = buffer; + } +}; + +#endif // CAST_HPP diff --git a/util/compute_angle.cpp b/util/compute_angle.cpp new file mode 100644 index 000000000..e83b67b75 --- /dev/null +++ b/util/compute_angle.cpp @@ -0,0 +1,54 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "compute_angle.hpp" + +#include "trigonometry_table.hpp" +#include "../util/mercator.hpp" + +#include + +#include + +double ComputeAngle::OfThreeFixedPointCoordinates(const FixedPointCoordinate &first, + const FixedPointCoordinate &second, + const FixedPointCoordinate &third) +{ + const double v1x = (first.lon - second.lon) / COORDINATE_PRECISION; + const double v1y = mercator::lat2y(first.lat / COORDINATE_PRECISION) - + mercator::lat2y(second.lat / COORDINATE_PRECISION); + const double v2x = (third.lon - second.lon) / COORDINATE_PRECISION; + const double v2y = mercator::lat2y(third.lat / COORDINATE_PRECISION) - + mercator::lat2y(second.lat / COORDINATE_PRECISION); + + double angle = (atan2_lookup(v2y, v2x) - atan2_lookup(v1y, v1x)) * 180. / M_PI; + while (angle < 0.) + { + angle += 360.; + } + return angle; +} diff --git a/util/compute_angle.hpp b/util/compute_angle.hpp new file mode 100644 index 000000000..73682bceb --- /dev/null +++ b/util/compute_angle.hpp @@ -0,0 +1,42 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef COMPUTE_ANGLE_HPP +#define COMPUTE_ANGLE_HPP + +struct FixedPointCoordinate; + +struct ComputeAngle +{ + // Get angle of line segment (A,C)->(C,B) + // atan2 magic, formerly cosine theorem + static double OfThreeFixedPointCoordinates(const FixedPointCoordinate &first, + const FixedPointCoordinate &second, + const FixedPointCoordinate &third); +}; + +#endif // COMPUTE_ANGLE_HPP diff --git a/util/container.hpp b/util/container.hpp new file mode 100644 index 000000000..a35d56a6d --- /dev/null +++ b/util/container.hpp @@ -0,0 +1,85 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef CONTAINER_HPP_ +#define CONTAINER_HPP_ + +#include +#include +#include + +namespace osrm +{ +template void sort_unique_resize(std::vector &vector) +{ + std::sort(vector.begin(), vector.end()); + const auto number_of_unique_elements = + std::unique(vector.begin(), vector.end()) - vector.begin(); + vector.resize(number_of_unique_elements); +} + +// template inline void sort_unique_resize_shrink_vector(std::vector &vector) +// { +// sort_unique_resize(vector); +// vector.shrink_to_fit(); +// } + +// template inline void remove_consecutive_duplicates_from_vector(std::vector +// &vector) +// { +// const auto number_of_unique_elements = std::unique(vector.begin(), vector.end()) - +// vector.begin(); +// vector.resize(number_of_unique_elements); +// } + +template +Function for_each_pair(ForwardIterator begin, ForwardIterator end, Function function) +{ + if (begin == end) + { + return function; + } + + auto next = begin; + next = std::next(next); + + while (next != end) + { + function(*begin, *next); + begin = std::next(begin); + next = std::next(next); + } + return function; +} + +template +Function for_each_pair(ContainerT &container, Function function) +{ + return for_each_pair(std::begin(container), std::end(container), function); +} +} +#endif /* CONTAINER_HPP_ */ diff --git a/util/datastore_options.hpp b/util/datastore_options.hpp new file mode 100644 index 000000000..1992860b5 --- /dev/null +++ b/util/datastore_options.hpp @@ -0,0 +1,273 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef DATASTORE_OPTIONS_HPP +#define DATASTORE_OPTIONS_HPP + +#include "boost_filesystem_2_fix.hpp" +#include "git_sha.hpp" +#include "ini_file.hpp" +#include "osrm_exception.hpp" +#include "simple_logger.hpp" + +#include + +#include +#include +#include + +#include + +// generate boost::program_options object for the routing part +bool GenerateDataStoreOptions(const int argc, const char *argv[], ServerPaths &paths) +{ + // declare a group of options that will be allowed only on command line + boost::program_options::options_description generic_options("Options"); + generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")( + "springclean,s", "Remove all regions in shared memory")( + "config,c", boost::program_options::value(&paths["config"]) + ->default_value("server.ini"), + "Path to a configuration file"); + + // declare a group of options that will be allowed both on command line + // as well as in a config file + boost::program_options::options_description config_options("Configuration"); + config_options.add_options()( + "hsgrdata", boost::program_options::value(&paths["hsgrdata"]), + ".hsgr file")("nodesdata", + boost::program_options::value(&paths["nodesdata"]), + ".nodes file")( + "edgesdata", boost::program_options::value(&paths["edgesdata"]), + ".edges file")("geometry", + boost::program_options::value(&paths["geometry"]), + ".geometry file")( + "ramindex", boost::program_options::value(&paths["ramindex"]), + ".ramIndex file")( + "fileindex", boost::program_options::value(&paths["fileindex"]), + ".fileIndex file")( + "namesdata", boost::program_options::value(&paths["namesdata"]), + ".names file")("timestamp", + boost::program_options::value(&paths["timestamp"]), + ".timestamp file"); + + // hidden options, will be allowed both on command line and in config + // file, but will not be shown to the user + boost::program_options::options_description hidden_options("Hidden options"); + hidden_options.add_options()( + "base,b", boost::program_options::value(&paths["base"]), + "base path to .osrm file"); + + // positional option + boost::program_options::positional_options_description positional_options; + positional_options.add("base", 1); + + // combine above options for parsing + boost::program_options::options_description cmdline_options; + cmdline_options.add(generic_options).add(config_options).add(hidden_options); + + boost::program_options::options_description config_file_options; + config_file_options.add(config_options).add(hidden_options); + + boost::program_options::options_description visible_options( + boost::filesystem::basename(argv[0]) + " [] "); + visible_options.add(generic_options).add(config_options); + + // parse command line options + boost::program_options::variables_map option_variables; + boost::program_options::store(boost::program_options::command_line_parser(argc, argv) + .options(cmdline_options) + .positional(positional_options) + .run(), + option_variables); + + if (option_variables.count("version")) + { + SimpleLogger().Write() << g_GIT_DESCRIPTION; + return false; + } + + if (option_variables.count("help")) + { + SimpleLogger().Write() << visible_options; + return false; + } + + boost::program_options::notify(option_variables); + + const bool parameter_present = (paths.find("hsgrdata") != paths.end() && + !paths.find("hsgrdata")->second.string().empty()) || + (paths.find("nodesdata") != paths.end() && + !paths.find("nodesdata")->second.string().empty()) || + (paths.find("edgesdata") != paths.end() && + !paths.find("edgesdata")->second.string().empty()) || + (paths.find("geometry") != paths.end() && + !paths.find("geometry")->second.string().empty()) || + (paths.find("ramindex") != paths.end() && + !paths.find("ramindex")->second.string().empty()) || + (paths.find("fileindex") != paths.end() && + !paths.find("fileindex")->second.string().empty()) || + (paths.find("timestamp") != paths.end() && + !paths.find("timestamp")->second.string().empty()); + + if (parameter_present) + { + if ((paths.find("config") != paths.end() && + boost::filesystem::is_regular_file(paths.find("config")->second)) || + option_variables.count("base")) + { + SimpleLogger().Write(logWARNING) << "conflicting parameters"; + SimpleLogger().Write() << visible_options; + return false; + } + } + + // parse config file + ServerPaths::iterator path_iterator = paths.find("config"); + if (path_iterator != paths.end() && boost::filesystem::is_regular_file(path_iterator->second) && + !option_variables.count("base")) + { + SimpleLogger().Write() << "Reading options from: " << path_iterator->second.string(); + std::string ini_file_contents = read_file_lower_content(path_iterator->second); + std::stringstream config_stream(ini_file_contents); + boost::program_options::store(parse_config_file(config_stream, config_file_options), + option_variables); + boost::program_options::notify(option_variables); + } + else if (option_variables.count("base")) + { + path_iterator = paths.find("base"); + BOOST_ASSERT(paths.end() != path_iterator); + std::string base_string = path_iterator->second.string(); + + path_iterator = paths.find("hsgrdata"); + if (path_iterator != paths.end()) + { + path_iterator->second = base_string + ".hsgr"; + } + + path_iterator = paths.find("nodesdata"); + if (path_iterator != paths.end()) + { + path_iterator->second = base_string + ".nodes"; + } + + path_iterator = paths.find("edgesdata"); + if (path_iterator != paths.end()) + { + path_iterator->second = base_string + ".edges"; + } + + path_iterator = paths.find("geometry"); + if (path_iterator != paths.end()) + { + path_iterator->second = base_string + ".geometry"; + } + + path_iterator = paths.find("ramindex"); + if (path_iterator != paths.end()) + { + path_iterator->second = base_string + ".ramIndex"; + } + + path_iterator = paths.find("fileindex"); + if (path_iterator != paths.end()) + { + path_iterator->second = base_string + ".fileIndex"; + } + + path_iterator = paths.find("namesdata"); + if (path_iterator != paths.end()) + { + path_iterator->second = base_string + ".names"; + } + + path_iterator = paths.find("timestamp"); + if (path_iterator != paths.end()) + { + path_iterator->second = base_string + ".timestamp"; + } + } + + path_iterator = paths.find("hsgrdata"); + if (path_iterator == paths.end() || path_iterator->second.string().empty()) + { + throw osrm::exception(".hsgr file must be specified"); + } + AssertPathExists(path_iterator->second); + + path_iterator = paths.find("nodesdata"); + if (path_iterator == paths.end() || path_iterator->second.string().empty()) + { + throw osrm::exception(".nodes file must be specified"); + } + AssertPathExists(path_iterator->second); + + path_iterator = paths.find("edgesdata"); + if (path_iterator == paths.end() || path_iterator->second.string().empty()) + { + throw osrm::exception(".edges file must be specified"); + } + AssertPathExists(path_iterator->second); + + path_iterator = paths.find("geometry"); + if (path_iterator == paths.end() || path_iterator->second.string().empty()) + { + throw osrm::exception(".geometry file must be specified"); + } + AssertPathExists(path_iterator->second); + + path_iterator = paths.find("ramindex"); + if (path_iterator == paths.end() || path_iterator->second.string().empty()) + { + throw osrm::exception(".ramindex file must be specified"); + } + AssertPathExists(path_iterator->second); + + path_iterator = paths.find("fileindex"); + if (path_iterator == paths.end() || path_iterator->second.string().empty()) + { + throw osrm::exception(".fileindex file must be specified"); + } + AssertPathExists(path_iterator->second); + + path_iterator = paths.find("namesdata"); + if (path_iterator == paths.end() || path_iterator->second.string().empty()) + { + throw osrm::exception(".names file must be specified"); + } + AssertPathExists(path_iterator->second); + + path_iterator = paths.find("timestamp"); + if (path_iterator == paths.end() || path_iterator->second.string().empty()) + { + throw osrm::exception(".timestamp file must be specified"); + } + + return true; +} + +#endif /* DATASTORE_OPTIONS_HPP */ diff --git a/util/fingerprint.cpp.in b/util/fingerprint.cpp.in new file mode 100644 index 000000000..6f9a6658f --- /dev/null +++ b/util/fingerprint.cpp.in @@ -0,0 +1,103 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "fingerprint.hpp" + +#include "osrm_exception.hpp" + +#include + +#include +#include + +#cmakedefine01 HAS64BITS +#cmakedefine MD5PREPARE "${MD5PREPARE}" +#cmakedefine MD5RTREE "${MD5RTREE}" +#cmakedefine MD5GRAPH "${MD5GRAPH}" +#cmakedefine MD5OBJECTS "${MD5OBJECTS}" + +FingerPrint::FingerPrint() : magic_number(1297240911) +{ + md5_prepare[32] = md5_tree[32] = md5_graph[32] = md5_objects[32] = '\0'; + + boost::uuids::name_generator gen(named_uuid); + std::string temp_string; + + std::memcpy(md5_prepare, MD5PREPARE, strlen(MD5PREPARE)); + temp_string += md5_prepare; + std::memcpy(md5_tree, MD5RTREE, 32); + temp_string += md5_tree; + std::memcpy(md5_graph, MD5GRAPH, 32); + temp_string += md5_graph; + std::memcpy(md5_objects, MD5OBJECTS, 32); + temp_string += md5_objects; + + named_uuid = gen(temp_string); + has_64_bits = HAS64BITS; +} + +FingerPrint::~FingerPrint() {} + +const boost::uuids::uuid &FingerPrint::GetFingerPrint() const { return named_uuid; } + +bool FingerPrint::IsMagicNumberOK() const { return 1297240911 == magic_number; } + +bool FingerPrint::TestGraphUtil(const FingerPrint &other) const +{ + if (!other.IsMagicNumberOK()) + { + throw osrm::exception("hsgr input file misses magic number. Check or reprocess the file"); + } + return std::equal(md5_graph, md5_graph + 32, other.md5_graph); +} + +bool FingerPrint::TestPrepare(const FingerPrint &other) const +{ + if (!other.IsMagicNumberOK()) + { + throw osrm::exception("osrm input file misses magic number. Check or reprocess the file"); + } + return std::equal(md5_prepare, md5_prepare + 32, other.md5_prepare); +} + +bool FingerPrint::TestRTree(const FingerPrint &other) const +{ + if (!other.IsMagicNumberOK()) + { + throw osrm::exception("r-tree input file misses magic number. Check or reprocess the file"); + } + return std::equal(md5_tree, md5_tree + 32, other.md5_tree); +} + +bool FingerPrint::TestQueryObjects(const FingerPrint &other) const +{ + if (!other.IsMagicNumberOK()) + { + throw osrm::exception("missing magic number. Check or reprocess the file"); + } + return std::equal(md5_objects, md5_objects + 32, other.md5_objects); +} diff --git a/util/fingerprint.hpp b/util/fingerprint.hpp new file mode 100644 index 000000000..494a877ab --- /dev/null +++ b/util/fingerprint.hpp @@ -0,0 +1,59 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef FINGERPRINT_H +#define FINGERPRINT_H + +#include + +// implements a singleton, i.e. there is one and only one conviguration object +class FingerPrint +{ + public: + FingerPrint(); + FingerPrint(const FingerPrint &) = delete; + ~FingerPrint(); + const boost::uuids::uuid &GetFingerPrint() const; + bool IsMagicNumberOK() const; + bool TestGraphUtil(const FingerPrint &other) const; + bool TestPrepare(const FingerPrint &other) const; + bool TestRTree(const FingerPrint &other) const; + bool TestQueryObjects(const FingerPrint &other) const; + + private: + const unsigned magic_number; + char md5_prepare[33]; + char md5_tree[33]; + char md5_graph[33]; + char md5_objects[33]; + + // initialize to {6ba7b810-9dad-11d1-80b4-00c04fd430c8} + boost::uuids::uuid named_uuid; + bool has_64_bits; +}; + +#endif /* FingerPrint_H */ diff --git a/util/floating_point.hpp b/util/floating_point.hpp new file mode 100644 index 000000000..5c4810279 --- /dev/null +++ b/util/floating_point.hpp @@ -0,0 +1,44 @@ +/* +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef FLOATING_POINT_HPP +#define FLOATING_POINT_HPP + +#include + +#include +#include + +namespace osrm +{ +template bool epsilon_compare(const FloatT number1, const FloatT number2) +{ + static_assert(std::is_floating_point::value, "type must be floating point"); + return (std::abs(number1 - number2) < std::numeric_limits::epsilon()); +} +} + +#endif // FLOATING_POINT_HPP diff --git a/util/git_sha.cpp.in b/util/git_sha.cpp.in new file mode 100644 index 000000000..5b19337e9 --- /dev/null +++ b/util/git_sha.cpp.in @@ -0,0 +1,31 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "git_sha.hpp" + +#define GIT_DESCRIPTION "${GIT_DESCRIPTION}" +char g_GIT_DESCRIPTION[] = GIT_DESCRIPTION; diff --git a/util/git_sha.hpp b/util/git_sha.hpp new file mode 100644 index 000000000..9e55deff3 --- /dev/null +++ b/util/git_sha.hpp @@ -0,0 +1,33 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef GIT_SHA_HPP +#define GIT_SHA_HPP + +extern char g_GIT_DESCRIPTION[]; + +#endif // GIT_SHA_HPP diff --git a/util/graph_loader.hpp b/util/graph_loader.hpp new file mode 100644 index 000000000..44f628034 --- /dev/null +++ b/util/graph_loader.hpp @@ -0,0 +1,320 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef GRAPH_LOADER_HPP +#define GRAPH_LOADER_HPP + +#include "fingerprint.hpp" +#include "osrm_exception.hpp" +#include "simple_logger.hpp" +#include "../data_structures/external_memory_node.hpp" +#include "../data_structures/import_edge.hpp" +#include "../data_structures/query_node.hpp" +#include "../data_structures/restriction.hpp" +#include "../typedefs.h" + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +template +NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, + std::vector &edge_list, + std::vector &barrier_node_list, + std::vector &traffic_light_node_list, + std::vector *int_to_ext_node_id_map, + std::vector &restriction_list) +{ + const FingerPrint fingerprint_orig; + FingerPrint fingerprint_loaded; + input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint)); + + if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig)) + { + SimpleLogger().Write(logWARNING) << ".osrm was prepared with different build.\n" + "Reprocess to get rid of this warning."; + } + + std::unordered_map ext_to_int_id_map; + + NodeID n; + input_stream.read((char *)&n, sizeof(NodeID)); + SimpleLogger().Write() << "Importing n = " << n << " nodes "; + + ExternalMemoryNode current_node; + for (NodeID i = 0; i < n; ++i) + { + input_stream.read((char *)¤t_node, sizeof(ExternalMemoryNode)); + int_to_ext_node_id_map->emplace_back(current_node.lat, current_node.lon, + current_node.node_id); + ext_to_int_id_map.emplace(current_node.node_id, i); + if (current_node.barrier) + { + barrier_node_list.emplace_back(i); + } + if (current_node.traffic_lights) + { + traffic_light_node_list.emplace_back(i); + } + } + + // tighten vector sizes + barrier_node_list.shrink_to_fit(); + traffic_light_node_list.shrink_to_fit(); + + // renumber nodes in turn restrictions + for (TurnRestriction ¤t_restriction : restriction_list) + { + auto internal_id_iter = ext_to_int_id_map.find(current_restriction.from.node); + if (internal_id_iter == ext_to_int_id_map.end()) + { + SimpleLogger().Write(logDEBUG) << "Unmapped from node " << current_restriction.from.node + << " of restriction"; + continue; + } + current_restriction.from.node = internal_id_iter->second; + + internal_id_iter = ext_to_int_id_map.find(current_restriction.via.node); + if (internal_id_iter == ext_to_int_id_map.end()) + { + SimpleLogger().Write(logDEBUG) << "Unmapped via node " << current_restriction.via.node + << " of restriction"; + continue; + } + + current_restriction.via.node = internal_id_iter->second; + + internal_id_iter = ext_to_int_id_map.find(current_restriction.to.node); + if (internal_id_iter == ext_to_int_id_map.end()) + { + SimpleLogger().Write(logDEBUG) << "Unmapped to node " << current_restriction.to.node + << " of restriction"; + continue; + } + current_restriction.to.node = internal_id_iter->second; + } + + EdgeWeight weight; + NodeID source, target; + unsigned nameID; + int length; + short dir; // direction (0 = open, 1 = forward, 2+ = open) + bool is_roundabout, ignore_in_grid, is_access_restricted, is_split; + TravelMode travel_mode; + + EdgeID m; + input_stream.read((char *)&m, sizeof(unsigned)); + edge_list.reserve(m); + SimpleLogger().Write() << " and " << m << " edges "; + + for (EdgeID i = 0; i < m; ++i) + { + input_stream.read((char *)&source, sizeof(unsigned)); + input_stream.read((char *)&target, sizeof(unsigned)); + input_stream.read((char *)&length, sizeof(int)); + input_stream.read((char *)&dir, sizeof(short)); + input_stream.read((char *)&weight, sizeof(int)); + input_stream.read((char *)&nameID, sizeof(unsigned)); + input_stream.read((char *)&is_roundabout, sizeof(bool)); + input_stream.read((char *)&ignore_in_grid, sizeof(bool)); + input_stream.read((char *)&is_access_restricted, sizeof(bool)); + input_stream.read((char *)&travel_mode, sizeof(TravelMode)); + input_stream.read((char *)&is_split, sizeof(bool)); + + BOOST_ASSERT_MSG(length > 0, "loaded null length edge"); + BOOST_ASSERT_MSG(weight > 0, "loaded null weight"); + BOOST_ASSERT_MSG(0 <= dir && dir <= 2, "loaded bogus direction"); + + bool forward = true; + bool backward = true; + if (1 == dir) + { + backward = false; + } + if (2 == dir) + { + forward = false; + } + + // translate the external NodeIDs to internal IDs + auto internal_id_iter = ext_to_int_id_map.find(source); + if (ext_to_int_id_map.find(source) == ext_to_int_id_map.end()) + { +#ifndef NDEBUG + SimpleLogger().Write(logWARNING) << " unresolved source NodeID: " << source; +#endif + continue; + } + source = internal_id_iter->second; + internal_id_iter = ext_to_int_id_map.find(target); + if (ext_to_int_id_map.find(target) == ext_to_int_id_map.end()) + { +#ifndef NDEBUG + SimpleLogger().Write(logWARNING) << "unresolved target NodeID : " << target; +#endif + continue; + } + target = internal_id_iter->second; + BOOST_ASSERT_MSG(source != SPECIAL_NODEID && target != SPECIAL_NODEID, + "nonexisting source or target"); + + if (source > target) + { + std::swap(source, target); + std::swap(forward, backward); + } + + edge_list.emplace_back(source, target, nameID, weight, forward, backward, is_roundabout, + ignore_in_grid, is_access_restricted, travel_mode, is_split); + } + ext_to_int_id_map.clear(); + + tbb::parallel_sort(edge_list.begin(), edge_list.end()); + + for (unsigned i = 1; i < edge_list.size(); ++i) + { + if ((edge_list[i - 1].target == edge_list[i].target) && + (edge_list[i - 1].source == edge_list[i].source)) + { + const bool edge_flags_equivalent = (edge_list[i - 1].forward == edge_list[i].forward) && + (edge_list[i - 1].backward == edge_list[i].backward); + const bool edge_flags_are_superset1 = + (edge_list[i - 1].forward && edge_list[i - 1].backward) && + (edge_list[i].forward != edge_list[i].backward); + const bool edge_flags_are_superset_2 = + (edge_list[i].forward && edge_list[i].backward) && + (edge_list[i - 1].forward != edge_list[i - 1].backward); + + if (edge_flags_equivalent) + { + edge_list[i].weight = std::min(edge_list[i - 1].weight, edge_list[i].weight); + edge_list[i - 1].source = SPECIAL_NODEID; + } + else if (edge_flags_are_superset1) + { + if (edge_list[i - 1].weight <= edge_list[i].weight) + { + // edge i-1 is smaller and goes in both directions. Throw away the other edge + edge_list[i].source = SPECIAL_NODEID; + } + else + { + // edge i-1 is open in both directions, but edge i is smaller in one direction. + // Close edge i-1 in this direction + edge_list[i - 1].forward = !edge_list[i].forward; + edge_list[i - 1].backward = !edge_list[i].backward; + } + } + else if (edge_flags_are_superset_2) + { + if (edge_list[i - 1].weight <= edge_list[i].weight) + { + // edge i-1 is smaller for one direction. edge i is open in both. close edge i + // in the other direction + edge_list[i].forward = !edge_list[i - 1].forward; + edge_list[i].backward = !edge_list[i - 1].backward; + } + else + { + // edge i is smaller and goes in both direction. Throw away edge i-1 + edge_list[i - 1].source = SPECIAL_NODEID; + } + } + } + } + const auto new_end_iter = + std::remove_if(edge_list.begin(), edge_list.end(), [](const EdgeT &edge) + { + return edge.source == SPECIAL_NODEID || edge.target == SPECIAL_NODEID; + }); + edge_list.erase(new_end_iter, edge_list.end()); // remove excess candidates. + edge_list.shrink_to_fit(); + SimpleLogger().Write() << "Graph loaded ok and has " << edge_list.size() << " edges"; + return n; +} + +template +unsigned readHSGRFromStream(const boost::filesystem::path &hsgr_file, + std::vector &node_list, + std::vector &edge_list, + unsigned *check_sum) +{ + if (!boost::filesystem::exists(hsgr_file)) + { + throw osrm::exception("hsgr file does not exist"); + } + if (0 == boost::filesystem::file_size(hsgr_file)) + { + throw osrm::exception("hsgr file is empty"); + } + + boost::filesystem::ifstream hsgr_input_stream(hsgr_file, std::ios::binary); + + FingerPrint fingerprint_loaded, fingerprint_orig; + hsgr_input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint)); + if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig)) + { + SimpleLogger().Write(logWARNING) << ".hsgr was prepared with different build.\n" + "Reprocess to get rid of this warning."; + } + + unsigned number_of_nodes = 0; + unsigned number_of_edges = 0; + hsgr_input_stream.read((char *)check_sum, sizeof(unsigned)); + hsgr_input_stream.read((char *)&number_of_nodes, sizeof(unsigned)); + BOOST_ASSERT_MSG(0 != number_of_nodes, "number of nodes is zero"); + hsgr_input_stream.read((char *)&number_of_edges, sizeof(unsigned)); + + SimpleLogger().Write() << "number_of_nodes: " << number_of_nodes + << ", number_of_edges: " << number_of_edges; + + // BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero"); + node_list.resize(number_of_nodes); + hsgr_input_stream.read((char *)&(node_list[0]), number_of_nodes * sizeof(NodeT)); + + edge_list.resize(number_of_edges); + if (number_of_edges > 0) + { + hsgr_input_stream.read((char *)&(edge_list[0]), number_of_edges * sizeof(EdgeT)); + } + hsgr_input_stream.close(); + + return number_of_nodes; +} + +#endif // GRAPH_LOADER_HPP diff --git a/util/ini_file.hpp b/util/ini_file.hpp new file mode 100644 index 000000000..20616257a --- /dev/null +++ b/util/ini_file.hpp @@ -0,0 +1,51 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef INI_FILE_HPP +#define INI_FILE_HPP + +#include +#include + +#include +#include + +namespace +{ + +// support old capitalized option names by down-casing them with a regex replace +std::string read_file_lower_content(const boost::filesystem::path &path) +{ + boost::filesystem::fstream config_stream(path); + std::string ini_file_content((std::istreambuf_iterator(config_stream)), + std::istreambuf_iterator()); + std::transform(std::begin(ini_file_content), std::end(ini_file_content), + std::begin(ini_file_content), ::tolower); + return ini_file_content; +} +} +#endif // INI_FILE_HPP diff --git a/util/integer_range.hpp b/util/integer_range.hpp new file mode 100644 index 000000000..030b2fa63 --- /dev/null +++ b/util/integer_range.hpp @@ -0,0 +1,70 @@ +/* + +Copyright (c) 2013,2014, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef INTEGER_RANGE_HPP +#define INTEGER_RANGE_HPP + +#include + +namespace osrm +{ + +template class range +{ + private: + Integer last; + Integer iter; + + public: + range(Integer start, Integer end) : last(end), iter(start) + { + static_assert(std::is_integral::value, "range type must be integral"); + } + + // Iterable functions + const range &begin() const { return *this; } + const range &end() const { return *this; } + Integer front() const { return iter; } + Integer back() const { return last - 1; } + + // Iterator functions + bool operator!=(const range &) const { return iter < last; } + void operator++() { ++iter; } + Integer operator*() const { return iter; } +}; + +// convenience function to construct an integer range with type deduction +template +range irange(const Integer first, + const Integer last, + typename std::enable_if::value>::type * = 0) +{ + return range(first, last); +} +} + +#endif // INTEGER_RANGE_HPP diff --git a/util/iterator_range.hpp b/util/iterator_range.hpp new file mode 100644 index 000000000..a057d7c92 --- /dev/null +++ b/util/iterator_range.hpp @@ -0,0 +1,72 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef RANGE_HPP_ +#define RANGE_HPP_ + +namespace osrm +{ +namespace util +{ +template class Range +{ + public: + Range(Iterator begin, Iterator end) : begin_(begin), end_(end) {} + + Iterator begin() const { return begin_; } + Iterator end() const { return end_; } + + private: + Iterator begin_; + Iterator end_; +}; + +// Convenience functions for template parameter inference, +// akin to std::make_pair. + +template Range range(Iterator begin, Iterator end) +{ + return Range(begin, end); +} + +template +Range reverse(Reversable *reversable) +{ + return Range(reversable->rbegin(), reversable->rend()); +} + +template +Range +const_reverse(const ConstReversable *const_reversable) +{ + return Range(const_reversable->crbegin(), + const_reversable->crend()); +} +} +} + +#endif // RANGE_HPP_ diff --git a/util/json_renderer.hpp b/util/json_renderer.hpp new file mode 100644 index 000000000..adb7c544e --- /dev/null +++ b/util/json_renderer.hpp @@ -0,0 +1,184 @@ +/* + +Copyright (c) 2014, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +// based on +// https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp + +#ifndef JSON_RENDERER_HPP +#define JSON_RENDERER_HPP + +#include "cast.hpp" + +#include + +namespace JSON +{ + +struct Renderer : mapbox::util::static_visitor<> +{ + explicit Renderer(std::ostream &_out) : out(_out) {} + + void operator()(const String &string) const { out << "\"" << string.value << "\""; } + + void operator()(const Number &number) const + { + out.precision(10); + out << number.value; + } + + void operator()(const Object &object) const + { + out << "{"; + auto iterator = object.values.begin(); + while (iterator != object.values.end()) + { + out << "\"" << (*iterator).first << "\":"; + mapbox::util::apply_visitor(Renderer(out), (*iterator).second); + if (++iterator != object.values.end()) + { + out << ","; + } + } + out << "}"; + } + + void operator()(const Array &array) const + { + out << "["; + std::vector::const_iterator iterator; + iterator = array.values.begin(); + while (iterator != array.values.end()) + { + mapbox::util::apply_visitor(Renderer(out), *iterator); + if (++iterator != array.values.end()) + { + out << ","; + } + } + out << "]"; + } + + void operator()(const True &) const { out << "true"; } + + void operator()(const False &) const { out << "false"; } + + void operator()(const Null &) const { out << "null"; } + + private: + std::ostream &out; +}; + +struct ArrayRenderer : mapbox::util::static_visitor<> +{ + explicit ArrayRenderer(std::vector &_out) : out(_out) {} + + void operator()(const String &string) const + { + out.push_back('\"'); + out.insert(out.end(), string.value.begin(), string.value.end()); + out.push_back('\"'); + } + + void operator()(const Number &number) const + { + const std::string number_string = cast::double_fixed_to_string(number.value); + out.insert(out.end(), number_string.begin(), number_string.end()); + } + + void operator()(const Object &object) const + { + out.push_back('{'); + auto iterator = object.values.begin(); + while (iterator != object.values.end()) + { + out.push_back('\"'); + out.insert(out.end(), (*iterator).first.begin(), (*iterator).first.end()); + out.push_back('\"'); + out.push_back(':'); + + mapbox::util::apply_visitor(ArrayRenderer(out), (*iterator).second); + if (++iterator != object.values.end()) + { + out.push_back(','); + } + } + out.push_back('}'); + } + + void operator()(const Array &array) const + { + out.push_back('['); + std::vector::const_iterator iterator; + iterator = array.values.begin(); + while (iterator != array.values.end()) + { + mapbox::util::apply_visitor(ArrayRenderer(out), *iterator); + if (++iterator != array.values.end()) + { + out.push_back(','); + } + } + out.push_back(']'); + } + + void operator()(const True &) const + { + const std::string temp("true"); + out.insert(out.end(), temp.begin(), temp.end()); + } + + void operator()(const False &) const + { + const std::string temp("false"); + out.insert(out.end(), temp.begin(), temp.end()); + } + + void operator()(const Null &) const + { + const std::string temp("null"); + out.insert(out.end(), temp.begin(), temp.end()); + } + + private: + std::vector &out; +}; + +inline void render(std::ostream &out, const Object &object) +{ + Value value = object; + mapbox::util::apply_visitor(Renderer(out), value); +} + +inline void render(std::vector &out, const Object &object) +{ + Value value = object; + mapbox::util::apply_visitor(ArrayRenderer(out), value); +} + +} // namespace JSON + +#endif // JSON_RENDERER_HPP diff --git a/util/lua_util.hpp b/util/lua_util.hpp new file mode 100644 index 000000000..f367949da --- /dev/null +++ b/util/lua_util.hpp @@ -0,0 +1,66 @@ +/* + +Copyright (c) 2014, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef LUA_UTIL_HPP +#define LUA_UTIL_HPP + +extern "C" { +#include +#include +#include +} + +#include +#include + +#include +#include + +template void LUA_print(T output) { std::cout << "[LUA] " << output << std::endl; } + +// Check if the lua function is defined +inline bool lua_function_exists(lua_State *lua_state, const char *name) +{ + luabind::object globals_table = luabind::globals(lua_state); + luabind::object lua_function = globals_table[name]; + return lua_function && (luabind::type(lua_function) == LUA_TFUNCTION); +} + +// Add the folder contain the script to the lua load path, so script can easily require() other lua +// scripts inside that folder, or subfolders. +// See http://lua-users.org/wiki/PackagePath for details on the package.path syntax. +inline void luaAddScriptFolderToLoadPath(lua_State *lua_state, const char *file_name) +{ + const boost::filesystem::path profile_path(file_name); + std::string folder = profile_path.parent_path().string(); + // TODO: This code is most probably not Windows safe since it uses UNIX'ish path delimiters + const std::string lua_code = + "package.path = \"" + folder + "/?.lua;profiles/?.lua;\" .. package.path"; + luaL_dostring(lua_state, lua_code.c_str()); +} + +#endif // LUA_UTIL_HPP diff --git a/util/make_unique.hpp b/util/make_unique.hpp new file mode 100644 index 000000000..b88145d17 --- /dev/null +++ b/util/make_unique.hpp @@ -0,0 +1,57 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef MAKE_UNIQUE_H_ +#define MAKE_UNIQUE_H_ + +#include +#include +#include + +namespace osrm +{ +// Taken from http://msdn.microsoft.com/en-us/library/dn439780.asp +// Note, that the snippet was broken there and needed minor massaging + +// make_unique +template std::unique_ptr make_unique(Types &&... Args) +{ + return (std::unique_ptr(new T(std::forward(Args)...))); +} + +// make_unique +template std::unique_ptr make_unique(std::size_t Size) +{ + return (std::unique_ptr(new T[Size]())); +} + +// make_unique disallowed +template +typename std::enable_if::value != 0, void>::type make_unique(Types &&...) = delete; +} + +#endif // MAKE_UNIQUE_H_ diff --git a/util/mercator.cpp b/util/mercator.cpp new file mode 100644 index 000000000..ddd80685d --- /dev/null +++ b/util/mercator.cpp @@ -0,0 +1,40 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "mercator.hpp" + +#include + +double mercator::y2lat(const double value) +{ + return 180. * M_1_PI * (2. * std::atan(std::exp(value * M_PI / 180.)) - M_PI_2); +} + +double mercator::lat2y(const double latitude) +{ + return 180. * M_1_PI * std::log(std::tan(M_PI_4 + latitude * (M_PI / 180.) / 2.)); +} diff --git a/util/mercator.hpp b/util/mercator.hpp new file mode 100644 index 000000000..2929db2f9 --- /dev/null +++ b/util/mercator.hpp @@ -0,0 +1,38 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef MERCATOR_HPP +#define MERCATOR_HPP + +struct mercator +{ + static double y2lat(const double value); + + static double lat2y(const double latitude); +}; + +#endif // MERCATOR_HPP diff --git a/util/osrm_exception.cpp b/util/osrm_exception.cpp new file mode 100644 index 000000000..e6b7986e3 --- /dev/null +++ b/util/osrm_exception.cpp @@ -0,0 +1,43 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "osrm_exception.hpp" + +namespace osrm +{ +// This function exists to 'anchor' the class, and stop the compiler from +// copying vtable and RTTI info into every object file that includes +// this header. (Caught by -Wweak-vtables under Clang.) + +// More information from the LLVM Coding Standards: +// If a class is defined in a header file and has a vtable (either it has +// virtual methods or it derives from classes with virtual methods), it must +// always have at least one out-of-line virtual method in the class. Without +// this, the compiler will copy the vtable and RTTI into every .o file that +// #includes the header, bloating .o file sizes and increasing link times. +void exception::anchor() const {} +} diff --git a/util/osrm_exception.hpp b/util/osrm_exception.hpp new file mode 100644 index 000000000..ac5044a79 --- /dev/null +++ b/util/osrm_exception.hpp @@ -0,0 +1,51 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef OSRM_EXCEPTION_HPP +#define OSRM_EXCEPTION_HPP + +#include +#include + +namespace osrm +{ +class exception final : public std::exception +{ + public: + explicit exception(const char *message) : message(message) {} + explicit exception(const std::string &message) : message(message) {} + + private: + // This function exists to 'anchor' the class, and stop the compiler from + // copying vtable and RTTI info into every object file that includes + // this header. (Caught by -Wweak-vtables under Clang.) + virtual void anchor() const; + const char *what() const noexcept { return message.c_str(); } + const std::string message; +}; +} +#endif /* OSRM_EXCEPTION_HPP */ diff --git a/util/range_algorithms.hpp b/util/range_algorithms.hpp new file mode 100644 index 000000000..5aafd8e17 --- /dev/null +++ b/util/range_algorithms.hpp @@ -0,0 +1,42 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, others 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. + */ + +#ifndef RANGE_ALGORITHMS_HPP +#define RANGE_ALGORITHMS_HPP + +#include + +namespace osrm +{ + +template +auto max_element(const Container &c) -> decltype(std::max_element(c.begin(), c.end())) +{ + return std::max_element(c.begin(), c.end()); +} + +template +auto max_element(const Container &c) -> decltype(std::max_element(c.cbegin(), c.cend())) +{ + return std::max_element(c.cbegin(), c.cend()); +} +} + +#endif // RANGE_ALGORITHMS_HPP diff --git a/util/routed_options.hpp b/util/routed_options.hpp new file mode 100644 index 000000000..74e79b070 --- /dev/null +++ b/util/routed_options.hpp @@ -0,0 +1,277 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef ROUTED_OPTIONS_HPP +#define ROUTED_OPTIONS_HPP + +#include "git_sha.hpp" +#include "ini_file.hpp" +#include "osrm_exception.hpp" +#include "simple_logger.hpp" + +#include +#include + +#include + +#include +#include +const static unsigned INIT_OK_START_ENGINE = 0; +const static unsigned INIT_OK_DO_NOT_START_ENGINE = 1; +const static unsigned INIT_FAILED = -1; + +inline void populate_base_path(ServerPaths &server_paths) +{ + // populate the server_path object + auto path_iterator = server_paths.find("base"); + + // if a base path has been set, we populate it. + if (path_iterator != server_paths.end()) + { + const std::string base_string = path_iterator->second.string(); + SimpleLogger().Write() << "populating base path: " << base_string; + + server_paths["hsgrdata"] = base_string + ".hsgr"; + BOOST_ASSERT(server_paths.find("hsgrdata") != server_paths.end()); + server_paths["nodesdata"] = base_string + ".nodes"; + BOOST_ASSERT(server_paths.find("nodesdata") != server_paths.end()); + server_paths["edgesdata"] = base_string + ".edges"; + BOOST_ASSERT(server_paths.find("edgesdata") != server_paths.end()); + server_paths["geometries"] = base_string + ".geometry"; + BOOST_ASSERT(server_paths.find("geometries") != server_paths.end()); + server_paths["ramindex"] = base_string + ".ramIndex"; + BOOST_ASSERT(server_paths.find("ramindex") != server_paths.end()); + server_paths["fileindex"] = base_string + ".fileIndex"; + BOOST_ASSERT(server_paths.find("fileindex") != server_paths.end()); + server_paths["namesdata"] = base_string + ".names"; + BOOST_ASSERT(server_paths.find("namesdata") != server_paths.end()); + server_paths["timestamp"] = base_string + ".timestamp"; + BOOST_ASSERT(server_paths.find("timestamp") != server_paths.end()); + } + + // check if files are give and whether they exist at all + path_iterator = server_paths.find("hsgrdata"); + if (path_iterator == server_paths.end() || + !boost::filesystem::is_regular_file(path_iterator->second)) + { + if (path_iterator == server_paths.end()) + { + SimpleLogger().Write() << "hsgrdata unset"; + } + if (!boost::filesystem::is_regular_file(path_iterator->second)) + { + SimpleLogger().Write() << "not a regular file"; + } + + throw osrm::exception(".hsgr not found: " + path_iterator->second.string()); + } + + path_iterator = server_paths.find("nodesdata"); + if (path_iterator == server_paths.end() || + !boost::filesystem::is_regular_file(path_iterator->second)) + { + throw osrm::exception(".nodes not found"); + } + + path_iterator = server_paths.find("edgesdata"); + if (path_iterator == server_paths.end() || + !boost::filesystem::is_regular_file(path_iterator->second)) + { + throw osrm::exception(".edges not found"); + } + + path_iterator = server_paths.find("geometries"); + if (path_iterator == server_paths.end() || + !boost::filesystem::is_regular_file(path_iterator->second)) + { + throw osrm::exception(".geometry not found"); + } + + path_iterator = server_paths.find("ramindex"); + if (path_iterator == server_paths.end() || + !boost::filesystem::is_regular_file(path_iterator->second)) + { + throw osrm::exception(".ramIndex not found"); + } + + path_iterator = server_paths.find("fileindex"); + if (path_iterator == server_paths.end() || + !boost::filesystem::is_regular_file(path_iterator->second)) + { + throw osrm::exception(".fileIndex not found"); + } + + path_iterator = server_paths.find("namesdata"); + if (path_iterator == server_paths.end() || + !boost::filesystem::is_regular_file(path_iterator->second)) + { + throw osrm::exception(".namesIndex not found"); + } + + SimpleLogger().Write() << "HSGR file:\t" << server_paths["hsgrdata"]; + SimpleLogger().Write(logDEBUG) << "Nodes file:\t" << server_paths["nodesdata"]; + SimpleLogger().Write(logDEBUG) << "Edges file:\t" << server_paths["edgesdata"]; + SimpleLogger().Write(logDEBUG) << "Geometry file:\t" << server_paths["geometries"]; + SimpleLogger().Write(logDEBUG) << "RAM file:\t" << server_paths["ramindex"]; + SimpleLogger().Write(logDEBUG) << "Index file:\t" << server_paths["fileindex"]; + SimpleLogger().Write(logDEBUG) << "Names file:\t" << server_paths["namesdata"]; + SimpleLogger().Write(logDEBUG) << "Timestamp file:\t" << server_paths["timestamp"]; +} + +// generate boost::program_options object for the routing part +inline unsigned GenerateServerProgramOptions(const int argc, + const char *argv[], + ServerPaths &paths, + std::string &ip_address, + int &ip_port, + int &requested_num_threads, + bool &use_shared_memory, + bool &trial, + int &max_locations_distance_table) +{ + // declare a group of options that will be allowed only on command line + boost::program_options::options_description generic_options("Options"); + generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")( + "config,c", boost::program_options::value(&paths["config"]) + ->default_value("server.ini"), + "Path to a configuration file")( + "trial", boost::program_options::value(&trial)->implicit_value(true), + "Quit after initialization"); + + // declare a group of options that will be allowed both on command line + // as well as in a config file + boost::program_options::options_description config_options("Configuration"); + config_options.add_options()( + "hsgrdata", boost::program_options::value(&paths["hsgrdata"]), + ".hsgr file")("nodesdata", + boost::program_options::value(&paths["nodesdata"]), + ".nodes file")( + "edgesdata", boost::program_options::value(&paths["edgesdata"]), + ".edges file")("geometry", + boost::program_options::value(&paths["geometries"]), + ".geometry file")( + "ramindex", boost::program_options::value(&paths["ramindex"]), + ".ramIndex file")( + "fileindex", boost::program_options::value(&paths["fileindex"]), + "File index file")( + "namesdata", boost::program_options::value(&paths["namesdata"]), + ".names file")("timestamp", + boost::program_options::value(&paths["timestamp"]), + ".timestamp file")( + "ip,i", boost::program_options::value(&ip_address)->default_value("0.0.0.0"), + "IP address")("port,p", boost::program_options::value(&ip_port)->default_value(5000), + "TCP/IP port")( + "threads,t", boost::program_options::value(&requested_num_threads)->default_value(8), + "Number of threads to use")( + "shared-memory,s", + boost::program_options::value(&use_shared_memory)->implicit_value(true), + "Load data from shared memory")( + "max-table-size,m", + boost::program_options::value(&max_locations_distance_table)->default_value(100), + "Max. locations supported in distance table query"); + + // hidden options, will be allowed both on command line and in config + // file, but will not be shown to the user + boost::program_options::options_description hidden_options("Hidden options"); + hidden_options.add_options()( + "base,b", boost::program_options::value(&paths["base"]), + "base path to .osrm file"); + + // positional option + boost::program_options::positional_options_description positional_options; + positional_options.add("base", 1); + + // combine above options for parsing + boost::program_options::options_description cmdline_options; + cmdline_options.add(generic_options).add(config_options).add(hidden_options); + + boost::program_options::options_description config_file_options; + config_file_options.add(config_options).add(hidden_options); + + boost::program_options::options_description visible_options( + boost::filesystem::basename(argv[0]) + " []"); + visible_options.add(generic_options).add(config_options); + + // parse command line options + boost::program_options::variables_map option_variables; + boost::program_options::store(boost::program_options::command_line_parser(argc, argv) + .options(cmdline_options) + .positional(positional_options) + .run(), + option_variables); + + if (option_variables.count("version")) + { + SimpleLogger().Write() << g_GIT_DESCRIPTION; + return INIT_OK_DO_NOT_START_ENGINE; + } + + if (option_variables.count("help")) + { + SimpleLogger().Write() << visible_options; + return INIT_OK_DO_NOT_START_ENGINE; + } + + boost::program_options::notify(option_variables); + + // parse config file + ServerPaths::iterator path_iterator = paths.find("config"); + if (path_iterator != paths.end() && boost::filesystem::is_regular_file(path_iterator->second) && + !option_variables.count("base")) + { + SimpleLogger().Write() << "Reading options from: " << path_iterator->second.string(); + std::string ini_file_contents = read_file_lower_content(path_iterator->second); + std::stringstream config_stream(ini_file_contents); + boost::program_options::store(parse_config_file(config_stream, config_file_options), + option_variables); + boost::program_options::notify(option_variables); + return INIT_OK_START_ENGINE; + } + + if (1 > requested_num_threads) + { + throw osrm::exception("Number of threads must be a positive number"); + } + + if (!use_shared_memory && option_variables.count("base")) + { + return INIT_OK_START_ENGINE; + } + if (use_shared_memory && !option_variables.count("base")) + { + return INIT_OK_START_ENGINE; + } + if (1 > max_locations_distance_table) + { + throw osrm::exception("Max location for distance table must be a positive number"); + } + + SimpleLogger().Write() << visible_options; + return INIT_OK_DO_NOT_START_ENGINE; +} + +#endif // ROUTED_OPTIONS_HPP diff --git a/util/simple_logger.cpp b/util/simple_logger.cpp new file mode 100644 index 000000000..5d8821233 --- /dev/null +++ b/util/simple_logger.cpp @@ -0,0 +1,135 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "simple_logger.hpp" + +#include "osrm_exception.hpp" + +#include + +#include + +#ifdef _MSC_VER +#include +#define isatty _isatty +#define fileno _fileno +#else +#include +#endif + +#include +#include +#include + +namespace +{ +static const char COL_RESET[]{"\x1b[0m"}; +static const char RED[]{"\x1b[31m"}; +#ifndef NDEBUG +static const char YELLOW[]{"\x1b[33m"}; +#endif +// static const char GREEN[] { "\x1b[32m"}; +// static const char BLUE[] { "\x1b[34m"}; +// static const char MAGENTA[] { "\x1b[35m"}; +// static const char CYAN[] { "\x1b[36m"}; +} + +void LogPolicy::Unmute() { m_is_mute = false; } + +void LogPolicy::Mute() { m_is_mute = true; } + +bool LogPolicy::IsMute() const { return m_is_mute; } + +LogPolicy &LogPolicy::GetInstance() +{ + static LogPolicy runningInstance; + return runningInstance; +} + +SimpleLogger::SimpleLogger() : level(logINFO) {} + +std::mutex &SimpleLogger::get_mutex() +{ + static std::mutex mtx; + return mtx; +} + +std::ostringstream &SimpleLogger::Write(LogLevel lvl) +{ + std::lock_guard lock(get_mutex()); + try + { + level = lvl; + os << "["; + switch (level) + { + case logWARNING: + os << "warn"; + break; + case logDEBUG: +#ifndef NDEBUG + os << "debug"; +#endif + break; + default: // logINFO: + os << "info"; + break; + } + os << "] "; + } + catch (const std::exception &e) + { + // encapsulate in osrm::exception + throw osrm::exception(std::string(e.what()) + ", getting ostringstream"); + } + return os; +} + +SimpleLogger::~SimpleLogger() +{ + std::lock_guard lock(get_mutex()); + if (!LogPolicy::GetInstance().IsMute()) + { + const bool is_terminal = static_cast(isatty(fileno(stdout))); + switch (level) + { + case logWARNING: + std::cerr << (is_terminal ? RED : "") << os.str() << (is_terminal ? COL_RESET : "") + << std::endl; + break; + case logDEBUG: +#ifndef NDEBUG + std::cout << (is_terminal ? YELLOW : "") << os.str() << (is_terminal ? COL_RESET : "") + << std::endl; +#endif + break; + default: // logINFO: + std::cout << os.str() << (is_terminal ? COL_RESET : "") << std::endl; + break; + } + } +} diff --git a/util/simple_logger.hpp b/util/simple_logger.hpp new file mode 100644 index 000000000..077fa2e41 --- /dev/null +++ b/util/simple_logger.hpp @@ -0,0 +1,74 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef SIMPLE_LOGGER_HPP +#define SIMPLE_LOGGER_HPP + +#include +#include +#include + +enum LogLevel +{ + logINFO, + logWARNING, + logDEBUG +}; + +class LogPolicy +{ + public: + void Unmute(); + + void Mute(); + + bool IsMute() const; + + static LogPolicy &GetInstance(); + + LogPolicy(const LogPolicy &) = delete; + + private: + LogPolicy() : m_is_mute(true) {} + std::atomic m_is_mute; +}; + +class SimpleLogger +{ + public: + SimpleLogger(); + + virtual ~SimpleLogger(); + std::mutex &get_mutex(); + std::ostringstream &Write(LogLevel l = logINFO); + + private: + std::ostringstream os; + LogLevel level; +}; + +#endif /* SIMPLE_LOGGER_HPP */ diff --git a/util/std_hash.hpp b/util/std_hash.hpp new file mode 100644 index 000000000..8b4af3dd8 --- /dev/null +++ b/util/std_hash.hpp @@ -0,0 +1,72 @@ +/* + +Copyright (c) 2014, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef STD_HASH_HPP +#define STD_HASH_HPP + +#include + +// this is largely inspired by boost's hash combine as can be found in +// "The C++ Standard Library" 2nd Edition. Nicolai M. Josuttis. 2012. + +namespace +{ + +template void hash_combine(std::size_t &seed, const T &val) +{ + seed ^= std::hash()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2); +} + +template void hash_val(std::size_t &seed, const T &val) { hash_combine(seed, val); } + +template +void hash_val(std::size_t &seed, const T &val, const Types &... args) +{ + hash_combine(seed, val); + hash_val(seed, args...); +} + +template std::size_t hash_val(const Types &... args) +{ + std::size_t seed = 0; + hash_val(seed, args...); + return seed; +} +} + +namespace std +{ +template struct hash> +{ + size_t operator()(const std::pair &pair) const + { + return hash_val(pair.first, pair.second); + } +}; +} + +#endif // STD_HASH_HPP diff --git a/util/string_util.hpp b/util/string_util.hpp new file mode 100644 index 000000000..08af55483 --- /dev/null +++ b/util/string_util.hpp @@ -0,0 +1,150 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef STRING_UTIL_HPP +#define STRING_UTIL_HPP + +#include + +#include + +#include +#include +#include + +// precision: position after decimal point +// length: maximum number of digits including comma and decimals +// work with negative values to prevent overflowing when taking -value +template static inline char *printInt(char *buffer, int value) +{ + bool minus = true; + if (value > 0) + { + minus = false; + value = -value; + } + buffer += length - 1; + for (int i = 0; i < precision; i++) + { + *buffer = '0' - (value % 10); + value /= 10; + buffer--; + } + *buffer = '.'; + buffer--; + for (int i = precision + 1; i < length; i++) + { + *buffer = '0' - (value % 10); + value /= 10; + if (value == 0) + break; + buffer--; + } + if (minus) + { + buffer--; + *buffer = '-'; + } + return buffer; +} + +inline void replaceAll(std::string &s, const std::string &sub, const std::string &other) +{ + boost::replace_all(s, sub, other); +} + +inline std::string EscapeJSONString(const std::string &input) +{ + std::string output; + output.reserve(input.size()); + for (auto iter = input.begin(); iter != input.end(); ++iter) + { + switch (iter[0]) + { + case '\\': + output += "\\\\"; + break; + case '"': + output += "\\\""; + break; + case '/': + output += "\\/"; + break; + case '\b': + output += "\\b"; + break; + case '\f': + output += "\\f"; + break; + case '\n': + output += "\\n"; + break; + case '\r': + output += "\\r"; + break; + case '\t': + output += "\\t"; + break; + default: + output += *iter; + break; + } + } + return output; +} + +static std::string originals[] = {"&", "\"", "<", ">", "'", "[", "]", "\\"}; +static std::string entities[] = { + "&", """, "<", ">", "'", "&91;", "&93;", " \"}; + +inline std::size_t URIDecode(const std::string &input, std::string &output) +{ + auto src_iter = input.begin(); + output.resize(input.size() + 1); + std::size_t decoded_length = 0; + for (decoded_length = 0; src_iter != input.end(); ++decoded_length) + { + if (src_iter[0] == '%' && src_iter[1] && src_iter[2] && isxdigit(src_iter[1]) && + isxdigit(src_iter[2])) + { + std::string::value_type a = src_iter[1]; + std::string::value_type b = src_iter[2]; + a -= src_iter[1] < 58 ? 48 : src_iter[1] < 71 ? 55 : 87; + b -= src_iter[2] < 58 ? 48 : src_iter[2] < 71 ? 55 : 87; + output[decoded_length] = 16 * a + b; + src_iter += 3; + continue; + } + output[decoded_length] = *src_iter++; + } + output.resize(decoded_length); + return decoded_length; +} + +inline std::size_t URIDecodeInPlace(std::string &URI) { return URIDecode(URI, URI); } + +#endif // STRING_UTIL_HPP diff --git a/util/timing_util.hpp b/util/timing_util.hpp new file mode 100644 index 000000000..2279bd083 --- /dev/null +++ b/util/timing_util.hpp @@ -0,0 +1,90 @@ +/* + +Copyright (c) 2014, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TIMING_UTIL_HPP +#define TIMING_UTIL_HPP + +#include +#include +#include +#include +#include + +struct GlobalTimer +{ + GlobalTimer() : time(0) {} + std::atomic time; +}; + +class GlobalTimerFactory +{ + public: + static GlobalTimerFactory &get() + { + static GlobalTimerFactory instance; + return instance; + } + + GlobalTimer &getGlobalTimer(const std::string &name) + { + std::lock_guard lock(map_mutex); + return timer_map[name]; + } + + private: + std::mutex map_mutex; + std::unordered_map timer_map; +}; + +#define GLOBAL_TIMER_AQUIRE(_X) \ + auto &_X##_global_timer = GlobalTimerFactory::get().getGlobalTimer(#_X) +#define GLOBAL_TIMER_RESET(_X) _X##_global_timer.time = 0 +#define GLOBAL_TIMER_START(_X) TIMER_START(_X) +#define GLOBAL_TIMER_STOP(_X) \ + TIMER_STOP(_X); \ + _X##_global_timer.time += TIMER_NSEC(_X) +#define GLOBAL_TIMER_NSEC(_X) static_cast(_X##_global_timer.time) +#define GLOBAL_TIMER_USEC(_X) (_X##_global_timer.time / 1000.0) +#define GLOBAL_TIMER_MSEC(_X) (_X##_global_timer.time / 1000.0 / 1000.0) +#define GLOBAL_TIMER_SEC(_X) (_X##_global_timer.time / 1000.0 / 1000.0 / 1000.0) + +#define TIMER_START(_X) auto _X##_start = std::chrono::steady_clock::now(), _X##_stop = _X##_start +#define TIMER_STOP(_X) _X##_stop = std::chrono::steady_clock::now() +#define TIMER_NSEC(_X) \ + std::chrono::duration_cast(_X##_stop - _X##_start).count() +#define TIMER_USEC(_X) \ + std::chrono::duration_cast(_X##_stop - _X##_start).count() +#define TIMER_MSEC(_X) \ + (0.000001 * \ + std::chrono::duration_cast(_X##_stop - _X##_start).count()) +#define TIMER_SEC(_X) \ + (0.000001 * \ + std::chrono::duration_cast(_X##_stop - _X##_start).count()) +#define TIMER_MIN(_X) \ + std::chrono::duration_cast(_X##_stop - _X##_start).count() + +#endif // TIMING_UTIL_HPP diff --git a/util/trigonometry_table.hpp b/util/trigonometry_table.hpp new file mode 100644 index 000000000..ebcf7ba4d --- /dev/null +++ b/util/trigonometry_table.hpp @@ -0,0 +1,448 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TRIGONOMETRY_TABLE_HPP +#define TRIGONOMETRY_TABLE_HPP + +#include "../typedefs.h" +#include + +#include + +constexpr unsigned short atan_table[4096] = { + 0x0000, 0x0014, 0x0028, 0x003d, 0x0051, 0x0065, 0x007a, 0x008e, 0x00a3, 0x00b7, 0x00cb, 0x00e0, + 0x00f4, 0x0108, 0x011d, 0x0131, 0x0146, 0x015a, 0x016e, 0x0183, 0x0197, 0x01ab, 0x01c0, 0x01d4, + 0x01e9, 0x01fd, 0x0211, 0x0226, 0x023a, 0x024e, 0x0263, 0x0277, 0x028c, 0x02a0, 0x02b4, 0x02c9, + 0x02dd, 0x02f1, 0x0306, 0x031a, 0x032f, 0x0343, 0x0357, 0x036c, 0x0380, 0x0394, 0x03a9, 0x03bd, + 0x03d2, 0x03e6, 0x03fa, 0x040f, 0x0423, 0x0437, 0x044c, 0x0460, 0x0475, 0x0489, 0x049d, 0x04b2, + 0x04c6, 0x04da, 0x04ef, 0x0503, 0x0517, 0x052c, 0x0540, 0x0555, 0x0569, 0x057d, 0x0592, 0x05a6, + 0x05ba, 0x05cf, 0x05e3, 0x05f8, 0x060c, 0x0620, 0x0635, 0x0649, 0x065d, 0x0672, 0x0686, 0x069b, + 0x06af, 0x06c3, 0x06d8, 0x06ec, 0x0700, 0x0715, 0x0729, 0x073d, 0x0752, 0x0766, 0x077b, 0x078f, + 0x07a3, 0x07b8, 0x07cc, 0x07e0, 0x07f5, 0x0809, 0x081d, 0x0832, 0x0846, 0x085b, 0x086f, 0x0883, + 0x0898, 0x08ac, 0x08c0, 0x08d5, 0x08e9, 0x08fd, 0x0912, 0x0926, 0x093b, 0x094f, 0x0963, 0x0978, + 0x098c, 0x09a0, 0x09b5, 0x09c9, 0x09dd, 0x09f2, 0x0a06, 0x0a1a, 0x0a2f, 0x0a43, 0x0a58, 0x0a6c, + 0x0a80, 0x0a95, 0x0aa9, 0x0abd, 0x0ad2, 0x0ae6, 0x0afa, 0x0b0f, 0x0b23, 0x0b37, 0x0b4c, 0x0b60, + 0x0b75, 0x0b89, 0x0b9d, 0x0bb2, 0x0bc6, 0x0bda, 0x0bef, 0x0c03, 0x0c17, 0x0c2c, 0x0c40, 0x0c54, + 0x0c69, 0x0c7d, 0x0c91, 0x0ca6, 0x0cba, 0x0cce, 0x0ce3, 0x0cf7, 0x0d0b, 0x0d20, 0x0d34, 0x0d48, + 0x0d5d, 0x0d71, 0x0d86, 0x0d9a, 0x0dae, 0x0dc3, 0x0dd7, 0x0deb, 0x0e00, 0x0e14, 0x0e28, 0x0e3d, + 0x0e51, 0x0e65, 0x0e7a, 0x0e8e, 0x0ea2, 0x0eb7, 0x0ecb, 0x0edf, 0x0ef4, 0x0f08, 0x0f1c, 0x0f31, + 0x0f45, 0x0f59, 0x0f6e, 0x0f82, 0x0f96, 0x0fab, 0x0fbf, 0x0fd3, 0x0fe8, 0x0ffc, 0x1010, 0x1025, + 0x1039, 0x104d, 0x1062, 0x1076, 0x108a, 0x109e, 0x10b3, 0x10c7, 0x10db, 0x10f0, 0x1104, 0x1118, + 0x112d, 0x1141, 0x1155, 0x116a, 0x117e, 0x1192, 0x11a7, 0x11bb, 0x11cf, 0x11e4, 0x11f8, 0x120c, + 0x1221, 0x1235, 0x1249, 0x125d, 0x1272, 0x1286, 0x129a, 0x12af, 0x12c3, 0x12d7, 0x12ec, 0x1300, + 0x1314, 0x1329, 0x133d, 0x1351, 0x1365, 0x137a, 0x138e, 0x13a2, 0x13b7, 0x13cb, 0x13df, 0x13f4, + 0x1408, 0x141c, 0x1431, 0x1445, 0x1459, 0x146d, 0x1482, 0x1496, 0x14aa, 0x14bf, 0x14d3, 0x14e7, + 0x14fb, 0x1510, 0x1524, 0x1538, 0x154d, 0x1561, 0x1575, 0x1589, 0x159e, 0x15b2, 0x15c6, 0x15db, + 0x15ef, 0x1603, 0x1617, 0x162c, 0x1640, 0x1654, 0x1669, 0x167d, 0x1691, 0x16a5, 0x16ba, 0x16ce, + 0x16e2, 0x16f7, 0x170b, 0x171f, 0x1733, 0x1748, 0x175c, 0x1770, 0x1784, 0x1799, 0x17ad, 0x17c1, + 0x17d6, 0x17ea, 0x17fe, 0x1812, 0x1827, 0x183b, 0x184f, 0x1863, 0x1878, 0x188c, 0x18a0, 0x18b4, + 0x18c9, 0x18dd, 0x18f1, 0x1905, 0x191a, 0x192e, 0x1942, 0x1957, 0x196b, 0x197f, 0x1993, 0x19a8, + 0x19bc, 0x19d0, 0x19e4, 0x19f9, 0x1a0d, 0x1a21, 0x1a35, 0x1a49, 0x1a5e, 0x1a72, 0x1a86, 0x1a9a, + 0x1aaf, 0x1ac3, 0x1ad7, 0x1aeb, 0x1b00, 0x1b14, 0x1b28, 0x1b3c, 0x1b51, 0x1b65, 0x1b79, 0x1b8d, + 0x1ba2, 0x1bb6, 0x1bca, 0x1bde, 0x1bf2, 0x1c07, 0x1c1b, 0x1c2f, 0x1c43, 0x1c58, 0x1c6c, 0x1c80, + 0x1c94, 0x1ca8, 0x1cbd, 0x1cd1, 0x1ce5, 0x1cf9, 0x1d0e, 0x1d22, 0x1d36, 0x1d4a, 0x1d5e, 0x1d73, + 0x1d87, 0x1d9b, 0x1daf, 0x1dc3, 0x1dd8, 0x1dec, 0x1e00, 0x1e14, 0x1e28, 0x1e3d, 0x1e51, 0x1e65, + 0x1e79, 0x1e8d, 0x1ea2, 0x1eb6, 0x1eca, 0x1ede, 0x1ef2, 0x1f07, 0x1f1b, 0x1f2f, 0x1f43, 0x1f57, + 0x1f6c, 0x1f80, 0x1f94, 0x1fa8, 0x1fbc, 0x1fd1, 0x1fe5, 0x1ff9, 0x200d, 0x2021, 0x2035, 0x204a, + 0x205e, 0x2072, 0x2086, 0x209a, 0x20ae, 0x20c3, 0x20d7, 0x20eb, 0x20ff, 0x2113, 0x2127, 0x213c, + 0x2150, 0x2164, 0x2178, 0x218c, 0x21a0, 0x21b5, 0x21c9, 0x21dd, 0x21f1, 0x2205, 0x2219, 0x222e, + 0x2242, 0x2256, 0x226a, 0x227e, 0x2292, 0x22a6, 0x22bb, 0x22cf, 0x22e3, 0x22f7, 0x230b, 0x231f, + 0x2333, 0x2348, 0x235c, 0x2370, 0x2384, 0x2398, 0x23ac, 0x23c0, 0x23d5, 0x23e9, 0x23fd, 0x2411, + 0x2425, 0x2439, 0x244d, 0x2461, 0x2476, 0x248a, 0x249e, 0x24b2, 0x24c6, 0x24da, 0x24ee, 0x2502, + 0x2517, 0x252b, 0x253f, 0x2553, 0x2567, 0x257b, 0x258f, 0x25a3, 0x25b7, 0x25cb, 0x25e0, 0x25f4, + 0x2608, 0x261c, 0x2630, 0x2644, 0x2658, 0x266c, 0x2680, 0x2694, 0x26a9, 0x26bd, 0x26d1, 0x26e5, + 0x26f9, 0x270d, 0x2721, 0x2735, 0x2749, 0x275d, 0x2771, 0x2785, 0x279a, 0x27ae, 0x27c2, 0x27d6, + 0x27ea, 0x27fe, 0x2812, 0x2826, 0x283a, 0x284e, 0x2862, 0x2876, 0x288a, 0x289e, 0x28b3, 0x28c7, + 0x28db, 0x28ef, 0x2903, 0x2917, 0x292b, 0x293f, 0x2953, 0x2967, 0x297b, 0x298f, 0x29a3, 0x29b7, + 0x29cb, 0x29df, 0x29f3, 0x2a07, 0x2a1b, 0x2a2f, 0x2a43, 0x2a58, 0x2a6c, 0x2a80, 0x2a94, 0x2aa8, + 0x2abc, 0x2ad0, 0x2ae4, 0x2af8, 0x2b0c, 0x2b20, 0x2b34, 0x2b48, 0x2b5c, 0x2b70, 0x2b84, 0x2b98, + 0x2bac, 0x2bc0, 0x2bd4, 0x2be8, 0x2bfc, 0x2c10, 0x2c24, 0x2c38, 0x2c4c, 0x2c60, 0x2c74, 0x2c88, + 0x2c9c, 0x2cb0, 0x2cc4, 0x2cd8, 0x2cec, 0x2d00, 0x2d14, 0x2d28, 0x2d3c, 0x2d50, 0x2d64, 0x2d78, + 0x2d8c, 0x2da0, 0x2db4, 0x2dc8, 0x2ddc, 0x2df0, 0x2e04, 0x2e18, 0x2e2c, 0x2e40, 0x2e54, 0x2e68, + 0x2e7c, 0x2e90, 0x2ea3, 0x2eb7, 0x2ecb, 0x2edf, 0x2ef3, 0x2f07, 0x2f1b, 0x2f2f, 0x2f43, 0x2f57, + 0x2f6b, 0x2f7f, 0x2f93, 0x2fa7, 0x2fbb, 0x2fcf, 0x2fe3, 0x2ff7, 0x300b, 0x301e, 0x3032, 0x3046, + 0x305a, 0x306e, 0x3082, 0x3096, 0x30aa, 0x30be, 0x30d2, 0x30e6, 0x30fa, 0x310e, 0x3122, 0x3135, + 0x3149, 0x315d, 0x3171, 0x3185, 0x3199, 0x31ad, 0x31c1, 0x31d5, 0x31e9, 0x31fd, 0x3210, 0x3224, + 0x3238, 0x324c, 0x3260, 0x3274, 0x3288, 0x329c, 0x32b0, 0x32c3, 0x32d7, 0x32eb, 0x32ff, 0x3313, + 0x3327, 0x333b, 0x334f, 0x3363, 0x3376, 0x338a, 0x339e, 0x33b2, 0x33c6, 0x33da, 0x33ee, 0x3401, + 0x3415, 0x3429, 0x343d, 0x3451, 0x3465, 0x3479, 0x348c, 0x34a0, 0x34b4, 0x34c8, 0x34dc, 0x34f0, + 0x3504, 0x3517, 0x352b, 0x353f, 0x3553, 0x3567, 0x357b, 0x358e, 0x35a2, 0x35b6, 0x35ca, 0x35de, + 0x35f2, 0x3605, 0x3619, 0x362d, 0x3641, 0x3655, 0x3668, 0x367c, 0x3690, 0x36a4, 0x36b8, 0x36cb, + 0x36df, 0x36f3, 0x3707, 0x371b, 0x372f, 0x3742, 0x3756, 0x376a, 0x377e, 0x3791, 0x37a5, 0x37b9, + 0x37cd, 0x37e1, 0x37f4, 0x3808, 0x381c, 0x3830, 0x3844, 0x3857, 0x386b, 0x387f, 0x3893, 0x38a6, + 0x38ba, 0x38ce, 0x38e2, 0x38f5, 0x3909, 0x391d, 0x3931, 0x3944, 0x3958, 0x396c, 0x3980, 0x3993, + 0x39a7, 0x39bb, 0x39cf, 0x39e2, 0x39f6, 0x3a0a, 0x3a1e, 0x3a31, 0x3a45, 0x3a59, 0x3a6d, 0x3a80, + 0x3a94, 0x3aa8, 0x3abb, 0x3acf, 0x3ae3, 0x3af7, 0x3b0a, 0x3b1e, 0x3b32, 0x3b45, 0x3b59, 0x3b6d, + 0x3b81, 0x3b94, 0x3ba8, 0x3bbc, 0x3bcf, 0x3be3, 0x3bf7, 0x3c0b, 0x3c1e, 0x3c32, 0x3c46, 0x3c59, + 0x3c6d, 0x3c81, 0x3c94, 0x3ca8, 0x3cbc, 0x3ccf, 0x3ce3, 0x3cf7, 0x3d0a, 0x3d1e, 0x3d32, 0x3d45, + 0x3d59, 0x3d6d, 0x3d80, 0x3d94, 0x3da8, 0x3dbb, 0x3dcf, 0x3de3, 0x3df6, 0x3e0a, 0x3e1e, 0x3e31, + 0x3e45, 0x3e59, 0x3e6c, 0x3e80, 0x3e93, 0x3ea7, 0x3ebb, 0x3ece, 0x3ee2, 0x3ef6, 0x3f09, 0x3f1d, + 0x3f30, 0x3f44, 0x3f58, 0x3f6b, 0x3f7f, 0x3f93, 0x3fa6, 0x3fba, 0x3fcd, 0x3fe1, 0x3ff5, 0x4008, + 0x401c, 0x402f, 0x4043, 0x4057, 0x406a, 0x407e, 0x4091, 0x40a5, 0x40b8, 0x40cc, 0x40e0, 0x40f3, + 0x4107, 0x411a, 0x412e, 0x4142, 0x4155, 0x4169, 0x417c, 0x4190, 0x41a3, 0x41b7, 0x41ca, 0x41de, + 0x41f2, 0x4205, 0x4219, 0x422c, 0x4240, 0x4253, 0x4267, 0x427a, 0x428e, 0x42a1, 0x42b5, 0x42c9, + 0x42dc, 0x42f0, 0x4303, 0x4317, 0x432a, 0x433e, 0x4351, 0x4365, 0x4378, 0x438c, 0x439f, 0x43b3, + 0x43c6, 0x43da, 0x43ed, 0x4401, 0x4414, 0x4428, 0x443b, 0x444f, 0x4462, 0x4476, 0x4489, 0x449d, + 0x44b0, 0x44c4, 0x44d7, 0x44eb, 0x44fe, 0x4512, 0x4525, 0x4539, 0x454c, 0x4560, 0x4573, 0x4586, + 0x459a, 0x45ad, 0x45c1, 0x45d4, 0x45e8, 0x45fb, 0x460f, 0x4622, 0x4636, 0x4649, 0x465c, 0x4670, + 0x4683, 0x4697, 0x46aa, 0x46be, 0x46d1, 0x46e5, 0x46f8, 0x470b, 0x471f, 0x4732, 0x4746, 0x4759, + 0x476c, 0x4780, 0x4793, 0x47a7, 0x47ba, 0x47cd, 0x47e1, 0x47f4, 0x4808, 0x481b, 0x482e, 0x4842, + 0x4855, 0x4869, 0x487c, 0x488f, 0x48a3, 0x48b6, 0x48ca, 0x48dd, 0x48f0, 0x4904, 0x4917, 0x492a, + 0x493e, 0x4951, 0x4965, 0x4978, 0x498b, 0x499f, 0x49b2, 0x49c5, 0x49d9, 0x49ec, 0x49ff, 0x4a13, + 0x4a26, 0x4a39, 0x4a4d, 0x4a60, 0x4a73, 0x4a87, 0x4a9a, 0x4aad, 0x4ac1, 0x4ad4, 0x4ae7, 0x4afb, + 0x4b0e, 0x4b21, 0x4b35, 0x4b48, 0x4b5b, 0x4b6f, 0x4b82, 0x4b95, 0x4ba8, 0x4bbc, 0x4bcf, 0x4be2, + 0x4bf6, 0x4c09, 0x4c1c, 0x4c2f, 0x4c43, 0x4c56, 0x4c69, 0x4c7d, 0x4c90, 0x4ca3, 0x4cb6, 0x4cca, + 0x4cdd, 0x4cf0, 0x4d03, 0x4d17, 0x4d2a, 0x4d3d, 0x4d50, 0x4d64, 0x4d77, 0x4d8a, 0x4d9d, 0x4db1, + 0x4dc4, 0x4dd7, 0x4dea, 0x4dfe, 0x4e11, 0x4e24, 0x4e37, 0x4e4b, 0x4e5e, 0x4e71, 0x4e84, 0x4e97, + 0x4eab, 0x4ebe, 0x4ed1, 0x4ee4, 0x4ef7, 0x4f0b, 0x4f1e, 0x4f31, 0x4f44, 0x4f57, 0x4f6b, 0x4f7e, + 0x4f91, 0x4fa4, 0x4fb7, 0x4fcb, 0x4fde, 0x4ff1, 0x5004, 0x5017, 0x502a, 0x503e, 0x5051, 0x5064, + 0x5077, 0x508a, 0x509d, 0x50b1, 0x50c4, 0x50d7, 0x50ea, 0x50fd, 0x5110, 0x5123, 0x5137, 0x514a, + 0x515d, 0x5170, 0x5183, 0x5196, 0x51a9, 0x51bc, 0x51d0, 0x51e3, 0x51f6, 0x5209, 0x521c, 0x522f, + 0x5242, 0x5255, 0x5268, 0x527c, 0x528f, 0x52a2, 0x52b5, 0x52c8, 0x52db, 0x52ee, 0x5301, 0x5314, + 0x5327, 0x533a, 0x534e, 0x5361, 0x5374, 0x5387, 0x539a, 0x53ad, 0x53c0, 0x53d3, 0x53e6, 0x53f9, + 0x540c, 0x541f, 0x5432, 0x5445, 0x5458, 0x546b, 0x547e, 0x5491, 0x54a5, 0x54b8, 0x54cb, 0x54de, + 0x54f1, 0x5504, 0x5517, 0x552a, 0x553d, 0x5550, 0x5563, 0x5576, 0x5589, 0x559c, 0x55af, 0x55c2, + 0x55d5, 0x55e8, 0x55fb, 0x560e, 0x5621, 0x5634, 0x5647, 0x565a, 0x566d, 0x5680, 0x5693, 0x56a6, + 0x56b9, 0x56cb, 0x56de, 0x56f1, 0x5704, 0x5717, 0x572a, 0x573d, 0x5750, 0x5763, 0x5776, 0x5789, + 0x579c, 0x57af, 0x57c2, 0x57d5, 0x57e8, 0x57fb, 0x580e, 0x5820, 0x5833, 0x5846, 0x5859, 0x586c, + 0x587f, 0x5892, 0x58a5, 0x58b8, 0x58cb, 0x58de, 0x58f0, 0x5903, 0x5916, 0x5929, 0x593c, 0x594f, + 0x5962, 0x5975, 0x5988, 0x599a, 0x59ad, 0x59c0, 0x59d3, 0x59e6, 0x59f9, 0x5a0c, 0x5a1f, 0x5a31, + 0x5a44, 0x5a57, 0x5a6a, 0x5a7d, 0x5a90, 0x5aa2, 0x5ab5, 0x5ac8, 0x5adb, 0x5aee, 0x5b01, 0x5b13, + 0x5b26, 0x5b39, 0x5b4c, 0x5b5f, 0x5b72, 0x5b84, 0x5b97, 0x5baa, 0x5bbd, 0x5bd0, 0x5be2, 0x5bf5, + 0x5c08, 0x5c1b, 0x5c2e, 0x5c40, 0x5c53, 0x5c66, 0x5c79, 0x5c8c, 0x5c9e, 0x5cb1, 0x5cc4, 0x5cd7, + 0x5ce9, 0x5cfc, 0x5d0f, 0x5d22, 0x5d34, 0x5d47, 0x5d5a, 0x5d6d, 0x5d7f, 0x5d92, 0x5da5, 0x5db8, + 0x5dca, 0x5ddd, 0x5df0, 0x5e03, 0x5e15, 0x5e28, 0x5e3b, 0x5e4d, 0x5e60, 0x5e73, 0x5e86, 0x5e98, + 0x5eab, 0x5ebe, 0x5ed0, 0x5ee3, 0x5ef6, 0x5f09, 0x5f1b, 0x5f2e, 0x5f41, 0x5f53, 0x5f66, 0x5f79, + 0x5f8b, 0x5f9e, 0x5fb1, 0x5fc3, 0x5fd6, 0x5fe9, 0x5ffb, 0x600e, 0x6021, 0x6033, 0x6046, 0x6059, + 0x606b, 0x607e, 0x6091, 0x60a3, 0x60b6, 0x60c8, 0x60db, 0x60ee, 0x6100, 0x6113, 0x6126, 0x6138, + 0x614b, 0x615d, 0x6170, 0x6183, 0x6195, 0x61a8, 0x61ba, 0x61cd, 0x61e0, 0x61f2, 0x6205, 0x6217, + 0x622a, 0x623d, 0x624f, 0x6262, 0x6274, 0x6287, 0x6299, 0x62ac, 0x62bf, 0x62d1, 0x62e4, 0x62f6, + 0x6309, 0x631b, 0x632e, 0x6340, 0x6353, 0x6366, 0x6378, 0x638b, 0x639d, 0x63b0, 0x63c2, 0x63d5, + 0x63e7, 0x63fa, 0x640c, 0x641f, 0x6431, 0x6444, 0x6456, 0x6469, 0x647b, 0x648e, 0x64a0, 0x64b3, + 0x64c5, 0x64d8, 0x64ea, 0x64fd, 0x650f, 0x6522, 0x6534, 0x6547, 0x6559, 0x656c, 0x657e, 0x6591, + 0x65a3, 0x65b5, 0x65c8, 0x65da, 0x65ed, 0x65ff, 0x6612, 0x6624, 0x6637, 0x6649, 0x665b, 0x666e, + 0x6680, 0x6693, 0x66a5, 0x66b8, 0x66ca, 0x66dc, 0x66ef, 0x6701, 0x6714, 0x6726, 0x6738, 0x674b, + 0x675d, 0x6770, 0x6782, 0x6794, 0x67a7, 0x67b9, 0x67cc, 0x67de, 0x67f0, 0x6803, 0x6815, 0x6827, + 0x683a, 0x684c, 0x685e, 0x6871, 0x6883, 0x6896, 0x68a8, 0x68ba, 0x68cd, 0x68df, 0x68f1, 0x6904, + 0x6916, 0x6928, 0x693b, 0x694d, 0x695f, 0x6972, 0x6984, 0x6996, 0x69a8, 0x69bb, 0x69cd, 0x69df, + 0x69f2, 0x6a04, 0x6a16, 0x6a29, 0x6a3b, 0x6a4d, 0x6a5f, 0x6a72, 0x6a84, 0x6a96, 0x6aa9, 0x6abb, + 0x6acd, 0x6adf, 0x6af2, 0x6b04, 0x6b16, 0x6b28, 0x6b3b, 0x6b4d, 0x6b5f, 0x6b71, 0x6b84, 0x6b96, + 0x6ba8, 0x6bba, 0x6bcd, 0x6bdf, 0x6bf1, 0x6c03, 0x6c15, 0x6c28, 0x6c3a, 0x6c4c, 0x6c5e, 0x6c70, + 0x6c83, 0x6c95, 0x6ca7, 0x6cb9, 0x6ccb, 0x6cde, 0x6cf0, 0x6d02, 0x6d14, 0x6d26, 0x6d39, 0x6d4b, + 0x6d5d, 0x6d6f, 0x6d81, 0x6d93, 0x6da6, 0x6db8, 0x6dca, 0x6ddc, 0x6dee, 0x6e00, 0x6e12, 0x6e25, + 0x6e37, 0x6e49, 0x6e5b, 0x6e6d, 0x6e7f, 0x6e91, 0x6ea3, 0x6eb6, 0x6ec8, 0x6eda, 0x6eec, 0x6efe, + 0x6f10, 0x6f22, 0x6f34, 0x6f46, 0x6f58, 0x6f6b, 0x6f7d, 0x6f8f, 0x6fa1, 0x6fb3, 0x6fc5, 0x6fd7, + 0x6fe9, 0x6ffb, 0x700d, 0x701f, 0x7031, 0x7043, 0x7055, 0x7068, 0x707a, 0x708c, 0x709e, 0x70b0, + 0x70c2, 0x70d4, 0x70e6, 0x70f8, 0x710a, 0x711c, 0x712e, 0x7140, 0x7152, 0x7164, 0x7176, 0x7188, + 0x719a, 0x71ac, 0x71be, 0x71d0, 0x71e2, 0x71f4, 0x7206, 0x7218, 0x722a, 0x723c, 0x724e, 0x7260, + 0x7272, 0x7284, 0x7296, 0x72a8, 0x72ba, 0x72cc, 0x72dd, 0x72ef, 0x7301, 0x7313, 0x7325, 0x7337, + 0x7349, 0x735b, 0x736d, 0x737f, 0x7391, 0x73a3, 0x73b5, 0x73c7, 0x73d8, 0x73ea, 0x73fc, 0x740e, + 0x7420, 0x7432, 0x7444, 0x7456, 0x7468, 0x747a, 0x748b, 0x749d, 0x74af, 0x74c1, 0x74d3, 0x74e5, + 0x74f7, 0x7509, 0x751a, 0x752c, 0x753e, 0x7550, 0x7562, 0x7574, 0x7585, 0x7597, 0x75a9, 0x75bb, + 0x75cd, 0x75df, 0x75f0, 0x7602, 0x7614, 0x7626, 0x7638, 0x764a, 0x765b, 0x766d, 0x767f, 0x7691, + 0x76a3, 0x76b4, 0x76c6, 0x76d8, 0x76ea, 0x76fb, 0x770d, 0x771f, 0x7731, 0x7743, 0x7754, 0x7766, + 0x7778, 0x778a, 0x779b, 0x77ad, 0x77bf, 0x77d1, 0x77e2, 0x77f4, 0x7806, 0x7818, 0x7829, 0x783b, + 0x784d, 0x785e, 0x7870, 0x7882, 0x7894, 0x78a5, 0x78b7, 0x78c9, 0x78da, 0x78ec, 0x78fe, 0x7910, + 0x7921, 0x7933, 0x7945, 0x7956, 0x7968, 0x797a, 0x798b, 0x799d, 0x79af, 0x79c0, 0x79d2, 0x79e4, + 0x79f5, 0x7a07, 0x7a19, 0x7a2a, 0x7a3c, 0x7a4e, 0x7a5f, 0x7a71, 0x7a82, 0x7a94, 0x7aa6, 0x7ab7, + 0x7ac9, 0x7adb, 0x7aec, 0x7afe, 0x7b0f, 0x7b21, 0x7b33, 0x7b44, 0x7b56, 0x7b67, 0x7b79, 0x7b8b, + 0x7b9c, 0x7bae, 0x7bbf, 0x7bd1, 0x7be2, 0x7bf4, 0x7c06, 0x7c17, 0x7c29, 0x7c3a, 0x7c4c, 0x7c5d, + 0x7c6f, 0x7c81, 0x7c92, 0x7ca4, 0x7cb5, 0x7cc7, 0x7cd8, 0x7cea, 0x7cfb, 0x7d0d, 0x7d1e, 0x7d30, + 0x7d41, 0x7d53, 0x7d64, 0x7d76, 0x7d87, 0x7d99, 0x7daa, 0x7dbc, 0x7dcd, 0x7ddf, 0x7df0, 0x7e02, + 0x7e13, 0x7e25, 0x7e36, 0x7e48, 0x7e59, 0x7e6b, 0x7e7c, 0x7e8e, 0x7e9f, 0x7eb0, 0x7ec2, 0x7ed3, + 0x7ee5, 0x7ef6, 0x7f08, 0x7f19, 0x7f2b, 0x7f3c, 0x7f4d, 0x7f5f, 0x7f70, 0x7f82, 0x7f93, 0x7fa4, + 0x7fb6, 0x7fc7, 0x7fd9, 0x7fea, 0x7ffb, 0x800d, 0x801e, 0x8030, 0x8041, 0x8052, 0x8064, 0x8075, + 0x8086, 0x8098, 0x80a9, 0x80bb, 0x80cc, 0x80dd, 0x80ef, 0x8100, 0x8111, 0x8123, 0x8134, 0x8145, + 0x8157, 0x8168, 0x8179, 0x818b, 0x819c, 0x81ad, 0x81bf, 0x81d0, 0x81e1, 0x81f3, 0x8204, 0x8215, + 0x8226, 0x8238, 0x8249, 0x825a, 0x826c, 0x827d, 0x828e, 0x829f, 0x82b1, 0x82c2, 0x82d3, 0x82e5, + 0x82f6, 0x8307, 0x8318, 0x832a, 0x833b, 0x834c, 0x835d, 0x836f, 0x8380, 0x8391, 0x83a2, 0x83b3, + 0x83c5, 0x83d6, 0x83e7, 0x83f8, 0x840a, 0x841b, 0x842c, 0x843d, 0x844e, 0x8460, 0x8471, 0x8482, + 0x8493, 0x84a4, 0x84b6, 0x84c7, 0x84d8, 0x84e9, 0x84fa, 0x850b, 0x851d, 0x852e, 0x853f, 0x8550, + 0x8561, 0x8572, 0x8584, 0x8595, 0x85a6, 0x85b7, 0x85c8, 0x85d9, 0x85ea, 0x85fb, 0x860d, 0x861e, + 0x862f, 0x8640, 0x8651, 0x8662, 0x8673, 0x8684, 0x8695, 0x86a7, 0x86b8, 0x86c9, 0x86da, 0x86eb, + 0x86fc, 0x870d, 0x871e, 0x872f, 0x8740, 0x8751, 0x8762, 0x8773, 0x8784, 0x8796, 0x87a7, 0x87b8, + 0x87c9, 0x87da, 0x87eb, 0x87fc, 0x880d, 0x881e, 0x882f, 0x8840, 0x8851, 0x8862, 0x8873, 0x8884, + 0x8895, 0x88a6, 0x88b7, 0x88c8, 0x88d9, 0x88ea, 0x88fb, 0x890c, 0x891d, 0x892e, 0x893f, 0x8950, + 0x8961, 0x8972, 0x8983, 0x8994, 0x89a5, 0x89b6, 0x89c6, 0x89d7, 0x89e8, 0x89f9, 0x8a0a, 0x8a1b, + 0x8a2c, 0x8a3d, 0x8a4e, 0x8a5f, 0x8a70, 0x8a81, 0x8a92, 0x8aa3, 0x8ab3, 0x8ac4, 0x8ad5, 0x8ae6, + 0x8af7, 0x8b08, 0x8b19, 0x8b2a, 0x8b3b, 0x8b4b, 0x8b5c, 0x8b6d, 0x8b7e, 0x8b8f, 0x8ba0, 0x8bb1, + 0x8bc1, 0x8bd2, 0x8be3, 0x8bf4, 0x8c05, 0x8c16, 0x8c27, 0x8c37, 0x8c48, 0x8c59, 0x8c6a, 0x8c7b, + 0x8c8c, 0x8c9c, 0x8cad, 0x8cbe, 0x8ccf, 0x8ce0, 0x8cf0, 0x8d01, 0x8d12, 0x8d23, 0x8d34, 0x8d44, + 0x8d55, 0x8d66, 0x8d77, 0x8d87, 0x8d98, 0x8da9, 0x8dba, 0x8dca, 0x8ddb, 0x8dec, 0x8dfd, 0x8e0d, + 0x8e1e, 0x8e2f, 0x8e40, 0x8e50, 0x8e61, 0x8e72, 0x8e83, 0x8e93, 0x8ea4, 0x8eb5, 0x8ec5, 0x8ed6, + 0x8ee7, 0x8ef8, 0x8f08, 0x8f19, 0x8f2a, 0x8f3a, 0x8f4b, 0x8f5c, 0x8f6c, 0x8f7d, 0x8f8e, 0x8f9e, + 0x8faf, 0x8fc0, 0x8fd0, 0x8fe1, 0x8ff2, 0x9002, 0x9013, 0x9024, 0x9034, 0x9045, 0x9056, 0x9066, + 0x9077, 0x9088, 0x9098, 0x90a9, 0x90b9, 0x90ca, 0x90db, 0x90eb, 0x90fc, 0x910c, 0x911d, 0x912e, + 0x913e, 0x914f, 0x915f, 0x9170, 0x9181, 0x9191, 0x91a2, 0x91b2, 0x91c3, 0x91d3, 0x91e4, 0x91f5, + 0x9205, 0x9216, 0x9226, 0x9237, 0x9247, 0x9258, 0x9268, 0x9279, 0x9289, 0x929a, 0x92aa, 0x92bb, + 0x92cc, 0x92dc, 0x92ed, 0x92fd, 0x930e, 0x931e, 0x932f, 0x933f, 0x9350, 0x9360, 0x9370, 0x9381, + 0x9391, 0x93a2, 0x93b2, 0x93c3, 0x93d3, 0x93e4, 0x93f4, 0x9405, 0x9415, 0x9426, 0x9436, 0x9447, + 0x9457, 0x9467, 0x9478, 0x9488, 0x9499, 0x94a9, 0x94ba, 0x94ca, 0x94da, 0x94eb, 0x94fb, 0x950c, + 0x951c, 0x952c, 0x953d, 0x954d, 0x955e, 0x956e, 0x957e, 0x958f, 0x959f, 0x95af, 0x95c0, 0x95d0, + 0x95e1, 0x95f1, 0x9601, 0x9612, 0x9622, 0x9632, 0x9643, 0x9653, 0x9663, 0x9674, 0x9684, 0x9694, + 0x96a5, 0x96b5, 0x96c5, 0x96d6, 0x96e6, 0x96f6, 0x9707, 0x9717, 0x9727, 0x9738, 0x9748, 0x9758, + 0x9768, 0x9779, 0x9789, 0x9799, 0x97aa, 0x97ba, 0x97ca, 0x97da, 0x97eb, 0x97fb, 0x980b, 0x981b, + 0x982c, 0x983c, 0x984c, 0x985c, 0x986d, 0x987d, 0x988d, 0x989d, 0x98ad, 0x98be, 0x98ce, 0x98de, + 0x98ee, 0x98ff, 0x990f, 0x991f, 0x992f, 0x993f, 0x9950, 0x9960, 0x9970, 0x9980, 0x9990, 0x99a0, + 0x99b1, 0x99c1, 0x99d1, 0x99e1, 0x99f1, 0x9a01, 0x9a12, 0x9a22, 0x9a32, 0x9a42, 0x9a52, 0x9a62, + 0x9a72, 0x9a83, 0x9a93, 0x9aa3, 0x9ab3, 0x9ac3, 0x9ad3, 0x9ae3, 0x9af3, 0x9b04, 0x9b14, 0x9b24, + 0x9b34, 0x9b44, 0x9b54, 0x9b64, 0x9b74, 0x9b84, 0x9b94, 0x9ba4, 0x9bb5, 0x9bc5, 0x9bd5, 0x9be5, + 0x9bf5, 0x9c05, 0x9c15, 0x9c25, 0x9c35, 0x9c45, 0x9c55, 0x9c65, 0x9c75, 0x9c85, 0x9c95, 0x9ca5, + 0x9cb5, 0x9cc5, 0x9cd5, 0x9ce5, 0x9cf5, 0x9d05, 0x9d15, 0x9d25, 0x9d35, 0x9d45, 0x9d55, 0x9d65, + 0x9d75, 0x9d85, 0x9d95, 0x9da5, 0x9db5, 0x9dc5, 0x9dd5, 0x9de5, 0x9df5, 0x9e05, 0x9e15, 0x9e25, + 0x9e35, 0x9e45, 0x9e55, 0x9e65, 0x9e74, 0x9e84, 0x9e94, 0x9ea4, 0x9eb4, 0x9ec4, 0x9ed4, 0x9ee4, + 0x9ef4, 0x9f04, 0x9f14, 0x9f23, 0x9f33, 0x9f43, 0x9f53, 0x9f63, 0x9f73, 0x9f83, 0x9f93, 0x9fa3, + 0x9fb2, 0x9fc2, 0x9fd2, 0x9fe2, 0x9ff2, 0xa002, 0xa012, 0xa021, 0xa031, 0xa041, 0xa051, 0xa061, + 0xa071, 0xa080, 0xa090, 0xa0a0, 0xa0b0, 0xa0c0, 0xa0cf, 0xa0df, 0xa0ef, 0xa0ff, 0xa10f, 0xa11e, + 0xa12e, 0xa13e, 0xa14e, 0xa15e, 0xa16d, 0xa17d, 0xa18d, 0xa19d, 0xa1ac, 0xa1bc, 0xa1cc, 0xa1dc, + 0xa1eb, 0xa1fb, 0xa20b, 0xa21b, 0xa22a, 0xa23a, 0xa24a, 0xa25a, 0xa269, 0xa279, 0xa289, 0xa298, + 0xa2a8, 0xa2b8, 0xa2c8, 0xa2d7, 0xa2e7, 0xa2f7, 0xa306, 0xa316, 0xa326, 0xa335, 0xa345, 0xa355, + 0xa364, 0xa374, 0xa384, 0xa393, 0xa3a3, 0xa3b3, 0xa3c2, 0xa3d2, 0xa3e2, 0xa3f1, 0xa401, 0xa411, + 0xa420, 0xa430, 0xa440, 0xa44f, 0xa45f, 0xa46e, 0xa47e, 0xa48e, 0xa49d, 0xa4ad, 0xa4bc, 0xa4cc, + 0xa4dc, 0xa4eb, 0xa4fb, 0xa50a, 0xa51a, 0xa52a, 0xa539, 0xa549, 0xa558, 0xa568, 0xa577, 0xa587, + 0xa597, 0xa5a6, 0xa5b6, 0xa5c5, 0xa5d5, 0xa5e4, 0xa5f4, 0xa603, 0xa613, 0xa622, 0xa632, 0xa641, + 0xa651, 0xa660, 0xa670, 0xa67f, 0xa68f, 0xa69e, 0xa6ae, 0xa6bd, 0xa6cd, 0xa6dc, 0xa6ec, 0xa6fb, + 0xa70b, 0xa71a, 0xa72a, 0xa739, 0xa749, 0xa758, 0xa768, 0xa777, 0xa787, 0xa796, 0xa7a5, 0xa7b5, + 0xa7c4, 0xa7d4, 0xa7e3, 0xa7f3, 0xa802, 0xa812, 0xa821, 0xa830, 0xa840, 0xa84f, 0xa85f, 0xa86e, + 0xa87d, 0xa88d, 0xa89c, 0xa8ac, 0xa8bb, 0xa8ca, 0xa8da, 0xa8e9, 0xa8f8, 0xa908, 0xa917, 0xa927, + 0xa936, 0xa945, 0xa955, 0xa964, 0xa973, 0xa983, 0xa992, 0xa9a1, 0xa9b1, 0xa9c0, 0xa9cf, 0xa9df, + 0xa9ee, 0xa9fd, 0xaa0d, 0xaa1c, 0xaa2b, 0xaa3b, 0xaa4a, 0xaa59, 0xaa69, 0xaa78, 0xaa87, 0xaa96, + 0xaaa6, 0xaab5, 0xaac4, 0xaad4, 0xaae3, 0xaaf2, 0xab01, 0xab11, 0xab20, 0xab2f, 0xab3e, 0xab4e, + 0xab5d, 0xab6c, 0xab7b, 0xab8b, 0xab9a, 0xaba9, 0xabb8, 0xabc7, 0xabd7, 0xabe6, 0xabf5, 0xac04, + 0xac14, 0xac23, 0xac32, 0xac41, 0xac50, 0xac60, 0xac6f, 0xac7e, 0xac8d, 0xac9c, 0xacab, 0xacbb, + 0xacca, 0xacd9, 0xace8, 0xacf7, 0xad06, 0xad16, 0xad25, 0xad34, 0xad43, 0xad52, 0xad61, 0xad70, + 0xad80, 0xad8f, 0xad9e, 0xadad, 0xadbc, 0xadcb, 0xadda, 0xade9, 0xadf8, 0xae08, 0xae17, 0xae26, + 0xae35, 0xae44, 0xae53, 0xae62, 0xae71, 0xae80, 0xae8f, 0xae9e, 0xaead, 0xaebd, 0xaecc, 0xaedb, + 0xaeea, 0xaef9, 0xaf08, 0xaf17, 0xaf26, 0xaf35, 0xaf44, 0xaf53, 0xaf62, 0xaf71, 0xaf80, 0xaf8f, + 0xaf9e, 0xafad, 0xafbc, 0xafcb, 0xafda, 0xafe9, 0xaff8, 0xb007, 0xb016, 0xb025, 0xb034, 0xb043, + 0xb052, 0xb061, 0xb070, 0xb07f, 0xb08e, 0xb09d, 0xb0ac, 0xb0bb, 0xb0ca, 0xb0d9, 0xb0e8, 0xb0f6, + 0xb105, 0xb114, 0xb123, 0xb132, 0xb141, 0xb150, 0xb15f, 0xb16e, 0xb17d, 0xb18c, 0xb19b, 0xb1aa, + 0xb1b8, 0xb1c7, 0xb1d6, 0xb1e5, 0xb1f4, 0xb203, 0xb212, 0xb221, 0xb22f, 0xb23e, 0xb24d, 0xb25c, + 0xb26b, 0xb27a, 0xb289, 0xb297, 0xb2a6, 0xb2b5, 0xb2c4, 0xb2d3, 0xb2e2, 0xb2f1, 0xb2ff, 0xb30e, + 0xb31d, 0xb32c, 0xb33b, 0xb349, 0xb358, 0xb367, 0xb376, 0xb385, 0xb393, 0xb3a2, 0xb3b1, 0xb3c0, + 0xb3cf, 0xb3dd, 0xb3ec, 0xb3fb, 0xb40a, 0xb418, 0xb427, 0xb436, 0xb445, 0xb453, 0xb462, 0xb471, + 0xb480, 0xb48e, 0xb49d, 0xb4ac, 0xb4bb, 0xb4c9, 0xb4d8, 0xb4e7, 0xb4f6, 0xb504, 0xb513, 0xb522, + 0xb530, 0xb53f, 0xb54e, 0xb55c, 0xb56b, 0xb57a, 0xb588, 0xb597, 0xb5a6, 0xb5b5, 0xb5c3, 0xb5d2, + 0xb5e1, 0xb5ef, 0xb5fe, 0xb60d, 0xb61b, 0xb62a, 0xb638, 0xb647, 0xb656, 0xb664, 0xb673, 0xb682, + 0xb690, 0xb69f, 0xb6ae, 0xb6bc, 0xb6cb, 0xb6d9, 0xb6e8, 0xb6f7, 0xb705, 0xb714, 0xb722, 0xb731, + 0xb740, 0xb74e, 0xb75d, 0xb76b, 0xb77a, 0xb788, 0xb797, 0xb7a6, 0xb7b4, 0xb7c3, 0xb7d1, 0xb7e0, + 0xb7ee, 0xb7fd, 0xb80b, 0xb81a, 0xb829, 0xb837, 0xb846, 0xb854, 0xb863, 0xb871, 0xb880, 0xb88e, + 0xb89d, 0xb8ab, 0xb8ba, 0xb8c8, 0xb8d7, 0xb8e5, 0xb8f4, 0xb902, 0xb911, 0xb91f, 0xb92e, 0xb93c, + 0xb94b, 0xb959, 0xb968, 0xb976, 0xb984, 0xb993, 0xb9a1, 0xb9b0, 0xb9be, 0xb9cd, 0xb9db, 0xb9ea, + 0xb9f8, 0xba06, 0xba15, 0xba23, 0xba32, 0xba40, 0xba4f, 0xba5d, 0xba6b, 0xba7a, 0xba88, 0xba97, + 0xbaa5, 0xbab3, 0xbac2, 0xbad0, 0xbade, 0xbaed, 0xbafb, 0xbb0a, 0xbb18, 0xbb26, 0xbb35, 0xbb43, + 0xbb51, 0xbb60, 0xbb6e, 0xbb7c, 0xbb8b, 0xbb99, 0xbba8, 0xbbb6, 0xbbc4, 0xbbd3, 0xbbe1, 0xbbef, + 0xbbfd, 0xbc0c, 0xbc1a, 0xbc28, 0xbc37, 0xbc45, 0xbc53, 0xbc62, 0xbc70, 0xbc7e, 0xbc8c, 0xbc9b, + 0xbca9, 0xbcb7, 0xbcc6, 0xbcd4, 0xbce2, 0xbcf0, 0xbcff, 0xbd0d, 0xbd1b, 0xbd29, 0xbd38, 0xbd46, + 0xbd54, 0xbd62, 0xbd71, 0xbd7f, 0xbd8d, 0xbd9b, 0xbdaa, 0xbdb8, 0xbdc6, 0xbdd4, 0xbde2, 0xbdf1, + 0xbdff, 0xbe0d, 0xbe1b, 0xbe29, 0xbe38, 0xbe46, 0xbe54, 0xbe62, 0xbe70, 0xbe7f, 0xbe8d, 0xbe9b, + 0xbea9, 0xbeb7, 0xbec5, 0xbed4, 0xbee2, 0xbef0, 0xbefe, 0xbf0c, 0xbf1a, 0xbf28, 0xbf37, 0xbf45, + 0xbf53, 0xbf61, 0xbf6f, 0xbf7d, 0xbf8b, 0xbf99, 0xbfa7, 0xbfb6, 0xbfc4, 0xbfd2, 0xbfe0, 0xbfee, + 0xbffc, 0xc00a, 0xc018, 0xc026, 0xc034, 0xc042, 0xc051, 0xc05f, 0xc06d, 0xc07b, 0xc089, 0xc097, + 0xc0a5, 0xc0b3, 0xc0c1, 0xc0cf, 0xc0dd, 0xc0eb, 0xc0f9, 0xc107, 0xc115, 0xc123, 0xc131, 0xc13f, + 0xc14d, 0xc15b, 0xc169, 0xc177, 0xc185, 0xc193, 0xc1a1, 0xc1af, 0xc1bd, 0xc1cb, 0xc1d9, 0xc1e7, + 0xc1f5, 0xc203, 0xc211, 0xc21f, 0xc22d, 0xc23b, 0xc249, 0xc257, 0xc265, 0xc273, 0xc281, 0xc28f, + 0xc29d, 0xc2ab, 0xc2b8, 0xc2c6, 0xc2d4, 0xc2e2, 0xc2f0, 0xc2fe, 0xc30c, 0xc31a, 0xc328, 0xc336, + 0xc344, 0xc352, 0xc35f, 0xc36d, 0xc37b, 0xc389, 0xc397, 0xc3a5, 0xc3b3, 0xc3c1, 0xc3ce, 0xc3dc, + 0xc3ea, 0xc3f8, 0xc406, 0xc414, 0xc422, 0xc42f, 0xc43d, 0xc44b, 0xc459, 0xc467, 0xc475, 0xc482, + 0xc490, 0xc49e, 0xc4ac, 0xc4ba, 0xc4c7, 0xc4d5, 0xc4e3, 0xc4f1, 0xc4ff, 0xc50d, 0xc51a, 0xc528, + 0xc536, 0xc544, 0xc551, 0xc55f, 0xc56d, 0xc57b, 0xc589, 0xc596, 0xc5a4, 0xc5b2, 0xc5c0, 0xc5cd, + 0xc5db, 0xc5e9, 0xc5f7, 0xc604, 0xc612, 0xc620, 0xc62d, 0xc63b, 0xc649, 0xc657, 0xc664, 0xc672, + 0xc680, 0xc68d, 0xc69b, 0xc6a9, 0xc6b7, 0xc6c4, 0xc6d2, 0xc6e0, 0xc6ed, 0xc6fb, 0xc709, 0xc716, + 0xc724, 0xc732, 0xc73f, 0xc74d, 0xc75b, 0xc768, 0xc776, 0xc784, 0xc791, 0xc79f, 0xc7ad, 0xc7ba, + 0xc7c8, 0xc7d6, 0xc7e3, 0xc7f1, 0xc7fe, 0xc80c, 0xc81a, 0xc827, 0xc835, 0xc842, 0xc850, 0xc85e, + 0xc86b, 0xc879, 0xc886, 0xc894, 0xc8a2, 0xc8af, 0xc8bd, 0xc8ca, 0xc8d8, 0xc8e5, 0xc8f3, 0xc901, + 0xc90e, 0xc91c, 0xc929, 0xc937, 0xc944, 0xc952, 0xc95f, 0xc96d, 0xc97b, 0xc988, 0xc996, 0xc9a3, + 0xc9b1, 0xc9be, 0xc9cc, 0xc9d9, 0xc9e7, 0xc9f4, 0xca02, 0xca0f, 0xca1d, 0xca2a, 0xca38, 0xca45, + 0xca53, 0xca60, 0xca6e, 0xca7b, 0xca89, 0xca96, 0xcaa4, 0xcab1, 0xcabe, 0xcacc, 0xcad9, 0xcae7, + 0xcaf4, 0xcb02, 0xcb0f, 0xcb1d, 0xcb2a, 0xcb37, 0xcb45, 0xcb52, 0xcb60, 0xcb6d, 0xcb7b, 0xcb88, + 0xcb95, 0xcba3, 0xcbb0, 0xcbbe, 0xcbcb, 0xcbd8, 0xcbe6, 0xcbf3, 0xcc01, 0xcc0e, 0xcc1b, 0xcc29, + 0xcc36, 0xcc43, 0xcc51, 0xcc5e, 0xcc6c, 0xcc79, 0xcc86, 0xcc94, 0xcca1, 0xccae, 0xccbc, 0xccc9, + 0xccd6, 0xcce4, 0xccf1, 0xccfe, 0xcd0c, 0xcd19, 0xcd26, 0xcd34, 0xcd41, 0xcd4e, 0xcd5b, 0xcd69, + 0xcd76, 0xcd83, 0xcd91, 0xcd9e, 0xcdab, 0xcdb9, 0xcdc6, 0xcdd3, 0xcde0, 0xcdee, 0xcdfb, 0xce08, + 0xce15, 0xce23, 0xce30, 0xce3d, 0xce4a, 0xce58, 0xce65, 0xce72, 0xce7f, 0xce8d, 0xce9a, 0xcea7, + 0xceb4, 0xcec2, 0xcecf, 0xcedc, 0xcee9, 0xcef6, 0xcf04, 0xcf11, 0xcf1e, 0xcf2b, 0xcf38, 0xcf46, + 0xcf53, 0xcf60, 0xcf6d, 0xcf7a, 0xcf87, 0xcf95, 0xcfa2, 0xcfaf, 0xcfbc, 0xcfc9, 0xcfd6, 0xcfe4, + 0xcff1, 0xcffe, 0xd00b, 0xd018, 0xd025, 0xd032, 0xd040, 0xd04d, 0xd05a, 0xd067, 0xd074, 0xd081, + 0xd08e, 0xd09b, 0xd0a9, 0xd0b6, 0xd0c3, 0xd0d0, 0xd0dd, 0xd0ea, 0xd0f7, 0xd104, 0xd111, 0xd11e, + 0xd12b, 0xd139, 0xd146, 0xd153, 0xd160, 0xd16d, 0xd17a, 0xd187, 0xd194, 0xd1a1, 0xd1ae, 0xd1bb, + 0xd1c8, 0xd1d5, 0xd1e2, 0xd1ef, 0xd1fc, 0xd209, 0xd216, 0xd223, 0xd230, 0xd23d, 0xd24a, 0xd257, + 0xd264, 0xd271, 0xd27e, 0xd28b, 0xd298, 0xd2a5, 0xd2b2, 0xd2bf, 0xd2cc, 0xd2d9, 0xd2e6, 0xd2f3, + 0xd300, 0xd30d, 0xd31a, 0xd327, 0xd334, 0xd341, 0xd34e, 0xd35b, 0xd368, 0xd375, 0xd382, 0xd38f, + 0xd39c, 0xd3a8, 0xd3b5, 0xd3c2, 0xd3cf, 0xd3dc, 0xd3e9, 0xd3f6, 0xd403, 0xd410, 0xd41d, 0xd42a, + 0xd436, 0xd443, 0xd450, 0xd45d, 0xd46a, 0xd477, 0xd484, 0xd491, 0xd49e, 0xd4aa, 0xd4b7, 0xd4c4, + 0xd4d1, 0xd4de, 0xd4eb, 0xd4f8, 0xd504, 0xd511, 0xd51e, 0xd52b, 0xd538, 0xd545, 0xd551, 0xd55e, + 0xd56b, 0xd578, 0xd585, 0xd591, 0xd59e, 0xd5ab, 0xd5b8, 0xd5c5, 0xd5d1, 0xd5de, 0xd5eb, 0xd5f8, + 0xd605, 0xd611, 0xd61e, 0xd62b, 0xd638, 0xd645, 0xd651, 0xd65e, 0xd66b, 0xd678, 0xd684, 0xd691, + 0xd69e, 0xd6ab, 0xd6b7, 0xd6c4, 0xd6d1, 0xd6de, 0xd6ea, 0xd6f7, 0xd704, 0xd710, 0xd71d, 0xd72a, + 0xd737, 0xd743, 0xd750, 0xd75d, 0xd769, 0xd776, 0xd783, 0xd78f, 0xd79c, 0xd7a9, 0xd7b6, 0xd7c2, + 0xd7cf, 0xd7dc, 0xd7e8, 0xd7f5, 0xd802, 0xd80e, 0xd81b, 0xd828, 0xd834, 0xd841, 0xd84e, 0xd85a, + 0xd867, 0xd873, 0xd880, 0xd88d, 0xd899, 0xd8a6, 0xd8b3, 0xd8bf, 0xd8cc, 0xd8d8, 0xd8e5, 0xd8f2, + 0xd8fe, 0xd90b, 0xd917, 0xd924, 0xd931, 0xd93d, 0xd94a, 0xd956, 0xd963, 0xd970, 0xd97c, 0xd989, + 0xd995, 0xd9a2, 0xd9ae, 0xd9bb, 0xd9c8, 0xd9d4, 0xd9e1, 0xd9ed, 0xd9fa, 0xda06, 0xda13, 0xda1f, + 0xda2c, 0xda38, 0xda45, 0xda51, 0xda5e, 0xda6a, 0xda77, 0xda84, 0xda90, 0xda9d, 0xdaa9, 0xdab6, + 0xdac2, 0xdacf, 0xdadb, 0xdae7, 0xdaf4, 0xdb00, 0xdb0d, 0xdb19, 0xdb26, 0xdb32, 0xdb3f, 0xdb4b, + 0xdb58, 0xdb64, 0xdb71, 0xdb7d, 0xdb8a, 0xdb96, 0xdba2, 0xdbaf, 0xdbbb, 0xdbc8, 0xdbd4, 0xdbe1, + 0xdbed, 0xdbf9, 0xdc06, 0xdc12, 0xdc1f, 0xdc2b, 0xdc38, 0xdc44, 0xdc50, 0xdc5d, 0xdc69, 0xdc76, + 0xdc82, 0xdc8e, 0xdc9b, 0xdca7, 0xdcb3, 0xdcc0, 0xdccc, 0xdcd9, 0xdce5, 0xdcf1, 0xdcfe, 0xdd0a, + 0xdd16, 0xdd23, 0xdd2f, 0xdd3b, 0xdd48, 0xdd54, 0xdd60, 0xdd6d, 0xdd79, 0xdd85, 0xdd92, 0xdd9e, + 0xddaa, 0xddb7, 0xddc3, 0xddcf, 0xdddc, 0xdde8, 0xddf4, 0xde01, 0xde0d, 0xde19, 0xde25, 0xde32, + 0xde3e, 0xde4a, 0xde57, 0xde63, 0xde6f, 0xde7b, 0xde88, 0xde94, 0xdea0, 0xdeac, 0xdeb9, 0xdec5, + 0xded1, 0xdedd, 0xdeea, 0xdef6, 0xdf02, 0xdf0e, 0xdf1b, 0xdf27, 0xdf33, 0xdf3f, 0xdf4c, 0xdf58, + 0xdf64, 0xdf70, 0xdf7c, 0xdf89, 0xdf95, 0xdfa1, 0xdfad, 0xdfb9, 0xdfc6, 0xdfd2, 0xdfde, 0xdfea, + 0xdff6, 0xe003, 0xe00f, 0xe01b, 0xe027, 0xe033, 0xe03f, 0xe04c, 0xe058, 0xe064, 0xe070, 0xe07c, + 0xe088, 0xe094, 0xe0a1, 0xe0ad, 0xe0b9, 0xe0c5, 0xe0d1, 0xe0dd, 0xe0e9, 0xe0f5, 0xe102, 0xe10e, + 0xe11a, 0xe126, 0xe132, 0xe13e, 0xe14a, 0xe156, 0xe162, 0xe16e, 0xe17b, 0xe187, 0xe193, 0xe19f, + 0xe1ab, 0xe1b7, 0xe1c3, 0xe1cf, 0xe1db, 0xe1e7, 0xe1f3, 0xe1ff, 0xe20b, 0xe217, 0xe223, 0xe22f, + 0xe23c, 0xe248, 0xe254, 0xe260, 0xe26c, 0xe278, 0xe284, 0xe290, 0xe29c, 0xe2a8, 0xe2b4, 0xe2c0, + 0xe2cc, 0xe2d8, 0xe2e4, 0xe2f0, 0xe2fc, 0xe308, 0xe314, 0xe320, 0xe32c, 0xe338, 0xe344, 0xe350, + 0xe35c, 0xe368, 0xe374, 0xe380, 0xe38b, 0xe397, 0xe3a3, 0xe3af, 0xe3bb, 0xe3c7, 0xe3d3, 0xe3df, + 0xe3eb, 0xe3f7, 0xe403, 0xe40f, 0xe41b, 0xe427, 0xe433, 0xe43f, 0xe44a, 0xe456, 0xe462, 0xe46e, + 0xe47a, 0xe486, 0xe492, 0xe49e, 0xe4aa, 0xe4b6, 0xe4c1, 0xe4cd, 0xe4d9, 0xe4e5, 0xe4f1, 0xe4fd, + 0xe509, 0xe515, 0xe520, 0xe52c, 0xe538, 0xe544, 0xe550, 0xe55c, 0xe567, 0xe573, 0xe57f, 0xe58b, + 0xe597, 0xe5a3, 0xe5af, 0xe5ba, 0xe5c6, 0xe5d2, 0xe5de, 0xe5ea, 0xe5f5, 0xe601, 0xe60d, 0xe619, + 0xe625, 0xe630, 0xe63c, 0xe648, 0xe654, 0xe660, 0xe66b, 0xe677, 0xe683, 0xe68f, 0xe69a, 0xe6a6, + 0xe6b2, 0xe6be, 0xe6ca, 0xe6d5, 0xe6e1, 0xe6ed, 0xe6f9, 0xe704, 0xe710, 0xe71c, 0xe727, 0xe733, + 0xe73f, 0xe74b, 0xe756, 0xe762, 0xe76e, 0xe77a, 0xe785, 0xe791, 0xe79d, 0xe7a8, 0xe7b4, 0xe7c0, + 0xe7cb, 0xe7d7, 0xe7e3, 0xe7ef, 0xe7fa, 0xe806, 0xe812, 0xe81d, 0xe829, 0xe835, 0xe840, 0xe84c, + 0xe858, 0xe863, 0xe86f, 0xe87b, 0xe886, 0xe892, 0xe89e, 0xe8a9, 0xe8b5, 0xe8c0, 0xe8cc, 0xe8d8, + 0xe8e3, 0xe8ef, 0xe8fb, 0xe906, 0xe912, 0xe91d, 0xe929, 0xe935, 0xe940, 0xe94c, 0xe958, 0xe963, + 0xe96f, 0xe97a, 0xe986, 0xe991, 0xe99d, 0xe9a9, 0xe9b4, 0xe9c0, 0xe9cb, 0xe9d7, 0xe9e3, 0xe9ee, + 0xe9fa, 0xea05, 0xea11, 0xea1c, 0xea28, 0xea33, 0xea3f, 0xea4a, 0xea56, 0xea62, 0xea6d, 0xea79, + 0xea84, 0xea90, 0xea9b, 0xeaa7, 0xeab2, 0xeabe, 0xeac9, 0xead5, 0xeae0, 0xeaec, 0xeaf7, 0xeb03, + 0xeb0e, 0xeb1a, 0xeb25, 0xeb31, 0xeb3c, 0xeb48, 0xeb53, 0xeb5f, 0xeb6a, 0xeb76, 0xeb81, 0xeb8d, + 0xeb98, 0xeba3, 0xebaf, 0xebba, 0xebc6, 0xebd1, 0xebdd, 0xebe8, 0xebf4, 0xebff, 0xec0a, 0xec16, + 0xec21, 0xec2d, 0xec38, 0xec44, 0xec4f, 0xec5a, 0xec66, 0xec71, 0xec7d, 0xec88, 0xec93, 0xec9f, + 0xecaa, 0xecb6, 0xecc1, 0xeccc, 0xecd8, 0xece3, 0xecef, 0xecfa, 0xed05, 0xed11, 0xed1c, 0xed27, + 0xed33, 0xed3e, 0xed4a, 0xed55, 0xed60, 0xed6c, 0xed77, 0xed82, 0xed8e, 0xed99, 0xeda4, 0xedb0, + 0xedbb, 0xedc6, 0xedd2, 0xeddd, 0xede8, 0xedf4, 0xedff, 0xee0a, 0xee15, 0xee21, 0xee2c, 0xee37, + 0xee43, 0xee4e, 0xee59, 0xee65, 0xee70, 0xee7b, 0xee86, 0xee92, 0xee9d, 0xeea8, 0xeeb3, 0xeebf, + 0xeeca, 0xeed5, 0xeee1, 0xeeec, 0xeef7, 0xef02, 0xef0e, 0xef19, 0xef24, 0xef2f, 0xef3a, 0xef46, + 0xef51, 0xef5c, 0xef67, 0xef73, 0xef7e, 0xef89, 0xef94, 0xef9f, 0xefab, 0xefb6, 0xefc1, 0xefcc, + 0xefd7, 0xefe3, 0xefee, 0xeff9, 0xf004, 0xf00f, 0xf01b, 0xf026, 0xf031, 0xf03c, 0xf047, 0xf052, + 0xf05e, 0xf069, 0xf074, 0xf07f, 0xf08a, 0xf095, 0xf0a1, 0xf0ac, 0xf0b7, 0xf0c2, 0xf0cd, 0xf0d8, + 0xf0e3, 0xf0ef, 0xf0fa, 0xf105, 0xf110, 0xf11b, 0xf126, 0xf131, 0xf13c, 0xf147, 0xf153, 0xf15e, + 0xf169, 0xf174, 0xf17f, 0xf18a, 0xf195, 0xf1a0, 0xf1ab, 0xf1b6, 0xf1c2, 0xf1cd, 0xf1d8, 0xf1e3, + 0xf1ee, 0xf1f9, 0xf204, 0xf20f, 0xf21a, 0xf225, 0xf230, 0xf23b, 0xf246, 0xf251, 0xf25c, 0xf267, + 0xf272, 0xf27d, 0xf288, 0xf293, 0xf29f, 0xf2aa, 0xf2b5, 0xf2c0, 0xf2cb, 0xf2d6, 0xf2e1, 0xf2ec, + 0xf2f7, 0xf302, 0xf30d, 0xf318, 0xf323, 0xf32e, 0xf339, 0xf344, 0xf34f, 0xf35a, 0xf364, 0xf36f, + 0xf37a, 0xf385, 0xf390, 0xf39b, 0xf3a6, 0xf3b1, 0xf3bc, 0xf3c7, 0xf3d2, 0xf3dd, 0xf3e8, 0xf3f3, + 0xf3fe, 0xf409, 0xf414, 0xf41f, 0xf42a, 0xf435, 0xf43f, 0xf44a, 0xf455, 0xf460, 0xf46b, 0xf476, + 0xf481, 0xf48c, 0xf497, 0xf4a2, 0xf4ad, 0xf4b7, 0xf4c2, 0xf4cd, 0xf4d8, 0xf4e3, 0xf4ee, 0xf4f9, + 0xf504, 0xf50f, 0xf519, 0xf524, 0xf52f, 0xf53a, 0xf545, 0xf550, 0xf55b, 0xf565, 0xf570, 0xf57b, + 0xf586, 0xf591, 0xf59c, 0xf5a6, 0xf5b1, 0xf5bc, 0xf5c7, 0xf5d2, 0xf5dd, 0xf5e7, 0xf5f2, 0xf5fd, + 0xf608, 0xf613, 0xf61d, 0xf628, 0xf633, 0xf63e, 0xf649, 0xf653, 0xf65e, 0xf669, 0xf674, 0xf67f, + 0xf689, 0xf694, 0xf69f, 0xf6aa, 0xf6b4, 0xf6bf, 0xf6ca, 0xf6d5, 0xf6e0, 0xf6ea, 0xf6f5, 0xf700, + 0xf70b, 0xf715, 0xf720, 0xf72b, 0xf736, 0xf740, 0xf74b, 0xf756, 0xf760, 0xf76b, 0xf776, 0xf781, + 0xf78b, 0xf796, 0xf7a1, 0xf7ab, 0xf7b6, 0xf7c1, 0xf7cc, 0xf7d6, 0xf7e1, 0xf7ec, 0xf7f6, 0xf801, + 0xf80c, 0xf816, 0xf821, 0xf82c, 0xf836, 0xf841, 0xf84c, 0xf856, 0xf861, 0xf86c, 0xf876, 0xf881, + 0xf88c, 0xf896, 0xf8a1, 0xf8ac, 0xf8b6, 0xf8c1, 0xf8cc, 0xf8d6, 0xf8e1, 0xf8ec, 0xf8f6, 0xf901, + 0xf90b, 0xf916, 0xf921, 0xf92b, 0xf936, 0xf941, 0xf94b, 0xf956, 0xf960, 0xf96b, 0xf976, 0xf980, + 0xf98b, 0xf995, 0xf9a0, 0xf9aa, 0xf9b5, 0xf9c0, 0xf9ca, 0xf9d5, 0xf9df, 0xf9ea, 0xf9f4, 0xf9ff, + 0xfa0a, 0xfa14, 0xfa1f, 0xfa29, 0xfa34, 0xfa3e, 0xfa49, 0xfa53, 0xfa5e, 0xfa69, 0xfa73, 0xfa7e, + 0xfa88, 0xfa93, 0xfa9d, 0xfaa8, 0xfab2, 0xfabd, 0xfac7, 0xfad2, 0xfadc, 0xfae7, 0xfaf1, 0xfafc, + 0xfb06, 0xfb11, 0xfb1b, 0xfb26, 0xfb30, 0xfb3b, 0xfb45, 0xfb50, 0xfb5a, 0xfb65, 0xfb6f, 0xfb7a, + 0xfb84, 0xfb8f, 0xfb99, 0xfba4, 0xfbae, 0xfbb8, 0xfbc3, 0xfbcd, 0xfbd8, 0xfbe2, 0xfbed, 0xfbf7, + 0xfc02, 0xfc0c, 0xfc16, 0xfc21, 0xfc2b, 0xfc36, 0xfc40, 0xfc4b, 0xfc55, 0xfc5f, 0xfc6a, 0xfc74, + 0xfc7f, 0xfc89, 0xfc93, 0xfc9e, 0xfca8, 0xfcb3, 0xfcbd, 0xfcc7, 0xfcd2, 0xfcdc, 0xfce7, 0xfcf1, + 0xfcfb, 0xfd06, 0xfd10, 0xfd1a, 0xfd25, 0xfd2f, 0xfd3a, 0xfd44, 0xfd4e, 0xfd59, 0xfd63, 0xfd6d, + 0xfd78, 0xfd82, 0xfd8c, 0xfd97, 0xfda1, 0xfdab, 0xfdb6, 0xfdc0, 0xfdca, 0xfdd5, 0xfddf, 0xfde9, + 0xfdf4, 0xfdfe, 0xfe08, 0xfe13, 0xfe1d, 0xfe27, 0xfe32, 0xfe3c, 0xfe46, 0xfe50, 0xfe5b, 0xfe65, + 0xfe6f, 0xfe7a, 0xfe84, 0xfe8e, 0xfe98, 0xfea3, 0xfead, 0xfeb7, 0xfec1, 0xfecc, 0xfed6, 0xfee0, + 0xfeeb, 0xfef5, 0xfeff, 0xff09, 0xff14, 0xff1e, 0xff28, 0xff32, 0xff3c, 0xff47, 0xff51, 0xff5b, + 0xff65, 0xff70, 0xff7a, 0xff84, 0xff8e, 0xff98, 0xffa3, 0xffad, 0xffb7, 0xffc1, 0xffcc, 0xffd6, + 0xffe0, 0xffea, 0xfff4, 0xffff}; + +// max value is pi/4 +constexpr double SCALING_FACTOR = 4. / M_PI * 0xFFFF; + +inline double atan2_lookup(double y, double x) +{ + if (std::abs(x) < std::numeric_limits::epsilon()) + { + if (y >= 0.) + { + return M_PI / 2.; + } + else + { + return -M_PI / 2.; + } + } + + unsigned octant = 0; + + if (x < 0.) + { + octant = 1; + x = -x; + } + if (y < 0.) + { + octant |= 2; + y = -y; + } + + double t = y / x; + if (t > 1.0) + { + octant |= 4; + t = 1.0 / t; + } + + double angle = atan_table[(unsigned)(t * 4095)] / SCALING_FACTOR; + + switch (octant) + { + case 0: + break; + case 1: + angle = M_PI - angle; + break; + case 2: + angle = -angle; + break; + case 3: + angle = -M_PI + angle; + break; + case 4: + angle = M_PI / 2.0 - angle; + break; + case 5: + angle = M_PI / 2.0 + angle; + break; + case 6: + angle = -M_PI / 2.0 + angle; + break; + case 7: + angle = -M_PI / 2.0 - angle; + break; + } + return angle; +} + +#endif // TRIGONOMETRY_TABLE_HPP diff --git a/util/xml_renderer.hpp b/util/xml_renderer.hpp new file mode 100644 index 000000000..bbf2287e1 --- /dev/null +++ b/util/xml_renderer.hpp @@ -0,0 +1,140 @@ +/* + +Copyright (c) 2014, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef XML_RENDERER_HPP +#define XML_RENDERER_HPP + +#include "cast.hpp" + +#include + +namespace JSON +{ + +struct XMLToArrayRenderer : mapbox::util::static_visitor<> +{ + explicit XMLToArrayRenderer(std::vector &_out) : out(_out) {} + + void operator()(const String &string) const + { + out.push_back('\"'); + out.insert(out.end(), string.value.begin(), string.value.end()); + out.push_back('\"'); + } + + void operator()(const Number &number) const + { + const std::string number_string = cast::double_fixed_to_string(number.value); + out.insert(out.end(), number_string.begin(), number_string.end()); + } + + void operator()(const Object &object) const + { + auto iterator = object.values.begin(); + while (iterator != object.values.end()) + { + if (iterator->first.at(0) != '_') + { + out.push_back('<'); + out.insert(out.end(), (*iterator).first.begin(), (*iterator).first.end()); + } + else + { + out.push_back(' '); + out.insert(out.end(), ++(*iterator).first.begin(), (*iterator).first.end()); + out.push_back('='); + } + mapbox::util::apply_visitor(XMLToArrayRenderer(out), (*iterator).second); + if (iterator->first.at(0) != '_') + { + out.push_back('/'); + out.push_back('>'); + } + ++iterator; + } + } + + void operator()(const Array &array) const + { + std::vector::const_iterator iterator; + iterator = array.values.begin(); + while (iterator != array.values.end()) + { + mapbox::util::apply_visitor(XMLToArrayRenderer(out), *iterator); + ++iterator; + } + } + + void operator()(const True &) const + { + const std::string temp("true"); + out.insert(out.end(), temp.begin(), temp.end()); + } + + void operator()(const False &) const + { + const std::string temp("false"); + out.insert(out.end(), temp.begin(), temp.end()); + } + + void operator()(const Null &) const + { + const std::string temp("null"); + out.insert(out.end(), temp.begin(), temp.end()); + } + + private: + std::vector &out; +}; + +template inline void xml_render(std::vector &out, const JSONObject &object) +{ + Value value = object; + mapbox::util::apply_visitor(XMLToArrayRenderer(out), value); +} + +template inline void gpx_render(std::vector &out, const JSONObject &object) +{ + // add header + + const std::string header{ + "Data (c) OpenStreetMap contributors (ODbL)"}; + out.insert(out.end(), header.begin(), header.end()); + + xml_render(out, object); + + const std::string footer{""}; + out.insert(out.end(), footer.begin(), footer.end()); +} +} // namespace JSON + +#endif // XML_RENDERER_HPP From 64a68597532e67e7dee7a5e63ba2d2204957dfca Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 18:37:52 +0100 Subject: [PATCH 140/360] reduce number of old-style casts --- tools/components.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tools/components.cpp b/tools/components.cpp index 733c8ff84..4ba8f997e 100644 --- a/tools/components.cpp +++ b/tools/components.cpp @@ -58,8 +58,8 @@ namespace struct TarjanEdgeData { TarjanEdgeData() : distance(INVALID_EDGE_WEIGHT), name_id(INVALID_NAMEID) {} - TarjanEdgeData(int distance, unsigned name_id) : distance(distance), name_id(name_id) {} - int distance; + TarjanEdgeData(unsigned distance, unsigned name_id) : distance(distance), name_id(name_id) {} + unsigned distance; unsigned name_id; }; @@ -97,7 +97,8 @@ int main(int argc, char *argv[]) std::ifstream restriction_ifstream(argv[2], std::ios::binary); const FingerPrint fingerprint_orig; FingerPrint fingerprint_loaded; - restriction_ifstream.read((char *)&fingerprint_loaded, sizeof(FingerPrint)); + restriction_ifstream.read(reinterpret_cast(&fingerprint_loaded), + sizeof(FingerPrint)); // check fingerprint and warn if necessary if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig)) @@ -111,13 +112,13 @@ int main(int argc, char *argv[]) throw osrm::exception("Could not access files"); } uint32_t usable_restrictions = 0; - restriction_ifstream.read((char *)&usable_restrictions, sizeof(uint32_t)); + restriction_ifstream.read(reinterpret_cast(&usable_restrictions), sizeof(uint32_t)); restriction_list.resize(usable_restrictions); // load restrictions if (usable_restrictions > 0) { - restriction_ifstream.read((char *)&(restriction_list[0]), + restriction_ifstream.read(reinterpret_cast(&restriction_list[0]), usable_restrictions * sizeof(TurnRestriction)); } restriction_ifstream.close(); @@ -147,7 +148,7 @@ int main(int argc, char *argv[]) // Building an node-based graph std::vector graph_edge_list; - for (const NodeBasedEdge &input_edge : edge_list) + for (const auto &input_edge : edge_list) { if (input_edge.source == input_edge.target) { @@ -157,14 +158,12 @@ int main(int argc, char *argv[]) if (input_edge.forward) { graph_edge_list.emplace_back(input_edge.source, input_edge.target, - (std::max)((int)input_edge.weight, 1), - input_edge.name_id); + (std::max)(input_edge.weight, 1), input_edge.name_id); } if (input_edge.backward) { graph_edge_list.emplace_back(input_edge.target, input_edge.source, - (std::max)((int)input_edge.weight, 1), - input_edge.name_id); + (std::max)(input_edge.weight, 1), input_edge.name_id); } } edge_list.clear(); @@ -226,7 +225,7 @@ int main(int argc, char *argv[]) SimpleLogger().Write() << "shapefile setup took " << TIMER_MSEC(SCC_RUN_SETUP) / 1000. << "s"; - uint64_t total_network_distance = 0; + uint64_t total_network_length = 0; p.reinit(graph->GetNumberOfNodes()); TIMER_START(SCC_OUTPUT); for (const NodeID source : osrm::irange(0u, graph->GetNumberOfNodes())) @@ -238,7 +237,7 @@ int main(int argc, char *argv[]) if (source < target || graph->EndEdges(target) == graph->FindEdge(target, source)) { - total_network_distance += + total_network_length += 100 * coordinate_calculation::euclidean_distance( coordinate_list[source].lat, coordinate_list[source].lon, coordinate_list[target].lat, coordinate_list[target].lon); @@ -278,7 +277,8 @@ int main(int argc, char *argv[]) << "s"; SimpleLogger().Write() << "total network distance: " - << (uint64_t)total_network_distance / 100 / 1000. << " km"; + << static_cast(total_network_length / 100 / 1000.) + << " km"; SimpleLogger().Write() << "finished component analysis"; } From 9a998d7b4129f8cdd48e894268425543db9de21c Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 18:40:01 +0100 Subject: [PATCH 141/360] rename short variable name to be more telling --- tools/components.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/components.cpp b/tools/components.cpp index 4ba8f997e..41e7a59ca 100644 --- a/tools/components.cpp +++ b/tools/components.cpp @@ -194,7 +194,7 @@ int main(int argc, char *argv[]) DeleteFileIfExists("component.shx"); DeleteFileIfExists("component.shp"); - Percent p(graph->GetNumberOfNodes()); + Percent percentage(graph->GetNumberOfNodes()); OGRRegisterAll(); @@ -226,11 +226,11 @@ int main(int argc, char *argv[]) << "s"; uint64_t total_network_length = 0; - p.reinit(graph->GetNumberOfNodes()); + percentage.reinit(graph->GetNumberOfNodes()); TIMER_START(SCC_OUTPUT); for (const NodeID source : osrm::irange(0u, graph->GetNumberOfNodes())) { - p.printIncrement(); + percentage.printIncrement(); for (const auto current_edge : graph->GetAdjacentEdgeRange(source)) { const TarjanGraph::NodeIterator target = graph->GetTarget(current_edge); From b192678abf178c4c5cdb3d68ef3b39d15409b72b Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 27 Jan 2015 18:44:06 +0100 Subject: [PATCH 142/360] add dummy case to switch statement. reflects all cases are covered and should shut up compiler warnings --- util/simple_logger.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/util/simple_logger.cpp b/util/simple_logger.cpp index 5d8821233..2f032300c 100644 --- a/util/simple_logger.cpp +++ b/util/simple_logger.cpp @@ -127,7 +127,8 @@ SimpleLogger::~SimpleLogger() << std::endl; #endif break; - default: // logINFO: + case logINFO: + default: std::cout << os.str() << (is_terminal ? COL_RESET : "") << std::endl; break; } From 86ca9bd0f9dd39632c6217465972db78109688a2 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 28 Jan 2015 10:09:46 +0100 Subject: [PATCH 143/360] mark simple logger write function as noexcept. --- Util/simple_logger.cpp | 39 ++++++++++++++++----------------------- Util/simple_logger.hpp | 4 ++-- util/simple_logger.cpp | 36 ++++++++++++++---------------------- util/simple_logger.hpp | 4 ++-- 4 files changed, 34 insertions(+), 49 deletions(-) diff --git a/Util/simple_logger.cpp b/Util/simple_logger.cpp index 5d8821233..325684af9 100644 --- a/Util/simple_logger.cpp +++ b/Util/simple_logger.cpp @@ -78,34 +78,26 @@ std::mutex &SimpleLogger::get_mutex() return mtx; } -std::ostringstream &SimpleLogger::Write(LogLevel lvl) +std::ostringstream &SimpleLogger::Write(LogLevel lvl) noexcept { std::lock_guard lock(get_mutex()); - try + level = lvl; + os << "["; + switch (level) { - level = lvl; - os << "["; - switch (level) - { - case logWARNING: - os << "warn"; - break; - case logDEBUG: + case logWARNING: + os << "warn"; + break; + case logDEBUG: #ifndef NDEBUG - os << "debug"; + os << "debug"; #endif - break; - default: // logINFO: - os << "info"; - break; - } - os << "] "; - } - catch (const std::exception &e) - { - // encapsulate in osrm::exception - throw osrm::exception(std::string(e.what()) + ", getting ostringstream"); + break; + default: // logINFO: + os << "info"; + break; } + os << "] "; return os; } @@ -127,7 +119,8 @@ SimpleLogger::~SimpleLogger() << std::endl; #endif break; - default: // logINFO: + case logINFO: + default: std::cout << os.str() << (is_terminal ? COL_RESET : "") << std::endl; break; } diff --git a/Util/simple_logger.hpp b/Util/simple_logger.hpp index 077fa2e41..f4dfc0b02 100644 --- a/Util/simple_logger.hpp +++ b/Util/simple_logger.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -64,7 +64,7 @@ class SimpleLogger virtual ~SimpleLogger(); std::mutex &get_mutex(); - std::ostringstream &Write(LogLevel l = logINFO); + std::ostringstream &Write(LogLevel l = logINFO) noexcept; private: std::ostringstream os; diff --git a/util/simple_logger.cpp b/util/simple_logger.cpp index 2f032300c..325684af9 100644 --- a/util/simple_logger.cpp +++ b/util/simple_logger.cpp @@ -78,34 +78,26 @@ std::mutex &SimpleLogger::get_mutex() return mtx; } -std::ostringstream &SimpleLogger::Write(LogLevel lvl) +std::ostringstream &SimpleLogger::Write(LogLevel lvl) noexcept { std::lock_guard lock(get_mutex()); - try + level = lvl; + os << "["; + switch (level) { - level = lvl; - os << "["; - switch (level) - { - case logWARNING: - os << "warn"; - break; - case logDEBUG: + case logWARNING: + os << "warn"; + break; + case logDEBUG: #ifndef NDEBUG - os << "debug"; + os << "debug"; #endif - break; - default: // logINFO: - os << "info"; - break; - } - os << "] "; - } - catch (const std::exception &e) - { - // encapsulate in osrm::exception - throw osrm::exception(std::string(e.what()) + ", getting ostringstream"); + break; + default: // logINFO: + os << "info"; + break; } + os << "] "; return os; } diff --git a/util/simple_logger.hpp b/util/simple_logger.hpp index 077fa2e41..f4dfc0b02 100644 --- a/util/simple_logger.hpp +++ b/util/simple_logger.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -64,7 +64,7 @@ class SimpleLogger virtual ~SimpleLogger(); std::mutex &get_mutex(); - std::ostringstream &Write(LogLevel l = logINFO); + std::ostringstream &Write(LogLevel l = logINFO) noexcept; private: std::ostringstream os; From 2a8084b6c62b87227d5a7ddca5d30aa55d7b5272 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 28 Jan 2015 10:10:28 +0100 Subject: [PATCH 144/360] clean up derived classed and their functions to correctly use final keyword: functions marked as final need to be marked virtual. use override specifier to do so --- .../data_structures/internal_datafacade.hpp | 56 +++++++++++-------- Server/data_structures/shared_datafacade.hpp | 55 ++++++++++-------- descriptors/gpx_descriptor.hpp | 4 +- descriptors/json_descriptor.hpp | 4 +- plugins/distance_table.hpp | 5 +- plugins/hello_world.hpp | 5 +- plugins/locate.hpp | 5 +- plugins/nearest.hpp | 5 +- plugins/timestamp.hpp | 5 +- plugins/viaroute.hpp | 5 +- .../data_structures/internal_datafacade.hpp | 56 +++++++++++-------- server/data_structures/shared_datafacade.hpp | 55 ++++++++++-------- 12 files changed, 148 insertions(+), 112 deletions(-) diff --git a/Server/data_structures/internal_datafacade.hpp b/Server/data_structures/internal_datafacade.hpp index 8a481c5c5..0a246b791 100644 --- a/Server/data_structures/internal_datafacade.hpp +++ b/Server/data_structures/internal_datafacade.hpp @@ -46,7 +46,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -template class InternalDataFacade : public BaseDataFacade +template class InternalDataFacade final : public BaseDataFacade { private: @@ -309,52 +309,60 @@ template class InternalDataFacade : public BaseDataFacadeGetNumberOfNodes(); } + unsigned GetNumberOfNodes() const override final { return m_query_graph->GetNumberOfNodes(); } - unsigned GetNumberOfEdges() const final { return m_query_graph->GetNumberOfEdges(); } + unsigned GetNumberOfEdges() const override final { return m_query_graph->GetNumberOfEdges(); } - unsigned GetOutDegree(const NodeID n) const final { return m_query_graph->GetOutDegree(n); } + unsigned GetOutDegree(const NodeID n) const override final + { + return m_query_graph->GetOutDegree(n); + } - NodeID GetTarget(const EdgeID e) const final { return m_query_graph->GetTarget(e); } + NodeID GetTarget(const EdgeID e) const override final { return m_query_graph->GetTarget(e); } - // EdgeDataT &GetEdgeData(const EdgeID e) final { return m_query_graph->GetEdgeData(e); } + // EdgeDataT &GetEdgeData(const EdgeID e) override final { return m_query_graph->GetEdgeData(e); + // } - EdgeDataT &GetEdgeData(const EdgeID e) const final { return m_query_graph->GetEdgeData(e); } + EdgeDataT &GetEdgeData(const EdgeID e) const override final + { + return m_query_graph->GetEdgeData(e); + } - EdgeID BeginEdges(const NodeID n) const final { return m_query_graph->BeginEdges(n); } + EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph->BeginEdges(n); } - EdgeID EndEdges(const NodeID n) const final { return m_query_graph->EndEdges(n); } + EdgeID EndEdges(const NodeID n) const override final { return m_query_graph->EndEdges(n); } - EdgeRange GetAdjacentEdgeRange(const NodeID node) const final + EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final { return m_query_graph->GetAdjacentEdgeRange(node); }; // searches for a specific edge - EdgeID FindEdge(const NodeID from, const NodeID to) const final + EdgeID FindEdge(const NodeID from, const NodeID to) const override final { return m_query_graph->FindEdge(from, to); } - EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const final + EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const override final { return m_query_graph->FindEdgeInEitherDirection(from, to); } - EdgeID FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const final + EdgeID + FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const override final { return m_query_graph->FindEdgeIndicateIfReverse(from, to, result); } // node and edge information access - FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const final + FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const override final { return m_coordinate_list->at(id); }; bool EdgeIsCompressed(const unsigned id) const { return m_edge_is_compressed.at(id); } - TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const final + TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const override final { return m_turn_instruction_list.at(id); } @@ -363,7 +371,7 @@ template class InternalDataFacade : public BaseDataFacade class InternalDataFacade : public BaseDataFacade resulting_phantom_node_vector; auto result = IncrementalFindPhantomNodeForCoordinate(input_coordinate, @@ -391,7 +399,7 @@ template class InternalDataFacade : public BaseDataFacade &resulting_phantom_node_vector, - const unsigned number_of_results) final + const unsigned number_of_results) override final { if (!m_static_rtree.get()) { @@ -402,14 +410,14 @@ template class InternalDataFacade : public BaseDataFacade class InternalDataFacade : public BaseDataFacade &result_nodes) const final + std::vector &result_nodes) const override final { const unsigned begin = m_geometry_indices.at(id); const unsigned end = m_geometry_indices.at(id + 1); @@ -443,7 +451,7 @@ template class InternalDataFacade : public BaseDataFacade #include -template class SharedDataFacade : public BaseDataFacade +template class SharedDataFacade final : public BaseDataFacade { private: @@ -282,54 +282,61 @@ template class SharedDataFacade : public BaseDataFacadeGetNumberOfNodes(); } + unsigned GetNumberOfNodes() const override final { return m_query_graph->GetNumberOfNodes(); } - unsigned GetNumberOfEdges() const final { return m_query_graph->GetNumberOfEdges(); } + unsigned GetNumberOfEdges() const override final { return m_query_graph->GetNumberOfEdges(); } - unsigned GetOutDegree(const NodeID n) const final { return m_query_graph->GetOutDegree(n); } + unsigned GetOutDegree(const NodeID n) const override final + { + return m_query_graph->GetOutDegree(n); + } - NodeID GetTarget(const EdgeID e) const final { return m_query_graph->GetTarget(e); } + NodeID GetTarget(const EdgeID e) const override final { return m_query_graph->GetTarget(e); } - EdgeDataT &GetEdgeData(const EdgeID e) const final { return m_query_graph->GetEdgeData(e); } + EdgeDataT &GetEdgeData(const EdgeID e) const override final + { + return m_query_graph->GetEdgeData(e); + } - EdgeID BeginEdges(const NodeID n) const final { return m_query_graph->BeginEdges(n); } + EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph->BeginEdges(n); } - EdgeID EndEdges(const NodeID n) const final { return m_query_graph->EndEdges(n); } + EdgeID EndEdges(const NodeID n) const override final { return m_query_graph->EndEdges(n); } - EdgeRange GetAdjacentEdgeRange(const NodeID node) const final + EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final { return m_query_graph->GetAdjacentEdgeRange(node); }; // searches for a specific edge - EdgeID FindEdge(const NodeID from, const NodeID to) const final + EdgeID FindEdge(const NodeID from, const NodeID to) const override final { return m_query_graph->FindEdge(from, to); } - EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const final + EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const override final { return m_query_graph->FindEdgeInEitherDirection(from, to); } - EdgeID FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const final + EdgeID + FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const override final { return m_query_graph->FindEdgeIndicateIfReverse(from, to, result); } // node and edge information access - FixedPointCoordinate GetCoordinateOfNode(const NodeID id) const final + FixedPointCoordinate GetCoordinateOfNode(const NodeID id) const override final { return m_coordinate_list->at(id); }; - virtual bool EdgeIsCompressed(const unsigned id) const final + virtual bool EdgeIsCompressed(const unsigned id) const override final { return m_edge_is_compressed.at(id); } virtual void GetUncompressedGeometry(const unsigned id, - std::vector &result_nodes) const final + std::vector &result_nodes) const override final { const unsigned begin = m_geometry_indices.at(id); const unsigned end = m_geometry_indices.at(id + 1); @@ -339,12 +346,12 @@ template class SharedDataFacade : public BaseDataFacade class SharedDataFacade : public BaseDataFacadefirst) { @@ -365,7 +372,7 @@ template class SharedDataFacade : public BaseDataFacade resulting_phantom_node_vector; auto result = IncrementalFindPhantomNodeForCoordinate(input_coordinate, @@ -381,7 +388,7 @@ template class SharedDataFacade : public BaseDataFacade &resulting_phantom_node_vector, - const unsigned number_of_results) final + const unsigned number_of_results) override final { if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first) { @@ -392,14 +399,14 @@ template class SharedDataFacade : public BaseDataFacade class SharedDataFacade : public BaseDataFacade class GPXDescriptor final : public BaseDescriptor class JSONDescriptor final : public BaseDescriptor< { } - void SetConfig(const DescriptorConfig &c) final { config = c; } + void SetConfig(const DescriptorConfig &c) override final { config = c; } unsigned DescribeLeg(const std::vector route_leg, const PhantomNodes &leg_phantoms, @@ -100,7 +100,7 @@ template class JSONDescriptor final : public BaseDescriptor< return added_element_count; } - void Run(const InternalRouteResult &raw_route, JSON::Object &json_result) final + void Run(const InternalRouteResult &raw_route, JSON::Object &json_result) override final { if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length) { diff --git a/plugins/distance_table.hpp b/plugins/distance_table.hpp index b7483f16f..0a8912640 100644 --- a/plugins/distance_table.hpp +++ b/plugins/distance_table.hpp @@ -65,9 +65,10 @@ template class DistanceTablePlugin final : public BasePlugin virtual ~DistanceTablePlugin() {} - const std::string GetDescriptor() const final { return descriptor_string; } + const std::string GetDescriptor() const override final { return descriptor_string; } - int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final + int HandleRequest(const RouteParameters &route_parameters, + JSON::Object &json_result) override final { if (!check_all_coordinates(route_parameters.coordinates)) { diff --git a/plugins/hello_world.hpp b/plugins/hello_world.hpp index 97c03095b..5b08663db 100644 --- a/plugins/hello_world.hpp +++ b/plugins/hello_world.hpp @@ -45,9 +45,10 @@ class HelloWorldPlugin final : public BasePlugin public: HelloWorldPlugin() : descriptor_string("hello") {} virtual ~HelloWorldPlugin() {} - const std::string GetDescriptor() const final { return descriptor_string; } + const std::string GetDescriptor() const override final { return descriptor_string; } - int HandleRequest(const RouteParameters &routeParameters, JSON::Object &json_result) final + int HandleRequest(const RouteParameters &routeParameters, + JSON::Object &json_result) override final { std::string temp_string; json_result.values["title"] = "Hello World"; diff --git a/plugins/locate.hpp b/plugins/locate.hpp index 262935a67..260361462 100644 --- a/plugins/locate.hpp +++ b/plugins/locate.hpp @@ -42,9 +42,10 @@ template class LocatePlugin final : public BasePlugin { public: explicit LocatePlugin(DataFacadeT *facade) : descriptor_string("locate"), facade(facade) {} - const std::string GetDescriptor() const final { return descriptor_string; } + const std::string GetDescriptor() const override final { return descriptor_string; } - int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final + int HandleRequest(const RouteParameters &route_parameters, + JSON::Object &json_result) override final { // check number of parameters if (route_parameters.coordinates.empty() || diff --git a/plugins/nearest.hpp b/plugins/nearest.hpp index 9add3040b..6221fcfb3 100644 --- a/plugins/nearest.hpp +++ b/plugins/nearest.hpp @@ -47,9 +47,10 @@ template class NearestPlugin final : public BasePlugin public: explicit NearestPlugin(DataFacadeT *facade) : facade(facade), descriptor_string("nearest") {} - const std::string GetDescriptor() const final { return descriptor_string; } + const std::string GetDescriptor() const override final { return descriptor_string; } - int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final + int HandleRequest(const RouteParameters &route_parameters, + JSON::Object &json_result) override final { // check number of parameters if (route_parameters.coordinates.empty() || diff --git a/plugins/timestamp.hpp b/plugins/timestamp.hpp index b86174a50..db265ec47 100644 --- a/plugins/timestamp.hpp +++ b/plugins/timestamp.hpp @@ -43,8 +43,9 @@ template class TimestampPlugin final : public BasePlugin : facade(facade), descriptor_string("timestamp") { } - const std::string GetDescriptor() const final { return descriptor_string; } - int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final + const std::string GetDescriptor() const override final { return descriptor_string; } + int HandleRequest(const RouteParameters &route_parameters, + JSON::Object &json_result) override final { json_result.values["status"] = 0; const std::string timestamp = facade->GetTimestamp(); diff --git a/plugins/viaroute.hpp b/plugins/viaroute.hpp index b253baa1c..630cba579 100644 --- a/plugins/viaroute.hpp +++ b/plugins/viaroute.hpp @@ -69,9 +69,10 @@ template class ViaRoutePlugin final : public BasePlugin virtual ~ViaRoutePlugin() {} - const std::string GetDescriptor() const final { return descriptor_string; } + const std::string GetDescriptor() const override final { return descriptor_string; } - int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final + int HandleRequest(const RouteParameters &route_parameters, + JSON::Object &json_result) override final { if (!check_all_coordinates(route_parameters.coordinates)) { diff --git a/server/data_structures/internal_datafacade.hpp b/server/data_structures/internal_datafacade.hpp index 8a481c5c5..0a246b791 100644 --- a/server/data_structures/internal_datafacade.hpp +++ b/server/data_structures/internal_datafacade.hpp @@ -46,7 +46,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -template class InternalDataFacade : public BaseDataFacade +template class InternalDataFacade final : public BaseDataFacade { private: @@ -309,52 +309,60 @@ template class InternalDataFacade : public BaseDataFacadeGetNumberOfNodes(); } + unsigned GetNumberOfNodes() const override final { return m_query_graph->GetNumberOfNodes(); } - unsigned GetNumberOfEdges() const final { return m_query_graph->GetNumberOfEdges(); } + unsigned GetNumberOfEdges() const override final { return m_query_graph->GetNumberOfEdges(); } - unsigned GetOutDegree(const NodeID n) const final { return m_query_graph->GetOutDegree(n); } + unsigned GetOutDegree(const NodeID n) const override final + { + return m_query_graph->GetOutDegree(n); + } - NodeID GetTarget(const EdgeID e) const final { return m_query_graph->GetTarget(e); } + NodeID GetTarget(const EdgeID e) const override final { return m_query_graph->GetTarget(e); } - // EdgeDataT &GetEdgeData(const EdgeID e) final { return m_query_graph->GetEdgeData(e); } + // EdgeDataT &GetEdgeData(const EdgeID e) override final { return m_query_graph->GetEdgeData(e); + // } - EdgeDataT &GetEdgeData(const EdgeID e) const final { return m_query_graph->GetEdgeData(e); } + EdgeDataT &GetEdgeData(const EdgeID e) const override final + { + return m_query_graph->GetEdgeData(e); + } - EdgeID BeginEdges(const NodeID n) const final { return m_query_graph->BeginEdges(n); } + EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph->BeginEdges(n); } - EdgeID EndEdges(const NodeID n) const final { return m_query_graph->EndEdges(n); } + EdgeID EndEdges(const NodeID n) const override final { return m_query_graph->EndEdges(n); } - EdgeRange GetAdjacentEdgeRange(const NodeID node) const final + EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final { return m_query_graph->GetAdjacentEdgeRange(node); }; // searches for a specific edge - EdgeID FindEdge(const NodeID from, const NodeID to) const final + EdgeID FindEdge(const NodeID from, const NodeID to) const override final { return m_query_graph->FindEdge(from, to); } - EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const final + EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const override final { return m_query_graph->FindEdgeInEitherDirection(from, to); } - EdgeID FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const final + EdgeID + FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const override final { return m_query_graph->FindEdgeIndicateIfReverse(from, to, result); } // node and edge information access - FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const final + FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const override final { return m_coordinate_list->at(id); }; bool EdgeIsCompressed(const unsigned id) const { return m_edge_is_compressed.at(id); } - TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const final + TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const override final { return m_turn_instruction_list.at(id); } @@ -363,7 +371,7 @@ template class InternalDataFacade : public BaseDataFacade class InternalDataFacade : public BaseDataFacade resulting_phantom_node_vector; auto result = IncrementalFindPhantomNodeForCoordinate(input_coordinate, @@ -391,7 +399,7 @@ template class InternalDataFacade : public BaseDataFacade &resulting_phantom_node_vector, - const unsigned number_of_results) final + const unsigned number_of_results) override final { if (!m_static_rtree.get()) { @@ -402,14 +410,14 @@ template class InternalDataFacade : public BaseDataFacade class InternalDataFacade : public BaseDataFacade &result_nodes) const final + std::vector &result_nodes) const override final { const unsigned begin = m_geometry_indices.at(id); const unsigned end = m_geometry_indices.at(id + 1); @@ -443,7 +451,7 @@ template class InternalDataFacade : public BaseDataFacade #include -template class SharedDataFacade : public BaseDataFacade +template class SharedDataFacade final : public BaseDataFacade { private: @@ -282,54 +282,61 @@ template class SharedDataFacade : public BaseDataFacadeGetNumberOfNodes(); } + unsigned GetNumberOfNodes() const override final { return m_query_graph->GetNumberOfNodes(); } - unsigned GetNumberOfEdges() const final { return m_query_graph->GetNumberOfEdges(); } + unsigned GetNumberOfEdges() const override final { return m_query_graph->GetNumberOfEdges(); } - unsigned GetOutDegree(const NodeID n) const final { return m_query_graph->GetOutDegree(n); } + unsigned GetOutDegree(const NodeID n) const override final + { + return m_query_graph->GetOutDegree(n); + } - NodeID GetTarget(const EdgeID e) const final { return m_query_graph->GetTarget(e); } + NodeID GetTarget(const EdgeID e) const override final { return m_query_graph->GetTarget(e); } - EdgeDataT &GetEdgeData(const EdgeID e) const final { return m_query_graph->GetEdgeData(e); } + EdgeDataT &GetEdgeData(const EdgeID e) const override final + { + return m_query_graph->GetEdgeData(e); + } - EdgeID BeginEdges(const NodeID n) const final { return m_query_graph->BeginEdges(n); } + EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph->BeginEdges(n); } - EdgeID EndEdges(const NodeID n) const final { return m_query_graph->EndEdges(n); } + EdgeID EndEdges(const NodeID n) const override final { return m_query_graph->EndEdges(n); } - EdgeRange GetAdjacentEdgeRange(const NodeID node) const final + EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final { return m_query_graph->GetAdjacentEdgeRange(node); }; // searches for a specific edge - EdgeID FindEdge(const NodeID from, const NodeID to) const final + EdgeID FindEdge(const NodeID from, const NodeID to) const override final { return m_query_graph->FindEdge(from, to); } - EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const final + EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const override final { return m_query_graph->FindEdgeInEitherDirection(from, to); } - EdgeID FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const final + EdgeID + FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const override final { return m_query_graph->FindEdgeIndicateIfReverse(from, to, result); } // node and edge information access - FixedPointCoordinate GetCoordinateOfNode(const NodeID id) const final + FixedPointCoordinate GetCoordinateOfNode(const NodeID id) const override final { return m_coordinate_list->at(id); }; - virtual bool EdgeIsCompressed(const unsigned id) const final + virtual bool EdgeIsCompressed(const unsigned id) const override final { return m_edge_is_compressed.at(id); } virtual void GetUncompressedGeometry(const unsigned id, - std::vector &result_nodes) const final + std::vector &result_nodes) const override final { const unsigned begin = m_geometry_indices.at(id); const unsigned end = m_geometry_indices.at(id + 1); @@ -339,12 +346,12 @@ template class SharedDataFacade : public BaseDataFacade class SharedDataFacade : public BaseDataFacadefirst) { @@ -365,7 +372,7 @@ template class SharedDataFacade : public BaseDataFacade resulting_phantom_node_vector; auto result = IncrementalFindPhantomNodeForCoordinate(input_coordinate, @@ -381,7 +388,7 @@ template class SharedDataFacade : public BaseDataFacade &resulting_phantom_node_vector, - const unsigned number_of_results) final + const unsigned number_of_results) override final { if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first) { @@ -392,14 +399,14 @@ template class SharedDataFacade : public BaseDataFacade class SharedDataFacade : public BaseDataFacade Date: Wed, 28 Jan 2015 12:30:14 +0100 Subject: [PATCH 145/360] remove left-over directories from the renaming spree --- Include/osrm/coordinate.hpp | 71 --- Include/osrm/json_container.hpp | 94 ---- Include/osrm/libosrm_config.hpp | 48 -- Include/osrm/route_parameters.hpp | 92 ---- Include/osrm/server_paths.hpp | 38 -- Library/OSRM_impl.cpp | 178 ------- Server/Connection.cpp | 171 ------- Server/Http/Reply.cpp | 130 ----- Server/data_structures/datafacade_base.hpp | 126 ----- .../data_structures/internal_datafacade.hpp | 457 ------------------ Server/data_structures/shared_barriers.hpp | 60 --- Server/data_structures/shared_datafacade.hpp | 430 ---------------- Server/data_structures/shared_datatype.hpp | 227 --------- Server/http/compression_type.hpp | 42 -- Server/http/header.hpp | 54 --- Server/http/reply.cpp | 130 ----- Server/http/reply.hpp | 65 --- Server/http/request.hpp | 48 -- Util/bearing.cpp | 65 --- Util/bearing.hpp | 38 -- Util/boost_filesystem_2_fix.hpp | 144 ------ Util/cast.hpp | 185 ------- Util/compute_angle.cpp | 54 --- Util/compute_angle.hpp | 42 -- Util/container.hpp | 85 ---- Util/datastore_options.hpp | 273 ----------- Util/fingerprint.cpp.in | 103 ---- Util/fingerprint.hpp | 59 --- Util/floating_point.hpp | 44 -- Util/git_sha.cpp.in | 31 -- Util/git_sha.hpp | 33 -- Util/graph_loader.hpp | 320 ------------ Util/ini_file.hpp | 51 -- Util/integer_range.hpp | 70 --- Util/iterator_range.hpp | 72 --- Util/json_renderer.hpp | 184 ------- Util/lua_util.hpp | 66 --- Util/make_unique.hpp | 57 --- Util/mercator.cpp | 40 -- Util/mercator.hpp | 38 -- Util/osrm_exception.cpp | 43 -- Util/osrm_exception.hpp | 51 -- Util/range_algorithms.hpp | 42 -- Util/routed_options.hpp | 277 ----------- Util/simple_logger.cpp | 128 ----- Util/simple_logger.hpp | 74 --- Util/std_hash.hpp | 72 --- Util/string_util.hpp | 150 ------ Util/timing_util.hpp | 90 ---- Util/trigonometry_table.hpp | 448 ----------------- Util/xml_renderer.hpp | 140 ------ 51 files changed, 6030 deletions(-) delete mode 100644 Include/osrm/coordinate.hpp delete mode 100644 Include/osrm/json_container.hpp delete mode 100644 Include/osrm/libosrm_config.hpp delete mode 100644 Include/osrm/route_parameters.hpp delete mode 100644 Include/osrm/server_paths.hpp delete mode 100644 Library/OSRM_impl.cpp delete mode 100644 Server/Connection.cpp delete mode 100644 Server/Http/Reply.cpp delete mode 100644 Server/data_structures/datafacade_base.hpp delete mode 100644 Server/data_structures/internal_datafacade.hpp delete mode 100644 Server/data_structures/shared_barriers.hpp delete mode 100644 Server/data_structures/shared_datafacade.hpp delete mode 100644 Server/data_structures/shared_datatype.hpp delete mode 100644 Server/http/compression_type.hpp delete mode 100644 Server/http/header.hpp delete mode 100644 Server/http/reply.cpp delete mode 100644 Server/http/reply.hpp delete mode 100644 Server/http/request.hpp delete mode 100644 Util/bearing.cpp delete mode 100644 Util/bearing.hpp delete mode 100644 Util/boost_filesystem_2_fix.hpp delete mode 100644 Util/cast.hpp delete mode 100644 Util/compute_angle.cpp delete mode 100644 Util/compute_angle.hpp delete mode 100644 Util/container.hpp delete mode 100644 Util/datastore_options.hpp delete mode 100644 Util/fingerprint.cpp.in delete mode 100644 Util/fingerprint.hpp delete mode 100644 Util/floating_point.hpp delete mode 100644 Util/git_sha.cpp.in delete mode 100644 Util/git_sha.hpp delete mode 100644 Util/graph_loader.hpp delete mode 100644 Util/ini_file.hpp delete mode 100644 Util/integer_range.hpp delete mode 100644 Util/iterator_range.hpp delete mode 100644 Util/json_renderer.hpp delete mode 100644 Util/lua_util.hpp delete mode 100644 Util/make_unique.hpp delete mode 100644 Util/mercator.cpp delete mode 100644 Util/mercator.hpp delete mode 100644 Util/osrm_exception.cpp delete mode 100644 Util/osrm_exception.hpp delete mode 100644 Util/range_algorithms.hpp delete mode 100644 Util/routed_options.hpp delete mode 100644 Util/simple_logger.cpp delete mode 100644 Util/simple_logger.hpp delete mode 100644 Util/std_hash.hpp delete mode 100644 Util/string_util.hpp delete mode 100644 Util/timing_util.hpp delete mode 100644 Util/trigonometry_table.hpp delete mode 100644 Util/xml_renderer.hpp diff --git a/Include/osrm/coordinate.hpp b/Include/osrm/coordinate.hpp deleted file mode 100644 index 546515d49..000000000 --- a/Include/osrm/coordinate.hpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef COORDINATE_HPP_ -#define COORDINATE_HPP_ - -#include //for std::ostream -#include -#include - -namespace -{ -constexpr static const float COORDINATE_PRECISION = 1000000.f; -} - -struct FixedPointCoordinate -{ - int lat; - int lon; - - FixedPointCoordinate(); - FixedPointCoordinate(int lat, int lon); - - template - FixedPointCoordinate(const T &coordinate) - : lat(coordinate.lat), lon(coordinate.lon) - { - static_assert(std::is_same::value, - "coordinate types incompatible"); - static_assert(std::is_same::value, - "coordinate types incompatible"); - } - - bool is_valid() const; - bool operator==(const FixedPointCoordinate &other) const; - - float bearing(const FixedPointCoordinate &other) const; - void output(std::ostream &out) const; -}; - -inline std::ostream &operator<<(std::ostream &out_stream, FixedPointCoordinate const &coordinate) -{ - coordinate.output(out_stream); - return out_stream; -} - -#endif /* COORDINATE_HPP_ */ diff --git a/Include/osrm/json_container.hpp b/Include/osrm/json_container.hpp deleted file mode 100644 index 9bbbec433..000000000 --- a/Include/osrm/json_container.hpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - -Copyright (c) 2013, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -// based on -// https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp - -#ifndef JSON_CONTAINER_H -#define JSON_CONTAINER_H - -#include - -#include -#include -#include -#include - -namespace JSON -{ - -struct Object; -struct Array; - -struct String -{ - String() {} - String(const char *value) : value(value) {} - String(const std::string &value) : value(value) {} - std::string value; -}; - -struct Number -{ - Number() {} - Number(double value) : value(static_cast(value)) {} - double value; -}; - -struct True -{ -}; - -struct False -{ -}; - -struct Null -{ -}; - -using Value = mapbox::util::variant, - mapbox::util::recursive_wrapper, - True, - False, - Null>; - -struct Object -{ - std::unordered_map values; -}; - -struct Array -{ - std::vector values; -}; - -} // namespace JSON - -#endif // JSON_CONTAINER_H diff --git a/Include/osrm/libosrm_config.hpp b/Include/osrm/libosrm_config.hpp deleted file mode 100644 index 2f0edaf35..000000000 --- a/Include/osrm/libosrm_config.hpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef SERVER_CONFIG_HPP -#define SERVER_CONFIG_HPP - -#include - -struct libosrm_config -{ - libosrm_config(const libosrm_config &) = delete; - libosrm_config() : max_locations_distance_table(100), use_shared_memory(false) {} - - libosrm_config(const ServerPaths &paths, const bool flag, const int max) - : server_paths(paths), max_locations_distance_table(max), use_shared_memory(flag) - { - } - - ServerPaths server_paths; - int max_locations_distance_table; - bool use_shared_memory; -}; - -#endif // SERVER_CONFIG_HPP diff --git a/Include/osrm/route_parameters.hpp b/Include/osrm/route_parameters.hpp deleted file mode 100644 index 0a450d571..000000000 --- a/Include/osrm/route_parameters.hpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - -Copyright (c) 2013, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef ROUTE_PARAMETERS_H -#define ROUTE_PARAMETERS_H - -#include - -#include - -#include -#include - -struct RouteParameters -{ - RouteParameters(); - - void setZoomLevel(const short level); - - void setNumberOfResults(const short number); - - void setAlternateRouteFlag(const bool flag); - - void setUTurn(const bool flag); - - void setAllUTurns(const bool flag); - - void setDeprecatedAPIFlag(const std::string &); - - void setChecksum(const unsigned check_sum); - - void setInstructionFlag(const bool flag); - - void setService(const std::string &service); - - void setOutputFormat(const std::string &format); - - void setJSONpParameter(const std::string ¶meter); - - void addHint(const std::string &hint); - - void setLanguage(const std::string &language); - - void setGeometryFlag(const bool flag); - - void setCompressionFlag(const bool flag); - - void addCoordinate(const boost::fusion::vector &coordinates); - - short zoom_level; - bool print_instructions; - bool alternate_route; - bool geometry; - bool compression; - bool deprecatedAPI; - bool uturn_default; - unsigned check_sum; - short num_results; - std::string service; - std::string output_format; - std::string jsonp_parameter; - std::string language; - std::vector hints; - std::vector uturns; - std::vector coordinates; -}; - -#endif // ROUTE_PARAMETERS_H diff --git a/Include/osrm/server_paths.hpp b/Include/osrm/server_paths.hpp deleted file mode 100644 index 52b60c7c4..000000000 --- a/Include/osrm/server_paths.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - -Copyright (c) 2013, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef SERVER_PATH_H -#define SERVER_PATH_H - -#include - -#include -#include - -typedef std::unordered_map ServerPaths; - -#endif // SERVER_PATH_H diff --git a/Library/OSRM_impl.cpp b/Library/OSRM_impl.cpp deleted file mode 100644 index aea85a44c..000000000 --- a/Library/OSRM_impl.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -namespace boost -{ -namespace interprocess -{ -class named_mutex; -} -} - -#include "osrm_impl.hpp" -#include "osrm.hpp" - -#include "../plugins/distance_table.hpp" -#include "../plugins/hello_world.hpp" -#include "../plugins/locate.hpp" -#include "../plugins/nearest.hpp" -#include "../plugins/timestamp.hpp" -#include "../plugins/viaroute.hpp" -#include "../server/data_structures/datafacade_base.hpp" -#include "../server/data_structures/internal_datafacade.hpp" -#include "../server/data_structures/shared_barriers.hpp" -#include "../server/data_structures/shared_datafacade.hpp" -#include "../util/make_unique.hpp" -#include "../util/routed_options.hpp" -#include "../util/simple_logger.hpp" - -#include -#include -#include - -#include - -#include -#include -#include -#include - -OSRM_impl::OSRM_impl(libosrm_config &lib_config) -{ - if (lib_config.use_shared_memory) - { - barrier = osrm::make_unique(); - query_data_facade = new SharedDataFacade(); - } - else - { - // populate base path - populate_base_path(lib_config.server_paths); - query_data_facade = new InternalDataFacade(lib_config.server_paths); - } - - // The following plugins handle all requests. - RegisterPlugin(new DistanceTablePlugin>( - query_data_facade, lib_config.max_locations_distance_table)); - RegisterPlugin(new HelloWorldPlugin()); - RegisterPlugin(new LocatePlugin>(query_data_facade)); - RegisterPlugin(new NearestPlugin>(query_data_facade)); - RegisterPlugin(new TimestampPlugin>(query_data_facade)); - RegisterPlugin(new ViaRoutePlugin>(query_data_facade)); -} - -OSRM_impl::~OSRM_impl() -{ - delete query_data_facade; - for (PluginMap::value_type &plugin_pointer : plugin_map) - { - delete plugin_pointer.second; - } -} - -void OSRM_impl::RegisterPlugin(BasePlugin *plugin) -{ - SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor(); - if (plugin_map.find(plugin->GetDescriptor()) != plugin_map.end()) - { - delete plugin_map.find(plugin->GetDescriptor())->second; - } - plugin_map.emplace(plugin->GetDescriptor(), plugin); -} - -int OSRM_impl::RunQuery(RouteParameters &route_parameters, JSON::Object &json_result) -{ - const auto &plugin_iterator = plugin_map.find(route_parameters.service); - - if (plugin_map.end() == plugin_iterator) - { - return 400; - } - - increase_concurrent_query_count(); - plugin_iterator->second->HandleRequest(route_parameters, json_result); - decrease_concurrent_query_count(); - return 200; -} - -// decrease number of concurrent queries -void OSRM_impl::decrease_concurrent_query_count() -{ - if (!barrier) - { - return; - } - // lock query - boost::interprocess::scoped_lock query_lock( - barrier->query_mutex); - - // decrement query count - --(barrier->number_of_queries); - BOOST_ASSERT_MSG(0 <= barrier->number_of_queries, "invalid number of queries"); - - // notify all processes that were waiting for this condition - if (0 == barrier->number_of_queries) - { - barrier->no_running_queries_condition.notify_all(); - } -} - -// increase number of concurrent queries -void OSRM_impl::increase_concurrent_query_count() -{ - if (!barrier) - { - return; - } - - // lock update pending - boost::interprocess::scoped_lock pending_lock( - barrier->pending_update_mutex); - - // lock query - boost::interprocess::scoped_lock query_lock( - barrier->query_mutex); - - // unlock update pending - pending_lock.unlock(); - - // increment query count - ++(barrier->number_of_queries); - - (static_cast *>(query_data_facade)) - ->CheckAndReloadFacade(); -} - -// proxy code for compilation firewall -OSRM::OSRM(libosrm_config &lib_config) : OSRM_pimpl_(osrm::make_unique(lib_config)) {} - -OSRM::~OSRM() { OSRM_pimpl_.reset(); } - -int OSRM::RunQuery(RouteParameters &route_parameters, JSON::Object &json_result) -{ - return OSRM_pimpl_->RunQuery(route_parameters, json_result); -} diff --git a/Server/Connection.cpp b/Server/Connection.cpp deleted file mode 100644 index 0f16f465f..000000000 --- a/Server/Connection.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "connection.hpp" -#include "request_handler.hpp" -#include "request_parser.hpp" - -#include -#include -#include -#include - -#include -#include - -namespace http -{ - -Connection::Connection(boost::asio::io_service &io_service, RequestHandler &handler) - : strand(io_service), TCP_socket(io_service), request_handler(handler) -{ -} - -boost::asio::ip::tcp::socket &Connection::socket() { return TCP_socket; } - -/// Start the first asynchronous operation for the connection. -void Connection::start() -{ - TCP_socket.async_read_some( - boost::asio::buffer(incoming_data_buffer), - strand.wrap(boost::bind(&Connection::handle_read, this->shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); -} - -void Connection::handle_read(const boost::system::error_code &error, std::size_t bytes_transferred) -{ - if (error) - { - return; - } - - // no error detected, let's parse the request - compression_type compression_type(no_compression); - osrm::tribool result; - std::tie(result, compression_type) = - RequestParser().parse(current_request, incoming_data_buffer.data(), - incoming_data_buffer.data() + bytes_transferred); - - // the request has been parsed - if (result == osrm::tribool::yes) - { - current_request.endpoint = TCP_socket.remote_endpoint().address(); - request_handler.handle_request(current_request, current_reply); - - // Header compression_header; - std::vector compressed_output; - std::vector output_buffer; - - // compress the result w/ gzip/deflate if requested - switch (compression_type) - { - case deflate_rfc1951: - // use deflate for compression - current_reply.headers.insert(current_reply.headers.begin(), - {"Content-Encoding", "deflate"}); - compressed_output = compress_buffers(current_reply.content, compression_type); - current_reply.set_size(static_cast(compressed_output.size())); - output_buffer = current_reply.headers_to_buffers(); - output_buffer.push_back(boost::asio::buffer(compressed_output)); - break; - case gzip_rfc1952: - // use gzip for compression - current_reply.headers.insert(current_reply.headers.begin(), - {"Content-Encoding", "gzip"}); - compressed_output = compress_buffers(current_reply.content, compression_type); - current_reply.set_size(static_cast(compressed_output.size())); - output_buffer = current_reply.headers_to_buffers(); - output_buffer.push_back(boost::asio::buffer(compressed_output)); - break; - case no_compression: - // don't use any compression - current_reply.set_uncompressed_size(); - output_buffer = current_reply.to_buffers(); - break; - } - // write result to stream - boost::asio::async_write( - TCP_socket, output_buffer, - strand.wrap(boost::bind(&Connection::handle_write, this->shared_from_this(), - boost::asio::placeholders::error))); - } - else if (result == osrm::tribool::no) - { // request is not parseable - current_reply = reply::stock_reply(reply::bad_request); - - boost::asio::async_write( - TCP_socket, current_reply.to_buffers(), - strand.wrap(boost::bind(&Connection::handle_write, this->shared_from_this(), - boost::asio::placeholders::error))); - } - else - { - // we don't have a result yet, so continue reading - TCP_socket.async_read_some( - boost::asio::buffer(incoming_data_buffer), - strand.wrap(boost::bind(&Connection::handle_read, this->shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); - } -} - -/// Handle completion of a write operation. -void Connection::handle_write(const boost::system::error_code &error) -{ - if (!error) - { - // Initiate graceful connection closure. - boost::system::error_code ignore_error; - TCP_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignore_error); - } -} - -std::vector Connection::compress_buffers(const std::vector &uncompressed_data, - const compression_type compression_type) -{ - boost::iostreams::gzip_params compression_parameters; - - // there's a trade-off between speed and size. speed wins - compression_parameters.level = boost::iostreams::zlib::best_speed; - // check which compression flavor is used - if (deflate_rfc1951 == compression_type) - { - compression_parameters.noheader = true; - } - - std::vector compressed_data; - // plug data into boost's compression stream - boost::iostreams::filtering_ostream gzip_stream; - gzip_stream.push(boost::iostreams::gzip_compressor(compression_parameters)); - gzip_stream.push(boost::iostreams::back_inserter(compressed_data)); - gzip_stream.write(&uncompressed_data[0], uncompressed_data.size()); - boost::iostreams::close(gzip_stream); - - return compressed_data; -} -} diff --git a/Server/Http/Reply.cpp b/Server/Http/Reply.cpp deleted file mode 100644 index 2642e2be2..000000000 --- a/Server/Http/Reply.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "reply.hpp" - -#include "../../util/cast.hpp" - -namespace http -{ - -const char ok_html[] = ""; -const char bad_request_html[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}"; -const char internal_server_error_html[] = - "{\"status\": 500,\"status_message\":\"Internal Server Error\"}"; -const char seperators[] = {':', ' '}; -const char crlf[] = {'\r', '\n'}; -const std::string http_ok_string = "HTTP/1.0 200 OK\r\n"; -const std::string http_bad_request_string = "HTTP/1.0 400 Bad Request\r\n"; -const std::string http_internal_server_error_string = "HTTP/1.0 500 Internal Server Error\r\n"; - -void reply::set_size(const std::size_t size) -{ - for (header &h : headers) - { - if ("Content-Length" == h.name) - { - h.value = cast::integral_to_string(size); - } - } -} - -void reply::set_uncompressed_size() { set_size(content.size()); } - -std::vector reply::to_buffers() -{ - std::vector buffers; - buffers.push_back(status_to_buffer(status)); - for (const header &h : headers) - { - buffers.push_back(boost::asio::buffer(h.name)); - buffers.push_back(boost::asio::buffer(seperators)); - buffers.push_back(boost::asio::buffer(h.value)); - buffers.push_back(boost::asio::buffer(crlf)); - } - buffers.push_back(boost::asio::buffer(crlf)); - buffers.push_back(boost::asio::buffer(content)); - return buffers; -} - -std::vector reply::headers_to_buffers() -{ - std::vector buffers; - buffers.push_back(status_to_buffer(status)); - for (const header ¤t_header : headers) - { - buffers.push_back(boost::asio::buffer(current_header.name)); - buffers.push_back(boost::asio::buffer(seperators)); - buffers.push_back(boost::asio::buffer(current_header.value)); - buffers.push_back(boost::asio::buffer(crlf)); - } - buffers.push_back(boost::asio::buffer(crlf)); - return buffers; -} - -reply reply::stock_reply(const reply::status_type status) -{ - reply reply; - reply.status = status; - reply.content.clear(); - - const std::string status_string = reply.status_to_string(status); - reply.content.insert(reply.content.end(), status_string.begin(), status_string.end()); - reply.headers.emplace_back("Access-Control-Allow-Origin", "*"); - reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size())); - reply.headers.emplace_back("Content-Type", "text/html"); - return reply; -} - -std::string reply::status_to_string(const reply::status_type status) -{ - if (reply::ok == status) - { - return ok_html; - } - if (reply::bad_request == status) - { - return bad_request_html; - } - return internal_server_error_html; -} - -boost::asio::const_buffer reply::status_to_buffer(const reply::status_type status) -{ - if (reply::ok == status) - { - return boost::asio::buffer(http_ok_string); - } - if (reply::internal_server_error == status) - { - return boost::asio::buffer(http_internal_server_error_string); - } - return boost::asio::buffer(http_bad_request_string); -} - -reply::reply() : status(ok) {} -} diff --git a/Server/data_structures/datafacade_base.hpp b/Server/data_structures/datafacade_base.hpp deleted file mode 100644 index 0dbeef4b6..000000000 --- a/Server/data_structures/datafacade_base.hpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef DATAFACADE_BASE_HPP -#define DATAFACADE_BASE_HPP - -// Exposes all data access interfaces to the algorithms via base class ptr - -#include "../../data_structures/edge_based_node.hpp" -#include "../../data_structures/external_memory_node.hpp" -#include "../../data_structures/phantom_node.hpp" -#include "../../data_structures/turn_instructions.hpp" -#include "../../util/integer_range.hpp" -#include "../../util/osrm_exception.hpp" -#include "../../util/string_util.hpp" -#include "../../typedefs.h" - -#include - -#include - -typedef osrm::range EdgeRange; - -template class BaseDataFacade -{ - public: - typedef EdgeBasedNode RTreeLeaf; - typedef EdgeDataT EdgeData; - BaseDataFacade() {} - virtual ~BaseDataFacade() {} - - // search graph access - virtual unsigned GetNumberOfNodes() const = 0; - - virtual unsigned GetNumberOfEdges() const = 0; - - virtual unsigned GetOutDegree(const NodeID n) const = 0; - - virtual NodeID GetTarget(const EdgeID e) const = 0; - - // virtual EdgeDataT &GetEdgeData(const EdgeID e) = 0; - - virtual const EdgeDataT &GetEdgeData(const EdgeID e) const = 0; - - virtual EdgeID BeginEdges(const NodeID n) const = 0; - - virtual EdgeID EndEdges(const NodeID n) const = 0; - - virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0; - - // searches for a specific edge - virtual EdgeID FindEdge(const NodeID from, const NodeID to) const = 0; - - virtual EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const = 0; - - virtual EdgeID - FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const = 0; - - // node and edge information access - virtual FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const = 0; - - virtual bool EdgeIsCompressed(const unsigned id) const = 0; - - virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const = 0; - - virtual void GetUncompressedGeometry(const unsigned id, - std::vector &result_nodes) const = 0; - - virtual TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const = 0; - - virtual TravelMode GetTravelModeForEdgeID(const unsigned id) const = 0; - - virtual bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate, - FixedPointCoordinate &result, - const unsigned zoom_level = 18) = 0; - - virtual bool - IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, - std::vector &resulting_phantom_node_vector, - const unsigned number_of_results) = 0; - - virtual bool - IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, - PhantomNode &resulting_phantom_node) = 0; - - virtual unsigned GetCheckSum() const = 0; - - virtual unsigned GetNameIndexFromEdgeID(const unsigned id) const = 0; - - virtual void GetName(const unsigned name_id, std::string &result) const = 0; - - std::string GetEscapedNameForNameID(const unsigned name_id) const - { - std::string temporary_string; - GetName(name_id, temporary_string); - return EscapeJSONString(temporary_string); - } - - virtual std::string GetTimestamp() const = 0; -}; - -#endif // DATAFACADE_BASE_HPP diff --git a/Server/data_structures/internal_datafacade.hpp b/Server/data_structures/internal_datafacade.hpp deleted file mode 100644 index 0a246b791..000000000 --- a/Server/data_structures/internal_datafacade.hpp +++ /dev/null @@ -1,457 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef INTERNAL_DATAFACADE_HPP -#define INTERNAL_DATAFACADE_HPP - -// implements all data storage when shared memory is _NOT_ used - -#include "datafacade_base.hpp" - -#include "../../data_structures/original_edge_data.hpp" -#include "../../data_structures/query_node.hpp" -#include "../../data_structures/query_edge.hpp" -#include "../../data_structures/shared_memory_vector_wrapper.hpp" -#include "../../data_structures/static_graph.hpp" -#include "../../data_structures/static_rtree.hpp" -#include "../../data_structures/range_table.hpp" -#include "../../util/boost_filesystem_2_fix.hpp" -#include "../../util/graph_loader.hpp" -#include "../../util/simple_logger.hpp" - -#include -#include - -template class InternalDataFacade final : public BaseDataFacade -{ - - private: - typedef BaseDataFacade super; - typedef StaticGraph QueryGraph; - typedef typename QueryGraph::InputEdge InputEdge; - typedef typename super::RTreeLeaf RTreeLeaf; - - InternalDataFacade() {} - - unsigned m_check_sum; - unsigned m_number_of_nodes; - QueryGraph *m_query_graph; - std::string m_timestamp; - - std::shared_ptr::vector> m_coordinate_list; - ShM::vector m_via_node_list; - ShM::vector m_name_ID_list; - ShM::vector m_turn_instruction_list; - ShM::vector m_travel_mode_list; - ShM::vector m_names_char_list; - ShM::vector m_edge_is_compressed; - ShM::vector m_geometry_indices; - ShM::vector m_geometry_list; - - boost::thread_specific_ptr< - StaticRTree::vector, false>> m_static_rtree; - boost::filesystem::path ram_index_path; - boost::filesystem::path file_index_path; - RangeTable<16, false> m_name_table; - - void LoadTimestamp(const boost::filesystem::path ×tamp_path) - { - if (boost::filesystem::exists(timestamp_path)) - { - SimpleLogger().Write() << "Loading Timestamp"; - boost::filesystem::ifstream timestamp_stream(timestamp_path); - if (!timestamp_stream) - { - SimpleLogger().Write(logWARNING) << timestamp_path << " not found"; - } - getline(timestamp_stream, m_timestamp); - timestamp_stream.close(); - } - if (m_timestamp.empty()) - { - m_timestamp = "n/a"; - } - if (25 < m_timestamp.length()) - { - m_timestamp.resize(25); - } - } - - void LoadGraph(const boost::filesystem::path &hsgr_path) - { - typename ShM::vector node_list; - typename ShM::vector edge_list; - - SimpleLogger().Write() << "loading graph from " << hsgr_path.string(); - - m_number_of_nodes = readHSGRFromStream(hsgr_path, node_list, edge_list, &m_check_sum); - - BOOST_ASSERT_MSG(0 != node_list.size(), "node list empty"); - // BOOST_ASSERT_MSG(0 != edge_list.size(), "edge list empty"); - SimpleLogger().Write() << "loaded " << node_list.size() << " nodes and " << edge_list.size() - << " edges"; - m_query_graph = new QueryGraph(node_list, edge_list); - - BOOST_ASSERT_MSG(0 == node_list.size(), "node list not flushed"); - BOOST_ASSERT_MSG(0 == edge_list.size(), "edge list not flushed"); - SimpleLogger().Write() << "Data checksum is " << m_check_sum; - } - - void LoadNodeAndEdgeInformation(const boost::filesystem::path &nodes_file, - const boost::filesystem::path &edges_file) - { - boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary); - - QueryNode current_node; - unsigned number_of_coordinates = 0; - nodes_input_stream.read((char *)&number_of_coordinates, sizeof(unsigned)); - m_coordinate_list = - std::make_shared>(number_of_coordinates); - for (unsigned i = 0; i < number_of_coordinates; ++i) - { - nodes_input_stream.read((char *)¤t_node, sizeof(QueryNode)); - m_coordinate_list->at(i) = FixedPointCoordinate(current_node.lat, current_node.lon); - BOOST_ASSERT((std::abs(m_coordinate_list->at(i).lat) >> 30) == 0); - BOOST_ASSERT((std::abs(m_coordinate_list->at(i).lon) >> 30) == 0); - } - nodes_input_stream.close(); - - boost::filesystem::ifstream edges_input_stream(edges_file, std::ios::binary); - unsigned number_of_edges = 0; - edges_input_stream.read((char *)&number_of_edges, sizeof(unsigned)); - m_via_node_list.resize(number_of_edges); - m_name_ID_list.resize(number_of_edges); - m_turn_instruction_list.resize(number_of_edges); - m_travel_mode_list.resize(number_of_edges); - m_edge_is_compressed.resize(number_of_edges); - - unsigned compressed = 0; - - OriginalEdgeData current_edge_data; - for (unsigned i = 0; i < number_of_edges; ++i) - { - edges_input_stream.read((char *)&(current_edge_data), sizeof(OriginalEdgeData)); - m_via_node_list[i] = current_edge_data.via_node; - m_name_ID_list[i] = current_edge_data.name_id; - m_turn_instruction_list[i] = current_edge_data.turn_instruction; - m_travel_mode_list[i] = current_edge_data.travel_mode; - m_edge_is_compressed[i] = current_edge_data.compressed_geometry; - if (m_edge_is_compressed[i]) - { - ++compressed; - } - } - - edges_input_stream.close(); - } - - void LoadGeometries(const boost::filesystem::path &geometry_file) - { - std::ifstream geometry_stream(geometry_file.string().c_str(), std::ios::binary); - unsigned number_of_indices = 0; - unsigned number_of_compressed_geometries = 0; - - geometry_stream.read((char *)&number_of_indices, sizeof(unsigned)); - - m_geometry_indices.resize(number_of_indices); - if (number_of_indices > 0) - { - geometry_stream.read((char *)&(m_geometry_indices[0]), - number_of_indices * sizeof(unsigned)); - } - - geometry_stream.read((char *)&number_of_compressed_geometries, sizeof(unsigned)); - - BOOST_ASSERT(m_geometry_indices.back() == number_of_compressed_geometries); - m_geometry_list.resize(number_of_compressed_geometries); - - if (number_of_compressed_geometries > 0) - { - geometry_stream.read((char *)&(m_geometry_list[0]), - number_of_compressed_geometries * sizeof(unsigned)); - } - geometry_stream.close(); - } - - void LoadRTree() - { - BOOST_ASSERT_MSG(!m_coordinate_list->empty(), "coordinates must be loaded before r-tree"); - - m_static_rtree.reset( - new StaticRTree(ram_index_path, file_index_path, m_coordinate_list)); - } - - void LoadStreetNames(const boost::filesystem::path &names_file) - { - boost::filesystem::ifstream name_stream(names_file, std::ios::binary); - - name_stream >> m_name_table; - - unsigned number_of_chars = 0; - name_stream.read((char *)&number_of_chars, sizeof(unsigned)); - BOOST_ASSERT_MSG(0 != number_of_chars, "name file broken"); - m_names_char_list.resize(number_of_chars + 1); //+1 gives sentinel element - name_stream.read((char *)&m_names_char_list[0], number_of_chars * sizeof(char)); - if (0 == m_names_char_list.size()) - { - SimpleLogger().Write(logWARNING) << "list of street names is empty"; - } - name_stream.close(); - } - - public: - virtual ~InternalDataFacade() - { - delete m_query_graph; - m_static_rtree.reset(); - } - - explicit InternalDataFacade(const ServerPaths &server_paths) - { - // generate paths of data files - if (server_paths.find("hsgrdata") == server_paths.end()) - { - throw osrm::exception("no hsgr file given in ini file"); - } - if (server_paths.find("ramindex") == server_paths.end()) - { - throw osrm::exception("no ram index file given in ini file"); - } - if (server_paths.find("fileindex") == server_paths.end()) - { - throw osrm::exception("no leaf index file given in ini file"); - } - if (server_paths.find("geometries") == server_paths.end()) - { - throw osrm::exception("no geometries file given in ini file"); - } - if (server_paths.find("nodesdata") == server_paths.end()) - { - throw osrm::exception("no nodes file given in ini file"); - } - if (server_paths.find("edgesdata") == server_paths.end()) - { - throw osrm::exception("no edges file given in ini file"); - } - if (server_paths.find("namesdata") == server_paths.end()) - { - throw osrm::exception("no names file given in ini file"); - } - - ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata"); - BOOST_ASSERT(server_paths.end() != paths_iterator); - const boost::filesystem::path &hsgr_path = paths_iterator->second; - paths_iterator = server_paths.find("timestamp"); - BOOST_ASSERT(server_paths.end() != paths_iterator); - const boost::filesystem::path ×tamp_path = paths_iterator->second; - paths_iterator = server_paths.find("ramindex"); - BOOST_ASSERT(server_paths.end() != paths_iterator); - ram_index_path = paths_iterator->second; - paths_iterator = server_paths.find("fileindex"); - BOOST_ASSERT(server_paths.end() != paths_iterator); - file_index_path = paths_iterator->second; - paths_iterator = server_paths.find("nodesdata"); - BOOST_ASSERT(server_paths.end() != paths_iterator); - const boost::filesystem::path &nodes_data_path = paths_iterator->second; - paths_iterator = server_paths.find("edgesdata"); - BOOST_ASSERT(server_paths.end() != paths_iterator); - const boost::filesystem::path &edges_data_path = paths_iterator->second; - paths_iterator = server_paths.find("namesdata"); - BOOST_ASSERT(server_paths.end() != paths_iterator); - const boost::filesystem::path &names_data_path = paths_iterator->second; - paths_iterator = server_paths.find("geometries"); - BOOST_ASSERT(server_paths.end() != paths_iterator); - const boost::filesystem::path &geometries_path = paths_iterator->second; - - // load data - SimpleLogger().Write() << "loading graph data"; - AssertPathExists(hsgr_path); - LoadGraph(hsgr_path); - SimpleLogger().Write() << "loading edge information"; - AssertPathExists(nodes_data_path); - AssertPathExists(edges_data_path); - LoadNodeAndEdgeInformation(nodes_data_path, edges_data_path); - SimpleLogger().Write() << "loading geometries"; - AssertPathExists(geometries_path); - LoadGeometries(geometries_path); - SimpleLogger().Write() << "loading r-tree"; - AssertPathExists(ram_index_path); - AssertPathExists(file_index_path); - SimpleLogger().Write() << "loading timestamp"; - LoadTimestamp(timestamp_path); - SimpleLogger().Write() << "loading street names"; - AssertPathExists(names_data_path); - LoadStreetNames(names_data_path); - } - - // search graph access - unsigned GetNumberOfNodes() const override final { return m_query_graph->GetNumberOfNodes(); } - - unsigned GetNumberOfEdges() const override final { return m_query_graph->GetNumberOfEdges(); } - - unsigned GetOutDegree(const NodeID n) const override final - { - return m_query_graph->GetOutDegree(n); - } - - NodeID GetTarget(const EdgeID e) const override final { return m_query_graph->GetTarget(e); } - - // EdgeDataT &GetEdgeData(const EdgeID e) override final { return m_query_graph->GetEdgeData(e); - // } - - EdgeDataT &GetEdgeData(const EdgeID e) const override final - { - return m_query_graph->GetEdgeData(e); - } - - EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph->BeginEdges(n); } - - EdgeID EndEdges(const NodeID n) const override final { return m_query_graph->EndEdges(n); } - - EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final - { - return m_query_graph->GetAdjacentEdgeRange(node); - }; - - // searches for a specific edge - EdgeID FindEdge(const NodeID from, const NodeID to) const override final - { - return m_query_graph->FindEdge(from, to); - } - - EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const override final - { - return m_query_graph->FindEdgeInEitherDirection(from, to); - } - - EdgeID - FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const override final - { - return m_query_graph->FindEdgeIndicateIfReverse(from, to, result); - } - - // node and edge information access - FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const override final - { - return m_coordinate_list->at(id); - }; - - bool EdgeIsCompressed(const unsigned id) const { return m_edge_is_compressed.at(id); } - - TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const override final - { - return m_turn_instruction_list.at(id); - } - - TravelMode GetTravelModeForEdgeID(const unsigned id) const { return m_travel_mode_list.at(id); } - - bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate, - FixedPointCoordinate &result, - const unsigned zoom_level = 18) override final - { - if (!m_static_rtree.get()) - { - LoadRTree(); - } - - return m_static_rtree->LocateClosestEndPointForCoordinate(input_coordinate, result, - zoom_level); - } - - bool IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, - PhantomNode &resulting_phantom_node) override final - { - std::vector resulting_phantom_node_vector; - auto result = IncrementalFindPhantomNodeForCoordinate(input_coordinate, - resulting_phantom_node_vector, 1); - if (result) - { - BOOST_ASSERT(!resulting_phantom_node_vector.empty()); - resulting_phantom_node = resulting_phantom_node_vector.front(); - } - return result; - } - - bool - IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, - std::vector &resulting_phantom_node_vector, - const unsigned number_of_results) override final - { - if (!m_static_rtree.get()) - { - LoadRTree(); - } - - return m_static_rtree->IncrementalFindPhantomNodeForCoordinate( - input_coordinate, resulting_phantom_node_vector, number_of_results); - } - - unsigned GetCheckSum() const override final { return m_check_sum; } - - unsigned GetNameIndexFromEdgeID(const unsigned id) const override final - { - return m_name_ID_list.at(id); - }; - - void GetName(const unsigned name_id, std::string &result) const override final - { - if (UINT_MAX == name_id) - { - result = ""; - return; - } - auto range = m_name_table.GetRange(name_id); - - result.clear(); - if (range.begin() != range.end()) - { - result.resize(range.back() - range.front() + 1); - std::copy(m_names_char_list.begin() + range.front(), - m_names_char_list.begin() + range.back() + 1, result.begin()); - } - } - - virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const override final - { - return m_via_node_list.at(id); - } - - virtual void GetUncompressedGeometry(const unsigned id, - std::vector &result_nodes) const override final - { - const unsigned begin = m_geometry_indices.at(id); - const unsigned end = m_geometry_indices.at(id + 1); - - result_nodes.clear(); - result_nodes.insert(result_nodes.begin(), m_geometry_list.begin() + begin, - m_geometry_list.begin() + end); - } - - std::string GetTimestamp() const override final { return m_timestamp; } -}; - -#endif // INTERNAL_DATAFACADE_HPP diff --git a/Server/data_structures/shared_barriers.hpp b/Server/data_structures/shared_barriers.hpp deleted file mode 100644 index 2d7de7e74..000000000 --- a/Server/data_structures/shared_barriers.hpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef SHARED_BARRIERS_HPP -#define SHARED_BARRIERS_HPP - -#include -#include - -struct SharedBarriers -{ - - SharedBarriers() - : pending_update_mutex(boost::interprocess::open_or_create, "pending_update"), - update_mutex(boost::interprocess::open_or_create, "update"), - query_mutex(boost::interprocess::open_or_create, "query"), - no_running_queries_condition(boost::interprocess::open_or_create, "no_running_queries"), - update_ongoing(false), number_of_queries(0) - { - } - - // Mutex to protect access to the boolean variable - boost::interprocess::named_mutex pending_update_mutex; - boost::interprocess::named_mutex update_mutex; - boost::interprocess::named_mutex query_mutex; - - // Condition that no update is running - boost::interprocess::named_condition no_running_queries_condition; - - // Is there an ongoing update? - bool update_ongoing; - // Is there any query? - int number_of_queries; -}; - -#endif // SHARED_BARRIERS_HPP diff --git a/Server/data_structures/shared_datafacade.hpp b/Server/data_structures/shared_datafacade.hpp deleted file mode 100644 index c7951fb3b..000000000 --- a/Server/data_structures/shared_datafacade.hpp +++ /dev/null @@ -1,430 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef SHARED_DATAFACADE_HPP -#define SHARED_DATAFACADE_HPP - -// implements all data storage when shared memory _IS_ used - -#include "datafacade_base.hpp" -#include "shared_datatype.hpp" - -#include "../../data_structures/range_table.hpp" -#include "../../data_structures/static_graph.hpp" -#include "../../data_structures/static_rtree.hpp" -#include "../../util/boost_filesystem_2_fix.hpp" -#include "../../util/make_unique.hpp" -#include "../../util/simple_logger.hpp" - -#include -#include - -template class SharedDataFacade final : public BaseDataFacade -{ - - private: - typedef EdgeDataT EdgeData; - typedef BaseDataFacade super; - typedef StaticGraph QueryGraph; - typedef typename StaticGraph::NodeArrayEntry GraphNode; - typedef typename StaticGraph::EdgeArrayEntry GraphEdge; - typedef typename RangeTable<16, true>::BlockT NameIndexBlock; - typedef typename QueryGraph::InputEdge InputEdge; - typedef typename super::RTreeLeaf RTreeLeaf; - using SharedRTree = StaticRTree::vector, true>; - using TimeStampedRTreePair = std::pair>; - using RTreeNode = typename SharedRTree::TreeNode; - - SharedDataLayout *data_layout; - char *shared_memory; - SharedDataTimestamp *data_timestamp_ptr; - - SharedDataType CURRENT_LAYOUT; - SharedDataType CURRENT_DATA; - unsigned CURRENT_TIMESTAMP; - - unsigned m_check_sum; - std::unique_ptr m_query_graph; - std::unique_ptr m_layout_memory; - std::unique_ptr m_large_memory; - std::string m_timestamp; - - std::shared_ptr::vector> m_coordinate_list; - ShM::vector m_via_node_list; - ShM::vector m_name_ID_list; - ShM::vector m_turn_instruction_list; - ShM::vector m_travel_mode_list; - ShM::vector m_names_char_list; - ShM::vector m_name_begin_indices; - ShM::vector m_edge_is_compressed; - ShM::vector m_geometry_indices; - ShM::vector m_geometry_list; - - boost::thread_specific_ptr>> m_static_rtree; - boost::filesystem::path file_index_path; - - std::shared_ptr> m_name_table; - - void LoadChecksum() - { - m_check_sum = - *data_layout->GetBlockPtr(shared_memory, SharedDataLayout::HSGR_CHECKSUM); - SimpleLogger().Write() << "set checksum: " << m_check_sum; - } - - void LoadTimestamp() - { - char *timestamp_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::TIMESTAMP); - m_timestamp.resize(data_layout->GetBlockSize(SharedDataLayout::TIMESTAMP)); - std::copy(timestamp_ptr, - timestamp_ptr + data_layout->GetBlockSize(SharedDataLayout::TIMESTAMP), - m_timestamp.begin()); - } - - void LoadRTree() - { - BOOST_ASSERT_MSG(!m_coordinate_list->empty(), "coordinates must be loaded before r-tree"); - - RTreeNode *tree_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::R_SEARCH_TREE); - m_static_rtree.reset(new TimeStampedRTreePair( - CURRENT_TIMESTAMP, - osrm::make_unique( - tree_ptr, data_layout->num_entries[SharedDataLayout::R_SEARCH_TREE], - file_index_path, m_coordinate_list))); - } - - void LoadGraph() - { - GraphNode *graph_nodes_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::GRAPH_NODE_LIST); - - GraphEdge *graph_edges_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::GRAPH_EDGE_LIST); - - typename ShM::vector node_list( - graph_nodes_ptr, data_layout->num_entries[SharedDataLayout::GRAPH_NODE_LIST]); - typename ShM::vector edge_list( - graph_edges_ptr, data_layout->num_entries[SharedDataLayout::GRAPH_EDGE_LIST]); - m_query_graph.reset(new QueryGraph(node_list, edge_list)); - } - - void LoadNodeAndEdgeInformation() - { - - FixedPointCoordinate *coordinate_list_ptr = data_layout->GetBlockPtr( - shared_memory, SharedDataLayout::COORDINATE_LIST); - m_coordinate_list = osrm::make_unique::vector>( - coordinate_list_ptr, data_layout->num_entries[SharedDataLayout::COORDINATE_LIST]); - - TravelMode *travel_mode_list_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::TRAVEL_MODE); - typename ShM::vector travel_mode_list( - travel_mode_list_ptr, data_layout->num_entries[SharedDataLayout::TRAVEL_MODE]); - m_travel_mode_list.swap(travel_mode_list); - - TurnInstruction *turn_instruction_list_ptr = data_layout->GetBlockPtr( - shared_memory, SharedDataLayout::TURN_INSTRUCTION); - typename ShM::vector turn_instruction_list( - turn_instruction_list_ptr, - data_layout->num_entries[SharedDataLayout::TURN_INSTRUCTION]); - m_turn_instruction_list.swap(turn_instruction_list); - - unsigned *name_id_list_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::NAME_ID_LIST); - typename ShM::vector name_id_list( - name_id_list_ptr, data_layout->num_entries[SharedDataLayout::NAME_ID_LIST]); - m_name_ID_list.swap(name_id_list); - } - - void LoadViaNodeList() - { - NodeID *via_node_list_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::VIA_NODE_LIST); - typename ShM::vector via_node_list( - via_node_list_ptr, data_layout->num_entries[SharedDataLayout::VIA_NODE_LIST]); - m_via_node_list.swap(via_node_list); - } - - void LoadNames() - { - unsigned *offsets_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::NAME_OFFSETS); - NameIndexBlock *blocks_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::NAME_BLOCKS); - typename ShM::vector name_offsets( - offsets_ptr, data_layout->num_entries[SharedDataLayout::NAME_OFFSETS]); - typename ShM::vector name_blocks( - blocks_ptr, data_layout->num_entries[SharedDataLayout::NAME_BLOCKS]); - - char *names_list_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::NAME_CHAR_LIST); - typename ShM::vector names_char_list( - names_list_ptr, data_layout->num_entries[SharedDataLayout::NAME_CHAR_LIST]); - m_name_table = osrm::make_unique>( - name_offsets, name_blocks, static_cast(names_char_list.size())); - - m_names_char_list.swap(names_char_list); - } - - void LoadGeometries() - { - unsigned *geometries_compressed_ptr = data_layout->GetBlockPtr( - shared_memory, SharedDataLayout::GEOMETRIES_INDICATORS); - typename ShM::vector edge_is_compressed( - geometries_compressed_ptr, - data_layout->num_entries[SharedDataLayout::GEOMETRIES_INDICATORS]); - m_edge_is_compressed.swap(edge_is_compressed); - - unsigned *geometries_index_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::GEOMETRIES_INDEX); - typename ShM::vector geometry_begin_indices( - geometries_index_ptr, data_layout->num_entries[SharedDataLayout::GEOMETRIES_INDEX]); - m_geometry_indices.swap(geometry_begin_indices); - - unsigned *geometries_list_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::GEOMETRIES_LIST); - typename ShM::vector geometry_list( - geometries_list_ptr, data_layout->num_entries[SharedDataLayout::GEOMETRIES_LIST]); - m_geometry_list.swap(geometry_list); - } - - public: - virtual ~SharedDataFacade() {} - - SharedDataFacade() - { - data_timestamp_ptr = (SharedDataTimestamp *)SharedMemoryFactory::Get( - CURRENT_REGIONS, sizeof(SharedDataTimestamp), false, false)->Ptr(); - CURRENT_LAYOUT = LAYOUT_NONE; - CURRENT_DATA = DATA_NONE; - CURRENT_TIMESTAMP = 0; - - // load data - CheckAndReloadFacade(); - } - - void CheckAndReloadFacade() - { - if (CURRENT_LAYOUT != data_timestamp_ptr->layout || - CURRENT_DATA != data_timestamp_ptr->data || - CURRENT_TIMESTAMP != data_timestamp_ptr->timestamp) - { - // release the previous shared memory segments - SharedMemory::Remove(CURRENT_LAYOUT); - SharedMemory::Remove(CURRENT_DATA); - - CURRENT_LAYOUT = data_timestamp_ptr->layout; - CURRENT_DATA = data_timestamp_ptr->data; - CURRENT_TIMESTAMP = data_timestamp_ptr->timestamp; - - m_layout_memory.reset(SharedMemoryFactory::Get(CURRENT_LAYOUT)); - - data_layout = (SharedDataLayout *)(m_layout_memory->Ptr()); - - m_large_memory.reset(SharedMemoryFactory::Get(CURRENT_DATA)); - shared_memory = (char *)(m_large_memory->Ptr()); - - const char *file_index_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::FILE_INDEX_PATH); - file_index_path = boost::filesystem::path(file_index_ptr); - if (!boost::filesystem::exists(file_index_path)) - { - SimpleLogger().Write(logDEBUG) << "Leaf file name " << file_index_path.string(); - throw osrm::exception("Could not load leaf index file." - "Is any data loaded into shared memory?"); - } - - LoadGraph(); - LoadChecksum(); - LoadNodeAndEdgeInformation(); - LoadGeometries(); - LoadTimestamp(); - LoadViaNodeList(); - LoadNames(); - - data_layout->PrintInformation(); - - SimpleLogger().Write() << "number of geometries: " << m_coordinate_list->size(); - for (unsigned i = 0; i < m_coordinate_list->size(); ++i) - { - if (!GetCoordinateOfNode(i).is_valid()) - { - SimpleLogger().Write() << "coordinate " << i << " not valid"; - } - } - } - } - - // search graph access - unsigned GetNumberOfNodes() const override final { return m_query_graph->GetNumberOfNodes(); } - - unsigned GetNumberOfEdges() const override final { return m_query_graph->GetNumberOfEdges(); } - - unsigned GetOutDegree(const NodeID n) const override final - { - return m_query_graph->GetOutDegree(n); - } - - NodeID GetTarget(const EdgeID e) const override final { return m_query_graph->GetTarget(e); } - - EdgeDataT &GetEdgeData(const EdgeID e) const override final - { - return m_query_graph->GetEdgeData(e); - } - - EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph->BeginEdges(n); } - - EdgeID EndEdges(const NodeID n) const override final { return m_query_graph->EndEdges(n); } - - EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final - { - return m_query_graph->GetAdjacentEdgeRange(node); - }; - - // searches for a specific edge - EdgeID FindEdge(const NodeID from, const NodeID to) const override final - { - return m_query_graph->FindEdge(from, to); - } - - EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const override final - { - return m_query_graph->FindEdgeInEitherDirection(from, to); - } - - EdgeID - FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const override final - { - return m_query_graph->FindEdgeIndicateIfReverse(from, to, result); - } - - // node and edge information access - FixedPointCoordinate GetCoordinateOfNode(const NodeID id) const override final - { - return m_coordinate_list->at(id); - }; - - virtual bool EdgeIsCompressed(const unsigned id) const override final - { - return m_edge_is_compressed.at(id); - } - - virtual void GetUncompressedGeometry(const unsigned id, - std::vector &result_nodes) const override final - { - const unsigned begin = m_geometry_indices.at(id); - const unsigned end = m_geometry_indices.at(id + 1); - - result_nodes.clear(); - result_nodes.insert(result_nodes.begin(), m_geometry_list.begin() + begin, - m_geometry_list.begin() + end); - } - - virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const override final - { - return m_via_node_list.at(id); - } - - TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const override final - { - return m_turn_instruction_list.at(id); - } - - TravelMode GetTravelModeForEdgeID(const unsigned id) const { return m_travel_mode_list.at(id); } - - bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate, - FixedPointCoordinate &result, - const unsigned zoom_level = 18) override final - { - if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first) - { - LoadRTree(); - } - - return m_static_rtree->second->LocateClosestEndPointForCoordinate(input_coordinate, result, - zoom_level); - } - - bool IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, - PhantomNode &resulting_phantom_node) override final - { - std::vector resulting_phantom_node_vector; - auto result = IncrementalFindPhantomNodeForCoordinate(input_coordinate, - resulting_phantom_node_vector, 1); - if (result) - { - BOOST_ASSERT(!resulting_phantom_node_vector.empty()); - resulting_phantom_node = resulting_phantom_node_vector.front(); - } - return result; - } - - bool - IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, - std::vector &resulting_phantom_node_vector, - const unsigned number_of_results) override final - { - if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first) - { - LoadRTree(); - } - - return m_static_rtree->second->IncrementalFindPhantomNodeForCoordinate( - input_coordinate, resulting_phantom_node_vector, number_of_results); - } - - unsigned GetCheckSum() const override final { return m_check_sum; } - - unsigned GetNameIndexFromEdgeID(const unsigned id) const override final - { - return m_name_ID_list.at(id); - }; - - void GetName(const unsigned name_id, std::string &result) const override final - { - if (UINT_MAX == name_id) - { - result = ""; - return; - } - auto range = m_name_table->GetRange(name_id); - - result.clear(); - if (range.begin() != range.end()) - { - result.resize(range.back() - range.front() + 1); - std::copy(m_names_char_list.begin() + range.front(), - m_names_char_list.begin() + range.back() + 1, result.begin()); - } - } - - std::string GetTimestamp() const override final { return m_timestamp; } -}; - -#endif // SHARED_DATAFACADE_HPP diff --git a/Server/data_structures/shared_datatype.hpp b/Server/data_structures/shared_datatype.hpp deleted file mode 100644 index 0c0b23910..000000000 --- a/Server/data_structures/shared_datatype.hpp +++ /dev/null @@ -1,227 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef SHARED_DATA_TYPE_HPP -#define SHARED_DATA_TYPE_HPP - -#include "../../util/osrm_exception.hpp" -#include "../../util/simple_logger.hpp" - -#include - -#include - -namespace -{ -// Added at the start and end of each block as sanity check -constexpr static const char CANARY[] = "OSRM"; -} - -struct SharedDataLayout -{ - enum BlockID - { - NAME_OFFSETS = 0, - NAME_BLOCKS, - NAME_CHAR_LIST, - NAME_ID_LIST, - VIA_NODE_LIST, - GRAPH_NODE_LIST, - GRAPH_EDGE_LIST, - COORDINATE_LIST, - TURN_INSTRUCTION, - TRAVEL_MODE, - R_SEARCH_TREE, - GEOMETRIES_INDEX, - GEOMETRIES_LIST, - GEOMETRIES_INDICATORS, - HSGR_CHECKSUM, - TIMESTAMP, - FILE_INDEX_PATH, - NUM_BLOCKS - }; - - std::array num_entries; - std::array entry_size; - - SharedDataLayout() : num_entries(), entry_size() {} - - void PrintInformation() const - { - SimpleLogger().Write(logDEBUG) << "-"; - SimpleLogger().Write(logDEBUG) - << "name_offsets_size: " << num_entries[NAME_OFFSETS]; - SimpleLogger().Write(logDEBUG) - << "name_blocks_size: " << num_entries[NAME_BLOCKS]; - SimpleLogger().Write(logDEBUG) - << "name_char_list_size: " << num_entries[NAME_CHAR_LIST]; - SimpleLogger().Write(logDEBUG) - << "name_id_list_size: " << num_entries[NAME_ID_LIST]; - SimpleLogger().Write(logDEBUG) - << "via_node_list_size: " << num_entries[VIA_NODE_LIST]; - SimpleLogger().Write(logDEBUG) - << "graph_node_list_size: " << num_entries[GRAPH_NODE_LIST]; - SimpleLogger().Write(logDEBUG) - << "graph_edge_list_size: " << num_entries[GRAPH_EDGE_LIST]; - SimpleLogger().Write(logDEBUG) << "timestamp_length: " << num_entries[TIMESTAMP]; - SimpleLogger().Write(logDEBUG) - << "coordinate_list_size: " << num_entries[COORDINATE_LIST]; - SimpleLogger().Write(logDEBUG) - << "turn_instruction_list_size: " << num_entries[TURN_INSTRUCTION]; - SimpleLogger().Write(logDEBUG) - << "travel_mode_list_size: " << num_entries[TRAVEL_MODE]; - SimpleLogger().Write(logDEBUG) - << "r_search_tree_size: " << num_entries[R_SEARCH_TREE]; - SimpleLogger().Write(logDEBUG) - << "geometries_indicators: " << num_entries[GEOMETRIES_INDICATORS] << "/" - << ((num_entries[GEOMETRIES_INDICATORS] / 8) + 1); - SimpleLogger().Write(logDEBUG) - << "geometries_index_list_size: " << num_entries[GEOMETRIES_INDEX]; - SimpleLogger().Write(logDEBUG) - << "geometries_list_size: " << num_entries[GEOMETRIES_LIST]; - SimpleLogger().Write(logDEBUG) - << "sizeof(checksum): " << entry_size[HSGR_CHECKSUM]; - - SimpleLogger().Write(logDEBUG) << "NAME_OFFSETS " - << ": " << GetBlockSize(NAME_OFFSETS); - SimpleLogger().Write(logDEBUG) << "NAME_BLOCKS " - << ": " << GetBlockSize(NAME_BLOCKS); - SimpleLogger().Write(logDEBUG) << "NAME_CHAR_LIST " - << ": " << GetBlockSize(NAME_CHAR_LIST); - SimpleLogger().Write(logDEBUG) << "NAME_ID_LIST " - << ": " << GetBlockSize(NAME_ID_LIST); - SimpleLogger().Write(logDEBUG) << "VIA_NODE_LIST " - << ": " << GetBlockSize(VIA_NODE_LIST); - SimpleLogger().Write(logDEBUG) << "GRAPH_NODE_LIST " - << ": " << GetBlockSize(GRAPH_NODE_LIST); - SimpleLogger().Write(logDEBUG) << "GRAPH_EDGE_LIST " - << ": " << GetBlockSize(GRAPH_EDGE_LIST); - SimpleLogger().Write(logDEBUG) << "COORDINATE_LIST " - << ": " << GetBlockSize(COORDINATE_LIST); - SimpleLogger().Write(logDEBUG) << "TURN_INSTRUCTION " - << ": " << GetBlockSize(TURN_INSTRUCTION); - SimpleLogger().Write(logDEBUG) << "TRAVEL_MODE " - << ": " << GetBlockSize(TRAVEL_MODE); - SimpleLogger().Write(logDEBUG) << "R_SEARCH_TREE " - << ": " << GetBlockSize(R_SEARCH_TREE); - SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDEX " - << ": " << GetBlockSize(GEOMETRIES_INDEX); - SimpleLogger().Write(logDEBUG) << "GEOMETRIES_LIST " - << ": " << GetBlockSize(GEOMETRIES_LIST); - SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDICATORS" - << ": " << GetBlockSize(GEOMETRIES_INDICATORS); - SimpleLogger().Write(logDEBUG) << "HSGR_CHECKSUM " - << ": " << GetBlockSize(HSGR_CHECKSUM); - SimpleLogger().Write(logDEBUG) << "TIMESTAMP " - << ": " << GetBlockSize(TIMESTAMP); - SimpleLogger().Write(logDEBUG) << "FILE_INDEX_PATH " - << ": " << GetBlockSize(FILE_INDEX_PATH); - } - - template inline void SetBlockSize(BlockID bid, uint64_t entries) - { - num_entries[bid] = entries; - entry_size[bid] = sizeof(T); - } - - inline uint64_t GetBlockSize(BlockID bid) const - { - // special encoding - if (bid == GEOMETRIES_INDICATORS) - { - return (num_entries[GEOMETRIES_INDICATORS] / 32 + 1) * - entry_size[GEOMETRIES_INDICATORS]; - } - - return num_entries[bid] * entry_size[bid]; - } - - inline uint64_t GetSizeOfLayout() const - { - return GetBlockOffset(NUM_BLOCKS) + NUM_BLOCKS * 2 * sizeof(CANARY); - } - - inline uint64_t GetBlockOffset(BlockID bid) const - { - uint64_t result = sizeof(CANARY); - for (auto i = 0; i < bid; i++) - { - result += GetBlockSize((BlockID)i) + 2 * sizeof(CANARY); - } - return result; - } - - template - inline T *GetBlockPtr(char *shared_memory, BlockID bid) - { - T *ptr = (T *)(shared_memory + GetBlockOffset(bid)); - if (WRITE_CANARY) - { - char *start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY); - char *end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid); - std::copy(CANARY, CANARY + sizeof(CANARY), start_canary_ptr); - std::copy(CANARY, CANARY + sizeof(CANARY), end_canary_ptr); - } - else - { - char *start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY); - char *end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid); - bool start_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), start_canary_ptr); - bool end_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), end_canary_ptr); - if (!start_canary_alive) - { - throw osrm::exception("Start canary of block corrupted."); - } - if (!end_canary_alive) - { - throw osrm::exception("End canary of block corrupted."); - } - } - - return ptr; - } -}; - -enum SharedDataType -{ - CURRENT_REGIONS, - LAYOUT_1, - DATA_1, - LAYOUT_2, - DATA_2, - LAYOUT_NONE, - DATA_NONE -}; - -struct SharedDataTimestamp -{ - SharedDataType layout; - SharedDataType data; - unsigned timestamp; -}; - -#endif /* SHARED_DATA_TYPE_HPP */ diff --git a/Server/http/compression_type.hpp b/Server/http/compression_type.hpp deleted file mode 100644 index 49163adab..000000000 --- a/Server/http/compression_type.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef COMPRESSION_TYPE_HPP -#define COMPRESSION_TYPE_HPP - -namespace http -{ - -enum compression_type -{ - no_compression, - gzip_rfc1952, - deflate_rfc1951 -}; -} - -#endif // COMPRESSION_TYPE_HPP diff --git a/Server/http/header.hpp b/Server/http/header.hpp deleted file mode 100644 index 7996be439..000000000 --- a/Server/http/header.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef HEADER_HPP -#define HEADER_HPP - -#include -#include - -namespace http -{ -struct header -{ - // explicitly use default copy c'tor as adding move c'tor - header &operator=(const header &other) = default; - header(const std::string &name, const std::string &value) : name(name), value(value) {} - header(header &&other) : name(std::move(other.name)), value(std::move(other.value)) {} - - void clear() - { - name.clear(); - value.clear(); - } - - std::string name; - std::string value; -}; -} - -#endif // HEADER_HPP diff --git a/Server/http/reply.cpp b/Server/http/reply.cpp deleted file mode 100644 index 2642e2be2..000000000 --- a/Server/http/reply.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "reply.hpp" - -#include "../../util/cast.hpp" - -namespace http -{ - -const char ok_html[] = ""; -const char bad_request_html[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}"; -const char internal_server_error_html[] = - "{\"status\": 500,\"status_message\":\"Internal Server Error\"}"; -const char seperators[] = {':', ' '}; -const char crlf[] = {'\r', '\n'}; -const std::string http_ok_string = "HTTP/1.0 200 OK\r\n"; -const std::string http_bad_request_string = "HTTP/1.0 400 Bad Request\r\n"; -const std::string http_internal_server_error_string = "HTTP/1.0 500 Internal Server Error\r\n"; - -void reply::set_size(const std::size_t size) -{ - for (header &h : headers) - { - if ("Content-Length" == h.name) - { - h.value = cast::integral_to_string(size); - } - } -} - -void reply::set_uncompressed_size() { set_size(content.size()); } - -std::vector reply::to_buffers() -{ - std::vector buffers; - buffers.push_back(status_to_buffer(status)); - for (const header &h : headers) - { - buffers.push_back(boost::asio::buffer(h.name)); - buffers.push_back(boost::asio::buffer(seperators)); - buffers.push_back(boost::asio::buffer(h.value)); - buffers.push_back(boost::asio::buffer(crlf)); - } - buffers.push_back(boost::asio::buffer(crlf)); - buffers.push_back(boost::asio::buffer(content)); - return buffers; -} - -std::vector reply::headers_to_buffers() -{ - std::vector buffers; - buffers.push_back(status_to_buffer(status)); - for (const header ¤t_header : headers) - { - buffers.push_back(boost::asio::buffer(current_header.name)); - buffers.push_back(boost::asio::buffer(seperators)); - buffers.push_back(boost::asio::buffer(current_header.value)); - buffers.push_back(boost::asio::buffer(crlf)); - } - buffers.push_back(boost::asio::buffer(crlf)); - return buffers; -} - -reply reply::stock_reply(const reply::status_type status) -{ - reply reply; - reply.status = status; - reply.content.clear(); - - const std::string status_string = reply.status_to_string(status); - reply.content.insert(reply.content.end(), status_string.begin(), status_string.end()); - reply.headers.emplace_back("Access-Control-Allow-Origin", "*"); - reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size())); - reply.headers.emplace_back("Content-Type", "text/html"); - return reply; -} - -std::string reply::status_to_string(const reply::status_type status) -{ - if (reply::ok == status) - { - return ok_html; - } - if (reply::bad_request == status) - { - return bad_request_html; - } - return internal_server_error_html; -} - -boost::asio::const_buffer reply::status_to_buffer(const reply::status_type status) -{ - if (reply::ok == status) - { - return boost::asio::buffer(http_ok_string); - } - if (reply::internal_server_error == status) - { - return boost::asio::buffer(http_internal_server_error_string); - } - return boost::asio::buffer(http_bad_request_string); -} - -reply::reply() : status(ok) {} -} diff --git a/Server/http/reply.hpp b/Server/http/reply.hpp deleted file mode 100644 index a4b6cb69b..000000000 --- a/Server/http/reply.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef REPLY_HPP -#define REPLY_HPP - -#include "header.hpp" - -#include - -#include - -namespace http -{ -class reply -{ - public: - enum status_type - { - ok = 200, - bad_request = 400, - internal_server_error = 500 - } status; - - std::vector
headers; - std::vector to_buffers(); - std::vector headers_to_buffers(); - std::vector content; - static reply stock_reply(const status_type status); - void set_size(const std::size_t size); - void set_uncompressed_size(); - - reply(); - - private: - std::string status_to_string(reply::status_type status); - boost::asio::const_buffer status_to_buffer(reply::status_type status); -}; -} - -#endif // REPLY_HPP diff --git a/Server/http/request.hpp b/Server/http/request.hpp deleted file mode 100644 index 0ad622580..000000000 --- a/Server/http/request.hpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef REQUEST_HPP -#define REQUEST_HPP - -#include - -#include - -namespace http -{ - -struct request -{ - std::string uri; - std::string referrer; - std::string agent; - boost::asio::ip::address endpoint; -}; - -} // namespace http - -#endif // REQUEST_HPP diff --git a/Util/bearing.cpp b/Util/bearing.cpp deleted file mode 100644 index 92c47e6b8..000000000 --- a/Util/bearing.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "bearing.hpp" - -std::string bearing::get(const double heading) -{ - if (heading <= 22.5) - { - return "N"; - } - if (heading <= 67.5) - { - return "NE"; - } - if (heading <= 112.5) - { - return "E"; - } - if (heading <= 157.5) - { - return "SE"; - } - if (heading <= 202.5) - { - return "S"; - } - if (heading <= 247.5) - { - return "SW"; - } - if (heading <= 292.5) - { - return "W"; - } - if (heading <= 337.5) - { - return "NW"; - } - return "N"; -} diff --git a/Util/bearing.hpp b/Util/bearing.hpp deleted file mode 100644 index 0066e9e02..000000000 --- a/Util/bearing.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef BEARING_HPP -#define BEARING_HPP - -#include - -struct bearing -{ - static std::string get(const double heading); -}; - -#endif // BEARING_HPP diff --git a/Util/boost_filesystem_2_fix.hpp b/Util/boost_filesystem_2_fix.hpp deleted file mode 100644 index aeab380b2..000000000 --- a/Util/boost_filesystem_2_fix.hpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef BOOST_FILE_SYSTEM_FIX_H -#define BOOST_FILE_SYSTEM_FIX_H - -#include "osrm_exception.hpp" - -// #include -#include -// #include - -// This is one big workaround for latest boost renaming woes. - -#if BOOST_FILESYSTEM_VERSION < 3 -#warning Boost Installation with Filesystem3 missing, activating workaround -#include -#endif - -namespace boost -{ -namespace filesystem -{ - -// Validator for boost::filesystem::path, that verifies that the file -// exists. The validate() function must be defined in the same namespace -// as the target type, (boost::filesystem::path in this case), otherwise -// it is not called -// inline void validate( -// boost::any & v, -// const std::vector & values, -// boost::filesystem::path *, -// int -// ) { -// boost::program_options::validators::check_first_occurrence(v); -// const std::string & input_string = -// boost::program_options::validators::get_single_string(values); -// if(boost::filesystem::is_regular_file(input_string)) { -// v = boost::any(boost::filesystem::path(input_string)); -// } else { -// throw osrm::exception(input_string + " not found"); -// } -// } - -// adapted from: -// http://stackoverflow.com/questions/1746136/how-do-i-normalize-a-pathname-using-boostfilesystem -inline boost::filesystem::path -portable_canonical(const boost::filesystem::path &relative_path, - const boost::filesystem::path ¤t_path = boost::filesystem::current_path()) -{ - const boost::filesystem::path absolute_path = - boost::filesystem::absolute(relative_path, current_path); - - boost::filesystem::path canonical_path; - for (auto path_iterator = absolute_path.begin(); path_iterator != absolute_path.end(); - ++path_iterator) - { - if (".." == path_iterator->string()) - { - // /a/b/.. is not necessarily /a if b is a symbolic link - if (boost::filesystem::is_symlink(canonical_path)) - { - canonical_path /= *path_iterator; - } - else if (".." == canonical_path.filename()) - { - // /a/b/../.. is not /a/b/.. under most circumstances - // We can end up with ..s in our result because of symbolic links - canonical_path /= *path_iterator; - } - else - { - // Otherwise it should be safe to resolve the parent - canonical_path = canonical_path.parent_path(); - } - } - else if ("." == path_iterator->string()) - { - // Ignore - } - else - { - // Just cat other path entries - canonical_path /= *path_iterator; - } - } - BOOST_ASSERT(canonical_path.is_absolute()); - BOOST_ASSERT(boost::filesystem::exists(canonical_path)); - return canonical_path; -} - -#if BOOST_FILESYSTEM_VERSION < 3 - -inline path temp_directory_path() -{ - char *buffer; - buffer = tmpnam(nullptr); - - return path(buffer); -} - -inline path unique_path(const path &) { return temp_directory_path(); } - -#endif -} -} - -#ifndef BOOST_FILESYSTEM_VERSION -#define BOOST_FILESYSTEM_VERSION 3 -#endif - -inline void AssertPathExists(const boost::filesystem::path &path) -{ - if (!boost::filesystem::is_regular_file(path)) - { - throw osrm::exception(path.string() + " not found."); - } -} - -#endif /* BOOST_FILE_SYSTEM_FIX_H */ diff --git a/Util/cast.hpp b/Util/cast.hpp deleted file mode 100644 index e28b9ff84..000000000 --- a/Util/cast.hpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - -Copyright (c) 2013, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef CAST_HPP -#define CAST_HPP - -#include -#include - -#include -#include - -struct cast -{ - // convert scoped enums to integers - template - static auto enum_to_underlying(Enumeration const value) -> - typename std::underlying_type::type - { - return static_cast::type>(value); - } - - template - static typename std::enable_if::value, std::string>::type - integral_to_string(const Number value) - { - std::string output; - std::back_insert_iterator sink(output); - - if (8 == sizeof(Number)) - { - boost::spirit::karma::generate(sink, boost::spirit::karma::long_long, value); - } - else - { - if (std::is_signed::value) - { - boost::spirit::karma::generate(sink, boost::spirit::karma::int_, value); - } - else - { - boost::spirit::karma::generate(sink, boost::spirit::karma::uint_, value); - } - } - return output; - } - - static int string_to_int(const std::string &input) - { - auto first_digit = input.begin(); - // Delete any trailing white-spaces - while (first_digit != input.end() && std::isspace(*first_digit)) - { - ++first_digit; - } - int value = 0; - boost::spirit::qi::parse(first_digit, input.end(), boost::spirit::int_, value); - return value; - } - - static unsigned string_to_uint(const std::string &input) - { - auto first_digit = input.begin(); - // Delete any trailing white-spaces - while (first_digit != input.end() && (std::isspace(*first_digit) || '-' == *first_digit)) - { - ++first_digit; - } - unsigned value = 0; - boost::spirit::qi::parse(first_digit, input.end(), boost::spirit::uint_, value); - return value; - } - - static uint64_t string_to_uint64(const std::string &input) - { - auto first_digit = input.begin(); - // Delete any trailing white-spaces - while (first_digit != input.end() && std::isspace(*first_digit)) - { - ++first_digit; - } - uint64_t value = 0; - boost::spirit::qi::parse(first_digit, input.end(), boost::spirit::long_long, value); - return value; - } - - // source: http://tinodidriksen.com/2011/05/28/cpp-convert-string-to-double-speed/ - static double string_to_double(const char *p) - { - double r = 0.0; - bool neg = false; - if (*p == '-') - { - neg = true; - ++p; - } - while (*p >= '0' && *p <= '9') - { - r = (r * 10.0) + (*p - '0'); - ++p; - } - if (*p == '.') - { - double f = 0.0; - int n = 0; - ++p; - while (*p >= '0' && *p <= '9') - { - f = (f * 10.0) + (*p - '0'); - ++p; - ++n; - } - r += f / std::pow(10.0, n); - } - if (neg) - { - r = -r; - } - return r; - } - - template struct scientific_policy : boost::spirit::karma::real_policies - { - // we want the numbers always to be in fixed format - static int floatfield(T) { return boost::spirit::karma::real_policies::fmtflags::fixed; } - static unsigned int precision(T) { return 6; } - }; - typedef boost::spirit::karma::real_generator> science_type; - - static std::string double_fixed_to_string(const double value) - { - std::string output; - std::back_insert_iterator sink(output); - boost::spirit::karma::generate(sink, science_type(), value); - if (output.size() >= 2 && output[output.size() - 2] == '.' && - output[output.size() - 1] == '0') - { - output.resize(output.size() - 2); - } - return output; - } - - static std::string double_to_string(const double value) - { - std::string output; - std::back_insert_iterator sink(output); - boost::spirit::karma::generate(sink, value); - return output; - } - - static void double_with_two_digits_to_string(const double value, std::string &output) - { - // The largest 32-bit integer is 4294967295, that is 10 chars - // On the safe side, add 1 for sign, and 1 for trailing zero - char buffer[12]; - sprintf(buffer, "%g", value); - output = buffer; - } -}; - -#endif // CAST_HPP diff --git a/Util/compute_angle.cpp b/Util/compute_angle.cpp deleted file mode 100644 index e83b67b75..000000000 --- a/Util/compute_angle.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "compute_angle.hpp" - -#include "trigonometry_table.hpp" -#include "../util/mercator.hpp" - -#include - -#include - -double ComputeAngle::OfThreeFixedPointCoordinates(const FixedPointCoordinate &first, - const FixedPointCoordinate &second, - const FixedPointCoordinate &third) -{ - const double v1x = (first.lon - second.lon) / COORDINATE_PRECISION; - const double v1y = mercator::lat2y(first.lat / COORDINATE_PRECISION) - - mercator::lat2y(second.lat / COORDINATE_PRECISION); - const double v2x = (third.lon - second.lon) / COORDINATE_PRECISION; - const double v2y = mercator::lat2y(third.lat / COORDINATE_PRECISION) - - mercator::lat2y(second.lat / COORDINATE_PRECISION); - - double angle = (atan2_lookup(v2y, v2x) - atan2_lookup(v1y, v1x)) * 180. / M_PI; - while (angle < 0.) - { - angle += 360.; - } - return angle; -} diff --git a/Util/compute_angle.hpp b/Util/compute_angle.hpp deleted file mode 100644 index 73682bceb..000000000 --- a/Util/compute_angle.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef COMPUTE_ANGLE_HPP -#define COMPUTE_ANGLE_HPP - -struct FixedPointCoordinate; - -struct ComputeAngle -{ - // Get angle of line segment (A,C)->(C,B) - // atan2 magic, formerly cosine theorem - static double OfThreeFixedPointCoordinates(const FixedPointCoordinate &first, - const FixedPointCoordinate &second, - const FixedPointCoordinate &third); -}; - -#endif // COMPUTE_ANGLE_HPP diff --git a/Util/container.hpp b/Util/container.hpp deleted file mode 100644 index a35d56a6d..000000000 --- a/Util/container.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - -Copyright (c) 2013, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef CONTAINER_HPP_ -#define CONTAINER_HPP_ - -#include -#include -#include - -namespace osrm -{ -template void sort_unique_resize(std::vector &vector) -{ - std::sort(vector.begin(), vector.end()); - const auto number_of_unique_elements = - std::unique(vector.begin(), vector.end()) - vector.begin(); - vector.resize(number_of_unique_elements); -} - -// template inline void sort_unique_resize_shrink_vector(std::vector &vector) -// { -// sort_unique_resize(vector); -// vector.shrink_to_fit(); -// } - -// template inline void remove_consecutive_duplicates_from_vector(std::vector -// &vector) -// { -// const auto number_of_unique_elements = std::unique(vector.begin(), vector.end()) - -// vector.begin(); -// vector.resize(number_of_unique_elements); -// } - -template -Function for_each_pair(ForwardIterator begin, ForwardIterator end, Function function) -{ - if (begin == end) - { - return function; - } - - auto next = begin; - next = std::next(next); - - while (next != end) - { - function(*begin, *next); - begin = std::next(begin); - next = std::next(next); - } - return function; -} - -template -Function for_each_pair(ContainerT &container, Function function) -{ - return for_each_pair(std::begin(container), std::end(container), function); -} -} -#endif /* CONTAINER_HPP_ */ diff --git a/Util/datastore_options.hpp b/Util/datastore_options.hpp deleted file mode 100644 index 1992860b5..000000000 --- a/Util/datastore_options.hpp +++ /dev/null @@ -1,273 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef DATASTORE_OPTIONS_HPP -#define DATASTORE_OPTIONS_HPP - -#include "boost_filesystem_2_fix.hpp" -#include "git_sha.hpp" -#include "ini_file.hpp" -#include "osrm_exception.hpp" -#include "simple_logger.hpp" - -#include - -#include -#include -#include - -#include - -// generate boost::program_options object for the routing part -bool GenerateDataStoreOptions(const int argc, const char *argv[], ServerPaths &paths) -{ - // declare a group of options that will be allowed only on command line - boost::program_options::options_description generic_options("Options"); - generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")( - "springclean,s", "Remove all regions in shared memory")( - "config,c", boost::program_options::value(&paths["config"]) - ->default_value("server.ini"), - "Path to a configuration file"); - - // declare a group of options that will be allowed both on command line - // as well as in a config file - boost::program_options::options_description config_options("Configuration"); - config_options.add_options()( - "hsgrdata", boost::program_options::value(&paths["hsgrdata"]), - ".hsgr file")("nodesdata", - boost::program_options::value(&paths["nodesdata"]), - ".nodes file")( - "edgesdata", boost::program_options::value(&paths["edgesdata"]), - ".edges file")("geometry", - boost::program_options::value(&paths["geometry"]), - ".geometry file")( - "ramindex", boost::program_options::value(&paths["ramindex"]), - ".ramIndex file")( - "fileindex", boost::program_options::value(&paths["fileindex"]), - ".fileIndex file")( - "namesdata", boost::program_options::value(&paths["namesdata"]), - ".names file")("timestamp", - boost::program_options::value(&paths["timestamp"]), - ".timestamp file"); - - // hidden options, will be allowed both on command line and in config - // file, but will not be shown to the user - boost::program_options::options_description hidden_options("Hidden options"); - hidden_options.add_options()( - "base,b", boost::program_options::value(&paths["base"]), - "base path to .osrm file"); - - // positional option - boost::program_options::positional_options_description positional_options; - positional_options.add("base", 1); - - // combine above options for parsing - boost::program_options::options_description cmdline_options; - cmdline_options.add(generic_options).add(config_options).add(hidden_options); - - boost::program_options::options_description config_file_options; - config_file_options.add(config_options).add(hidden_options); - - boost::program_options::options_description visible_options( - boost::filesystem::basename(argv[0]) + " [] "); - visible_options.add(generic_options).add(config_options); - - // parse command line options - boost::program_options::variables_map option_variables; - boost::program_options::store(boost::program_options::command_line_parser(argc, argv) - .options(cmdline_options) - .positional(positional_options) - .run(), - option_variables); - - if (option_variables.count("version")) - { - SimpleLogger().Write() << g_GIT_DESCRIPTION; - return false; - } - - if (option_variables.count("help")) - { - SimpleLogger().Write() << visible_options; - return false; - } - - boost::program_options::notify(option_variables); - - const bool parameter_present = (paths.find("hsgrdata") != paths.end() && - !paths.find("hsgrdata")->second.string().empty()) || - (paths.find("nodesdata") != paths.end() && - !paths.find("nodesdata")->second.string().empty()) || - (paths.find("edgesdata") != paths.end() && - !paths.find("edgesdata")->second.string().empty()) || - (paths.find("geometry") != paths.end() && - !paths.find("geometry")->second.string().empty()) || - (paths.find("ramindex") != paths.end() && - !paths.find("ramindex")->second.string().empty()) || - (paths.find("fileindex") != paths.end() && - !paths.find("fileindex")->second.string().empty()) || - (paths.find("timestamp") != paths.end() && - !paths.find("timestamp")->second.string().empty()); - - if (parameter_present) - { - if ((paths.find("config") != paths.end() && - boost::filesystem::is_regular_file(paths.find("config")->second)) || - option_variables.count("base")) - { - SimpleLogger().Write(logWARNING) << "conflicting parameters"; - SimpleLogger().Write() << visible_options; - return false; - } - } - - // parse config file - ServerPaths::iterator path_iterator = paths.find("config"); - if (path_iterator != paths.end() && boost::filesystem::is_regular_file(path_iterator->second) && - !option_variables.count("base")) - { - SimpleLogger().Write() << "Reading options from: " << path_iterator->second.string(); - std::string ini_file_contents = read_file_lower_content(path_iterator->second); - std::stringstream config_stream(ini_file_contents); - boost::program_options::store(parse_config_file(config_stream, config_file_options), - option_variables); - boost::program_options::notify(option_variables); - } - else if (option_variables.count("base")) - { - path_iterator = paths.find("base"); - BOOST_ASSERT(paths.end() != path_iterator); - std::string base_string = path_iterator->second.string(); - - path_iterator = paths.find("hsgrdata"); - if (path_iterator != paths.end()) - { - path_iterator->second = base_string + ".hsgr"; - } - - path_iterator = paths.find("nodesdata"); - if (path_iterator != paths.end()) - { - path_iterator->second = base_string + ".nodes"; - } - - path_iterator = paths.find("edgesdata"); - if (path_iterator != paths.end()) - { - path_iterator->second = base_string + ".edges"; - } - - path_iterator = paths.find("geometry"); - if (path_iterator != paths.end()) - { - path_iterator->second = base_string + ".geometry"; - } - - path_iterator = paths.find("ramindex"); - if (path_iterator != paths.end()) - { - path_iterator->second = base_string + ".ramIndex"; - } - - path_iterator = paths.find("fileindex"); - if (path_iterator != paths.end()) - { - path_iterator->second = base_string + ".fileIndex"; - } - - path_iterator = paths.find("namesdata"); - if (path_iterator != paths.end()) - { - path_iterator->second = base_string + ".names"; - } - - path_iterator = paths.find("timestamp"); - if (path_iterator != paths.end()) - { - path_iterator->second = base_string + ".timestamp"; - } - } - - path_iterator = paths.find("hsgrdata"); - if (path_iterator == paths.end() || path_iterator->second.string().empty()) - { - throw osrm::exception(".hsgr file must be specified"); - } - AssertPathExists(path_iterator->second); - - path_iterator = paths.find("nodesdata"); - if (path_iterator == paths.end() || path_iterator->second.string().empty()) - { - throw osrm::exception(".nodes file must be specified"); - } - AssertPathExists(path_iterator->second); - - path_iterator = paths.find("edgesdata"); - if (path_iterator == paths.end() || path_iterator->second.string().empty()) - { - throw osrm::exception(".edges file must be specified"); - } - AssertPathExists(path_iterator->second); - - path_iterator = paths.find("geometry"); - if (path_iterator == paths.end() || path_iterator->second.string().empty()) - { - throw osrm::exception(".geometry file must be specified"); - } - AssertPathExists(path_iterator->second); - - path_iterator = paths.find("ramindex"); - if (path_iterator == paths.end() || path_iterator->second.string().empty()) - { - throw osrm::exception(".ramindex file must be specified"); - } - AssertPathExists(path_iterator->second); - - path_iterator = paths.find("fileindex"); - if (path_iterator == paths.end() || path_iterator->second.string().empty()) - { - throw osrm::exception(".fileindex file must be specified"); - } - AssertPathExists(path_iterator->second); - - path_iterator = paths.find("namesdata"); - if (path_iterator == paths.end() || path_iterator->second.string().empty()) - { - throw osrm::exception(".names file must be specified"); - } - AssertPathExists(path_iterator->second); - - path_iterator = paths.find("timestamp"); - if (path_iterator == paths.end() || path_iterator->second.string().empty()) - { - throw osrm::exception(".timestamp file must be specified"); - } - - return true; -} - -#endif /* DATASTORE_OPTIONS_HPP */ diff --git a/Util/fingerprint.cpp.in b/Util/fingerprint.cpp.in deleted file mode 100644 index 6f9a6658f..000000000 --- a/Util/fingerprint.cpp.in +++ /dev/null @@ -1,103 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "fingerprint.hpp" - -#include "osrm_exception.hpp" - -#include - -#include -#include - -#cmakedefine01 HAS64BITS -#cmakedefine MD5PREPARE "${MD5PREPARE}" -#cmakedefine MD5RTREE "${MD5RTREE}" -#cmakedefine MD5GRAPH "${MD5GRAPH}" -#cmakedefine MD5OBJECTS "${MD5OBJECTS}" - -FingerPrint::FingerPrint() : magic_number(1297240911) -{ - md5_prepare[32] = md5_tree[32] = md5_graph[32] = md5_objects[32] = '\0'; - - boost::uuids::name_generator gen(named_uuid); - std::string temp_string; - - std::memcpy(md5_prepare, MD5PREPARE, strlen(MD5PREPARE)); - temp_string += md5_prepare; - std::memcpy(md5_tree, MD5RTREE, 32); - temp_string += md5_tree; - std::memcpy(md5_graph, MD5GRAPH, 32); - temp_string += md5_graph; - std::memcpy(md5_objects, MD5OBJECTS, 32); - temp_string += md5_objects; - - named_uuid = gen(temp_string); - has_64_bits = HAS64BITS; -} - -FingerPrint::~FingerPrint() {} - -const boost::uuids::uuid &FingerPrint::GetFingerPrint() const { return named_uuid; } - -bool FingerPrint::IsMagicNumberOK() const { return 1297240911 == magic_number; } - -bool FingerPrint::TestGraphUtil(const FingerPrint &other) const -{ - if (!other.IsMagicNumberOK()) - { - throw osrm::exception("hsgr input file misses magic number. Check or reprocess the file"); - } - return std::equal(md5_graph, md5_graph + 32, other.md5_graph); -} - -bool FingerPrint::TestPrepare(const FingerPrint &other) const -{ - if (!other.IsMagicNumberOK()) - { - throw osrm::exception("osrm input file misses magic number. Check or reprocess the file"); - } - return std::equal(md5_prepare, md5_prepare + 32, other.md5_prepare); -} - -bool FingerPrint::TestRTree(const FingerPrint &other) const -{ - if (!other.IsMagicNumberOK()) - { - throw osrm::exception("r-tree input file misses magic number. Check or reprocess the file"); - } - return std::equal(md5_tree, md5_tree + 32, other.md5_tree); -} - -bool FingerPrint::TestQueryObjects(const FingerPrint &other) const -{ - if (!other.IsMagicNumberOK()) - { - throw osrm::exception("missing magic number. Check or reprocess the file"); - } - return std::equal(md5_objects, md5_objects + 32, other.md5_objects); -} diff --git a/Util/fingerprint.hpp b/Util/fingerprint.hpp deleted file mode 100644 index 494a877ab..000000000 --- a/Util/fingerprint.hpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef FINGERPRINT_H -#define FINGERPRINT_H - -#include - -// implements a singleton, i.e. there is one and only one conviguration object -class FingerPrint -{ - public: - FingerPrint(); - FingerPrint(const FingerPrint &) = delete; - ~FingerPrint(); - const boost::uuids::uuid &GetFingerPrint() const; - bool IsMagicNumberOK() const; - bool TestGraphUtil(const FingerPrint &other) const; - bool TestPrepare(const FingerPrint &other) const; - bool TestRTree(const FingerPrint &other) const; - bool TestQueryObjects(const FingerPrint &other) const; - - private: - const unsigned magic_number; - char md5_prepare[33]; - char md5_tree[33]; - char md5_graph[33]; - char md5_objects[33]; - - // initialize to {6ba7b810-9dad-11d1-80b4-00c04fd430c8} - boost::uuids::uuid named_uuid; - bool has_64_bits; -}; - -#endif /* FingerPrint_H */ diff --git a/Util/floating_point.hpp b/Util/floating_point.hpp deleted file mode 100644 index 5c4810279..000000000 --- a/Util/floating_point.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef FLOATING_POINT_HPP -#define FLOATING_POINT_HPP - -#include - -#include -#include - -namespace osrm -{ -template bool epsilon_compare(const FloatT number1, const FloatT number2) -{ - static_assert(std::is_floating_point::value, "type must be floating point"); - return (std::abs(number1 - number2) < std::numeric_limits::epsilon()); -} -} - -#endif // FLOATING_POINT_HPP diff --git a/Util/git_sha.cpp.in b/Util/git_sha.cpp.in deleted file mode 100644 index 5b19337e9..000000000 --- a/Util/git_sha.cpp.in +++ /dev/null @@ -1,31 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "git_sha.hpp" - -#define GIT_DESCRIPTION "${GIT_DESCRIPTION}" -char g_GIT_DESCRIPTION[] = GIT_DESCRIPTION; diff --git a/Util/git_sha.hpp b/Util/git_sha.hpp deleted file mode 100644 index 9e55deff3..000000000 --- a/Util/git_sha.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef GIT_SHA_HPP -#define GIT_SHA_HPP - -extern char g_GIT_DESCRIPTION[]; - -#endif // GIT_SHA_HPP diff --git a/Util/graph_loader.hpp b/Util/graph_loader.hpp deleted file mode 100644 index 44f628034..000000000 --- a/Util/graph_loader.hpp +++ /dev/null @@ -1,320 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef GRAPH_LOADER_HPP -#define GRAPH_LOADER_HPP - -#include "fingerprint.hpp" -#include "osrm_exception.hpp" -#include "simple_logger.hpp" -#include "../data_structures/external_memory_node.hpp" -#include "../data_structures/import_edge.hpp" -#include "../data_structures/query_node.hpp" -#include "../data_structures/restriction.hpp" -#include "../typedefs.h" - -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include - -template -NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, - std::vector &edge_list, - std::vector &barrier_node_list, - std::vector &traffic_light_node_list, - std::vector *int_to_ext_node_id_map, - std::vector &restriction_list) -{ - const FingerPrint fingerprint_orig; - FingerPrint fingerprint_loaded; - input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint)); - - if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig)) - { - SimpleLogger().Write(logWARNING) << ".osrm was prepared with different build.\n" - "Reprocess to get rid of this warning."; - } - - std::unordered_map ext_to_int_id_map; - - NodeID n; - input_stream.read((char *)&n, sizeof(NodeID)); - SimpleLogger().Write() << "Importing n = " << n << " nodes "; - - ExternalMemoryNode current_node; - for (NodeID i = 0; i < n; ++i) - { - input_stream.read((char *)¤t_node, sizeof(ExternalMemoryNode)); - int_to_ext_node_id_map->emplace_back(current_node.lat, current_node.lon, - current_node.node_id); - ext_to_int_id_map.emplace(current_node.node_id, i); - if (current_node.barrier) - { - barrier_node_list.emplace_back(i); - } - if (current_node.traffic_lights) - { - traffic_light_node_list.emplace_back(i); - } - } - - // tighten vector sizes - barrier_node_list.shrink_to_fit(); - traffic_light_node_list.shrink_to_fit(); - - // renumber nodes in turn restrictions - for (TurnRestriction ¤t_restriction : restriction_list) - { - auto internal_id_iter = ext_to_int_id_map.find(current_restriction.from.node); - if (internal_id_iter == ext_to_int_id_map.end()) - { - SimpleLogger().Write(logDEBUG) << "Unmapped from node " << current_restriction.from.node - << " of restriction"; - continue; - } - current_restriction.from.node = internal_id_iter->second; - - internal_id_iter = ext_to_int_id_map.find(current_restriction.via.node); - if (internal_id_iter == ext_to_int_id_map.end()) - { - SimpleLogger().Write(logDEBUG) << "Unmapped via node " << current_restriction.via.node - << " of restriction"; - continue; - } - - current_restriction.via.node = internal_id_iter->second; - - internal_id_iter = ext_to_int_id_map.find(current_restriction.to.node); - if (internal_id_iter == ext_to_int_id_map.end()) - { - SimpleLogger().Write(logDEBUG) << "Unmapped to node " << current_restriction.to.node - << " of restriction"; - continue; - } - current_restriction.to.node = internal_id_iter->second; - } - - EdgeWeight weight; - NodeID source, target; - unsigned nameID; - int length; - short dir; // direction (0 = open, 1 = forward, 2+ = open) - bool is_roundabout, ignore_in_grid, is_access_restricted, is_split; - TravelMode travel_mode; - - EdgeID m; - input_stream.read((char *)&m, sizeof(unsigned)); - edge_list.reserve(m); - SimpleLogger().Write() << " and " << m << " edges "; - - for (EdgeID i = 0; i < m; ++i) - { - input_stream.read((char *)&source, sizeof(unsigned)); - input_stream.read((char *)&target, sizeof(unsigned)); - input_stream.read((char *)&length, sizeof(int)); - input_stream.read((char *)&dir, sizeof(short)); - input_stream.read((char *)&weight, sizeof(int)); - input_stream.read((char *)&nameID, sizeof(unsigned)); - input_stream.read((char *)&is_roundabout, sizeof(bool)); - input_stream.read((char *)&ignore_in_grid, sizeof(bool)); - input_stream.read((char *)&is_access_restricted, sizeof(bool)); - input_stream.read((char *)&travel_mode, sizeof(TravelMode)); - input_stream.read((char *)&is_split, sizeof(bool)); - - BOOST_ASSERT_MSG(length > 0, "loaded null length edge"); - BOOST_ASSERT_MSG(weight > 0, "loaded null weight"); - BOOST_ASSERT_MSG(0 <= dir && dir <= 2, "loaded bogus direction"); - - bool forward = true; - bool backward = true; - if (1 == dir) - { - backward = false; - } - if (2 == dir) - { - forward = false; - } - - // translate the external NodeIDs to internal IDs - auto internal_id_iter = ext_to_int_id_map.find(source); - if (ext_to_int_id_map.find(source) == ext_to_int_id_map.end()) - { -#ifndef NDEBUG - SimpleLogger().Write(logWARNING) << " unresolved source NodeID: " << source; -#endif - continue; - } - source = internal_id_iter->second; - internal_id_iter = ext_to_int_id_map.find(target); - if (ext_to_int_id_map.find(target) == ext_to_int_id_map.end()) - { -#ifndef NDEBUG - SimpleLogger().Write(logWARNING) << "unresolved target NodeID : " << target; -#endif - continue; - } - target = internal_id_iter->second; - BOOST_ASSERT_MSG(source != SPECIAL_NODEID && target != SPECIAL_NODEID, - "nonexisting source or target"); - - if (source > target) - { - std::swap(source, target); - std::swap(forward, backward); - } - - edge_list.emplace_back(source, target, nameID, weight, forward, backward, is_roundabout, - ignore_in_grid, is_access_restricted, travel_mode, is_split); - } - ext_to_int_id_map.clear(); - - tbb::parallel_sort(edge_list.begin(), edge_list.end()); - - for (unsigned i = 1; i < edge_list.size(); ++i) - { - if ((edge_list[i - 1].target == edge_list[i].target) && - (edge_list[i - 1].source == edge_list[i].source)) - { - const bool edge_flags_equivalent = (edge_list[i - 1].forward == edge_list[i].forward) && - (edge_list[i - 1].backward == edge_list[i].backward); - const bool edge_flags_are_superset1 = - (edge_list[i - 1].forward && edge_list[i - 1].backward) && - (edge_list[i].forward != edge_list[i].backward); - const bool edge_flags_are_superset_2 = - (edge_list[i].forward && edge_list[i].backward) && - (edge_list[i - 1].forward != edge_list[i - 1].backward); - - if (edge_flags_equivalent) - { - edge_list[i].weight = std::min(edge_list[i - 1].weight, edge_list[i].weight); - edge_list[i - 1].source = SPECIAL_NODEID; - } - else if (edge_flags_are_superset1) - { - if (edge_list[i - 1].weight <= edge_list[i].weight) - { - // edge i-1 is smaller and goes in both directions. Throw away the other edge - edge_list[i].source = SPECIAL_NODEID; - } - else - { - // edge i-1 is open in both directions, but edge i is smaller in one direction. - // Close edge i-1 in this direction - edge_list[i - 1].forward = !edge_list[i].forward; - edge_list[i - 1].backward = !edge_list[i].backward; - } - } - else if (edge_flags_are_superset_2) - { - if (edge_list[i - 1].weight <= edge_list[i].weight) - { - // edge i-1 is smaller for one direction. edge i is open in both. close edge i - // in the other direction - edge_list[i].forward = !edge_list[i - 1].forward; - edge_list[i].backward = !edge_list[i - 1].backward; - } - else - { - // edge i is smaller and goes in both direction. Throw away edge i-1 - edge_list[i - 1].source = SPECIAL_NODEID; - } - } - } - } - const auto new_end_iter = - std::remove_if(edge_list.begin(), edge_list.end(), [](const EdgeT &edge) - { - return edge.source == SPECIAL_NODEID || edge.target == SPECIAL_NODEID; - }); - edge_list.erase(new_end_iter, edge_list.end()); // remove excess candidates. - edge_list.shrink_to_fit(); - SimpleLogger().Write() << "Graph loaded ok and has " << edge_list.size() << " edges"; - return n; -} - -template -unsigned readHSGRFromStream(const boost::filesystem::path &hsgr_file, - std::vector &node_list, - std::vector &edge_list, - unsigned *check_sum) -{ - if (!boost::filesystem::exists(hsgr_file)) - { - throw osrm::exception("hsgr file does not exist"); - } - if (0 == boost::filesystem::file_size(hsgr_file)) - { - throw osrm::exception("hsgr file is empty"); - } - - boost::filesystem::ifstream hsgr_input_stream(hsgr_file, std::ios::binary); - - FingerPrint fingerprint_loaded, fingerprint_orig; - hsgr_input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint)); - if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig)) - { - SimpleLogger().Write(logWARNING) << ".hsgr was prepared with different build.\n" - "Reprocess to get rid of this warning."; - } - - unsigned number_of_nodes = 0; - unsigned number_of_edges = 0; - hsgr_input_stream.read((char *)check_sum, sizeof(unsigned)); - hsgr_input_stream.read((char *)&number_of_nodes, sizeof(unsigned)); - BOOST_ASSERT_MSG(0 != number_of_nodes, "number of nodes is zero"); - hsgr_input_stream.read((char *)&number_of_edges, sizeof(unsigned)); - - SimpleLogger().Write() << "number_of_nodes: " << number_of_nodes - << ", number_of_edges: " << number_of_edges; - - // BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero"); - node_list.resize(number_of_nodes); - hsgr_input_stream.read((char *)&(node_list[0]), number_of_nodes * sizeof(NodeT)); - - edge_list.resize(number_of_edges); - if (number_of_edges > 0) - { - hsgr_input_stream.read((char *)&(edge_list[0]), number_of_edges * sizeof(EdgeT)); - } - hsgr_input_stream.close(); - - return number_of_nodes; -} - -#endif // GRAPH_LOADER_HPP diff --git a/Util/ini_file.hpp b/Util/ini_file.hpp deleted file mode 100644 index 20616257a..000000000 --- a/Util/ini_file.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef INI_FILE_HPP -#define INI_FILE_HPP - -#include -#include - -#include -#include - -namespace -{ - -// support old capitalized option names by down-casing them with a regex replace -std::string read_file_lower_content(const boost::filesystem::path &path) -{ - boost::filesystem::fstream config_stream(path); - std::string ini_file_content((std::istreambuf_iterator(config_stream)), - std::istreambuf_iterator()); - std::transform(std::begin(ini_file_content), std::end(ini_file_content), - std::begin(ini_file_content), ::tolower); - return ini_file_content; -} -} -#endif // INI_FILE_HPP diff --git a/Util/integer_range.hpp b/Util/integer_range.hpp deleted file mode 100644 index 030b2fa63..000000000 --- a/Util/integer_range.hpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - -Copyright (c) 2013,2014, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef INTEGER_RANGE_HPP -#define INTEGER_RANGE_HPP - -#include - -namespace osrm -{ - -template class range -{ - private: - Integer last; - Integer iter; - - public: - range(Integer start, Integer end) : last(end), iter(start) - { - static_assert(std::is_integral::value, "range type must be integral"); - } - - // Iterable functions - const range &begin() const { return *this; } - const range &end() const { return *this; } - Integer front() const { return iter; } - Integer back() const { return last - 1; } - - // Iterator functions - bool operator!=(const range &) const { return iter < last; } - void operator++() { ++iter; } - Integer operator*() const { return iter; } -}; - -// convenience function to construct an integer range with type deduction -template -range irange(const Integer first, - const Integer last, - typename std::enable_if::value>::type * = 0) -{ - return range(first, last); -} -} - -#endif // INTEGER_RANGE_HPP diff --git a/Util/iterator_range.hpp b/Util/iterator_range.hpp deleted file mode 100644 index a057d7c92..000000000 --- a/Util/iterator_range.hpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - -Copyright (c) 2013, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef RANGE_HPP_ -#define RANGE_HPP_ - -namespace osrm -{ -namespace util -{ -template class Range -{ - public: - Range(Iterator begin, Iterator end) : begin_(begin), end_(end) {} - - Iterator begin() const { return begin_; } - Iterator end() const { return end_; } - - private: - Iterator begin_; - Iterator end_; -}; - -// Convenience functions for template parameter inference, -// akin to std::make_pair. - -template Range range(Iterator begin, Iterator end) -{ - return Range(begin, end); -} - -template -Range reverse(Reversable *reversable) -{ - return Range(reversable->rbegin(), reversable->rend()); -} - -template -Range -const_reverse(const ConstReversable *const_reversable) -{ - return Range(const_reversable->crbegin(), - const_reversable->crend()); -} -} -} - -#endif // RANGE_HPP_ diff --git a/Util/json_renderer.hpp b/Util/json_renderer.hpp deleted file mode 100644 index adb7c544e..000000000 --- a/Util/json_renderer.hpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - -Copyright (c) 2014, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -// based on -// https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp - -#ifndef JSON_RENDERER_HPP -#define JSON_RENDERER_HPP - -#include "cast.hpp" - -#include - -namespace JSON -{ - -struct Renderer : mapbox::util::static_visitor<> -{ - explicit Renderer(std::ostream &_out) : out(_out) {} - - void operator()(const String &string) const { out << "\"" << string.value << "\""; } - - void operator()(const Number &number) const - { - out.precision(10); - out << number.value; - } - - void operator()(const Object &object) const - { - out << "{"; - auto iterator = object.values.begin(); - while (iterator != object.values.end()) - { - out << "\"" << (*iterator).first << "\":"; - mapbox::util::apply_visitor(Renderer(out), (*iterator).second); - if (++iterator != object.values.end()) - { - out << ","; - } - } - out << "}"; - } - - void operator()(const Array &array) const - { - out << "["; - std::vector::const_iterator iterator; - iterator = array.values.begin(); - while (iterator != array.values.end()) - { - mapbox::util::apply_visitor(Renderer(out), *iterator); - if (++iterator != array.values.end()) - { - out << ","; - } - } - out << "]"; - } - - void operator()(const True &) const { out << "true"; } - - void operator()(const False &) const { out << "false"; } - - void operator()(const Null &) const { out << "null"; } - - private: - std::ostream &out; -}; - -struct ArrayRenderer : mapbox::util::static_visitor<> -{ - explicit ArrayRenderer(std::vector &_out) : out(_out) {} - - void operator()(const String &string) const - { - out.push_back('\"'); - out.insert(out.end(), string.value.begin(), string.value.end()); - out.push_back('\"'); - } - - void operator()(const Number &number) const - { - const std::string number_string = cast::double_fixed_to_string(number.value); - out.insert(out.end(), number_string.begin(), number_string.end()); - } - - void operator()(const Object &object) const - { - out.push_back('{'); - auto iterator = object.values.begin(); - while (iterator != object.values.end()) - { - out.push_back('\"'); - out.insert(out.end(), (*iterator).first.begin(), (*iterator).first.end()); - out.push_back('\"'); - out.push_back(':'); - - mapbox::util::apply_visitor(ArrayRenderer(out), (*iterator).second); - if (++iterator != object.values.end()) - { - out.push_back(','); - } - } - out.push_back('}'); - } - - void operator()(const Array &array) const - { - out.push_back('['); - std::vector::const_iterator iterator; - iterator = array.values.begin(); - while (iterator != array.values.end()) - { - mapbox::util::apply_visitor(ArrayRenderer(out), *iterator); - if (++iterator != array.values.end()) - { - out.push_back(','); - } - } - out.push_back(']'); - } - - void operator()(const True &) const - { - const std::string temp("true"); - out.insert(out.end(), temp.begin(), temp.end()); - } - - void operator()(const False &) const - { - const std::string temp("false"); - out.insert(out.end(), temp.begin(), temp.end()); - } - - void operator()(const Null &) const - { - const std::string temp("null"); - out.insert(out.end(), temp.begin(), temp.end()); - } - - private: - std::vector &out; -}; - -inline void render(std::ostream &out, const Object &object) -{ - Value value = object; - mapbox::util::apply_visitor(Renderer(out), value); -} - -inline void render(std::vector &out, const Object &object) -{ - Value value = object; - mapbox::util::apply_visitor(ArrayRenderer(out), value); -} - -} // namespace JSON - -#endif // JSON_RENDERER_HPP diff --git a/Util/lua_util.hpp b/Util/lua_util.hpp deleted file mode 100644 index f367949da..000000000 --- a/Util/lua_util.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - -Copyright (c) 2014, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef LUA_UTIL_HPP -#define LUA_UTIL_HPP - -extern "C" { -#include -#include -#include -} - -#include -#include - -#include -#include - -template void LUA_print(T output) { std::cout << "[LUA] " << output << std::endl; } - -// Check if the lua function is defined -inline bool lua_function_exists(lua_State *lua_state, const char *name) -{ - luabind::object globals_table = luabind::globals(lua_state); - luabind::object lua_function = globals_table[name]; - return lua_function && (luabind::type(lua_function) == LUA_TFUNCTION); -} - -// Add the folder contain the script to the lua load path, so script can easily require() other lua -// scripts inside that folder, or subfolders. -// See http://lua-users.org/wiki/PackagePath for details on the package.path syntax. -inline void luaAddScriptFolderToLoadPath(lua_State *lua_state, const char *file_name) -{ - const boost::filesystem::path profile_path(file_name); - std::string folder = profile_path.parent_path().string(); - // TODO: This code is most probably not Windows safe since it uses UNIX'ish path delimiters - const std::string lua_code = - "package.path = \"" + folder + "/?.lua;profiles/?.lua;\" .. package.path"; - luaL_dostring(lua_state, lua_code.c_str()); -} - -#endif // LUA_UTIL_HPP diff --git a/Util/make_unique.hpp b/Util/make_unique.hpp deleted file mode 100644 index b88145d17..000000000 --- a/Util/make_unique.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - -Copyright (c) 2013, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef MAKE_UNIQUE_H_ -#define MAKE_UNIQUE_H_ - -#include -#include -#include - -namespace osrm -{ -// Taken from http://msdn.microsoft.com/en-us/library/dn439780.asp -// Note, that the snippet was broken there and needed minor massaging - -// make_unique -template std::unique_ptr make_unique(Types &&... Args) -{ - return (std::unique_ptr(new T(std::forward(Args)...))); -} - -// make_unique -template std::unique_ptr make_unique(std::size_t Size) -{ - return (std::unique_ptr(new T[Size]())); -} - -// make_unique disallowed -template -typename std::enable_if::value != 0, void>::type make_unique(Types &&...) = delete; -} - -#endif // MAKE_UNIQUE_H_ diff --git a/Util/mercator.cpp b/Util/mercator.cpp deleted file mode 100644 index ddd80685d..000000000 --- a/Util/mercator.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "mercator.hpp" - -#include - -double mercator::y2lat(const double value) -{ - return 180. * M_1_PI * (2. * std::atan(std::exp(value * M_PI / 180.)) - M_PI_2); -} - -double mercator::lat2y(const double latitude) -{ - return 180. * M_1_PI * std::log(std::tan(M_PI_4 + latitude * (M_PI / 180.) / 2.)); -} diff --git a/Util/mercator.hpp b/Util/mercator.hpp deleted file mode 100644 index 2929db2f9..000000000 --- a/Util/mercator.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef MERCATOR_HPP -#define MERCATOR_HPP - -struct mercator -{ - static double y2lat(const double value); - - static double lat2y(const double latitude); -}; - -#endif // MERCATOR_HPP diff --git a/Util/osrm_exception.cpp b/Util/osrm_exception.cpp deleted file mode 100644 index e6b7986e3..000000000 --- a/Util/osrm_exception.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "osrm_exception.hpp" - -namespace osrm -{ -// This function exists to 'anchor' the class, and stop the compiler from -// copying vtable and RTTI info into every object file that includes -// this header. (Caught by -Wweak-vtables under Clang.) - -// More information from the LLVM Coding Standards: -// If a class is defined in a header file and has a vtable (either it has -// virtual methods or it derives from classes with virtual methods), it must -// always have at least one out-of-line virtual method in the class. Without -// this, the compiler will copy the vtable and RTTI into every .o file that -// #includes the header, bloating .o file sizes and increasing link times. -void exception::anchor() const {} -} diff --git a/Util/osrm_exception.hpp b/Util/osrm_exception.hpp deleted file mode 100644 index ac5044a79..000000000 --- a/Util/osrm_exception.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef OSRM_EXCEPTION_HPP -#define OSRM_EXCEPTION_HPP - -#include -#include - -namespace osrm -{ -class exception final : public std::exception -{ - public: - explicit exception(const char *message) : message(message) {} - explicit exception(const std::string &message) : message(message) {} - - private: - // This function exists to 'anchor' the class, and stop the compiler from - // copying vtable and RTTI info into every object file that includes - // this header. (Caught by -Wweak-vtables under Clang.) - virtual void anchor() const; - const char *what() const noexcept { return message.c_str(); } - const std::string message; -}; -} -#endif /* OSRM_EXCEPTION_HPP */ diff --git a/Util/range_algorithms.hpp b/Util/range_algorithms.hpp deleted file mode 100644 index 5aafd8e17..000000000 --- a/Util/range_algorithms.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - open source routing machine - Copyright (C) Dennis Luxen, others 2010 - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU AFFERO General Public License as published by -the Free Software Foundation; either version 3 of the License, or -any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -or see http://www.gnu.org/licenses/agpl.txt. - */ - -#ifndef RANGE_ALGORITHMS_HPP -#define RANGE_ALGORITHMS_HPP - -#include - -namespace osrm -{ - -template -auto max_element(const Container &c) -> decltype(std::max_element(c.begin(), c.end())) -{ - return std::max_element(c.begin(), c.end()); -} - -template -auto max_element(const Container &c) -> decltype(std::max_element(c.cbegin(), c.cend())) -{ - return std::max_element(c.cbegin(), c.cend()); -} -} - -#endif // RANGE_ALGORITHMS_HPP diff --git a/Util/routed_options.hpp b/Util/routed_options.hpp deleted file mode 100644 index 74e79b070..000000000 --- a/Util/routed_options.hpp +++ /dev/null @@ -1,277 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef ROUTED_OPTIONS_HPP -#define ROUTED_OPTIONS_HPP - -#include "git_sha.hpp" -#include "ini_file.hpp" -#include "osrm_exception.hpp" -#include "simple_logger.hpp" - -#include -#include - -#include - -#include -#include -const static unsigned INIT_OK_START_ENGINE = 0; -const static unsigned INIT_OK_DO_NOT_START_ENGINE = 1; -const static unsigned INIT_FAILED = -1; - -inline void populate_base_path(ServerPaths &server_paths) -{ - // populate the server_path object - auto path_iterator = server_paths.find("base"); - - // if a base path has been set, we populate it. - if (path_iterator != server_paths.end()) - { - const std::string base_string = path_iterator->second.string(); - SimpleLogger().Write() << "populating base path: " << base_string; - - server_paths["hsgrdata"] = base_string + ".hsgr"; - BOOST_ASSERT(server_paths.find("hsgrdata") != server_paths.end()); - server_paths["nodesdata"] = base_string + ".nodes"; - BOOST_ASSERT(server_paths.find("nodesdata") != server_paths.end()); - server_paths["edgesdata"] = base_string + ".edges"; - BOOST_ASSERT(server_paths.find("edgesdata") != server_paths.end()); - server_paths["geometries"] = base_string + ".geometry"; - BOOST_ASSERT(server_paths.find("geometries") != server_paths.end()); - server_paths["ramindex"] = base_string + ".ramIndex"; - BOOST_ASSERT(server_paths.find("ramindex") != server_paths.end()); - server_paths["fileindex"] = base_string + ".fileIndex"; - BOOST_ASSERT(server_paths.find("fileindex") != server_paths.end()); - server_paths["namesdata"] = base_string + ".names"; - BOOST_ASSERT(server_paths.find("namesdata") != server_paths.end()); - server_paths["timestamp"] = base_string + ".timestamp"; - BOOST_ASSERT(server_paths.find("timestamp") != server_paths.end()); - } - - // check if files are give and whether they exist at all - path_iterator = server_paths.find("hsgrdata"); - if (path_iterator == server_paths.end() || - !boost::filesystem::is_regular_file(path_iterator->second)) - { - if (path_iterator == server_paths.end()) - { - SimpleLogger().Write() << "hsgrdata unset"; - } - if (!boost::filesystem::is_regular_file(path_iterator->second)) - { - SimpleLogger().Write() << "not a regular file"; - } - - throw osrm::exception(".hsgr not found: " + path_iterator->second.string()); - } - - path_iterator = server_paths.find("nodesdata"); - if (path_iterator == server_paths.end() || - !boost::filesystem::is_regular_file(path_iterator->second)) - { - throw osrm::exception(".nodes not found"); - } - - path_iterator = server_paths.find("edgesdata"); - if (path_iterator == server_paths.end() || - !boost::filesystem::is_regular_file(path_iterator->second)) - { - throw osrm::exception(".edges not found"); - } - - path_iterator = server_paths.find("geometries"); - if (path_iterator == server_paths.end() || - !boost::filesystem::is_regular_file(path_iterator->second)) - { - throw osrm::exception(".geometry not found"); - } - - path_iterator = server_paths.find("ramindex"); - if (path_iterator == server_paths.end() || - !boost::filesystem::is_regular_file(path_iterator->second)) - { - throw osrm::exception(".ramIndex not found"); - } - - path_iterator = server_paths.find("fileindex"); - if (path_iterator == server_paths.end() || - !boost::filesystem::is_regular_file(path_iterator->second)) - { - throw osrm::exception(".fileIndex not found"); - } - - path_iterator = server_paths.find("namesdata"); - if (path_iterator == server_paths.end() || - !boost::filesystem::is_regular_file(path_iterator->second)) - { - throw osrm::exception(".namesIndex not found"); - } - - SimpleLogger().Write() << "HSGR file:\t" << server_paths["hsgrdata"]; - SimpleLogger().Write(logDEBUG) << "Nodes file:\t" << server_paths["nodesdata"]; - SimpleLogger().Write(logDEBUG) << "Edges file:\t" << server_paths["edgesdata"]; - SimpleLogger().Write(logDEBUG) << "Geometry file:\t" << server_paths["geometries"]; - SimpleLogger().Write(logDEBUG) << "RAM file:\t" << server_paths["ramindex"]; - SimpleLogger().Write(logDEBUG) << "Index file:\t" << server_paths["fileindex"]; - SimpleLogger().Write(logDEBUG) << "Names file:\t" << server_paths["namesdata"]; - SimpleLogger().Write(logDEBUG) << "Timestamp file:\t" << server_paths["timestamp"]; -} - -// generate boost::program_options object for the routing part -inline unsigned GenerateServerProgramOptions(const int argc, - const char *argv[], - ServerPaths &paths, - std::string &ip_address, - int &ip_port, - int &requested_num_threads, - bool &use_shared_memory, - bool &trial, - int &max_locations_distance_table) -{ - // declare a group of options that will be allowed only on command line - boost::program_options::options_description generic_options("Options"); - generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")( - "config,c", boost::program_options::value(&paths["config"]) - ->default_value("server.ini"), - "Path to a configuration file")( - "trial", boost::program_options::value(&trial)->implicit_value(true), - "Quit after initialization"); - - // declare a group of options that will be allowed both on command line - // as well as in a config file - boost::program_options::options_description config_options("Configuration"); - config_options.add_options()( - "hsgrdata", boost::program_options::value(&paths["hsgrdata"]), - ".hsgr file")("nodesdata", - boost::program_options::value(&paths["nodesdata"]), - ".nodes file")( - "edgesdata", boost::program_options::value(&paths["edgesdata"]), - ".edges file")("geometry", - boost::program_options::value(&paths["geometries"]), - ".geometry file")( - "ramindex", boost::program_options::value(&paths["ramindex"]), - ".ramIndex file")( - "fileindex", boost::program_options::value(&paths["fileindex"]), - "File index file")( - "namesdata", boost::program_options::value(&paths["namesdata"]), - ".names file")("timestamp", - boost::program_options::value(&paths["timestamp"]), - ".timestamp file")( - "ip,i", boost::program_options::value(&ip_address)->default_value("0.0.0.0"), - "IP address")("port,p", boost::program_options::value(&ip_port)->default_value(5000), - "TCP/IP port")( - "threads,t", boost::program_options::value(&requested_num_threads)->default_value(8), - "Number of threads to use")( - "shared-memory,s", - boost::program_options::value(&use_shared_memory)->implicit_value(true), - "Load data from shared memory")( - "max-table-size,m", - boost::program_options::value(&max_locations_distance_table)->default_value(100), - "Max. locations supported in distance table query"); - - // hidden options, will be allowed both on command line and in config - // file, but will not be shown to the user - boost::program_options::options_description hidden_options("Hidden options"); - hidden_options.add_options()( - "base,b", boost::program_options::value(&paths["base"]), - "base path to .osrm file"); - - // positional option - boost::program_options::positional_options_description positional_options; - positional_options.add("base", 1); - - // combine above options for parsing - boost::program_options::options_description cmdline_options; - cmdline_options.add(generic_options).add(config_options).add(hidden_options); - - boost::program_options::options_description config_file_options; - config_file_options.add(config_options).add(hidden_options); - - boost::program_options::options_description visible_options( - boost::filesystem::basename(argv[0]) + " []"); - visible_options.add(generic_options).add(config_options); - - // parse command line options - boost::program_options::variables_map option_variables; - boost::program_options::store(boost::program_options::command_line_parser(argc, argv) - .options(cmdline_options) - .positional(positional_options) - .run(), - option_variables); - - if (option_variables.count("version")) - { - SimpleLogger().Write() << g_GIT_DESCRIPTION; - return INIT_OK_DO_NOT_START_ENGINE; - } - - if (option_variables.count("help")) - { - SimpleLogger().Write() << visible_options; - return INIT_OK_DO_NOT_START_ENGINE; - } - - boost::program_options::notify(option_variables); - - // parse config file - ServerPaths::iterator path_iterator = paths.find("config"); - if (path_iterator != paths.end() && boost::filesystem::is_regular_file(path_iterator->second) && - !option_variables.count("base")) - { - SimpleLogger().Write() << "Reading options from: " << path_iterator->second.string(); - std::string ini_file_contents = read_file_lower_content(path_iterator->second); - std::stringstream config_stream(ini_file_contents); - boost::program_options::store(parse_config_file(config_stream, config_file_options), - option_variables); - boost::program_options::notify(option_variables); - return INIT_OK_START_ENGINE; - } - - if (1 > requested_num_threads) - { - throw osrm::exception("Number of threads must be a positive number"); - } - - if (!use_shared_memory && option_variables.count("base")) - { - return INIT_OK_START_ENGINE; - } - if (use_shared_memory && !option_variables.count("base")) - { - return INIT_OK_START_ENGINE; - } - if (1 > max_locations_distance_table) - { - throw osrm::exception("Max location for distance table must be a positive number"); - } - - SimpleLogger().Write() << visible_options; - return INIT_OK_DO_NOT_START_ENGINE; -} - -#endif // ROUTED_OPTIONS_HPP diff --git a/Util/simple_logger.cpp b/Util/simple_logger.cpp deleted file mode 100644 index 325684af9..000000000 --- a/Util/simple_logger.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "simple_logger.hpp" - -#include "osrm_exception.hpp" - -#include - -#include - -#ifdef _MSC_VER -#include -#define isatty _isatty -#define fileno _fileno -#else -#include -#endif - -#include -#include -#include - -namespace -{ -static const char COL_RESET[]{"\x1b[0m"}; -static const char RED[]{"\x1b[31m"}; -#ifndef NDEBUG -static const char YELLOW[]{"\x1b[33m"}; -#endif -// static const char GREEN[] { "\x1b[32m"}; -// static const char BLUE[] { "\x1b[34m"}; -// static const char MAGENTA[] { "\x1b[35m"}; -// static const char CYAN[] { "\x1b[36m"}; -} - -void LogPolicy::Unmute() { m_is_mute = false; } - -void LogPolicy::Mute() { m_is_mute = true; } - -bool LogPolicy::IsMute() const { return m_is_mute; } - -LogPolicy &LogPolicy::GetInstance() -{ - static LogPolicy runningInstance; - return runningInstance; -} - -SimpleLogger::SimpleLogger() : level(logINFO) {} - -std::mutex &SimpleLogger::get_mutex() -{ - static std::mutex mtx; - return mtx; -} - -std::ostringstream &SimpleLogger::Write(LogLevel lvl) noexcept -{ - std::lock_guard lock(get_mutex()); - level = lvl; - os << "["; - switch (level) - { - case logWARNING: - os << "warn"; - break; - case logDEBUG: -#ifndef NDEBUG - os << "debug"; -#endif - break; - default: // logINFO: - os << "info"; - break; - } - os << "] "; - return os; -} - -SimpleLogger::~SimpleLogger() -{ - std::lock_guard lock(get_mutex()); - if (!LogPolicy::GetInstance().IsMute()) - { - const bool is_terminal = static_cast(isatty(fileno(stdout))); - switch (level) - { - case logWARNING: - std::cerr << (is_terminal ? RED : "") << os.str() << (is_terminal ? COL_RESET : "") - << std::endl; - break; - case logDEBUG: -#ifndef NDEBUG - std::cout << (is_terminal ? YELLOW : "") << os.str() << (is_terminal ? COL_RESET : "") - << std::endl; -#endif - break; - case logINFO: - default: - std::cout << os.str() << (is_terminal ? COL_RESET : "") << std::endl; - break; - } - } -} diff --git a/Util/simple_logger.hpp b/Util/simple_logger.hpp deleted file mode 100644 index f4dfc0b02..000000000 --- a/Util/simple_logger.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef SIMPLE_LOGGER_HPP -#define SIMPLE_LOGGER_HPP - -#include -#include -#include - -enum LogLevel -{ - logINFO, - logWARNING, - logDEBUG -}; - -class LogPolicy -{ - public: - void Unmute(); - - void Mute(); - - bool IsMute() const; - - static LogPolicy &GetInstance(); - - LogPolicy(const LogPolicy &) = delete; - - private: - LogPolicy() : m_is_mute(true) {} - std::atomic m_is_mute; -}; - -class SimpleLogger -{ - public: - SimpleLogger(); - - virtual ~SimpleLogger(); - std::mutex &get_mutex(); - std::ostringstream &Write(LogLevel l = logINFO) noexcept; - - private: - std::ostringstream os; - LogLevel level; -}; - -#endif /* SIMPLE_LOGGER_HPP */ diff --git a/Util/std_hash.hpp b/Util/std_hash.hpp deleted file mode 100644 index 8b4af3dd8..000000000 --- a/Util/std_hash.hpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - -Copyright (c) 2014, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef STD_HASH_HPP -#define STD_HASH_HPP - -#include - -// this is largely inspired by boost's hash combine as can be found in -// "The C++ Standard Library" 2nd Edition. Nicolai M. Josuttis. 2012. - -namespace -{ - -template void hash_combine(std::size_t &seed, const T &val) -{ - seed ^= std::hash()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2); -} - -template void hash_val(std::size_t &seed, const T &val) { hash_combine(seed, val); } - -template -void hash_val(std::size_t &seed, const T &val, const Types &... args) -{ - hash_combine(seed, val); - hash_val(seed, args...); -} - -template std::size_t hash_val(const Types &... args) -{ - std::size_t seed = 0; - hash_val(seed, args...); - return seed; -} -} - -namespace std -{ -template struct hash> -{ - size_t operator()(const std::pair &pair) const - { - return hash_val(pair.first, pair.second); - } -}; -} - -#endif // STD_HASH_HPP diff --git a/Util/string_util.hpp b/Util/string_util.hpp deleted file mode 100644 index 08af55483..000000000 --- a/Util/string_util.hpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - -Copyright (c) 2013, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef STRING_UTIL_HPP -#define STRING_UTIL_HPP - -#include - -#include - -#include -#include -#include - -// precision: position after decimal point -// length: maximum number of digits including comma and decimals -// work with negative values to prevent overflowing when taking -value -template static inline char *printInt(char *buffer, int value) -{ - bool minus = true; - if (value > 0) - { - minus = false; - value = -value; - } - buffer += length - 1; - for (int i = 0; i < precision; i++) - { - *buffer = '0' - (value % 10); - value /= 10; - buffer--; - } - *buffer = '.'; - buffer--; - for (int i = precision + 1; i < length; i++) - { - *buffer = '0' - (value % 10); - value /= 10; - if (value == 0) - break; - buffer--; - } - if (minus) - { - buffer--; - *buffer = '-'; - } - return buffer; -} - -inline void replaceAll(std::string &s, const std::string &sub, const std::string &other) -{ - boost::replace_all(s, sub, other); -} - -inline std::string EscapeJSONString(const std::string &input) -{ - std::string output; - output.reserve(input.size()); - for (auto iter = input.begin(); iter != input.end(); ++iter) - { - switch (iter[0]) - { - case '\\': - output += "\\\\"; - break; - case '"': - output += "\\\""; - break; - case '/': - output += "\\/"; - break; - case '\b': - output += "\\b"; - break; - case '\f': - output += "\\f"; - break; - case '\n': - output += "\\n"; - break; - case '\r': - output += "\\r"; - break; - case '\t': - output += "\\t"; - break; - default: - output += *iter; - break; - } - } - return output; -} - -static std::string originals[] = {"&", "\"", "<", ">", "'", "[", "]", "\\"}; -static std::string entities[] = { - "&", """, "<", ">", "'", "&91;", "&93;", " \"}; - -inline std::size_t URIDecode(const std::string &input, std::string &output) -{ - auto src_iter = input.begin(); - output.resize(input.size() + 1); - std::size_t decoded_length = 0; - for (decoded_length = 0; src_iter != input.end(); ++decoded_length) - { - if (src_iter[0] == '%' && src_iter[1] && src_iter[2] && isxdigit(src_iter[1]) && - isxdigit(src_iter[2])) - { - std::string::value_type a = src_iter[1]; - std::string::value_type b = src_iter[2]; - a -= src_iter[1] < 58 ? 48 : src_iter[1] < 71 ? 55 : 87; - b -= src_iter[2] < 58 ? 48 : src_iter[2] < 71 ? 55 : 87; - output[decoded_length] = 16 * a + b; - src_iter += 3; - continue; - } - output[decoded_length] = *src_iter++; - } - output.resize(decoded_length); - return decoded_length; -} - -inline std::size_t URIDecodeInPlace(std::string &URI) { return URIDecode(URI, URI); } - -#endif // STRING_UTIL_HPP diff --git a/Util/timing_util.hpp b/Util/timing_util.hpp deleted file mode 100644 index 2279bd083..000000000 --- a/Util/timing_util.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - -Copyright (c) 2014, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TIMING_UTIL_HPP -#define TIMING_UTIL_HPP - -#include -#include -#include -#include -#include - -struct GlobalTimer -{ - GlobalTimer() : time(0) {} - std::atomic time; -}; - -class GlobalTimerFactory -{ - public: - static GlobalTimerFactory &get() - { - static GlobalTimerFactory instance; - return instance; - } - - GlobalTimer &getGlobalTimer(const std::string &name) - { - std::lock_guard lock(map_mutex); - return timer_map[name]; - } - - private: - std::mutex map_mutex; - std::unordered_map timer_map; -}; - -#define GLOBAL_TIMER_AQUIRE(_X) \ - auto &_X##_global_timer = GlobalTimerFactory::get().getGlobalTimer(#_X) -#define GLOBAL_TIMER_RESET(_X) _X##_global_timer.time = 0 -#define GLOBAL_TIMER_START(_X) TIMER_START(_X) -#define GLOBAL_TIMER_STOP(_X) \ - TIMER_STOP(_X); \ - _X##_global_timer.time += TIMER_NSEC(_X) -#define GLOBAL_TIMER_NSEC(_X) static_cast(_X##_global_timer.time) -#define GLOBAL_TIMER_USEC(_X) (_X##_global_timer.time / 1000.0) -#define GLOBAL_TIMER_MSEC(_X) (_X##_global_timer.time / 1000.0 / 1000.0) -#define GLOBAL_TIMER_SEC(_X) (_X##_global_timer.time / 1000.0 / 1000.0 / 1000.0) - -#define TIMER_START(_X) auto _X##_start = std::chrono::steady_clock::now(), _X##_stop = _X##_start -#define TIMER_STOP(_X) _X##_stop = std::chrono::steady_clock::now() -#define TIMER_NSEC(_X) \ - std::chrono::duration_cast(_X##_stop - _X##_start).count() -#define TIMER_USEC(_X) \ - std::chrono::duration_cast(_X##_stop - _X##_start).count() -#define TIMER_MSEC(_X) \ - (0.000001 * \ - std::chrono::duration_cast(_X##_stop - _X##_start).count()) -#define TIMER_SEC(_X) \ - (0.000001 * \ - std::chrono::duration_cast(_X##_stop - _X##_start).count()) -#define TIMER_MIN(_X) \ - std::chrono::duration_cast(_X##_stop - _X##_start).count() - -#endif // TIMING_UTIL_HPP diff --git a/Util/trigonometry_table.hpp b/Util/trigonometry_table.hpp deleted file mode 100644 index ebcf7ba4d..000000000 --- a/Util/trigonometry_table.hpp +++ /dev/null @@ -1,448 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef TRIGONOMETRY_TABLE_HPP -#define TRIGONOMETRY_TABLE_HPP - -#include "../typedefs.h" -#include - -#include - -constexpr unsigned short atan_table[4096] = { - 0x0000, 0x0014, 0x0028, 0x003d, 0x0051, 0x0065, 0x007a, 0x008e, 0x00a3, 0x00b7, 0x00cb, 0x00e0, - 0x00f4, 0x0108, 0x011d, 0x0131, 0x0146, 0x015a, 0x016e, 0x0183, 0x0197, 0x01ab, 0x01c0, 0x01d4, - 0x01e9, 0x01fd, 0x0211, 0x0226, 0x023a, 0x024e, 0x0263, 0x0277, 0x028c, 0x02a0, 0x02b4, 0x02c9, - 0x02dd, 0x02f1, 0x0306, 0x031a, 0x032f, 0x0343, 0x0357, 0x036c, 0x0380, 0x0394, 0x03a9, 0x03bd, - 0x03d2, 0x03e6, 0x03fa, 0x040f, 0x0423, 0x0437, 0x044c, 0x0460, 0x0475, 0x0489, 0x049d, 0x04b2, - 0x04c6, 0x04da, 0x04ef, 0x0503, 0x0517, 0x052c, 0x0540, 0x0555, 0x0569, 0x057d, 0x0592, 0x05a6, - 0x05ba, 0x05cf, 0x05e3, 0x05f8, 0x060c, 0x0620, 0x0635, 0x0649, 0x065d, 0x0672, 0x0686, 0x069b, - 0x06af, 0x06c3, 0x06d8, 0x06ec, 0x0700, 0x0715, 0x0729, 0x073d, 0x0752, 0x0766, 0x077b, 0x078f, - 0x07a3, 0x07b8, 0x07cc, 0x07e0, 0x07f5, 0x0809, 0x081d, 0x0832, 0x0846, 0x085b, 0x086f, 0x0883, - 0x0898, 0x08ac, 0x08c0, 0x08d5, 0x08e9, 0x08fd, 0x0912, 0x0926, 0x093b, 0x094f, 0x0963, 0x0978, - 0x098c, 0x09a0, 0x09b5, 0x09c9, 0x09dd, 0x09f2, 0x0a06, 0x0a1a, 0x0a2f, 0x0a43, 0x0a58, 0x0a6c, - 0x0a80, 0x0a95, 0x0aa9, 0x0abd, 0x0ad2, 0x0ae6, 0x0afa, 0x0b0f, 0x0b23, 0x0b37, 0x0b4c, 0x0b60, - 0x0b75, 0x0b89, 0x0b9d, 0x0bb2, 0x0bc6, 0x0bda, 0x0bef, 0x0c03, 0x0c17, 0x0c2c, 0x0c40, 0x0c54, - 0x0c69, 0x0c7d, 0x0c91, 0x0ca6, 0x0cba, 0x0cce, 0x0ce3, 0x0cf7, 0x0d0b, 0x0d20, 0x0d34, 0x0d48, - 0x0d5d, 0x0d71, 0x0d86, 0x0d9a, 0x0dae, 0x0dc3, 0x0dd7, 0x0deb, 0x0e00, 0x0e14, 0x0e28, 0x0e3d, - 0x0e51, 0x0e65, 0x0e7a, 0x0e8e, 0x0ea2, 0x0eb7, 0x0ecb, 0x0edf, 0x0ef4, 0x0f08, 0x0f1c, 0x0f31, - 0x0f45, 0x0f59, 0x0f6e, 0x0f82, 0x0f96, 0x0fab, 0x0fbf, 0x0fd3, 0x0fe8, 0x0ffc, 0x1010, 0x1025, - 0x1039, 0x104d, 0x1062, 0x1076, 0x108a, 0x109e, 0x10b3, 0x10c7, 0x10db, 0x10f0, 0x1104, 0x1118, - 0x112d, 0x1141, 0x1155, 0x116a, 0x117e, 0x1192, 0x11a7, 0x11bb, 0x11cf, 0x11e4, 0x11f8, 0x120c, - 0x1221, 0x1235, 0x1249, 0x125d, 0x1272, 0x1286, 0x129a, 0x12af, 0x12c3, 0x12d7, 0x12ec, 0x1300, - 0x1314, 0x1329, 0x133d, 0x1351, 0x1365, 0x137a, 0x138e, 0x13a2, 0x13b7, 0x13cb, 0x13df, 0x13f4, - 0x1408, 0x141c, 0x1431, 0x1445, 0x1459, 0x146d, 0x1482, 0x1496, 0x14aa, 0x14bf, 0x14d3, 0x14e7, - 0x14fb, 0x1510, 0x1524, 0x1538, 0x154d, 0x1561, 0x1575, 0x1589, 0x159e, 0x15b2, 0x15c6, 0x15db, - 0x15ef, 0x1603, 0x1617, 0x162c, 0x1640, 0x1654, 0x1669, 0x167d, 0x1691, 0x16a5, 0x16ba, 0x16ce, - 0x16e2, 0x16f7, 0x170b, 0x171f, 0x1733, 0x1748, 0x175c, 0x1770, 0x1784, 0x1799, 0x17ad, 0x17c1, - 0x17d6, 0x17ea, 0x17fe, 0x1812, 0x1827, 0x183b, 0x184f, 0x1863, 0x1878, 0x188c, 0x18a0, 0x18b4, - 0x18c9, 0x18dd, 0x18f1, 0x1905, 0x191a, 0x192e, 0x1942, 0x1957, 0x196b, 0x197f, 0x1993, 0x19a8, - 0x19bc, 0x19d0, 0x19e4, 0x19f9, 0x1a0d, 0x1a21, 0x1a35, 0x1a49, 0x1a5e, 0x1a72, 0x1a86, 0x1a9a, - 0x1aaf, 0x1ac3, 0x1ad7, 0x1aeb, 0x1b00, 0x1b14, 0x1b28, 0x1b3c, 0x1b51, 0x1b65, 0x1b79, 0x1b8d, - 0x1ba2, 0x1bb6, 0x1bca, 0x1bde, 0x1bf2, 0x1c07, 0x1c1b, 0x1c2f, 0x1c43, 0x1c58, 0x1c6c, 0x1c80, - 0x1c94, 0x1ca8, 0x1cbd, 0x1cd1, 0x1ce5, 0x1cf9, 0x1d0e, 0x1d22, 0x1d36, 0x1d4a, 0x1d5e, 0x1d73, - 0x1d87, 0x1d9b, 0x1daf, 0x1dc3, 0x1dd8, 0x1dec, 0x1e00, 0x1e14, 0x1e28, 0x1e3d, 0x1e51, 0x1e65, - 0x1e79, 0x1e8d, 0x1ea2, 0x1eb6, 0x1eca, 0x1ede, 0x1ef2, 0x1f07, 0x1f1b, 0x1f2f, 0x1f43, 0x1f57, - 0x1f6c, 0x1f80, 0x1f94, 0x1fa8, 0x1fbc, 0x1fd1, 0x1fe5, 0x1ff9, 0x200d, 0x2021, 0x2035, 0x204a, - 0x205e, 0x2072, 0x2086, 0x209a, 0x20ae, 0x20c3, 0x20d7, 0x20eb, 0x20ff, 0x2113, 0x2127, 0x213c, - 0x2150, 0x2164, 0x2178, 0x218c, 0x21a0, 0x21b5, 0x21c9, 0x21dd, 0x21f1, 0x2205, 0x2219, 0x222e, - 0x2242, 0x2256, 0x226a, 0x227e, 0x2292, 0x22a6, 0x22bb, 0x22cf, 0x22e3, 0x22f7, 0x230b, 0x231f, - 0x2333, 0x2348, 0x235c, 0x2370, 0x2384, 0x2398, 0x23ac, 0x23c0, 0x23d5, 0x23e9, 0x23fd, 0x2411, - 0x2425, 0x2439, 0x244d, 0x2461, 0x2476, 0x248a, 0x249e, 0x24b2, 0x24c6, 0x24da, 0x24ee, 0x2502, - 0x2517, 0x252b, 0x253f, 0x2553, 0x2567, 0x257b, 0x258f, 0x25a3, 0x25b7, 0x25cb, 0x25e0, 0x25f4, - 0x2608, 0x261c, 0x2630, 0x2644, 0x2658, 0x266c, 0x2680, 0x2694, 0x26a9, 0x26bd, 0x26d1, 0x26e5, - 0x26f9, 0x270d, 0x2721, 0x2735, 0x2749, 0x275d, 0x2771, 0x2785, 0x279a, 0x27ae, 0x27c2, 0x27d6, - 0x27ea, 0x27fe, 0x2812, 0x2826, 0x283a, 0x284e, 0x2862, 0x2876, 0x288a, 0x289e, 0x28b3, 0x28c7, - 0x28db, 0x28ef, 0x2903, 0x2917, 0x292b, 0x293f, 0x2953, 0x2967, 0x297b, 0x298f, 0x29a3, 0x29b7, - 0x29cb, 0x29df, 0x29f3, 0x2a07, 0x2a1b, 0x2a2f, 0x2a43, 0x2a58, 0x2a6c, 0x2a80, 0x2a94, 0x2aa8, - 0x2abc, 0x2ad0, 0x2ae4, 0x2af8, 0x2b0c, 0x2b20, 0x2b34, 0x2b48, 0x2b5c, 0x2b70, 0x2b84, 0x2b98, - 0x2bac, 0x2bc0, 0x2bd4, 0x2be8, 0x2bfc, 0x2c10, 0x2c24, 0x2c38, 0x2c4c, 0x2c60, 0x2c74, 0x2c88, - 0x2c9c, 0x2cb0, 0x2cc4, 0x2cd8, 0x2cec, 0x2d00, 0x2d14, 0x2d28, 0x2d3c, 0x2d50, 0x2d64, 0x2d78, - 0x2d8c, 0x2da0, 0x2db4, 0x2dc8, 0x2ddc, 0x2df0, 0x2e04, 0x2e18, 0x2e2c, 0x2e40, 0x2e54, 0x2e68, - 0x2e7c, 0x2e90, 0x2ea3, 0x2eb7, 0x2ecb, 0x2edf, 0x2ef3, 0x2f07, 0x2f1b, 0x2f2f, 0x2f43, 0x2f57, - 0x2f6b, 0x2f7f, 0x2f93, 0x2fa7, 0x2fbb, 0x2fcf, 0x2fe3, 0x2ff7, 0x300b, 0x301e, 0x3032, 0x3046, - 0x305a, 0x306e, 0x3082, 0x3096, 0x30aa, 0x30be, 0x30d2, 0x30e6, 0x30fa, 0x310e, 0x3122, 0x3135, - 0x3149, 0x315d, 0x3171, 0x3185, 0x3199, 0x31ad, 0x31c1, 0x31d5, 0x31e9, 0x31fd, 0x3210, 0x3224, - 0x3238, 0x324c, 0x3260, 0x3274, 0x3288, 0x329c, 0x32b0, 0x32c3, 0x32d7, 0x32eb, 0x32ff, 0x3313, - 0x3327, 0x333b, 0x334f, 0x3363, 0x3376, 0x338a, 0x339e, 0x33b2, 0x33c6, 0x33da, 0x33ee, 0x3401, - 0x3415, 0x3429, 0x343d, 0x3451, 0x3465, 0x3479, 0x348c, 0x34a0, 0x34b4, 0x34c8, 0x34dc, 0x34f0, - 0x3504, 0x3517, 0x352b, 0x353f, 0x3553, 0x3567, 0x357b, 0x358e, 0x35a2, 0x35b6, 0x35ca, 0x35de, - 0x35f2, 0x3605, 0x3619, 0x362d, 0x3641, 0x3655, 0x3668, 0x367c, 0x3690, 0x36a4, 0x36b8, 0x36cb, - 0x36df, 0x36f3, 0x3707, 0x371b, 0x372f, 0x3742, 0x3756, 0x376a, 0x377e, 0x3791, 0x37a5, 0x37b9, - 0x37cd, 0x37e1, 0x37f4, 0x3808, 0x381c, 0x3830, 0x3844, 0x3857, 0x386b, 0x387f, 0x3893, 0x38a6, - 0x38ba, 0x38ce, 0x38e2, 0x38f5, 0x3909, 0x391d, 0x3931, 0x3944, 0x3958, 0x396c, 0x3980, 0x3993, - 0x39a7, 0x39bb, 0x39cf, 0x39e2, 0x39f6, 0x3a0a, 0x3a1e, 0x3a31, 0x3a45, 0x3a59, 0x3a6d, 0x3a80, - 0x3a94, 0x3aa8, 0x3abb, 0x3acf, 0x3ae3, 0x3af7, 0x3b0a, 0x3b1e, 0x3b32, 0x3b45, 0x3b59, 0x3b6d, - 0x3b81, 0x3b94, 0x3ba8, 0x3bbc, 0x3bcf, 0x3be3, 0x3bf7, 0x3c0b, 0x3c1e, 0x3c32, 0x3c46, 0x3c59, - 0x3c6d, 0x3c81, 0x3c94, 0x3ca8, 0x3cbc, 0x3ccf, 0x3ce3, 0x3cf7, 0x3d0a, 0x3d1e, 0x3d32, 0x3d45, - 0x3d59, 0x3d6d, 0x3d80, 0x3d94, 0x3da8, 0x3dbb, 0x3dcf, 0x3de3, 0x3df6, 0x3e0a, 0x3e1e, 0x3e31, - 0x3e45, 0x3e59, 0x3e6c, 0x3e80, 0x3e93, 0x3ea7, 0x3ebb, 0x3ece, 0x3ee2, 0x3ef6, 0x3f09, 0x3f1d, - 0x3f30, 0x3f44, 0x3f58, 0x3f6b, 0x3f7f, 0x3f93, 0x3fa6, 0x3fba, 0x3fcd, 0x3fe1, 0x3ff5, 0x4008, - 0x401c, 0x402f, 0x4043, 0x4057, 0x406a, 0x407e, 0x4091, 0x40a5, 0x40b8, 0x40cc, 0x40e0, 0x40f3, - 0x4107, 0x411a, 0x412e, 0x4142, 0x4155, 0x4169, 0x417c, 0x4190, 0x41a3, 0x41b7, 0x41ca, 0x41de, - 0x41f2, 0x4205, 0x4219, 0x422c, 0x4240, 0x4253, 0x4267, 0x427a, 0x428e, 0x42a1, 0x42b5, 0x42c9, - 0x42dc, 0x42f0, 0x4303, 0x4317, 0x432a, 0x433e, 0x4351, 0x4365, 0x4378, 0x438c, 0x439f, 0x43b3, - 0x43c6, 0x43da, 0x43ed, 0x4401, 0x4414, 0x4428, 0x443b, 0x444f, 0x4462, 0x4476, 0x4489, 0x449d, - 0x44b0, 0x44c4, 0x44d7, 0x44eb, 0x44fe, 0x4512, 0x4525, 0x4539, 0x454c, 0x4560, 0x4573, 0x4586, - 0x459a, 0x45ad, 0x45c1, 0x45d4, 0x45e8, 0x45fb, 0x460f, 0x4622, 0x4636, 0x4649, 0x465c, 0x4670, - 0x4683, 0x4697, 0x46aa, 0x46be, 0x46d1, 0x46e5, 0x46f8, 0x470b, 0x471f, 0x4732, 0x4746, 0x4759, - 0x476c, 0x4780, 0x4793, 0x47a7, 0x47ba, 0x47cd, 0x47e1, 0x47f4, 0x4808, 0x481b, 0x482e, 0x4842, - 0x4855, 0x4869, 0x487c, 0x488f, 0x48a3, 0x48b6, 0x48ca, 0x48dd, 0x48f0, 0x4904, 0x4917, 0x492a, - 0x493e, 0x4951, 0x4965, 0x4978, 0x498b, 0x499f, 0x49b2, 0x49c5, 0x49d9, 0x49ec, 0x49ff, 0x4a13, - 0x4a26, 0x4a39, 0x4a4d, 0x4a60, 0x4a73, 0x4a87, 0x4a9a, 0x4aad, 0x4ac1, 0x4ad4, 0x4ae7, 0x4afb, - 0x4b0e, 0x4b21, 0x4b35, 0x4b48, 0x4b5b, 0x4b6f, 0x4b82, 0x4b95, 0x4ba8, 0x4bbc, 0x4bcf, 0x4be2, - 0x4bf6, 0x4c09, 0x4c1c, 0x4c2f, 0x4c43, 0x4c56, 0x4c69, 0x4c7d, 0x4c90, 0x4ca3, 0x4cb6, 0x4cca, - 0x4cdd, 0x4cf0, 0x4d03, 0x4d17, 0x4d2a, 0x4d3d, 0x4d50, 0x4d64, 0x4d77, 0x4d8a, 0x4d9d, 0x4db1, - 0x4dc4, 0x4dd7, 0x4dea, 0x4dfe, 0x4e11, 0x4e24, 0x4e37, 0x4e4b, 0x4e5e, 0x4e71, 0x4e84, 0x4e97, - 0x4eab, 0x4ebe, 0x4ed1, 0x4ee4, 0x4ef7, 0x4f0b, 0x4f1e, 0x4f31, 0x4f44, 0x4f57, 0x4f6b, 0x4f7e, - 0x4f91, 0x4fa4, 0x4fb7, 0x4fcb, 0x4fde, 0x4ff1, 0x5004, 0x5017, 0x502a, 0x503e, 0x5051, 0x5064, - 0x5077, 0x508a, 0x509d, 0x50b1, 0x50c4, 0x50d7, 0x50ea, 0x50fd, 0x5110, 0x5123, 0x5137, 0x514a, - 0x515d, 0x5170, 0x5183, 0x5196, 0x51a9, 0x51bc, 0x51d0, 0x51e3, 0x51f6, 0x5209, 0x521c, 0x522f, - 0x5242, 0x5255, 0x5268, 0x527c, 0x528f, 0x52a2, 0x52b5, 0x52c8, 0x52db, 0x52ee, 0x5301, 0x5314, - 0x5327, 0x533a, 0x534e, 0x5361, 0x5374, 0x5387, 0x539a, 0x53ad, 0x53c0, 0x53d3, 0x53e6, 0x53f9, - 0x540c, 0x541f, 0x5432, 0x5445, 0x5458, 0x546b, 0x547e, 0x5491, 0x54a5, 0x54b8, 0x54cb, 0x54de, - 0x54f1, 0x5504, 0x5517, 0x552a, 0x553d, 0x5550, 0x5563, 0x5576, 0x5589, 0x559c, 0x55af, 0x55c2, - 0x55d5, 0x55e8, 0x55fb, 0x560e, 0x5621, 0x5634, 0x5647, 0x565a, 0x566d, 0x5680, 0x5693, 0x56a6, - 0x56b9, 0x56cb, 0x56de, 0x56f1, 0x5704, 0x5717, 0x572a, 0x573d, 0x5750, 0x5763, 0x5776, 0x5789, - 0x579c, 0x57af, 0x57c2, 0x57d5, 0x57e8, 0x57fb, 0x580e, 0x5820, 0x5833, 0x5846, 0x5859, 0x586c, - 0x587f, 0x5892, 0x58a5, 0x58b8, 0x58cb, 0x58de, 0x58f0, 0x5903, 0x5916, 0x5929, 0x593c, 0x594f, - 0x5962, 0x5975, 0x5988, 0x599a, 0x59ad, 0x59c0, 0x59d3, 0x59e6, 0x59f9, 0x5a0c, 0x5a1f, 0x5a31, - 0x5a44, 0x5a57, 0x5a6a, 0x5a7d, 0x5a90, 0x5aa2, 0x5ab5, 0x5ac8, 0x5adb, 0x5aee, 0x5b01, 0x5b13, - 0x5b26, 0x5b39, 0x5b4c, 0x5b5f, 0x5b72, 0x5b84, 0x5b97, 0x5baa, 0x5bbd, 0x5bd0, 0x5be2, 0x5bf5, - 0x5c08, 0x5c1b, 0x5c2e, 0x5c40, 0x5c53, 0x5c66, 0x5c79, 0x5c8c, 0x5c9e, 0x5cb1, 0x5cc4, 0x5cd7, - 0x5ce9, 0x5cfc, 0x5d0f, 0x5d22, 0x5d34, 0x5d47, 0x5d5a, 0x5d6d, 0x5d7f, 0x5d92, 0x5da5, 0x5db8, - 0x5dca, 0x5ddd, 0x5df0, 0x5e03, 0x5e15, 0x5e28, 0x5e3b, 0x5e4d, 0x5e60, 0x5e73, 0x5e86, 0x5e98, - 0x5eab, 0x5ebe, 0x5ed0, 0x5ee3, 0x5ef6, 0x5f09, 0x5f1b, 0x5f2e, 0x5f41, 0x5f53, 0x5f66, 0x5f79, - 0x5f8b, 0x5f9e, 0x5fb1, 0x5fc3, 0x5fd6, 0x5fe9, 0x5ffb, 0x600e, 0x6021, 0x6033, 0x6046, 0x6059, - 0x606b, 0x607e, 0x6091, 0x60a3, 0x60b6, 0x60c8, 0x60db, 0x60ee, 0x6100, 0x6113, 0x6126, 0x6138, - 0x614b, 0x615d, 0x6170, 0x6183, 0x6195, 0x61a8, 0x61ba, 0x61cd, 0x61e0, 0x61f2, 0x6205, 0x6217, - 0x622a, 0x623d, 0x624f, 0x6262, 0x6274, 0x6287, 0x6299, 0x62ac, 0x62bf, 0x62d1, 0x62e4, 0x62f6, - 0x6309, 0x631b, 0x632e, 0x6340, 0x6353, 0x6366, 0x6378, 0x638b, 0x639d, 0x63b0, 0x63c2, 0x63d5, - 0x63e7, 0x63fa, 0x640c, 0x641f, 0x6431, 0x6444, 0x6456, 0x6469, 0x647b, 0x648e, 0x64a0, 0x64b3, - 0x64c5, 0x64d8, 0x64ea, 0x64fd, 0x650f, 0x6522, 0x6534, 0x6547, 0x6559, 0x656c, 0x657e, 0x6591, - 0x65a3, 0x65b5, 0x65c8, 0x65da, 0x65ed, 0x65ff, 0x6612, 0x6624, 0x6637, 0x6649, 0x665b, 0x666e, - 0x6680, 0x6693, 0x66a5, 0x66b8, 0x66ca, 0x66dc, 0x66ef, 0x6701, 0x6714, 0x6726, 0x6738, 0x674b, - 0x675d, 0x6770, 0x6782, 0x6794, 0x67a7, 0x67b9, 0x67cc, 0x67de, 0x67f0, 0x6803, 0x6815, 0x6827, - 0x683a, 0x684c, 0x685e, 0x6871, 0x6883, 0x6896, 0x68a8, 0x68ba, 0x68cd, 0x68df, 0x68f1, 0x6904, - 0x6916, 0x6928, 0x693b, 0x694d, 0x695f, 0x6972, 0x6984, 0x6996, 0x69a8, 0x69bb, 0x69cd, 0x69df, - 0x69f2, 0x6a04, 0x6a16, 0x6a29, 0x6a3b, 0x6a4d, 0x6a5f, 0x6a72, 0x6a84, 0x6a96, 0x6aa9, 0x6abb, - 0x6acd, 0x6adf, 0x6af2, 0x6b04, 0x6b16, 0x6b28, 0x6b3b, 0x6b4d, 0x6b5f, 0x6b71, 0x6b84, 0x6b96, - 0x6ba8, 0x6bba, 0x6bcd, 0x6bdf, 0x6bf1, 0x6c03, 0x6c15, 0x6c28, 0x6c3a, 0x6c4c, 0x6c5e, 0x6c70, - 0x6c83, 0x6c95, 0x6ca7, 0x6cb9, 0x6ccb, 0x6cde, 0x6cf0, 0x6d02, 0x6d14, 0x6d26, 0x6d39, 0x6d4b, - 0x6d5d, 0x6d6f, 0x6d81, 0x6d93, 0x6da6, 0x6db8, 0x6dca, 0x6ddc, 0x6dee, 0x6e00, 0x6e12, 0x6e25, - 0x6e37, 0x6e49, 0x6e5b, 0x6e6d, 0x6e7f, 0x6e91, 0x6ea3, 0x6eb6, 0x6ec8, 0x6eda, 0x6eec, 0x6efe, - 0x6f10, 0x6f22, 0x6f34, 0x6f46, 0x6f58, 0x6f6b, 0x6f7d, 0x6f8f, 0x6fa1, 0x6fb3, 0x6fc5, 0x6fd7, - 0x6fe9, 0x6ffb, 0x700d, 0x701f, 0x7031, 0x7043, 0x7055, 0x7068, 0x707a, 0x708c, 0x709e, 0x70b0, - 0x70c2, 0x70d4, 0x70e6, 0x70f8, 0x710a, 0x711c, 0x712e, 0x7140, 0x7152, 0x7164, 0x7176, 0x7188, - 0x719a, 0x71ac, 0x71be, 0x71d0, 0x71e2, 0x71f4, 0x7206, 0x7218, 0x722a, 0x723c, 0x724e, 0x7260, - 0x7272, 0x7284, 0x7296, 0x72a8, 0x72ba, 0x72cc, 0x72dd, 0x72ef, 0x7301, 0x7313, 0x7325, 0x7337, - 0x7349, 0x735b, 0x736d, 0x737f, 0x7391, 0x73a3, 0x73b5, 0x73c7, 0x73d8, 0x73ea, 0x73fc, 0x740e, - 0x7420, 0x7432, 0x7444, 0x7456, 0x7468, 0x747a, 0x748b, 0x749d, 0x74af, 0x74c1, 0x74d3, 0x74e5, - 0x74f7, 0x7509, 0x751a, 0x752c, 0x753e, 0x7550, 0x7562, 0x7574, 0x7585, 0x7597, 0x75a9, 0x75bb, - 0x75cd, 0x75df, 0x75f0, 0x7602, 0x7614, 0x7626, 0x7638, 0x764a, 0x765b, 0x766d, 0x767f, 0x7691, - 0x76a3, 0x76b4, 0x76c6, 0x76d8, 0x76ea, 0x76fb, 0x770d, 0x771f, 0x7731, 0x7743, 0x7754, 0x7766, - 0x7778, 0x778a, 0x779b, 0x77ad, 0x77bf, 0x77d1, 0x77e2, 0x77f4, 0x7806, 0x7818, 0x7829, 0x783b, - 0x784d, 0x785e, 0x7870, 0x7882, 0x7894, 0x78a5, 0x78b7, 0x78c9, 0x78da, 0x78ec, 0x78fe, 0x7910, - 0x7921, 0x7933, 0x7945, 0x7956, 0x7968, 0x797a, 0x798b, 0x799d, 0x79af, 0x79c0, 0x79d2, 0x79e4, - 0x79f5, 0x7a07, 0x7a19, 0x7a2a, 0x7a3c, 0x7a4e, 0x7a5f, 0x7a71, 0x7a82, 0x7a94, 0x7aa6, 0x7ab7, - 0x7ac9, 0x7adb, 0x7aec, 0x7afe, 0x7b0f, 0x7b21, 0x7b33, 0x7b44, 0x7b56, 0x7b67, 0x7b79, 0x7b8b, - 0x7b9c, 0x7bae, 0x7bbf, 0x7bd1, 0x7be2, 0x7bf4, 0x7c06, 0x7c17, 0x7c29, 0x7c3a, 0x7c4c, 0x7c5d, - 0x7c6f, 0x7c81, 0x7c92, 0x7ca4, 0x7cb5, 0x7cc7, 0x7cd8, 0x7cea, 0x7cfb, 0x7d0d, 0x7d1e, 0x7d30, - 0x7d41, 0x7d53, 0x7d64, 0x7d76, 0x7d87, 0x7d99, 0x7daa, 0x7dbc, 0x7dcd, 0x7ddf, 0x7df0, 0x7e02, - 0x7e13, 0x7e25, 0x7e36, 0x7e48, 0x7e59, 0x7e6b, 0x7e7c, 0x7e8e, 0x7e9f, 0x7eb0, 0x7ec2, 0x7ed3, - 0x7ee5, 0x7ef6, 0x7f08, 0x7f19, 0x7f2b, 0x7f3c, 0x7f4d, 0x7f5f, 0x7f70, 0x7f82, 0x7f93, 0x7fa4, - 0x7fb6, 0x7fc7, 0x7fd9, 0x7fea, 0x7ffb, 0x800d, 0x801e, 0x8030, 0x8041, 0x8052, 0x8064, 0x8075, - 0x8086, 0x8098, 0x80a9, 0x80bb, 0x80cc, 0x80dd, 0x80ef, 0x8100, 0x8111, 0x8123, 0x8134, 0x8145, - 0x8157, 0x8168, 0x8179, 0x818b, 0x819c, 0x81ad, 0x81bf, 0x81d0, 0x81e1, 0x81f3, 0x8204, 0x8215, - 0x8226, 0x8238, 0x8249, 0x825a, 0x826c, 0x827d, 0x828e, 0x829f, 0x82b1, 0x82c2, 0x82d3, 0x82e5, - 0x82f6, 0x8307, 0x8318, 0x832a, 0x833b, 0x834c, 0x835d, 0x836f, 0x8380, 0x8391, 0x83a2, 0x83b3, - 0x83c5, 0x83d6, 0x83e7, 0x83f8, 0x840a, 0x841b, 0x842c, 0x843d, 0x844e, 0x8460, 0x8471, 0x8482, - 0x8493, 0x84a4, 0x84b6, 0x84c7, 0x84d8, 0x84e9, 0x84fa, 0x850b, 0x851d, 0x852e, 0x853f, 0x8550, - 0x8561, 0x8572, 0x8584, 0x8595, 0x85a6, 0x85b7, 0x85c8, 0x85d9, 0x85ea, 0x85fb, 0x860d, 0x861e, - 0x862f, 0x8640, 0x8651, 0x8662, 0x8673, 0x8684, 0x8695, 0x86a7, 0x86b8, 0x86c9, 0x86da, 0x86eb, - 0x86fc, 0x870d, 0x871e, 0x872f, 0x8740, 0x8751, 0x8762, 0x8773, 0x8784, 0x8796, 0x87a7, 0x87b8, - 0x87c9, 0x87da, 0x87eb, 0x87fc, 0x880d, 0x881e, 0x882f, 0x8840, 0x8851, 0x8862, 0x8873, 0x8884, - 0x8895, 0x88a6, 0x88b7, 0x88c8, 0x88d9, 0x88ea, 0x88fb, 0x890c, 0x891d, 0x892e, 0x893f, 0x8950, - 0x8961, 0x8972, 0x8983, 0x8994, 0x89a5, 0x89b6, 0x89c6, 0x89d7, 0x89e8, 0x89f9, 0x8a0a, 0x8a1b, - 0x8a2c, 0x8a3d, 0x8a4e, 0x8a5f, 0x8a70, 0x8a81, 0x8a92, 0x8aa3, 0x8ab3, 0x8ac4, 0x8ad5, 0x8ae6, - 0x8af7, 0x8b08, 0x8b19, 0x8b2a, 0x8b3b, 0x8b4b, 0x8b5c, 0x8b6d, 0x8b7e, 0x8b8f, 0x8ba0, 0x8bb1, - 0x8bc1, 0x8bd2, 0x8be3, 0x8bf4, 0x8c05, 0x8c16, 0x8c27, 0x8c37, 0x8c48, 0x8c59, 0x8c6a, 0x8c7b, - 0x8c8c, 0x8c9c, 0x8cad, 0x8cbe, 0x8ccf, 0x8ce0, 0x8cf0, 0x8d01, 0x8d12, 0x8d23, 0x8d34, 0x8d44, - 0x8d55, 0x8d66, 0x8d77, 0x8d87, 0x8d98, 0x8da9, 0x8dba, 0x8dca, 0x8ddb, 0x8dec, 0x8dfd, 0x8e0d, - 0x8e1e, 0x8e2f, 0x8e40, 0x8e50, 0x8e61, 0x8e72, 0x8e83, 0x8e93, 0x8ea4, 0x8eb5, 0x8ec5, 0x8ed6, - 0x8ee7, 0x8ef8, 0x8f08, 0x8f19, 0x8f2a, 0x8f3a, 0x8f4b, 0x8f5c, 0x8f6c, 0x8f7d, 0x8f8e, 0x8f9e, - 0x8faf, 0x8fc0, 0x8fd0, 0x8fe1, 0x8ff2, 0x9002, 0x9013, 0x9024, 0x9034, 0x9045, 0x9056, 0x9066, - 0x9077, 0x9088, 0x9098, 0x90a9, 0x90b9, 0x90ca, 0x90db, 0x90eb, 0x90fc, 0x910c, 0x911d, 0x912e, - 0x913e, 0x914f, 0x915f, 0x9170, 0x9181, 0x9191, 0x91a2, 0x91b2, 0x91c3, 0x91d3, 0x91e4, 0x91f5, - 0x9205, 0x9216, 0x9226, 0x9237, 0x9247, 0x9258, 0x9268, 0x9279, 0x9289, 0x929a, 0x92aa, 0x92bb, - 0x92cc, 0x92dc, 0x92ed, 0x92fd, 0x930e, 0x931e, 0x932f, 0x933f, 0x9350, 0x9360, 0x9370, 0x9381, - 0x9391, 0x93a2, 0x93b2, 0x93c3, 0x93d3, 0x93e4, 0x93f4, 0x9405, 0x9415, 0x9426, 0x9436, 0x9447, - 0x9457, 0x9467, 0x9478, 0x9488, 0x9499, 0x94a9, 0x94ba, 0x94ca, 0x94da, 0x94eb, 0x94fb, 0x950c, - 0x951c, 0x952c, 0x953d, 0x954d, 0x955e, 0x956e, 0x957e, 0x958f, 0x959f, 0x95af, 0x95c0, 0x95d0, - 0x95e1, 0x95f1, 0x9601, 0x9612, 0x9622, 0x9632, 0x9643, 0x9653, 0x9663, 0x9674, 0x9684, 0x9694, - 0x96a5, 0x96b5, 0x96c5, 0x96d6, 0x96e6, 0x96f6, 0x9707, 0x9717, 0x9727, 0x9738, 0x9748, 0x9758, - 0x9768, 0x9779, 0x9789, 0x9799, 0x97aa, 0x97ba, 0x97ca, 0x97da, 0x97eb, 0x97fb, 0x980b, 0x981b, - 0x982c, 0x983c, 0x984c, 0x985c, 0x986d, 0x987d, 0x988d, 0x989d, 0x98ad, 0x98be, 0x98ce, 0x98de, - 0x98ee, 0x98ff, 0x990f, 0x991f, 0x992f, 0x993f, 0x9950, 0x9960, 0x9970, 0x9980, 0x9990, 0x99a0, - 0x99b1, 0x99c1, 0x99d1, 0x99e1, 0x99f1, 0x9a01, 0x9a12, 0x9a22, 0x9a32, 0x9a42, 0x9a52, 0x9a62, - 0x9a72, 0x9a83, 0x9a93, 0x9aa3, 0x9ab3, 0x9ac3, 0x9ad3, 0x9ae3, 0x9af3, 0x9b04, 0x9b14, 0x9b24, - 0x9b34, 0x9b44, 0x9b54, 0x9b64, 0x9b74, 0x9b84, 0x9b94, 0x9ba4, 0x9bb5, 0x9bc5, 0x9bd5, 0x9be5, - 0x9bf5, 0x9c05, 0x9c15, 0x9c25, 0x9c35, 0x9c45, 0x9c55, 0x9c65, 0x9c75, 0x9c85, 0x9c95, 0x9ca5, - 0x9cb5, 0x9cc5, 0x9cd5, 0x9ce5, 0x9cf5, 0x9d05, 0x9d15, 0x9d25, 0x9d35, 0x9d45, 0x9d55, 0x9d65, - 0x9d75, 0x9d85, 0x9d95, 0x9da5, 0x9db5, 0x9dc5, 0x9dd5, 0x9de5, 0x9df5, 0x9e05, 0x9e15, 0x9e25, - 0x9e35, 0x9e45, 0x9e55, 0x9e65, 0x9e74, 0x9e84, 0x9e94, 0x9ea4, 0x9eb4, 0x9ec4, 0x9ed4, 0x9ee4, - 0x9ef4, 0x9f04, 0x9f14, 0x9f23, 0x9f33, 0x9f43, 0x9f53, 0x9f63, 0x9f73, 0x9f83, 0x9f93, 0x9fa3, - 0x9fb2, 0x9fc2, 0x9fd2, 0x9fe2, 0x9ff2, 0xa002, 0xa012, 0xa021, 0xa031, 0xa041, 0xa051, 0xa061, - 0xa071, 0xa080, 0xa090, 0xa0a0, 0xa0b0, 0xa0c0, 0xa0cf, 0xa0df, 0xa0ef, 0xa0ff, 0xa10f, 0xa11e, - 0xa12e, 0xa13e, 0xa14e, 0xa15e, 0xa16d, 0xa17d, 0xa18d, 0xa19d, 0xa1ac, 0xa1bc, 0xa1cc, 0xa1dc, - 0xa1eb, 0xa1fb, 0xa20b, 0xa21b, 0xa22a, 0xa23a, 0xa24a, 0xa25a, 0xa269, 0xa279, 0xa289, 0xa298, - 0xa2a8, 0xa2b8, 0xa2c8, 0xa2d7, 0xa2e7, 0xa2f7, 0xa306, 0xa316, 0xa326, 0xa335, 0xa345, 0xa355, - 0xa364, 0xa374, 0xa384, 0xa393, 0xa3a3, 0xa3b3, 0xa3c2, 0xa3d2, 0xa3e2, 0xa3f1, 0xa401, 0xa411, - 0xa420, 0xa430, 0xa440, 0xa44f, 0xa45f, 0xa46e, 0xa47e, 0xa48e, 0xa49d, 0xa4ad, 0xa4bc, 0xa4cc, - 0xa4dc, 0xa4eb, 0xa4fb, 0xa50a, 0xa51a, 0xa52a, 0xa539, 0xa549, 0xa558, 0xa568, 0xa577, 0xa587, - 0xa597, 0xa5a6, 0xa5b6, 0xa5c5, 0xa5d5, 0xa5e4, 0xa5f4, 0xa603, 0xa613, 0xa622, 0xa632, 0xa641, - 0xa651, 0xa660, 0xa670, 0xa67f, 0xa68f, 0xa69e, 0xa6ae, 0xa6bd, 0xa6cd, 0xa6dc, 0xa6ec, 0xa6fb, - 0xa70b, 0xa71a, 0xa72a, 0xa739, 0xa749, 0xa758, 0xa768, 0xa777, 0xa787, 0xa796, 0xa7a5, 0xa7b5, - 0xa7c4, 0xa7d4, 0xa7e3, 0xa7f3, 0xa802, 0xa812, 0xa821, 0xa830, 0xa840, 0xa84f, 0xa85f, 0xa86e, - 0xa87d, 0xa88d, 0xa89c, 0xa8ac, 0xa8bb, 0xa8ca, 0xa8da, 0xa8e9, 0xa8f8, 0xa908, 0xa917, 0xa927, - 0xa936, 0xa945, 0xa955, 0xa964, 0xa973, 0xa983, 0xa992, 0xa9a1, 0xa9b1, 0xa9c0, 0xa9cf, 0xa9df, - 0xa9ee, 0xa9fd, 0xaa0d, 0xaa1c, 0xaa2b, 0xaa3b, 0xaa4a, 0xaa59, 0xaa69, 0xaa78, 0xaa87, 0xaa96, - 0xaaa6, 0xaab5, 0xaac4, 0xaad4, 0xaae3, 0xaaf2, 0xab01, 0xab11, 0xab20, 0xab2f, 0xab3e, 0xab4e, - 0xab5d, 0xab6c, 0xab7b, 0xab8b, 0xab9a, 0xaba9, 0xabb8, 0xabc7, 0xabd7, 0xabe6, 0xabf5, 0xac04, - 0xac14, 0xac23, 0xac32, 0xac41, 0xac50, 0xac60, 0xac6f, 0xac7e, 0xac8d, 0xac9c, 0xacab, 0xacbb, - 0xacca, 0xacd9, 0xace8, 0xacf7, 0xad06, 0xad16, 0xad25, 0xad34, 0xad43, 0xad52, 0xad61, 0xad70, - 0xad80, 0xad8f, 0xad9e, 0xadad, 0xadbc, 0xadcb, 0xadda, 0xade9, 0xadf8, 0xae08, 0xae17, 0xae26, - 0xae35, 0xae44, 0xae53, 0xae62, 0xae71, 0xae80, 0xae8f, 0xae9e, 0xaead, 0xaebd, 0xaecc, 0xaedb, - 0xaeea, 0xaef9, 0xaf08, 0xaf17, 0xaf26, 0xaf35, 0xaf44, 0xaf53, 0xaf62, 0xaf71, 0xaf80, 0xaf8f, - 0xaf9e, 0xafad, 0xafbc, 0xafcb, 0xafda, 0xafe9, 0xaff8, 0xb007, 0xb016, 0xb025, 0xb034, 0xb043, - 0xb052, 0xb061, 0xb070, 0xb07f, 0xb08e, 0xb09d, 0xb0ac, 0xb0bb, 0xb0ca, 0xb0d9, 0xb0e8, 0xb0f6, - 0xb105, 0xb114, 0xb123, 0xb132, 0xb141, 0xb150, 0xb15f, 0xb16e, 0xb17d, 0xb18c, 0xb19b, 0xb1aa, - 0xb1b8, 0xb1c7, 0xb1d6, 0xb1e5, 0xb1f4, 0xb203, 0xb212, 0xb221, 0xb22f, 0xb23e, 0xb24d, 0xb25c, - 0xb26b, 0xb27a, 0xb289, 0xb297, 0xb2a6, 0xb2b5, 0xb2c4, 0xb2d3, 0xb2e2, 0xb2f1, 0xb2ff, 0xb30e, - 0xb31d, 0xb32c, 0xb33b, 0xb349, 0xb358, 0xb367, 0xb376, 0xb385, 0xb393, 0xb3a2, 0xb3b1, 0xb3c0, - 0xb3cf, 0xb3dd, 0xb3ec, 0xb3fb, 0xb40a, 0xb418, 0xb427, 0xb436, 0xb445, 0xb453, 0xb462, 0xb471, - 0xb480, 0xb48e, 0xb49d, 0xb4ac, 0xb4bb, 0xb4c9, 0xb4d8, 0xb4e7, 0xb4f6, 0xb504, 0xb513, 0xb522, - 0xb530, 0xb53f, 0xb54e, 0xb55c, 0xb56b, 0xb57a, 0xb588, 0xb597, 0xb5a6, 0xb5b5, 0xb5c3, 0xb5d2, - 0xb5e1, 0xb5ef, 0xb5fe, 0xb60d, 0xb61b, 0xb62a, 0xb638, 0xb647, 0xb656, 0xb664, 0xb673, 0xb682, - 0xb690, 0xb69f, 0xb6ae, 0xb6bc, 0xb6cb, 0xb6d9, 0xb6e8, 0xb6f7, 0xb705, 0xb714, 0xb722, 0xb731, - 0xb740, 0xb74e, 0xb75d, 0xb76b, 0xb77a, 0xb788, 0xb797, 0xb7a6, 0xb7b4, 0xb7c3, 0xb7d1, 0xb7e0, - 0xb7ee, 0xb7fd, 0xb80b, 0xb81a, 0xb829, 0xb837, 0xb846, 0xb854, 0xb863, 0xb871, 0xb880, 0xb88e, - 0xb89d, 0xb8ab, 0xb8ba, 0xb8c8, 0xb8d7, 0xb8e5, 0xb8f4, 0xb902, 0xb911, 0xb91f, 0xb92e, 0xb93c, - 0xb94b, 0xb959, 0xb968, 0xb976, 0xb984, 0xb993, 0xb9a1, 0xb9b0, 0xb9be, 0xb9cd, 0xb9db, 0xb9ea, - 0xb9f8, 0xba06, 0xba15, 0xba23, 0xba32, 0xba40, 0xba4f, 0xba5d, 0xba6b, 0xba7a, 0xba88, 0xba97, - 0xbaa5, 0xbab3, 0xbac2, 0xbad0, 0xbade, 0xbaed, 0xbafb, 0xbb0a, 0xbb18, 0xbb26, 0xbb35, 0xbb43, - 0xbb51, 0xbb60, 0xbb6e, 0xbb7c, 0xbb8b, 0xbb99, 0xbba8, 0xbbb6, 0xbbc4, 0xbbd3, 0xbbe1, 0xbbef, - 0xbbfd, 0xbc0c, 0xbc1a, 0xbc28, 0xbc37, 0xbc45, 0xbc53, 0xbc62, 0xbc70, 0xbc7e, 0xbc8c, 0xbc9b, - 0xbca9, 0xbcb7, 0xbcc6, 0xbcd4, 0xbce2, 0xbcf0, 0xbcff, 0xbd0d, 0xbd1b, 0xbd29, 0xbd38, 0xbd46, - 0xbd54, 0xbd62, 0xbd71, 0xbd7f, 0xbd8d, 0xbd9b, 0xbdaa, 0xbdb8, 0xbdc6, 0xbdd4, 0xbde2, 0xbdf1, - 0xbdff, 0xbe0d, 0xbe1b, 0xbe29, 0xbe38, 0xbe46, 0xbe54, 0xbe62, 0xbe70, 0xbe7f, 0xbe8d, 0xbe9b, - 0xbea9, 0xbeb7, 0xbec5, 0xbed4, 0xbee2, 0xbef0, 0xbefe, 0xbf0c, 0xbf1a, 0xbf28, 0xbf37, 0xbf45, - 0xbf53, 0xbf61, 0xbf6f, 0xbf7d, 0xbf8b, 0xbf99, 0xbfa7, 0xbfb6, 0xbfc4, 0xbfd2, 0xbfe0, 0xbfee, - 0xbffc, 0xc00a, 0xc018, 0xc026, 0xc034, 0xc042, 0xc051, 0xc05f, 0xc06d, 0xc07b, 0xc089, 0xc097, - 0xc0a5, 0xc0b3, 0xc0c1, 0xc0cf, 0xc0dd, 0xc0eb, 0xc0f9, 0xc107, 0xc115, 0xc123, 0xc131, 0xc13f, - 0xc14d, 0xc15b, 0xc169, 0xc177, 0xc185, 0xc193, 0xc1a1, 0xc1af, 0xc1bd, 0xc1cb, 0xc1d9, 0xc1e7, - 0xc1f5, 0xc203, 0xc211, 0xc21f, 0xc22d, 0xc23b, 0xc249, 0xc257, 0xc265, 0xc273, 0xc281, 0xc28f, - 0xc29d, 0xc2ab, 0xc2b8, 0xc2c6, 0xc2d4, 0xc2e2, 0xc2f0, 0xc2fe, 0xc30c, 0xc31a, 0xc328, 0xc336, - 0xc344, 0xc352, 0xc35f, 0xc36d, 0xc37b, 0xc389, 0xc397, 0xc3a5, 0xc3b3, 0xc3c1, 0xc3ce, 0xc3dc, - 0xc3ea, 0xc3f8, 0xc406, 0xc414, 0xc422, 0xc42f, 0xc43d, 0xc44b, 0xc459, 0xc467, 0xc475, 0xc482, - 0xc490, 0xc49e, 0xc4ac, 0xc4ba, 0xc4c7, 0xc4d5, 0xc4e3, 0xc4f1, 0xc4ff, 0xc50d, 0xc51a, 0xc528, - 0xc536, 0xc544, 0xc551, 0xc55f, 0xc56d, 0xc57b, 0xc589, 0xc596, 0xc5a4, 0xc5b2, 0xc5c0, 0xc5cd, - 0xc5db, 0xc5e9, 0xc5f7, 0xc604, 0xc612, 0xc620, 0xc62d, 0xc63b, 0xc649, 0xc657, 0xc664, 0xc672, - 0xc680, 0xc68d, 0xc69b, 0xc6a9, 0xc6b7, 0xc6c4, 0xc6d2, 0xc6e0, 0xc6ed, 0xc6fb, 0xc709, 0xc716, - 0xc724, 0xc732, 0xc73f, 0xc74d, 0xc75b, 0xc768, 0xc776, 0xc784, 0xc791, 0xc79f, 0xc7ad, 0xc7ba, - 0xc7c8, 0xc7d6, 0xc7e3, 0xc7f1, 0xc7fe, 0xc80c, 0xc81a, 0xc827, 0xc835, 0xc842, 0xc850, 0xc85e, - 0xc86b, 0xc879, 0xc886, 0xc894, 0xc8a2, 0xc8af, 0xc8bd, 0xc8ca, 0xc8d8, 0xc8e5, 0xc8f3, 0xc901, - 0xc90e, 0xc91c, 0xc929, 0xc937, 0xc944, 0xc952, 0xc95f, 0xc96d, 0xc97b, 0xc988, 0xc996, 0xc9a3, - 0xc9b1, 0xc9be, 0xc9cc, 0xc9d9, 0xc9e7, 0xc9f4, 0xca02, 0xca0f, 0xca1d, 0xca2a, 0xca38, 0xca45, - 0xca53, 0xca60, 0xca6e, 0xca7b, 0xca89, 0xca96, 0xcaa4, 0xcab1, 0xcabe, 0xcacc, 0xcad9, 0xcae7, - 0xcaf4, 0xcb02, 0xcb0f, 0xcb1d, 0xcb2a, 0xcb37, 0xcb45, 0xcb52, 0xcb60, 0xcb6d, 0xcb7b, 0xcb88, - 0xcb95, 0xcba3, 0xcbb0, 0xcbbe, 0xcbcb, 0xcbd8, 0xcbe6, 0xcbf3, 0xcc01, 0xcc0e, 0xcc1b, 0xcc29, - 0xcc36, 0xcc43, 0xcc51, 0xcc5e, 0xcc6c, 0xcc79, 0xcc86, 0xcc94, 0xcca1, 0xccae, 0xccbc, 0xccc9, - 0xccd6, 0xcce4, 0xccf1, 0xccfe, 0xcd0c, 0xcd19, 0xcd26, 0xcd34, 0xcd41, 0xcd4e, 0xcd5b, 0xcd69, - 0xcd76, 0xcd83, 0xcd91, 0xcd9e, 0xcdab, 0xcdb9, 0xcdc6, 0xcdd3, 0xcde0, 0xcdee, 0xcdfb, 0xce08, - 0xce15, 0xce23, 0xce30, 0xce3d, 0xce4a, 0xce58, 0xce65, 0xce72, 0xce7f, 0xce8d, 0xce9a, 0xcea7, - 0xceb4, 0xcec2, 0xcecf, 0xcedc, 0xcee9, 0xcef6, 0xcf04, 0xcf11, 0xcf1e, 0xcf2b, 0xcf38, 0xcf46, - 0xcf53, 0xcf60, 0xcf6d, 0xcf7a, 0xcf87, 0xcf95, 0xcfa2, 0xcfaf, 0xcfbc, 0xcfc9, 0xcfd6, 0xcfe4, - 0xcff1, 0xcffe, 0xd00b, 0xd018, 0xd025, 0xd032, 0xd040, 0xd04d, 0xd05a, 0xd067, 0xd074, 0xd081, - 0xd08e, 0xd09b, 0xd0a9, 0xd0b6, 0xd0c3, 0xd0d0, 0xd0dd, 0xd0ea, 0xd0f7, 0xd104, 0xd111, 0xd11e, - 0xd12b, 0xd139, 0xd146, 0xd153, 0xd160, 0xd16d, 0xd17a, 0xd187, 0xd194, 0xd1a1, 0xd1ae, 0xd1bb, - 0xd1c8, 0xd1d5, 0xd1e2, 0xd1ef, 0xd1fc, 0xd209, 0xd216, 0xd223, 0xd230, 0xd23d, 0xd24a, 0xd257, - 0xd264, 0xd271, 0xd27e, 0xd28b, 0xd298, 0xd2a5, 0xd2b2, 0xd2bf, 0xd2cc, 0xd2d9, 0xd2e6, 0xd2f3, - 0xd300, 0xd30d, 0xd31a, 0xd327, 0xd334, 0xd341, 0xd34e, 0xd35b, 0xd368, 0xd375, 0xd382, 0xd38f, - 0xd39c, 0xd3a8, 0xd3b5, 0xd3c2, 0xd3cf, 0xd3dc, 0xd3e9, 0xd3f6, 0xd403, 0xd410, 0xd41d, 0xd42a, - 0xd436, 0xd443, 0xd450, 0xd45d, 0xd46a, 0xd477, 0xd484, 0xd491, 0xd49e, 0xd4aa, 0xd4b7, 0xd4c4, - 0xd4d1, 0xd4de, 0xd4eb, 0xd4f8, 0xd504, 0xd511, 0xd51e, 0xd52b, 0xd538, 0xd545, 0xd551, 0xd55e, - 0xd56b, 0xd578, 0xd585, 0xd591, 0xd59e, 0xd5ab, 0xd5b8, 0xd5c5, 0xd5d1, 0xd5de, 0xd5eb, 0xd5f8, - 0xd605, 0xd611, 0xd61e, 0xd62b, 0xd638, 0xd645, 0xd651, 0xd65e, 0xd66b, 0xd678, 0xd684, 0xd691, - 0xd69e, 0xd6ab, 0xd6b7, 0xd6c4, 0xd6d1, 0xd6de, 0xd6ea, 0xd6f7, 0xd704, 0xd710, 0xd71d, 0xd72a, - 0xd737, 0xd743, 0xd750, 0xd75d, 0xd769, 0xd776, 0xd783, 0xd78f, 0xd79c, 0xd7a9, 0xd7b6, 0xd7c2, - 0xd7cf, 0xd7dc, 0xd7e8, 0xd7f5, 0xd802, 0xd80e, 0xd81b, 0xd828, 0xd834, 0xd841, 0xd84e, 0xd85a, - 0xd867, 0xd873, 0xd880, 0xd88d, 0xd899, 0xd8a6, 0xd8b3, 0xd8bf, 0xd8cc, 0xd8d8, 0xd8e5, 0xd8f2, - 0xd8fe, 0xd90b, 0xd917, 0xd924, 0xd931, 0xd93d, 0xd94a, 0xd956, 0xd963, 0xd970, 0xd97c, 0xd989, - 0xd995, 0xd9a2, 0xd9ae, 0xd9bb, 0xd9c8, 0xd9d4, 0xd9e1, 0xd9ed, 0xd9fa, 0xda06, 0xda13, 0xda1f, - 0xda2c, 0xda38, 0xda45, 0xda51, 0xda5e, 0xda6a, 0xda77, 0xda84, 0xda90, 0xda9d, 0xdaa9, 0xdab6, - 0xdac2, 0xdacf, 0xdadb, 0xdae7, 0xdaf4, 0xdb00, 0xdb0d, 0xdb19, 0xdb26, 0xdb32, 0xdb3f, 0xdb4b, - 0xdb58, 0xdb64, 0xdb71, 0xdb7d, 0xdb8a, 0xdb96, 0xdba2, 0xdbaf, 0xdbbb, 0xdbc8, 0xdbd4, 0xdbe1, - 0xdbed, 0xdbf9, 0xdc06, 0xdc12, 0xdc1f, 0xdc2b, 0xdc38, 0xdc44, 0xdc50, 0xdc5d, 0xdc69, 0xdc76, - 0xdc82, 0xdc8e, 0xdc9b, 0xdca7, 0xdcb3, 0xdcc0, 0xdccc, 0xdcd9, 0xdce5, 0xdcf1, 0xdcfe, 0xdd0a, - 0xdd16, 0xdd23, 0xdd2f, 0xdd3b, 0xdd48, 0xdd54, 0xdd60, 0xdd6d, 0xdd79, 0xdd85, 0xdd92, 0xdd9e, - 0xddaa, 0xddb7, 0xddc3, 0xddcf, 0xdddc, 0xdde8, 0xddf4, 0xde01, 0xde0d, 0xde19, 0xde25, 0xde32, - 0xde3e, 0xde4a, 0xde57, 0xde63, 0xde6f, 0xde7b, 0xde88, 0xde94, 0xdea0, 0xdeac, 0xdeb9, 0xdec5, - 0xded1, 0xdedd, 0xdeea, 0xdef6, 0xdf02, 0xdf0e, 0xdf1b, 0xdf27, 0xdf33, 0xdf3f, 0xdf4c, 0xdf58, - 0xdf64, 0xdf70, 0xdf7c, 0xdf89, 0xdf95, 0xdfa1, 0xdfad, 0xdfb9, 0xdfc6, 0xdfd2, 0xdfde, 0xdfea, - 0xdff6, 0xe003, 0xe00f, 0xe01b, 0xe027, 0xe033, 0xe03f, 0xe04c, 0xe058, 0xe064, 0xe070, 0xe07c, - 0xe088, 0xe094, 0xe0a1, 0xe0ad, 0xe0b9, 0xe0c5, 0xe0d1, 0xe0dd, 0xe0e9, 0xe0f5, 0xe102, 0xe10e, - 0xe11a, 0xe126, 0xe132, 0xe13e, 0xe14a, 0xe156, 0xe162, 0xe16e, 0xe17b, 0xe187, 0xe193, 0xe19f, - 0xe1ab, 0xe1b7, 0xe1c3, 0xe1cf, 0xe1db, 0xe1e7, 0xe1f3, 0xe1ff, 0xe20b, 0xe217, 0xe223, 0xe22f, - 0xe23c, 0xe248, 0xe254, 0xe260, 0xe26c, 0xe278, 0xe284, 0xe290, 0xe29c, 0xe2a8, 0xe2b4, 0xe2c0, - 0xe2cc, 0xe2d8, 0xe2e4, 0xe2f0, 0xe2fc, 0xe308, 0xe314, 0xe320, 0xe32c, 0xe338, 0xe344, 0xe350, - 0xe35c, 0xe368, 0xe374, 0xe380, 0xe38b, 0xe397, 0xe3a3, 0xe3af, 0xe3bb, 0xe3c7, 0xe3d3, 0xe3df, - 0xe3eb, 0xe3f7, 0xe403, 0xe40f, 0xe41b, 0xe427, 0xe433, 0xe43f, 0xe44a, 0xe456, 0xe462, 0xe46e, - 0xe47a, 0xe486, 0xe492, 0xe49e, 0xe4aa, 0xe4b6, 0xe4c1, 0xe4cd, 0xe4d9, 0xe4e5, 0xe4f1, 0xe4fd, - 0xe509, 0xe515, 0xe520, 0xe52c, 0xe538, 0xe544, 0xe550, 0xe55c, 0xe567, 0xe573, 0xe57f, 0xe58b, - 0xe597, 0xe5a3, 0xe5af, 0xe5ba, 0xe5c6, 0xe5d2, 0xe5de, 0xe5ea, 0xe5f5, 0xe601, 0xe60d, 0xe619, - 0xe625, 0xe630, 0xe63c, 0xe648, 0xe654, 0xe660, 0xe66b, 0xe677, 0xe683, 0xe68f, 0xe69a, 0xe6a6, - 0xe6b2, 0xe6be, 0xe6ca, 0xe6d5, 0xe6e1, 0xe6ed, 0xe6f9, 0xe704, 0xe710, 0xe71c, 0xe727, 0xe733, - 0xe73f, 0xe74b, 0xe756, 0xe762, 0xe76e, 0xe77a, 0xe785, 0xe791, 0xe79d, 0xe7a8, 0xe7b4, 0xe7c0, - 0xe7cb, 0xe7d7, 0xe7e3, 0xe7ef, 0xe7fa, 0xe806, 0xe812, 0xe81d, 0xe829, 0xe835, 0xe840, 0xe84c, - 0xe858, 0xe863, 0xe86f, 0xe87b, 0xe886, 0xe892, 0xe89e, 0xe8a9, 0xe8b5, 0xe8c0, 0xe8cc, 0xe8d8, - 0xe8e3, 0xe8ef, 0xe8fb, 0xe906, 0xe912, 0xe91d, 0xe929, 0xe935, 0xe940, 0xe94c, 0xe958, 0xe963, - 0xe96f, 0xe97a, 0xe986, 0xe991, 0xe99d, 0xe9a9, 0xe9b4, 0xe9c0, 0xe9cb, 0xe9d7, 0xe9e3, 0xe9ee, - 0xe9fa, 0xea05, 0xea11, 0xea1c, 0xea28, 0xea33, 0xea3f, 0xea4a, 0xea56, 0xea62, 0xea6d, 0xea79, - 0xea84, 0xea90, 0xea9b, 0xeaa7, 0xeab2, 0xeabe, 0xeac9, 0xead5, 0xeae0, 0xeaec, 0xeaf7, 0xeb03, - 0xeb0e, 0xeb1a, 0xeb25, 0xeb31, 0xeb3c, 0xeb48, 0xeb53, 0xeb5f, 0xeb6a, 0xeb76, 0xeb81, 0xeb8d, - 0xeb98, 0xeba3, 0xebaf, 0xebba, 0xebc6, 0xebd1, 0xebdd, 0xebe8, 0xebf4, 0xebff, 0xec0a, 0xec16, - 0xec21, 0xec2d, 0xec38, 0xec44, 0xec4f, 0xec5a, 0xec66, 0xec71, 0xec7d, 0xec88, 0xec93, 0xec9f, - 0xecaa, 0xecb6, 0xecc1, 0xeccc, 0xecd8, 0xece3, 0xecef, 0xecfa, 0xed05, 0xed11, 0xed1c, 0xed27, - 0xed33, 0xed3e, 0xed4a, 0xed55, 0xed60, 0xed6c, 0xed77, 0xed82, 0xed8e, 0xed99, 0xeda4, 0xedb0, - 0xedbb, 0xedc6, 0xedd2, 0xeddd, 0xede8, 0xedf4, 0xedff, 0xee0a, 0xee15, 0xee21, 0xee2c, 0xee37, - 0xee43, 0xee4e, 0xee59, 0xee65, 0xee70, 0xee7b, 0xee86, 0xee92, 0xee9d, 0xeea8, 0xeeb3, 0xeebf, - 0xeeca, 0xeed5, 0xeee1, 0xeeec, 0xeef7, 0xef02, 0xef0e, 0xef19, 0xef24, 0xef2f, 0xef3a, 0xef46, - 0xef51, 0xef5c, 0xef67, 0xef73, 0xef7e, 0xef89, 0xef94, 0xef9f, 0xefab, 0xefb6, 0xefc1, 0xefcc, - 0xefd7, 0xefe3, 0xefee, 0xeff9, 0xf004, 0xf00f, 0xf01b, 0xf026, 0xf031, 0xf03c, 0xf047, 0xf052, - 0xf05e, 0xf069, 0xf074, 0xf07f, 0xf08a, 0xf095, 0xf0a1, 0xf0ac, 0xf0b7, 0xf0c2, 0xf0cd, 0xf0d8, - 0xf0e3, 0xf0ef, 0xf0fa, 0xf105, 0xf110, 0xf11b, 0xf126, 0xf131, 0xf13c, 0xf147, 0xf153, 0xf15e, - 0xf169, 0xf174, 0xf17f, 0xf18a, 0xf195, 0xf1a0, 0xf1ab, 0xf1b6, 0xf1c2, 0xf1cd, 0xf1d8, 0xf1e3, - 0xf1ee, 0xf1f9, 0xf204, 0xf20f, 0xf21a, 0xf225, 0xf230, 0xf23b, 0xf246, 0xf251, 0xf25c, 0xf267, - 0xf272, 0xf27d, 0xf288, 0xf293, 0xf29f, 0xf2aa, 0xf2b5, 0xf2c0, 0xf2cb, 0xf2d6, 0xf2e1, 0xf2ec, - 0xf2f7, 0xf302, 0xf30d, 0xf318, 0xf323, 0xf32e, 0xf339, 0xf344, 0xf34f, 0xf35a, 0xf364, 0xf36f, - 0xf37a, 0xf385, 0xf390, 0xf39b, 0xf3a6, 0xf3b1, 0xf3bc, 0xf3c7, 0xf3d2, 0xf3dd, 0xf3e8, 0xf3f3, - 0xf3fe, 0xf409, 0xf414, 0xf41f, 0xf42a, 0xf435, 0xf43f, 0xf44a, 0xf455, 0xf460, 0xf46b, 0xf476, - 0xf481, 0xf48c, 0xf497, 0xf4a2, 0xf4ad, 0xf4b7, 0xf4c2, 0xf4cd, 0xf4d8, 0xf4e3, 0xf4ee, 0xf4f9, - 0xf504, 0xf50f, 0xf519, 0xf524, 0xf52f, 0xf53a, 0xf545, 0xf550, 0xf55b, 0xf565, 0xf570, 0xf57b, - 0xf586, 0xf591, 0xf59c, 0xf5a6, 0xf5b1, 0xf5bc, 0xf5c7, 0xf5d2, 0xf5dd, 0xf5e7, 0xf5f2, 0xf5fd, - 0xf608, 0xf613, 0xf61d, 0xf628, 0xf633, 0xf63e, 0xf649, 0xf653, 0xf65e, 0xf669, 0xf674, 0xf67f, - 0xf689, 0xf694, 0xf69f, 0xf6aa, 0xf6b4, 0xf6bf, 0xf6ca, 0xf6d5, 0xf6e0, 0xf6ea, 0xf6f5, 0xf700, - 0xf70b, 0xf715, 0xf720, 0xf72b, 0xf736, 0xf740, 0xf74b, 0xf756, 0xf760, 0xf76b, 0xf776, 0xf781, - 0xf78b, 0xf796, 0xf7a1, 0xf7ab, 0xf7b6, 0xf7c1, 0xf7cc, 0xf7d6, 0xf7e1, 0xf7ec, 0xf7f6, 0xf801, - 0xf80c, 0xf816, 0xf821, 0xf82c, 0xf836, 0xf841, 0xf84c, 0xf856, 0xf861, 0xf86c, 0xf876, 0xf881, - 0xf88c, 0xf896, 0xf8a1, 0xf8ac, 0xf8b6, 0xf8c1, 0xf8cc, 0xf8d6, 0xf8e1, 0xf8ec, 0xf8f6, 0xf901, - 0xf90b, 0xf916, 0xf921, 0xf92b, 0xf936, 0xf941, 0xf94b, 0xf956, 0xf960, 0xf96b, 0xf976, 0xf980, - 0xf98b, 0xf995, 0xf9a0, 0xf9aa, 0xf9b5, 0xf9c0, 0xf9ca, 0xf9d5, 0xf9df, 0xf9ea, 0xf9f4, 0xf9ff, - 0xfa0a, 0xfa14, 0xfa1f, 0xfa29, 0xfa34, 0xfa3e, 0xfa49, 0xfa53, 0xfa5e, 0xfa69, 0xfa73, 0xfa7e, - 0xfa88, 0xfa93, 0xfa9d, 0xfaa8, 0xfab2, 0xfabd, 0xfac7, 0xfad2, 0xfadc, 0xfae7, 0xfaf1, 0xfafc, - 0xfb06, 0xfb11, 0xfb1b, 0xfb26, 0xfb30, 0xfb3b, 0xfb45, 0xfb50, 0xfb5a, 0xfb65, 0xfb6f, 0xfb7a, - 0xfb84, 0xfb8f, 0xfb99, 0xfba4, 0xfbae, 0xfbb8, 0xfbc3, 0xfbcd, 0xfbd8, 0xfbe2, 0xfbed, 0xfbf7, - 0xfc02, 0xfc0c, 0xfc16, 0xfc21, 0xfc2b, 0xfc36, 0xfc40, 0xfc4b, 0xfc55, 0xfc5f, 0xfc6a, 0xfc74, - 0xfc7f, 0xfc89, 0xfc93, 0xfc9e, 0xfca8, 0xfcb3, 0xfcbd, 0xfcc7, 0xfcd2, 0xfcdc, 0xfce7, 0xfcf1, - 0xfcfb, 0xfd06, 0xfd10, 0xfd1a, 0xfd25, 0xfd2f, 0xfd3a, 0xfd44, 0xfd4e, 0xfd59, 0xfd63, 0xfd6d, - 0xfd78, 0xfd82, 0xfd8c, 0xfd97, 0xfda1, 0xfdab, 0xfdb6, 0xfdc0, 0xfdca, 0xfdd5, 0xfddf, 0xfde9, - 0xfdf4, 0xfdfe, 0xfe08, 0xfe13, 0xfe1d, 0xfe27, 0xfe32, 0xfe3c, 0xfe46, 0xfe50, 0xfe5b, 0xfe65, - 0xfe6f, 0xfe7a, 0xfe84, 0xfe8e, 0xfe98, 0xfea3, 0xfead, 0xfeb7, 0xfec1, 0xfecc, 0xfed6, 0xfee0, - 0xfeeb, 0xfef5, 0xfeff, 0xff09, 0xff14, 0xff1e, 0xff28, 0xff32, 0xff3c, 0xff47, 0xff51, 0xff5b, - 0xff65, 0xff70, 0xff7a, 0xff84, 0xff8e, 0xff98, 0xffa3, 0xffad, 0xffb7, 0xffc1, 0xffcc, 0xffd6, - 0xffe0, 0xffea, 0xfff4, 0xffff}; - -// max value is pi/4 -constexpr double SCALING_FACTOR = 4. / M_PI * 0xFFFF; - -inline double atan2_lookup(double y, double x) -{ - if (std::abs(x) < std::numeric_limits::epsilon()) - { - if (y >= 0.) - { - return M_PI / 2.; - } - else - { - return -M_PI / 2.; - } - } - - unsigned octant = 0; - - if (x < 0.) - { - octant = 1; - x = -x; - } - if (y < 0.) - { - octant |= 2; - y = -y; - } - - double t = y / x; - if (t > 1.0) - { - octant |= 4; - t = 1.0 / t; - } - - double angle = atan_table[(unsigned)(t * 4095)] / SCALING_FACTOR; - - switch (octant) - { - case 0: - break; - case 1: - angle = M_PI - angle; - break; - case 2: - angle = -angle; - break; - case 3: - angle = -M_PI + angle; - break; - case 4: - angle = M_PI / 2.0 - angle; - break; - case 5: - angle = M_PI / 2.0 + angle; - break; - case 6: - angle = -M_PI / 2.0 + angle; - break; - case 7: - angle = -M_PI / 2.0 - angle; - break; - } - return angle; -} - -#endif // TRIGONOMETRY_TABLE_HPP diff --git a/Util/xml_renderer.hpp b/Util/xml_renderer.hpp deleted file mode 100644 index bbf2287e1..000000000 --- a/Util/xml_renderer.hpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - -Copyright (c) 2014, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef XML_RENDERER_HPP -#define XML_RENDERER_HPP - -#include "cast.hpp" - -#include - -namespace JSON -{ - -struct XMLToArrayRenderer : mapbox::util::static_visitor<> -{ - explicit XMLToArrayRenderer(std::vector &_out) : out(_out) {} - - void operator()(const String &string) const - { - out.push_back('\"'); - out.insert(out.end(), string.value.begin(), string.value.end()); - out.push_back('\"'); - } - - void operator()(const Number &number) const - { - const std::string number_string = cast::double_fixed_to_string(number.value); - out.insert(out.end(), number_string.begin(), number_string.end()); - } - - void operator()(const Object &object) const - { - auto iterator = object.values.begin(); - while (iterator != object.values.end()) - { - if (iterator->first.at(0) != '_') - { - out.push_back('<'); - out.insert(out.end(), (*iterator).first.begin(), (*iterator).first.end()); - } - else - { - out.push_back(' '); - out.insert(out.end(), ++(*iterator).first.begin(), (*iterator).first.end()); - out.push_back('='); - } - mapbox::util::apply_visitor(XMLToArrayRenderer(out), (*iterator).second); - if (iterator->first.at(0) != '_') - { - out.push_back('/'); - out.push_back('>'); - } - ++iterator; - } - } - - void operator()(const Array &array) const - { - std::vector::const_iterator iterator; - iterator = array.values.begin(); - while (iterator != array.values.end()) - { - mapbox::util::apply_visitor(XMLToArrayRenderer(out), *iterator); - ++iterator; - } - } - - void operator()(const True &) const - { - const std::string temp("true"); - out.insert(out.end(), temp.begin(), temp.end()); - } - - void operator()(const False &) const - { - const std::string temp("false"); - out.insert(out.end(), temp.begin(), temp.end()); - } - - void operator()(const Null &) const - { - const std::string temp("null"); - out.insert(out.end(), temp.begin(), temp.end()); - } - - private: - std::vector &out; -}; - -template inline void xml_render(std::vector &out, const JSONObject &object) -{ - Value value = object; - mapbox::util::apply_visitor(XMLToArrayRenderer(out), value); -} - -template inline void gpx_render(std::vector &out, const JSONObject &object) -{ - // add header - - const std::string header{ - "Data (c) OpenStreetMap contributors (ODbL)"}; - out.insert(out.end(), header.begin(), header.end()); - - xml_render(out, object); - - const std::string footer{""}; - out.insert(out.end(), footer.begin(), footer.end()); -} -} // namespace JSON - -#endif // XML_RENDERER_HPP From 73cc040792bcf290254073a00406e9c1fcf41380 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 28 Jan 2015 12:32:09 +0100 Subject: [PATCH 146/360] add new lower case files and directories to .gitignore --- .gitignore | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 6a154a4b3..24b71f20d 100644 --- a/.gitignore +++ b/.gitignore @@ -36,8 +36,8 @@ Thumbs.db # build related files # ####################### /build/ -/Util/fingerprint.cpp -/Util/git_sha.cpp +/util/fingerprint.cpp +/util/git_sha.cpp /cmake/postinst # Eclipse related files # @@ -53,25 +53,13 @@ Thumbs.db stxxl.log stxxl.errlog -# compiled protobuffers # -######################### -/DataStructures/pbf-proto/*.pb.h -/DataStructures/pbf-proto/*.pb.cc - # External Libs # ################# /lib/ /win/lib -# Visual Studio Temp + build Files # +# Compiled Binary Files # #################################### -/win/*.user -/win/*.ncb -/win/*.suo -/win/Debug/ -/win/Release/ -/win/bin/ -/win/bin-debug/ /osrm-extract /osrm-io-benchmark /osrm-components From 3503cd9b7104882c5d4b31dab1c92473ed1dd3f1 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 28 Jan 2015 12:35:52 +0100 Subject: [PATCH 147/360] remove another windows directory from ignored files/dirs --- .gitignore | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.gitignore b/.gitignore index 24b71f20d..5d5cad2e3 100644 --- a/.gitignore +++ b/.gitignore @@ -53,11 +53,6 @@ Thumbs.db stxxl.log stxxl.errlog -# External Libs # -################# -/lib/ -/win/lib - # Compiled Binary Files # #################################### /osrm-extract From 46f3426c35e91c717915b3975a3ab456dc59e12e Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 28 Jan 2015 12:40:42 +0100 Subject: [PATCH 148/360] remove Http dir --- server/Http/Reply.cpp | 130 ------------------------------------------ 1 file changed, 130 deletions(-) delete mode 100644 server/Http/Reply.cpp diff --git a/server/Http/Reply.cpp b/server/Http/Reply.cpp deleted file mode 100644 index 2642e2be2..000000000 --- a/server/Http/Reply.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "reply.hpp" - -#include "../../util/cast.hpp" - -namespace http -{ - -const char ok_html[] = ""; -const char bad_request_html[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}"; -const char internal_server_error_html[] = - "{\"status\": 500,\"status_message\":\"Internal Server Error\"}"; -const char seperators[] = {':', ' '}; -const char crlf[] = {'\r', '\n'}; -const std::string http_ok_string = "HTTP/1.0 200 OK\r\n"; -const std::string http_bad_request_string = "HTTP/1.0 400 Bad Request\r\n"; -const std::string http_internal_server_error_string = "HTTP/1.0 500 Internal Server Error\r\n"; - -void reply::set_size(const std::size_t size) -{ - for (header &h : headers) - { - if ("Content-Length" == h.name) - { - h.value = cast::integral_to_string(size); - } - } -} - -void reply::set_uncompressed_size() { set_size(content.size()); } - -std::vector reply::to_buffers() -{ - std::vector buffers; - buffers.push_back(status_to_buffer(status)); - for (const header &h : headers) - { - buffers.push_back(boost::asio::buffer(h.name)); - buffers.push_back(boost::asio::buffer(seperators)); - buffers.push_back(boost::asio::buffer(h.value)); - buffers.push_back(boost::asio::buffer(crlf)); - } - buffers.push_back(boost::asio::buffer(crlf)); - buffers.push_back(boost::asio::buffer(content)); - return buffers; -} - -std::vector reply::headers_to_buffers() -{ - std::vector buffers; - buffers.push_back(status_to_buffer(status)); - for (const header ¤t_header : headers) - { - buffers.push_back(boost::asio::buffer(current_header.name)); - buffers.push_back(boost::asio::buffer(seperators)); - buffers.push_back(boost::asio::buffer(current_header.value)); - buffers.push_back(boost::asio::buffer(crlf)); - } - buffers.push_back(boost::asio::buffer(crlf)); - return buffers; -} - -reply reply::stock_reply(const reply::status_type status) -{ - reply reply; - reply.status = status; - reply.content.clear(); - - const std::string status_string = reply.status_to_string(status); - reply.content.insert(reply.content.end(), status_string.begin(), status_string.end()); - reply.headers.emplace_back("Access-Control-Allow-Origin", "*"); - reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size())); - reply.headers.emplace_back("Content-Type", "text/html"); - return reply; -} - -std::string reply::status_to_string(const reply::status_type status) -{ - if (reply::ok == status) - { - return ok_html; - } - if (reply::bad_request == status) - { - return bad_request_html; - } - return internal_server_error_html; -} - -boost::asio::const_buffer reply::status_to_buffer(const reply::status_type status) -{ - if (reply::ok == status) - { - return boost::asio::buffer(http_ok_string); - } - if (reply::internal_server_error == status) - { - return boost::asio::buffer(http_internal_server_error_string); - } - return boost::asio::buffer(http_bad_request_string); -} - -reply::reply() : status(ok) {} -} From ade94c87b5959b439cfe47476b82b593ff5ec408 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 29 Jan 2015 12:50:06 +0100 Subject: [PATCH 149/360] remove constexpr keyword that MSVC2013CTP isnt able to handle --- server/data_structures/shared_datatype.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/data_structures/shared_datatype.hpp b/server/data_structures/shared_datatype.hpp index 0c0b23910..f4cc6ca1c 100644 --- a/server/data_structures/shared_datatype.hpp +++ b/server/data_structures/shared_datatype.hpp @@ -38,7 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace { // Added at the start and end of each block as sanity check -constexpr static const char CANARY[] = "OSRM"; +static const char CANARY[] = "OSRM"; } struct SharedDataLayout From 8b2ca6b13db0e4937414f3e0b04777b4a20c7d81 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 29 Jan 2015 11:38:03 +0100 Subject: [PATCH 150/360] check if stxxl compiles with or without libgomp, fixes #1361 --- CMakeLists.txt | 5 ++++- cmake/check_stxxl.cmake | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 cmake/check_stxxl.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index f01518799..18ed94326 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,7 +176,7 @@ endif() # Activate C++11 if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - ADD_DEFINITIONS(-std=c++11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ") endif() # Configuring other platform dependencies @@ -265,6 +265,9 @@ target_link_libraries(OSRM ${STXXL_LIBRARY}) target_link_libraries(osrm-extract ${STXXL_LIBRARY}) target_link_libraries(osrm-prepare ${STXXL_LIBRARY}) +# check if we need to link against libgomp +include(check_stxxl) + if(MINGW) # STXXL needs OpenMP library target_link_libraries(osrm-extract gomp) diff --git a/cmake/check_stxxl.cmake b/cmake/check_stxxl.cmake new file mode 100644 index 000000000..0b437f3a3 --- /dev/null +++ b/cmake/check_stxxl.cmake @@ -0,0 +1,24 @@ +INCLUDE (CheckCXXSourceCompiles) +unset(STXXL_WORKS CACHE) +set (STXXL_CHECK_SRC "#include \n int main() { stxxl::vector vec; return 0;}") +set (CMAKE_TRY_COMPILE_CONFIGURATION ${CMAKE_BUILD_TYPE}) +set (CMAKE_REQUIRED_INCLUDES "${STXXL_INCLUDE_DIR}") +set (CMAKE_REQUIRED_LIBRARIES "${STXXL_LIBRARY}") + +CHECK_CXX_SOURCE_COMPILES("${STXXL_CHECK_SRC}" STXXL_WORKS) + +if(STXXL_WORKS) + message(STATUS "STXXL can be used without linking against libgomp") +else() + unset(STXXL_WORKS) + message(STATUS "STXXL failed without libgomp, retrying ..") + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} -lgomp) + + CHECK_CXX_SOURCE_COMPILES("${STXXL_CHECK_SRC}" STXXL_WORKS) + + if (STXXL_WORKS) + target_link_libraries(osrm-extract gomp) + else() + message(FATAL "STXXL failed failed, libgomp missing?") + endif() +endif() From d241aef502b240d9b47345560bd2f1c7124cb770 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 29 Jan 2015 12:41:38 +0100 Subject: [PATCH 151/360] fix checking for successful compilation of stxxl with OpenMP --- cmake/check_stxxl.cmake | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cmake/check_stxxl.cmake b/cmake/check_stxxl.cmake index 0b437f3a3..7f399f096 100644 --- a/cmake/check_stxxl.cmake +++ b/cmake/check_stxxl.cmake @@ -10,15 +10,15 @@ CHECK_CXX_SOURCE_COMPILES("${STXXL_CHECK_SRC}" STXXL_WORKS) if(STXXL_WORKS) message(STATUS "STXXL can be used without linking against libgomp") else() - unset(STXXL_WORKS) - message(STATUS "STXXL failed without libgomp, retrying ..") - set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} -lgomp) + message(STATUS "Linking STXXL failed without libgomp, retrying ..") + find_package(OpenMP) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}${OpenMP_CXX_FLAGS}") + CHECK_CXX_SOURCE_COMPILES("${STXXL_CHECK_SRC}" STXXL_LINKS) - CHECK_CXX_SOURCE_COMPILES("${STXXL_CHECK_SRC}" STXXL_WORKS) - - if (STXXL_WORKS) + if (STXXL_LINKS) + message(STATUS "STXXL needs to link against OpenMP") target_link_libraries(osrm-extract gomp) else() - message(FATAL "STXXL failed failed, libgomp missing?") + message(FATAL_ERROR "STXXL failed failed, libgomp missing?") endif() endif() From da469911d3f332685ed4f8dab7c1bcdc3c7cdc28 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 29 Jan 2015 16:23:04 +0100 Subject: [PATCH 152/360] always link against libgomp --- CMakeLists.txt | 31 ++++++++++++++++--------------- cmake/check_stxxl.cmake | 24 ------------------------ 2 files changed, 16 insertions(+), 39 deletions(-) delete mode 100644 cmake/check_stxxl.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 18ed94326..49bd7be61 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,9 +122,17 @@ if(CMAKE_BUILD_TYPE MATCHES Release) message(STATUS "Configuring OSRM in release mode") # Check if LTO is available set(LTO_FLAGS "") - CHECK_CXX_COMPILER_FLAG("-flto" HAS_LTO_FLAG) - if (HAS_LTO_FLAG) - set(LTO_FLAGS "${LTO_FLAGS} -flto") + check_cxx_compiler_flag("-flto" LTO_AVAILABLE) + if (LTO_AVAILABLE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto") + set(CHECK_LTO_SRC "int main(){return 0;}") + CHECK_CXX_SOURCE_COMPILES("${CHECK_LTO_SRC}" LTO_WORKS) + if(LTO_WORKS) + message(STATUS "LTO working") + else() + message(STATUS "LTO broken") + set(CMAKE_CXX_FLAGS "${OLD_CXX_FLAGS}") + endif() # Since gcc 4.9 the LTO format is non-standart ('slim'), so we need to use the build-in tools if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND @@ -132,9 +140,8 @@ if(CMAKE_BUILD_TYPE MATCHES Release) message(STATUS "Using gcc specific binutils for LTO.") set(CMAKE_AR "/usr/bin/gcc-ar") set(CMAKE_RANLIB "/usr/bin/gcc-ranlib") -# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3") endif() - endif (HAS_LTO_FLAG) + endif () endif() if (NOT WIN32) @@ -246,7 +253,7 @@ include_directories(${LUABIND_INCLUDE_DIR}) target_link_libraries(osrm-extract ${LUABIND_LIBRARY}) target_link_libraries(osrm-prepare ${LUABIND_LIBRARY}) -if( LUAJIT_FOUND ) +if(LUAJIT_FOUND) target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES}) target_link_libraries(osrm-prepare ${LUAJIT_LIBRARIES}) else() @@ -259,21 +266,15 @@ find_package(EXPAT REQUIRED) include_directories(${EXPAT_INCLUDE_DIRS}) target_link_libraries(osrm-extract ${EXPAT_LIBRARIES}) -find_package( STXXL REQUIRED ) +find_package(STXXL REQUIRED) include_directories(${STXXL_INCLUDE_DIR}) target_link_libraries(OSRM ${STXXL_LIBRARY}) target_link_libraries(osrm-extract ${STXXL_LIBRARY}) target_link_libraries(osrm-prepare ${STXXL_LIBRARY}) -# check if we need to link against libgomp -include(check_stxxl) +target_link_libraries(osrm-extract gomp) -if(MINGW) - # STXXL needs OpenMP library - target_link_libraries(osrm-extract gomp) -endif() - -find_package( OSMPBF REQUIRED ) +find_package(OSMPBF REQUIRED) include_directories(${OSMPBF_INCLUDE_DIR}) target_link_libraries(osrm-extract ${OSMPBF_LIBRARY}) target_link_libraries(osrm-prepare ${OSMPBF_LIBRARY}) diff --git a/cmake/check_stxxl.cmake b/cmake/check_stxxl.cmake deleted file mode 100644 index 7f399f096..000000000 --- a/cmake/check_stxxl.cmake +++ /dev/null @@ -1,24 +0,0 @@ -INCLUDE (CheckCXXSourceCompiles) -unset(STXXL_WORKS CACHE) -set (STXXL_CHECK_SRC "#include \n int main() { stxxl::vector vec; return 0;}") -set (CMAKE_TRY_COMPILE_CONFIGURATION ${CMAKE_BUILD_TYPE}) -set (CMAKE_REQUIRED_INCLUDES "${STXXL_INCLUDE_DIR}") -set (CMAKE_REQUIRED_LIBRARIES "${STXXL_LIBRARY}") - -CHECK_CXX_SOURCE_COMPILES("${STXXL_CHECK_SRC}" STXXL_WORKS) - -if(STXXL_WORKS) - message(STATUS "STXXL can be used without linking against libgomp") -else() - message(STATUS "Linking STXXL failed without libgomp, retrying ..") - find_package(OpenMP) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}${OpenMP_CXX_FLAGS}") - CHECK_CXX_SOURCE_COMPILES("${STXXL_CHECK_SRC}" STXXL_LINKS) - - if (STXXL_LINKS) - message(STATUS "STXXL needs to link against OpenMP") - target_link_libraries(osrm-extract gomp) - else() - message(FATAL_ERROR "STXXL failed failed, libgomp missing?") - endif() -endif() From 36aadc21a7f75ab77346ce31d45de5d8b12b78d9 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 29 Jan 2015 16:44:32 +0100 Subject: [PATCH 153/360] fix names of fwd declarations --- library/osrm_impl.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/library/osrm_impl.hpp b/library/osrm_impl.hpp index 8f12ba69c..55674c84b 100644 --- a/library/osrm_impl.hpp +++ b/library/osrm_impl.hpp @@ -29,10 +29,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define OSRM_IMPL_HPP class BasePlugin; -namespace http -{ -class Reply; -} struct RouteParameters; #include "../data_structures/query_edge.hpp" From a883b73981a872600fdc1f5d406aaeb5bdae3fdd Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 29 Jan 2015 17:01:08 +0100 Subject: [PATCH 154/360] add explicit cmake checking step for libgomp --- CMakeLists.txt | 5 ++++- cmake/FindGomp.cmake | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 cmake/FindGomp.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 49bd7be61..834031b15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -272,7 +272,10 @@ target_link_libraries(OSRM ${STXXL_LIBRARY}) target_link_libraries(osrm-extract ${STXXL_LIBRARY}) target_link_libraries(osrm-prepare ${STXXL_LIBRARY}) -target_link_libraries(osrm-extract gomp) +find_package(Gomp REQUIRED) +if(LIBGOMP_FOUND) + target_link_libraries(osrm-extract gomp) +endif() find_package(OSMPBF REQUIRED) include_directories(${OSMPBF_INCLUDE_DIR}) diff --git a/cmake/FindGomp.cmake b/cmake/FindGomp.cmake new file mode 100644 index 000000000..3721e8156 --- /dev/null +++ b/cmake/FindGomp.cmake @@ -0,0 +1,18 @@ +# - Try to find Libgomp +# Once done this will define +# LIBGOMP_FOUND - System has Libgomp +# LIBGOMP_INCLUDE_DIRS - The Libgomp include directories +# LIBGOMP_DEFINITIONS - Compiler switches required for using Libgomp + +message(STATUS "Checking if libgomp is present") + +find_library(LIBGOMP_LIBRARY NAMES gomp libgomp + HINTS ${PC_LIBXML_LIBDIR} ${PC_LIBXML_LIBRARY_DIRS} ) + +set(LIBGOMP_LIBRARIES ${LIBGOMP_LIBRARY} ) + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set LIBGOMP_FOUND to TRUE +# if all listed variables are TRUE +#find_package_handle_standard_args(Libgomp DEFAULT_MSG +# LIBGOMP_LIBRARY LIBGOMP_INCLUDE_DIR) From 97f64686630ce6ee50ca8fbcbc27f4ae20905d8d Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 29 Jan 2015 17:29:03 +0100 Subject: [PATCH 155/360] yet another try to unhack libgomp linking: use OpenMP binding if and only if present --- CMakeLists.txt | 7 ++++--- cmake/FindGomp.cmake | 18 ------------------ 2 files changed, 4 insertions(+), 21 deletions(-) delete mode 100644 cmake/FindGomp.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 834031b15..8c70efb56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -272,9 +272,10 @@ target_link_libraries(OSRM ${STXXL_LIBRARY}) target_link_libraries(osrm-extract ${STXXL_LIBRARY}) target_link_libraries(osrm-prepare ${STXXL_LIBRARY}) -find_package(Gomp REQUIRED) -if(LIBGOMP_FOUND) - target_link_libraries(osrm-extract gomp) +find_package(OpenMP) +if(OPENMP_FOUND) + message(STATUS "OpenMP support found. Linking just in case for stxxl") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") endif() find_package(OSMPBF REQUIRED) diff --git a/cmake/FindGomp.cmake b/cmake/FindGomp.cmake deleted file mode 100644 index 3721e8156..000000000 --- a/cmake/FindGomp.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# - Try to find Libgomp -# Once done this will define -# LIBGOMP_FOUND - System has Libgomp -# LIBGOMP_INCLUDE_DIRS - The Libgomp include directories -# LIBGOMP_DEFINITIONS - Compiler switches required for using Libgomp - -message(STATUS "Checking if libgomp is present") - -find_library(LIBGOMP_LIBRARY NAMES gomp libgomp - HINTS ${PC_LIBXML_LIBDIR} ${PC_LIBXML_LIBRARY_DIRS} ) - -set(LIBGOMP_LIBRARIES ${LIBGOMP_LIBRARY} ) - -include(FindPackageHandleStandardArgs) -# handle the QUIETLY and REQUIRED arguments and set LIBGOMP_FOUND to TRUE -# if all listed variables are TRUE -#find_package_handle_standard_args(Libgomp DEFAULT_MSG -# LIBGOMP_LIBRARY LIBGOMP_INCLUDE_DIR) From 9f5fc4ab0c43469f9bc1801ee0735457ab7a6599 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Sat, 31 Jan 2015 21:17:16 +0100 Subject: [PATCH 156/360] reorder includes --- extractor/extractor.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extractor/extractor.cpp b/extractor/extractor.cpp index 326a43e23..b7d84156c 100644 --- a/extractor/extractor.cpp +++ b/extractor/extractor.cpp @@ -41,13 +41,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../typedefs.h" +#include +#include + #include #include -#include -#include - #include #include From 129a6ed99e5851c7bacfff1530d308474f841305 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 4 Feb 2015 19:36:39 +0000 Subject: [PATCH 157/360] added lua binding for osmium::Way::id() --- extractor/scripting_environment.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/extractor/scripting_environment.cpp b/extractor/scripting_environment.cpp index c51651e40..1050fa9d1 100644 --- a/extractor/scripting_environment.cpp +++ b/extractor/scripting_environment.cpp @@ -118,6 +118,7 @@ void ScriptingEnvironment::init_lua_state(lua_State* lua_state) luabind::class_("Way") .def("get_value_by_key", &osmium::Way::get_value_by_key) .def("get_value_by_key", &get_value_by_key) + .def("id", &osmium::Way::id) ]; if (0 != luaL_dofile(lua_state, file_name.c_str())) From bf7646502923a975d99882f294d9590b8c4b7264 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 5 Feb 2015 11:22:46 +0100 Subject: [PATCH 158/360] use C++11s std::hypot() instead of hand-rolled code --- algorithms/douglas_peucker.cpp | 4 ++-- data_structures/coordinate_calculation.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/algorithms/douglas_peucker.cpp b/algorithms/douglas_peucker.cpp index 3de89da4e..b3a01f440 100644 --- a/algorithms/douglas_peucker.cpp +++ b/algorithms/douglas_peucker.cpp @@ -63,12 +63,12 @@ struct CoordinatePairCalculator // compute distance (a,c) const float x_value_1 = (first_lon - float_lon1) * cos((float_lat1 + first_lat) / 2.f); const float y_value_1 = first_lat - float_lat1; - const float dist1 = sqrt(std::pow(x_value_1, 2) + std::pow(y_value_1, 2)) * earth_radius; + const float dist1 = std::hypot(x_value_1, y_value_1) * earth_radius; // compute distance (b,c) const float x_value_2 = (second_lon - float_lon1) * cos((float_lat1 + second_lat) / 2.f); const float y_value_2 = second_lat - float_lat1; - const float dist2 = sqrt(std::pow(x_value_2, 2) + std::pow(y_value_2, 2)) * earth_radius; + const float dist2 = std::hypot(x_value_2, y_value_2) * earth_radius; // return the minimum return static_cast(std::min(dist1, dist2)); diff --git a/data_structures/coordinate_calculation.cpp b/data_structures/coordinate_calculation.cpp index 326a87981..05dc08789 100644 --- a/data_structures/coordinate_calculation.cpp +++ b/data_structures/coordinate_calculation.cpp @@ -103,7 +103,7 @@ float coordinate_calculation::euclidean_distance(const int lat1, const float x_value = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.f); const float y_value = float_lat2 - float_lat1; - return sqrt(x_value * x_value + y_value * y_value) * earth_radius; + return std::hypot(x_value, y_value) * earth_radius; } float coordinate_calculation::perpendicular_distance(const FixedPointCoordinate &source_coordinate, From 3d55622237209dcdb18d4cc7f08fa374af22e9d9 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 5 Feb 2015 11:37:55 +0100 Subject: [PATCH 159/360] search quietly for OpenMP --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c70efb56..2beaa31c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -272,6 +272,7 @@ target_link_libraries(OSRM ${STXXL_LIBRARY}) target_link_libraries(osrm-extract ${STXXL_LIBRARY}) target_link_libraries(osrm-prepare ${STXXL_LIBRARY}) +set(OpenMP_FIND_QUIETLY ON) find_package(OpenMP) if(OPENMP_FOUND) message(STATUS "OpenMP support found. Linking just in case for stxxl") From d77a88c21e6b847c02b2d52af0ee7519c634a851 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 4 Feb 2015 19:36:39 +0000 Subject: [PATCH 160/360] added lua binding for osmium::Way::id() Conflicts: extractor/scripting_environment.cpp --- extractor/scripting_environment.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/extractor/scripting_environment.cpp b/extractor/scripting_environment.cpp index 45e4d0226..f8235c93f 100644 --- a/extractor/scripting_environment.cpp +++ b/extractor/scripting_environment.cpp @@ -120,6 +120,7 @@ void ScriptingEnvironment::init_lua_state(lua_State *lua_state) luabind::class_("Way") .def("get_value_by_key", &osmium::Way::get_value_by_key) .def("get_value_by_key", &get_value_by_key) + .def("id", &osmium::Way::id) ]; if (0 != luaL_dofile(lua_state, file_name.c_str())) From f35fa0049ccd7d323f7a72eafb94655769638247 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 5 Feb 2015 11:54:30 +0100 Subject: [PATCH 161/360] reformat cherry-picked commit --- extractor/scripting_environment.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extractor/scripting_environment.cpp b/extractor/scripting_environment.cpp index f8235c93f..0cc073a39 100644 --- a/extractor/scripting_environment.cpp +++ b/extractor/scripting_environment.cpp @@ -120,7 +120,7 @@ void ScriptingEnvironment::init_lua_state(lua_State *lua_state) luabind::class_("Way") .def("get_value_by_key", &osmium::Way::get_value_by_key) .def("get_value_by_key", &get_value_by_key) - .def("id", &osmium::Way::id) + .def("id", &osmium::Way::id) ]; if (0 != luaL_dofile(lua_state, file_name.c_str())) From 3eb83d073764804747ef4ebc1aee2d115946cea5 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 5 Feb 2015 14:58:07 +0100 Subject: [PATCH 162/360] add override final specifier to GetTravelMode function in facades --- server/data_structures/internal_datafacade.hpp | 5 ++++- server/data_structures/shared_datafacade.hpp | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/server/data_structures/internal_datafacade.hpp b/server/data_structures/internal_datafacade.hpp index 0a246b791..1f4b6ef8c 100644 --- a/server/data_structures/internal_datafacade.hpp +++ b/server/data_structures/internal_datafacade.hpp @@ -360,7 +360,10 @@ template class InternalDataFacade final : public BaseDataFacad return m_coordinate_list->at(id); }; - bool EdgeIsCompressed(const unsigned id) const { return m_edge_is_compressed.at(id); } + bool EdgeIsCompressed(const unsigned id) const override final + { + return m_edge_is_compressed.at(id); + } TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const override final { diff --git a/server/data_structures/shared_datafacade.hpp b/server/data_structures/shared_datafacade.hpp index c7951fb3b..4944d320f 100644 --- a/server/data_structures/shared_datafacade.hpp +++ b/server/data_structures/shared_datafacade.hpp @@ -356,7 +356,10 @@ template class SharedDataFacade final : public BaseDataFacade< return m_turn_instruction_list.at(id); } - TravelMode GetTravelModeForEdgeID(const unsigned id) const { return m_travel_mode_list.at(id); } + TravelMode GetTravelModeForEdgeID(const unsigned id) const override final + { + return m_travel_mode_list.at(id); + } bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate, FixedPointCoordinate &result, From bb78bc8fe305eef39ca0a5d5e9dedc466f803dfb Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 5 Feb 2015 15:13:48 +0100 Subject: [PATCH 163/360] Squashed 'third_party/libosmium/' changes from 910f8f1..6522da5 6522da5 Merge pull request #79 from DennisOSRM/master 7c8d8dc add override keyword to close(), overridden function in include/osmium/io/detail/input_format.hpp d24841e Changes copyright dates in all files to a consistent "2013-2015". 3adc7d7 Another try to make it compile on Windows. 20dad8e Use auto instead of hard-coded types, hopefully fixes Windows build. b73ab3f Set build config in appveyor ctest call. 3e33857 Merge pull request #76 from BergWerkGIS/master c78ca6e Merge remote-tracking branch 'upstream/master' cf42013 enable test again 69e4a91 include compatibility.h 6f79b5c CMake: Remove Dart include, it seems to be superfluous. 4d40a18 Explicitly set copy constructors etc. for OutputIterator and test it. 69ee34c Run tests in build directory instead of source directory. 11c44c8 Fix typo. 675cc11 Fix formatting CMake config. 7aa3cb0 Add a benchmark counting amenity=post_box tags. 89fd942 Make it more evident that we handling constant tag lists. c72bbdf Add count() and empty() functions to Filter class. 88b9543 Disable annoying warnings from YouCompleteMe. 6cec403 Benchmarks: Only find files, not directories etc. in data dir. 09c4630 Follow redirects in benchmark download script. a8a552e Use Approx() function from Catch framework for floating point comparisons. 7db5086 Reorder data tests so fast tests run first. 24ce403 Fix #includes. ad9515c Add some comments in different config files to explain what they are. 987aa9c Some README updates. 3c18de7 Add configuration for YouCompleteMe Vim plugin. 433148e Explicit comparison against 0 to avoid warning with MSVC. e64a459 Small updates in benchmarks README. e4aff7f Add benchmark to compare static vs. dynamic index maps. f702634 Add missing include. 95a8c3b Merge branch 'master' of github.com:osmcode/libosmium 560a2ae Merge pull request #73 from osmcode/travis-fix f41e4ca remove incorrect cd f826107 Add some helper functions for working with entity_bits. 8fec1c1 Updated README: Lots of documentation is now on wiki. 6110cc8 Make cmake config work if no components are given. 8136557 Use 'Libosmium' instead of 'Osmium' as project name in doc. 10e631a Improved documenation: Dependencies to link with. 41d0ca4 Merge remote-tracking branch 'upstream/master' 6768026 SLN configuration is always 'Release' 5d985cf av: show env vars. 272ac88 don't use '%CONFIGURATION%' expands to e.g. 'Dev|x86' 59b15eb use cmake 3.1.0 again. old cmake on AppVeyor doesn't know yet about VS2014 SLN 0d0d71a try building with VS, Dev works only with VS at least locally 2fe6d02 name of geos.lib changed fc4662e test latest binary package d4a265f Add more labels to tests. 8722a3d Only check for valgrind if testing is enabled. cf7dc56 README improvements. 13a426e Fix cpack configuration. ae649c8 travis build: fix double install of make package c102040 Move cmake config for documentation into doc directory. 6064d55 Also list advanced cmake variables in travis build. c299bfa constexprt workaround for MSVC. afcf7a1 Cleanup/formatting of cmake config. a536720 Fix travis build by cloning osm-testdata in the right place. 2bdbf7f cmake: Don't clone osm-testdata repository any more. 5bdbb28 Rename test/osm-testdata to test/data-tests. 0ad0020 cmake: build data tests only by default on Dev builds 2cefa50 Add some benchmarks. 3fdb6e1 Remove outdated make_osmium_project.sh script. aca58ac Fix cmake config: overwriting of variables. 152e318 Fix compilation of examples that need wingetopt on Windows. ae17cd0 Remove superfluous warning on Windows for header test builds. f88d4c2 Switch to /W3 on Windows. 8edeba5 Remove duplicate copy constructor. cdb474e Cleanup examples cmake config ca9045a Cmake cleanup. 501eb61 Update to new version of catch unit test framework. 0646d6c Parenthesize expression to make test clearer and avoid warnings. dfdaeae Disable a warning that gdal throws on Windows. eacfe4f Explicitly test int !=0 to convert to bool. b3ba693 Cleanup of cmake config (mostly warning options Linux vs. Win) 3f5cb81 Appveyor: Also show advanced cmake variables. b544bd9 Never return valid but empty buffer from Reader.read() call. a34bb5d Declare var in a more local scope. b83e5f1 Merge pull request #66 from BergWerkGIS/master 04ef1b2 Last try for today, should solve geos test failures a749d6c hey AppVeyor: what's going on? 73131fb av: boost not found?? show directory tree 5e02886 av: should solve most "***Exception: Other" except for geos.dll related problem. should solve projection test fails. a7ae560 FlexReader now takes location handler as parameter. 6f1bd8d Disable non-existing Debian build in Makefile. 3d75178 Change warning level on MSVC. 3f0abc0 Appveyor: List cached variables from cmake. d1e1e9f Travis/Appveyor build in Dev and Release mode. Call ctest on Appveyor. 116bcc9 Fix default node location store. dedfe0e Make classes we submit to queue properly copyable. 8a432c9 Try the same ugly hack on OPLOutputBlock. 9c5b314 Try a hack to see whether it works on MSVC. 9592132 Give XMLOutputBlock a copy constructor. 991f91a Disable warning C4715: "not all control paths return a value" 340a4d7 Fix copy constructor. 7ceae00 Give OPLOutputBlock a copy constructor which basically does a move. e82951a Use rvalue as paremeter for queue submit function. 54a9cec Use explicit cast to double to silence warning. 7c5d04c Simplified use of ogr includes. 43fd388 Use appveyor supplied cmake. ce4311e cmake cleanup. 1108517 Disable warnings from MSVC in OGR headers. 2fe820c Harmonize signature of virtual member function dump_as_list(). 93c31b4 Parenthesize string in pragma message. 54ae1a0 Explicitly int to bool conversion to silence warning on MSVC. 4bde9b7 Formatting: Use spaces instead of tabs. 7224d84 cmake: Don't try to set C++ version with -std= with MSVC. 53fbcfd Remove trailing semikolon (which gcc doesn't like). 3b0c9ed Removed command that doesn't work on older cmakes. de6cc78 Merge pull request #62 from BergWerkGIS/master 9126530 Use less warning options on Windows. 6ec79fb Silence unknown pragma warning on Windows. b611589 Add static_cast to silence warning on windows. 18e54e9 remove call to build2.bat b0d9d28 try again with -DCMAKE_BUILD_TYPE=Release b495018 usage installed cmake, -DCMAKE_BUILD_TYPE=Dev 5bac95d Merge remote-tracking branch 'upstream/master' d41ea31 cmake: Do not use -Werror when using MSVC compiler 04cfe00 Provide convenience include file to include all index maps. 72fbaa7 Rename multimap indexes according to new schema. af49a27 Make registering index map types easier. 0a35701 av: remove debug echo calls 886c15f av: ditch -DCMAKE_BUILD_TYPE=Dev ad0a629 The great renaming of map index classes. 97b4d34 av: try again bf243b2 Move some hpp files into detail directory and fix include guards. 64e4841 av: try again calling cmake directly 1700789 Add way to dynamically choose node location index. da49b7f av: try again with build2.bat 4bf55f5 is appveyor working again? 5e63433 delete ws_32.lib patch. generate makefile instead of VS 1054016 Merge remote-tracking branch 'upstream/master' 8c198fc av: try even newer cmake 7cccb06 av: maybe newer cmake helps d04967a av: no existing env var was still there 80763c6 av: no build.bat, call cmake directly 3b58fc6 av: no cmds over spanning serveral lines? 33c09a0 CALL bat 34639c6 maybe double quotes? 72572de explicitly call VS2014 cmd prompt 6955e87 1st try on AppVeyor git-subtree-dir: third_party/libosmium git-subtree-split: 6522da53748e12379bbfaf70ad29ee7bd98ef02d --- .gitignore | 1 + .travis.yml | 18 +- .ycm_extra_conf.py | 44 +++ CMakeLists.txt | 309 +++++++++++------- Makefile | 10 +- README-changes-from-old-osmium | 43 --- README.md | 175 ++-------- appveyor.yml | 72 ++-- benchmarks/CMakeLists.txt | 48 +++ benchmarks/README.md | 41 +++ benchmarks/download_data.sh | 12 + benchmarks/osmium_benchmark_count.cpp | 54 +++ benchmarks/osmium_benchmark_count_tag.cpp | 55 ++++ benchmarks/osmium_benchmark_index_map.cpp | 41 +++ ...mium_benchmark_static_vs_dynamic_index.cpp | 136 ++++++++ benchmarks/run_benchmark_count.sh | 22 ++ benchmarks/run_benchmark_count_tag.sh | 22 ++ benchmarks/run_benchmark_index_map.sh | 27 ++ .../run_benchmark_static_vs_dynamic_index.sh | 21 ++ benchmarks/run_benchmarks.sh | 15 + benchmarks/setup.sh | 34 ++ cmake/FindOsmium.cmake | 46 ++- doc/CMakeLists.txt | 34 ++ doc/Doxyfile.in | 2 +- examples/CMakeLists.txt | 133 +++++--- examples/osmium_area_test.cpp | 4 +- examples/osmium_create_node_cache.cpp | 8 +- examples/osmium_index.cpp | 11 +- examples/osmium_serdump.cpp | 15 +- examples/osmium_toogr.cpp | 59 ++-- examples/osmium_toogr2.cpp | 25 +- examples/osmium_toogr2_exp.cpp | 35 +- examples/osmium_use_node_cache.cpp | 8 +- include/mmap_for_windows.hpp | 94 +++--- include/osmium/area/assembler.hpp | 2 +- .../osmium/area/detail/node_ref_segment.hpp | 2 +- include/osmium/area/detail/proto_ring.hpp | 2 +- include/osmium/area/detail/segment_list.hpp | 2 +- .../osmium/area/multipolygon_collector.hpp | 2 +- include/osmium/area/problem_reporter.hpp | 2 +- .../area/problem_reporter_exception.hpp | 2 +- include/osmium/area/problem_reporter_ogr.hpp | 44 ++- .../osmium/area/problem_reporter_stream.hpp | 2 +- include/osmium/builder/builder.hpp | 4 +- include/osmium/builder/builder_helper.hpp | 2 +- include/osmium/builder/osm_object_builder.hpp | 3 +- include/osmium/diff_handler.hpp | 2 +- include/osmium/diff_iterator.hpp | 2 +- include/osmium/diff_visitor.hpp | 2 +- include/osmium/dynamic_handler.hpp | 2 +- include/osmium/experimental/flex_reader.hpp | 27 +- include/osmium/geom/coordinates.hpp | 2 +- include/osmium/geom/factory.hpp | 2 +- include/osmium/geom/geojson.hpp | 2 +- include/osmium/geom/geos.hpp | 11 +- include/osmium/geom/haversine.hpp | 2 +- include/osmium/geom/mercator_projection.hpp | 2 +- include/osmium/geom/ogr.hpp | 46 ++- include/osmium/geom/projection.hpp | 15 +- include/osmium/geom/relations.hpp | 2 +- include/osmium/geom/util.hpp | 2 +- include/osmium/geom/wkb.hpp | 2 +- include/osmium/geom/wkt.hpp | 2 +- include/osmium/handler.hpp | 2 +- include/osmium/handler/chain.hpp | 2 +- include/osmium/handler/disk_store.hpp | 2 +- include/osmium/handler/dump.hpp | 2 +- .../handler/node_locations_for_ways.hpp | 7 +- include/osmium/handler/object_relations.hpp | 2 +- .../index/detail/create_map_with_fd.hpp | 73 +++++ .../osmium/index/detail/mmap_vector_anon.hpp | 12 +- .../osmium/index/detail/mmap_vector_base.hpp | 9 +- .../osmium/index/detail/mmap_vector_file.hpp | 8 +- include/osmium/index/detail/tmpfile.hpp | 8 +- include/osmium/index/detail/typed_mmap.hpp | 8 +- .../{map/vector.hpp => detail/vector_map.hpp} | 11 +- .../vector.hpp => detail/vector_multimap.hpp} | 11 +- include/osmium/index/index.hpp | 2 +- include/osmium/index/map.hpp | 106 +++++- include/osmium/index/map/all.hpp | 46 +++ include/osmium/index/map/dense_file_array.hpp | 67 ++++ include/osmium/index/map/dense_mem_array.hpp | 57 ++++ ...p_vector_anon.hpp => dense_mmap_array.hpp} | 17 +- include/osmium/index/map/dummy.hpp | 3 +- .../osmium/index/map/sparse_file_array.hpp | 67 ++++ .../{stl_vector.hpp => sparse_mem_array.hpp} | 17 +- .../map/{stl_map.hpp => sparse_mem_map.hpp} | 21 +- ...{sparse_table.hpp => sparse_mem_table.hpp} | 26 +- ..._vector_file.hpp => sparse_mmap_array.hpp} | 23 +- include/osmium/index/multimap.hpp | 7 +- include/osmium/index/multimap/all.hpp | 41 +++ include/osmium/index/multimap/hybrid.hpp | 17 +- ..._vector_file.hpp => sparse_file_array.hpp} | 12 +- .../{stl_vector.hpp => sparse_mem_array.hpp} | 12 +- ...l_multimap.hpp => sparse_mem_multimap.hpp} | 18 +- ..._vector_anon.hpp => sparse_mmap_array.hpp} | 12 +- include/osmium/index/node_locations_map.hpp | 70 ++++ include/osmium/io/any_compression.hpp | 11 +- include/osmium/io/any_input.hpp | 12 +- include/osmium/io/any_output.hpp | 12 +- include/osmium/io/bzip2_compression.hpp | 13 +- include/osmium/io/compression.hpp | 2 +- include/osmium/io/detail/input_format.hpp | 2 +- .../osmium/io/detail/opl_output_format.hpp | 92 +++--- include/osmium/io/detail/output_format.hpp | 2 +- include/osmium/io/detail/pbf.hpp | 2 +- include/osmium/io/detail/pbf_input_format.hpp | 2 +- .../osmium/io/detail/pbf_output_format.hpp | 2 +- include/osmium/io/detail/pbf_parser.hpp | 20 +- include/osmium/io/detail/pbf_stringtable.hpp | 2 +- include/osmium/io/detail/read_thread.hpp | 2 +- include/osmium/io/detail/read_write.hpp | 2 +- include/osmium/io/detail/write_thread.hpp | 2 +- include/osmium/io/detail/xml_input_format.hpp | 4 +- .../osmium/io/detail/xml_output_format.hpp | 151 ++++----- include/osmium/io/detail/zlib.hpp | 2 +- include/osmium/io/error.hpp | 3 +- include/osmium/io/file.hpp | 3 +- include/osmium/io/file_compression.hpp | 2 +- include/osmium/io/file_format.hpp | 2 +- include/osmium/io/gzip_compression.hpp | 11 +- include/osmium/io/header.hpp | 2 +- include/osmium/io/input_iterator.hpp | 3 +- include/osmium/io/opl_output.hpp | 2 +- include/osmium/io/output_iterator.hpp | 10 +- include/osmium/io/overwrite.hpp | 2 +- include/osmium/io/pbf_input.hpp | 12 +- include/osmium/io/pbf_output.hpp | 12 +- include/osmium/io/reader.hpp | 19 +- include/osmium/io/reader_iterator.hpp | 2 +- include/osmium/io/writer.hpp | 4 +- include/osmium/io/xml_input.hpp | 11 +- include/osmium/io/xml_output.hpp | 10 +- include/osmium/memory/buffer.hpp | 2 +- include/osmium/memory/collection.hpp | 3 +- include/osmium/memory/item.hpp | 2 +- include/osmium/memory/item_iterator.hpp | 2 +- include/osmium/object_pointer_collection.hpp | 2 +- include/osmium/osm.hpp | 2 +- include/osmium/osm/area.hpp | 2 +- include/osmium/osm/box.hpp | 4 +- include/osmium/osm/changeset.hpp | 2 +- include/osmium/osm/diff_object.hpp | 2 +- include/osmium/osm/entity.hpp | 7 +- include/osmium/osm/entity_bits.hpp | 8 +- include/osmium/osm/item_type.hpp | 2 +- include/osmium/osm/location.hpp | 2 +- include/osmium/osm/node.hpp | 2 +- include/osmium/osm/node_ref.hpp | 2 +- include/osmium/osm/node_ref_list.hpp | 2 +- include/osmium/osm/object.hpp | 2 +- include/osmium/osm/object_comparisons.hpp | 2 +- include/osmium/osm/relation.hpp | 2 +- include/osmium/osm/segment.hpp | 2 +- include/osmium/osm/tag.hpp | 2 +- include/osmium/osm/timestamp.hpp | 4 +- include/osmium/osm/types.hpp | 2 +- include/osmium/osm/undirected_segment.hpp | 2 +- include/osmium/osm/way.hpp | 2 +- include/osmium/relations/collector.hpp | 4 +- .../osmium/relations/detail/member_meta.hpp | 2 +- .../osmium/relations/detail/relation_meta.hpp | 2 +- include/osmium/tags/filter.hpp | 16 +- include/osmium/tags/regex_filter.hpp | 2 +- include/osmium/tags/taglist.hpp | 8 +- include/osmium/thread/function_wrapper.hpp | 5 +- include/osmium/thread/pool.hpp | 6 +- include/osmium/thread/queue.hpp | 3 +- include/osmium/thread/sorted_queue.hpp | 2 +- include/osmium/thread/util.hpp | 2 +- include/osmium/util/cast.hpp | 2 +- include/osmium/util/compatibility.hpp | 2 +- include/osmium/util/config.hpp | 2 +- include/osmium/util/double.hpp | 2 +- include/osmium/util/options.hpp | 2 +- include/osmium/util/verbose_output.hpp | 2 +- include/osmium/visitor.hpp | 2 +- make_osmium_project.sh | 96 ------ osmium.imp | 7 + test/CMakeLists.txt | 63 ++-- test/README | 1 + test/{osm-testdata => data-tests}/.gitignore | 0 test/data-tests/CMakeLists.txt | 121 +++++++ test/{osm-testdata => data-tests}/README.md | 0 .../include/check_basics_handler.hpp | 0 .../include/check_wkt_handler.hpp | 0 .../include/common.hpp | 7 +- .../include/testdata-testcases.hpp | 0 .../multipolygon.qgs | 0 .../run-testdata-multipolygon.bat | 0 .../run-testdata-multipolygon.sh | 0 .../testcases/test-100.cpp | 0 .../testcases/test-101.cpp | 0 .../testcases/test-110.cpp | 0 .../testdata-multipolygon.cpp | 24 +- .../testdata-overview.cpp | 25 +- .../testdata-testcases.cpp | 0 .../testdata-xml.cpp | 4 - test/include/catch.hpp | 40 ++- test/include/catch_orig.hpp | 29 +- test/include/utils.hpp | 18 + test/osm-testdata/CMakeLists.txt | 87 ----- test/t/basic/test_box.cpp | 2 +- test/t/basic/test_entity_bits.cpp | 6 + test/t/basic/test_node.cpp | 3 + test/t/basic/test_object_comparisons.cpp | 22 +- test/t/basic/test_way.cpp | 3 + test/t/geom/test_mercator.cpp | 16 +- test/t/geom/test_projection.cpp | 48 +-- test/t/index/test_id_to_location.cpp | 59 +++- test/t/index/test_typed_mmap.cpp | 2 +- test/t/io/test_bzip2.cpp | 5 +- test/t/io/test_output_iterator.cpp | 37 +++ test/t/io/test_reader.cpp | 15 +- test/valgrind.supp | 9 + 215 files changed, 2699 insertions(+), 1297 deletions(-) create mode 100644 .ycm_extra_conf.py delete mode 100644 README-changes-from-old-osmium create mode 100644 benchmarks/CMakeLists.txt create mode 100644 benchmarks/README.md create mode 100755 benchmarks/download_data.sh create mode 100644 benchmarks/osmium_benchmark_count.cpp create mode 100644 benchmarks/osmium_benchmark_count_tag.cpp create mode 100644 benchmarks/osmium_benchmark_index_map.cpp create mode 100644 benchmarks/osmium_benchmark_static_vs_dynamic_index.cpp create mode 100755 benchmarks/run_benchmark_count.sh create mode 100755 benchmarks/run_benchmark_count_tag.sh create mode 100755 benchmarks/run_benchmark_index_map.sh create mode 100755 benchmarks/run_benchmark_static_vs_dynamic_index.sh create mode 100755 benchmarks/run_benchmarks.sh create mode 100755 benchmarks/setup.sh create mode 100644 doc/CMakeLists.txt create mode 100644 include/osmium/index/detail/create_map_with_fd.hpp rename include/osmium/index/{map/vector.hpp => detail/vector_map.hpp} (96%) rename include/osmium/index/{multimap/vector.hpp => detail/vector_multimap.hpp} (94%) create mode 100644 include/osmium/index/map/all.hpp create mode 100644 include/osmium/index/map/dense_file_array.hpp create mode 100644 include/osmium/index/map/dense_mem_array.hpp rename include/osmium/index/map/{mmap_vector_anon.hpp => dense_mmap_array.hpp} (77%) create mode 100644 include/osmium/index/map/sparse_file_array.hpp rename include/osmium/index/map/{stl_vector.hpp => sparse_mem_array.hpp} (79%) rename include/osmium/index/map/{stl_map.hpp => sparse_mem_map.hpp} (86%) rename include/osmium/index/map/{sparse_table.hpp => sparse_mem_table.hpp} (86%) rename include/osmium/index/map/{mmap_vector_file.hpp => sparse_mmap_array.hpp} (74%) create mode 100644 include/osmium/index/multimap/all.hpp rename include/osmium/index/multimap/{mmap_vector_file.hpp => sparse_file_array.hpp} (81%) rename include/osmium/index/multimap/{stl_vector.hpp => sparse_mem_array.hpp} (82%) rename include/osmium/index/multimap/{stl_multimap.hpp => sparse_mem_multimap.hpp} (90%) rename include/osmium/index/multimap/{mmap_vector_anon.hpp => sparse_mmap_array.hpp} (81%) create mode 100644 include/osmium/index/node_locations_map.hpp delete mode 100755 make_osmium_project.sh rename test/{osm-testdata => data-tests}/.gitignore (100%) create mode 100644 test/data-tests/CMakeLists.txt rename test/{osm-testdata => data-tests}/README.md (100%) rename test/{osm-testdata => data-tests}/include/check_basics_handler.hpp (100%) rename test/{osm-testdata => data-tests}/include/check_wkt_handler.hpp (100%) rename test/{osm-testdata => data-tests}/include/common.hpp (78%) rename test/{osm-testdata => data-tests}/include/testdata-testcases.hpp (100%) rename test/{osm-testdata => data-tests}/multipolygon.qgs (100%) rename test/{osm-testdata => data-tests}/run-testdata-multipolygon.bat (100%) rename test/{osm-testdata => data-tests}/run-testdata-multipolygon.sh (100%) rename test/{osm-testdata => data-tests}/testcases/test-100.cpp (100%) rename test/{osm-testdata => data-tests}/testcases/test-101.cpp (100%) rename test/{osm-testdata => data-tests}/testcases/test-110.cpp (100%) rename test/{osm-testdata => data-tests}/testdata-multipolygon.cpp (92%) rename test/{osm-testdata => data-tests}/testdata-overview.cpp (86%) rename test/{osm-testdata => data-tests}/testdata-testcases.cpp (100%) rename test/{osm-testdata => data-tests}/testdata-xml.cpp (99%) create mode 100644 test/include/utils.hpp delete mode 100644 test/osm-testdata/CMakeLists.txt create mode 100644 test/t/io/test_output_iterator.cpp diff --git a/.gitignore b/.gitignore index 608d46daf..36118e129 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ core *.swp build* +.ycm_extra_conf.pyc diff --git a/.travis.yml b/.travis.yml index 2c420728e..ea8794ecb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,19 @@ +#----------------------------------------------------------------------------- +# +# Configuration for continuous integration service at travis-ci.org +# +#----------------------------------------------------------------------------- + language: cpp compiler: - gcc - clang +env: + - CONFIGURATION=Dev + - CONFIGURATION=Release + before_install: # we need at least g++-4.8 for c++11 features - sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test @@ -16,8 +26,8 @@ install: - sudo rm /usr/bin/cpp - sudo ln -s /usr/bin/cpp-4.8 /usr/bin/cpp # upgrade libosmium dependencies - - sudo apt-get install --yes make libboost-dev libboost-program-options-dev libsparsehash-dev libprotobuf-dev protobuf-compiler libgeos++-dev libproj-dev - - sudo apt-get install --yes make libgdal1h libgdal-dev + - sudo apt-get install --yes make libboost-dev libboost-program-options-dev libsparsehash-dev libprotobuf-dev protobuf-compiler libgeos++-dev libproj-dev libgdal1h libgdal-dev + - git clone https://github.com/osmcode/osm-testdata.git # OSMPBF is too old, install from git #- sudo apt-get install --yes libosmpbf-dev - git clone https://github.com/scrosby/OSM-binary.git @@ -26,8 +36,6 @@ install: - sudo make install - cd ../.. -#env: - before_script: - true @@ -35,7 +43,7 @@ script: - if [ "${CXX}" = 'g++' ]; then export CXX=g++-4.8; fi; - mkdir build - cd build - - cmake -L -DCMAKE_BUILD_TYPE=Dev .. + - cmake -LA -DCMAKE_BUILD_TYPE=${CONFIGURATION} .. - make VERBOSE=1 # Disable multipolygon test because it needs ruby and the 'json' gem, but the # travis ruby installation doesn't find the gem it did install itself. diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py new file mode 100644 index 000000000..b0f9d3eaf --- /dev/null +++ b/.ycm_extra_conf.py @@ -0,0 +1,44 @@ +#----------------------------------------------------------------------------- +# +# Configuration for YouCompleteMe Vim plugin +# +# http://valloric.github.io/YouCompleteMe/ +# +#----------------------------------------------------------------------------- + +# some default flags +# for more information install clang-3.2-doc package and +# check UsersManual.html +flags = [ +'-Werror', +'-Wall', +'-Wextra', +'-pedantic', +'-Wno-return-type', +'-Wno-unused-parameter', +'-Wno-unused-variable', + +'-std=c++11', + +# '-x' and 'c++' also required +# use 'c' for C projects +'-x', +'c++', + +# libosmium include dirs +'-Iinclude', +'-Itest/include', +'-Itest/data-test/include', + +# include third party libraries +'-I/usr/include/gdal', +] + +# youcompleteme is calling this function to get flags +# You can also set database for flags. Check: JSONCompilationDatabase.html in +# clang-3.2-doc package +def FlagsForFile( filename ): + return { + 'flags': flags, + 'do_cache': True + } diff --git a/CMakeLists.txt b/CMakeLists.txt index 19b88cfc2..373bf8eb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,18 +1,20 @@ -#---------------------------------------------------------------------- +#----------------------------------------------------------------------------- # -# Libosmium CMakeLists.txt +# CMake Config # -#---------------------------------------------------------------------- +# Libosmium +# +#----------------------------------------------------------------------------- cmake_minimum_required(VERSION 2.8 FATAL_ERROR) list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") -#---------------------------------------------------------------------- +#----------------------------------------------------------------------------- # # Project version # -#---------------------------------------------------------------------- +#----------------------------------------------------------------------------- project(libosmium) @@ -20,85 +22,103 @@ set(LIBOSMIUM_VERSION_MAJOR 0) set(LIBOSMIUM_VERSION_MINOR 0) set(LIBOSMIUM_VERSION_PATCH 1) -set(LIBOSMIUM_VERSION ${LIBOSMIUM_VERSION_MAJOR}.${LIBOSMIUM_VERSION_MINOR}.${LIBOSMIUM_VERSION_PATCH}) +set(LIBOSMIUM_VERSION + ${LIBOSMIUM_VERSION_MAJOR}.${LIBOSMIUM_VERSION_MINOR}.${LIBOSMIUM_VERSION_PATCH}) -#---------------------------------------------------------------------- +#----------------------------------------------------------------------------- # # Build options # # (Change with -DOPTION=VALUE on cmake command line.) # -#---------------------------------------------------------------------- - -option(BUILD_EXAMPLES "compile example programs" ON) -option(BUILD_UNIT_TESTS "compile unit tests, please run them with ctest" ON) -option(BUILD_DATA_TESTS "compile data tests, please run them with ctest" ON) +#----------------------------------------------------------------------------- if(CMAKE_BUILD_TYPE STREQUAL "Dev") - option(BUILD_HEADERS "compile every header file on its own" ON) + set(dev_build ON) else() - option(BUILD_HEADERS "compile every header file on its own" OFF) + set(dev_build OFF) endif() +option(BUILD_EXAMPLES "compile example programs" ON) +option(BUILD_TESTING "compile unit tests, please run them with ctest" ON) -#---------------------------------------------------------------------- +option(BUILD_HEADERS "compile every header file on its own" ${dev_build}) +option(BUILD_BENCHMARKS "compile benchmark programs" ${dev_build}) +option(BUILD_DATA_TESTS "compile data tests, please run them with ctest" ${dev_build}) + + +#----------------------------------------------------------------------------- # # Find external dependencies # -#---------------------------------------------------------------------- +#----------------------------------------------------------------------------- -# check that the essential libraries were found -if(BUILD_EXAMPLES OR BUILD_TESTING OR BUILD_UNIT_TESTS OR BUILD_DATA_TESTS OR BUILD_HEADERS) +find_package(Boost 1.38) +mark_as_advanced(CLEAR BOOST_ROOT) - find_package(Boost 1.38) - mark_as_advanced(CLEAR BOOST_ROOT) - - if(Boost_FOUND) - include_directories(${Boost_INCLUDE_DIRS}) - else() - set(BOOST_ROOT "NOT FOUND: please choose" CACHE PATH "") - message(FATAL_ERROR "PLEASE, specify the directory where the Boost library is installed in BOOST_ROOT") - endif() - - set(OSMIUM_INCLUDE_DIR include) - find_package(Osmium COMPONENTS io gdal geos proj sparsehash) - include_directories(${OSMIUM_INCLUDE_DIRS}) - - if(MSVC) - find_path(GETOPT_INCLUDE_DIR getopt.h) - find_library(GETOPT_LIBRARY NAMES wingetopt) - if(GETOPT_INCLUDE_DIR AND GETOPT_LIBRARY) - include_directories(${GETOPT_INCLUDE_DIR}) - list(APPEND OSMIUM_LIBRARIES ${GETOPT_LIBRARY}) - else() - set(GETOPT_MISSING 1) - endif() - endif() - - include_directories(include) +if(Boost_FOUND) + include_directories(${Boost_INCLUDE_DIRS}) +else() + set(BOOST_ROOT "NOT FOUND: please choose" CACHE PATH "") + message(FATAL_ERROR "PLEASE, specify the directory where the Boost library is installed in BOOST_ROOT") endif() -#---------------------------------------------------------------------- +set(OSMIUM_INCLUDE_DIR include) +find_package(Osmium COMPONENTS io gdal geos proj sparsehash) +include_directories(${OSMIUM_INCLUDE_DIRS}) + +if(MSVC) + find_path(GETOPT_INCLUDE_DIR getopt.h) + find_library(GETOPT_LIBRARY NAMES wingetopt) + if(GETOPT_INCLUDE_DIR AND GETOPT_LIBRARY) + include_directories(${GETOPT_INCLUDE_DIR}) + list(APPEND OSMIUM_LIBRARIES ${GETOPT_LIBRARY}) + else() + set(GETOPT_MISSING 1) + endif() +endif() + +include_directories(include) + + +#----------------------------------------------------------------------------- # # Decide which C++ version to use (Minimum/default: C++11). # -#---------------------------------------------------------------------- - -if(NOT USE_CPP_VERSION) - set(USE_CPP_VERSION c++11) +#----------------------------------------------------------------------------- +if(NOT MSVC) + if(NOT USE_CPP_VERSION) + set(USE_CPP_VERSION c++11) + endif() + message(STATUS "Use C++ version: ${USE_CPP_VERSION}") + # following only available from cmake 2.8.12: + # add_compile_options(-std=${USE_CPP_VERSION}) + # so using this instead: + add_definitions(-std=${USE_CPP_VERSION}) endif() -message(STATUS "Use C++ version: ${USE_CPP_VERSION}") -# following only available from cmake 2.8.12: -# add_compile_options(-std=${USE_CPP_VERSION}) -# so using this instead: -add_definitions(-std=${USE_CPP_VERSION}) -#---------------------------------------------------------------------- -set(CMAKE_CXX_FLAGS_DEV "-O3 -g" +#----------------------------------------------------------------------------- +# +# Compiler and Linker flags +# +#----------------------------------------------------------------------------- +if(MSVC) + set(USUAL_COMPILE_OPTIONS "/Ox") +else() + set(USUAL_COMPILE_OPTIONS "-O3 -g") +endif() + +if(WIN32) + add_definitions(-DWIN32 -D_WIN32 -DMSWIN32 -DBGDWIN32 + -DWINVER=0x0500 -D_WIN32_WINNT=0x0500 -D_WIN32_IE=0x0600) +endif() + +set(CMAKE_CXX_FLAGS_DEV "${USUAL_COMPILE_OPTIONS}" CACHE STRING "Flags used by the compiler during developer builds." FORCE) + set(CMAKE_EXE_LINKER_FLAGS_DEV "" CACHE STRING "Flags used by the linker during developer builds." FORCE) @@ -107,61 +127,76 @@ mark_as_advanced( CMAKE_EXE_LINKER_FLAGS_DEV ) -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g" +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${USUAL_COMPILE_OPTIONS}" CACHE STRING "Flags used by the compiler during RELWITHDEBINFO builds." FORCE) + +#----------------------------------------------------------------------------- +# +# Build Type +# +#----------------------------------------------------------------------------- set(CMAKE_CONFIGURATION_TYPES "Debug Release RelWithDebInfo MinSizeRel Dev") +# In 'Dev' mode: compile with very strict warnings and turn them into errors. +if(CMAKE_BUILD_TYPE STREQUAL "Dev") + if(NOT MSVC) + add_definitions(-Werror) + endif() + add_definitions(${OSMIUM_WARNING_OPTIONS}) +endif() + # Force RelWithDebInfo build type if none was given -if (CMAKE_BUILD_TYPE STREQUAL "") - set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build, options are: ${CMAKE_CONFIGURATION_TYPES}." FORCE) +if(CMAKE_BUILD_TYPE) + set(build_type ${CMAKE_BUILD_TYPE}) else() - set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING "Choose the type of build, options are: ${CMAKE_CONFIGURATION_TYPES}." FORCE) + set(build_type "RelWithDebInfo") endif() - -#---------------------------------------------------------------------- - -if(WIN32) - add_definitions(-DWIN32 -D_WIN32 -DMSWIN32 -DBGDWIN32 -DWINVER=0x0500 -D_WIN32_WINNT=0x0500 -D_WIN32_IE=0x0600) - set(CPACK_GENERATOR ZIP) -else() - set(CPACK_GENERATOR TGZ) -endif() +set(CMAKE_BUILD_TYPE ${build_type} + CACHE STRING + "Choose the type of build, options are: ${CMAKE_CONFIGURATION_TYPES}." + FORCE) -#---------------------------------------------------------------------- +#----------------------------------------------------------------------------- # -# Set up testing +# Unit and data tests # -#---------------------------------------------------------------------- +#----------------------------------------------------------------------------- enable_testing() -find_program(MEMORYCHECK_COMMAND valgrind) -set(MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full --show-reachable=yes --error-exitcode=1") -set(MEMORYCHECK_SUPPRESSIONS_FILE "${PROJECT_SOURCE_DIR}/test/valgrind.supp") +if(BUILD_TESTING OR BUILD_DATA_TESTS) + find_program(MEMORYCHECK_COMMAND valgrind) -if(BUILD_UNIT_TESTS OR BUILD_TESTING) + set(MEMORYCHECK_COMMAND_OPTIONS + "--trace-children=yes --leak-check=full --show-reachable=yes --error-exitcode=1") + + set(MEMORYCHECK_SUPPRESSIONS_FILE "${PROJECT_SOURCE_DIR}/test/valgrind.supp") +endif() + +if(BUILD_TESTING) add_subdirectory(test) endif() -if(BUILD_DATA_TESTS OR BUILD_TESTING) - add_subdirectory(test/osm-testdata) +if(BUILD_DATA_TESTS) + add_subdirectory(test/data-tests) endif() -#---------------------------------------------------------------------- +#----------------------------------------------------------------------------- # # Optional "cppcheck" target that checks C++ code # -#---------------------------------------------------------------------- +#----------------------------------------------------------------------------- message(STATUS "Looking for cppcheck") find_program(CPPCHECK cppcheck) if(CPPCHECK) message(STATUS "Looking for cppcheck - found") - set(CPPCHECK_OPTIONS --enable=warning,style,performance,portability,information,missingInclude) + set(CPPCHECK_OPTIONS + --enable=warning,style,performance,portability,information,missingInclude) # cpp doesn't find system includes for some reason, suppress that report set(CPPCHECK_OPTIONS ${CPPCHECK_OPTIONS} --suppress=missingIncludeSystem) @@ -169,7 +204,7 @@ if(CPPCHECK) file(GLOB_RECURSE ALL_INCLUDES include/osmium/*.hpp) file(GLOB ALL_EXAMPLES examples/*.cpp) file(GLOB ALL_UNIT_TESTS test/t/*/test_*.cpp) - file(GLOB ALL_DATA_TESTS test/osm-testdata/*.cpp) + file(GLOB ALL_DATA_TESTS test/data-tests/*.cpp) if(Osmium_DEBUG) message(STATUS "Checking includes : ${ALL_INCLUDES}") @@ -178,7 +213,11 @@ if(CPPCHECK) message(STATUS "Checking data test code: ${ALL_DATA_TESTS}") endif() - set(CPPCHECK_FILES ${ALL_INCLUDES} ${ALL_EXAMPLES} ${ALL_UNIT_TESTS} ${ALL_DATA_TESTS}) + set(CPPCHECK_FILES + ${ALL_INCLUDES} + ${ALL_EXAMPLES} + ${ALL_UNIT_TESTS} + ${ALL_DATA_TESTS}) add_custom_target(cppcheck ${CPPCHECK} @@ -188,48 +227,42 @@ if(CPPCHECK) ) else() message(STATUS "Looking for cppcheck - not found") - message(STATUS " Make target cppcheck not available") + message(STATUS " Build target 'cppcheck' will not be available.") endif(CPPCHECK) -#---------------------------------------------------------------------- +#----------------------------------------------------------------------------- # -# Doxygen-based documentation +# Examples, benchmarks and documentation # -#---------------------------------------------------------------------- -find_package(Doxygen) -if(DOXYGEN_FOUND) - configure_file(doc/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) - add_custom_target(doc - ${DOXYGEN_EXECUTABLE} - ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Generating API documentation with Doxygen" VERBATIM - ) - install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/doc/html" DESTINATION "share/doc/libosmium-dev") -else() - message(STATUS "Doxygen not found, so 'doc' target will not be available.") -endif() - - -#---------------------------------------------------------------------- +#----------------------------------------------------------------------------- if(BUILD_EXAMPLES) add_subdirectory(examples) endif() -#---------------------------------------------------------------------- -# This will try to compile include files on their own to detect missing -# include directives and other dependency-related problems. Note that if this -# work, it is not enough to be sure it will compile in production code. -# But if it reports an error we know we are missing something. -if(BUILD_HEADERS) - file(GLOB_RECURSE ALL_HPPS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/include" include/osmium/*.hpp) +if(BUILD_BENCHMARKS) + add_subdirectory(benchmarks) +endif() - # In 'Dev' mode: compile with very strict warnings and turn them into errors. - if(CMAKE_BUILD_TYPE STREQUAL "Dev") - add_definitions(-Werror ${OSMIUM_WARNING_OPTIONS}) - endif() +add_subdirectory(doc) + + +#----------------------------------------------------------------------------- +# +# Headers +# +# This will try to compile include files on their own to detect missing +# include directives and other dependency-related problems. Note that if this +# work, it is not enough to be sure it will compile in production code. +# But if it reports an error we know we are missing something. +# +#----------------------------------------------------------------------------- +if(BUILD_HEADERS) + file(GLOB_RECURSE + ALL_HPPS + RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/include" + include/osmium/*.hpp) file(MAKE_DIRECTORY header_check) @@ -244,7 +277,19 @@ if(BUILD_HEADERS) # There is no way in CMake to just compile but not link a C++ file, # so we pretend to build a library here. - add_library(${libname} OBJECT ${DUMMYCPP} include/${hpp}) + add_library(${libname} STATIC ${DUMMYCPP} include/${hpp}) + + if(MSVC) + # Remove warning LNK4221: "This object file does not define any + # previously undefined public symbols, so it will not be used by + # any link operation that consumes this library". This is a dummy + # library anyways. + target_link_libraries(${libname} /wd4221) + endif() + + #### this is better but only supported from cmake 3.0: + ###add_library(${libname} OBJECT ${DUMMYCPP} include/${hpp}) + endforeach() endif() @@ -254,6 +299,38 @@ install(DIRECTORY include/osmium DESTINATION include) # don't have it. We probably don't want to install it. #install(FILES include/boost_unicode_iterator.hpp DESTINATION include) -#---------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# +# Packaging +# +#----------------------------------------------------------------------------- + +set(CPACK_PACKAGE_VERSION_MAJOR ${LIBOSMIUM_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${LIBOSMIUM_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION_PATCH ${LIBOSMIUM_VERSION_PATCH}) + +if(WIN32) + set(CPACK_GENERATOR ZIP) +else() + set(CPACK_GENERATOR TGZ) +endif() + include(CPack) + +#----------------------------------------------------------------------------- +# +# Print warnings at the end +# +#----------------------------------------------------------------------------- +if(BUILD_DATA_TESTS AND OSM_TESTDATA STREQUAL "OSM_TESTDATA-NOTFOUND") + message("\n========================== WARNING ==========================") + message("osm-testdata directory not found, data tests were disabled!\n") + message("You can get it from https://github.com/osmcode/osm-testdata") + message("Clone it into the same directory libosmium is in") + message("or set the OSM_TESTDATA cmake variable to its path.") + message("=============================================================\n") +endif() + +#----------------------------------------------------------------------------- diff --git a/Makefile b/Makefile index b445e8e82..7b2b83d7b 100644 --- a/Makefile +++ b/Makefile @@ -11,11 +11,11 @@ clean: distclean: rm -fr build -deb: - debuild -I -us -uc - -deb-clean: - debuild clean +#deb: +# debuild -I -us -uc +# +#deb-clean: +# debuild clean indent: astyle --style=java --indent-namespaces --indent-switches --pad-header --lineend=linux --suffix=none --recursive include/\*.hpp examples/\*.cpp test/\*.cpp diff --git a/README-changes-from-old-osmium b/README-changes-from-old-osmium deleted file mode 100644 index 3e94500ea..000000000 --- a/README-changes-from-old-osmium +++ /dev/null @@ -1,43 +0,0 @@ - -Changes from old versions of Osmium -=================================== - -This version has some substantial changes and users of Osmium will have to -rewrite their code. Use the examples provided in the "example" directory -or in the osmium-contrib repository to get an idea what needs changing. -These examples are often similar to the examples provided with the old -Osmium so they should give you an idea how your code has to change. - -Here are some of the more important changes: - -* Osmium now needs C++11. It will not work with older compilers. You need - at least GCC 4.7.3 or clang (LLVM) 3.2. - -* Namespaces are now all lower case. Everything is in the "osmium" namespace - or sub-namespaces of it. Many classes and functions have been moved to - different, more logical or shorter namespaces. - -* You can't just instantiate OSM objects such as Nodes, Ways, or Relations. - You need a Buffer first to hold them and use the Builder classes to - create them. This is a bit more cumbersome, but greatly reduces the need - for memory management and makes Osmium faster and easier to parallelize. - -* Usually you don't act on single OSM objects any more, but on groups of - them in a Buffer. - -* Reading and writing of OSM data is much simpler. Use the Reader and Writer - classes as they hide much of the detail and have much nicer interfaces - than the old Input/Output classes. - -* The class Osmium::OSM::Position was renamed to osmium::Location. This - better reflects that it is a location on the planet we are talking about. - The word "position" has many meanings and is, for instance, often used - to denote a position in a file or buffer or so. - -* The dependency on boost has been greatly reduced. C++11 offers many - features that used to be only available with boost, such as shared_ptr. - Osmium now uses the C++11 versions of these. - -* Osmium now makes use of the new C++11 threading support when reading and - writing OSM files. - diff --git a/README.md b/README.md index 8c7957f3b..503440e8e 100644 --- a/README.md +++ b/README.md @@ -1,112 +1,47 @@ -# Osmium Library +# Libosmium http://osmcode.org/libosmium A fast and flexible C++ library for working with OpenStreetMap data. -NOTE: This is a beta version of the next-generation Osmium. For production -use, see the Osmium version at https://github.com/joto/osmium . - -There are a few applications that use the Osmium library in the examples -directory. See the [osmium-contrib](http://github.com/osmcode/osmium-contrib) -repository for more example code. - [![Build Status](https://secure.travis-ci.org/osmcode/libosmium.png)](http://travis-ci.org/osmcode/libosmium) [![Build status](https://ci.appveyor.com/api/projects/status/mkbg6e6stdgq7c1b?svg=true)](https://ci.appveyor.com/project/Mapbox/libosmium) Libosmium is developed on Linux, but also works on OSX and Windows (with some limitations). +There are a few applications that use the Osmium library in the examples +directory. See the [osmium-contrib](http://github.com/osmcode/osmium-contrib) +repository for more example code. + ## Prerequisites -Because Osmium uses many C++11 features you need a modern compiler and standard -C++ library. Osmium needs at least GCC 4.8 or clang (LLVM) 3.2. (Some parts may -work with older versions.) +Because Libosmium uses many C++11 features you need a modern compiler and +standard C++ library. Osmium needs at least GCC 4.8 or clang (LLVM) 3.4. +(Some parts may work with older versions.) -Different parts of Osmium (and the applications built on top of it) need +Different parts of Libosmium (and the applications built on top of it) need different libraries. You DO NOT NEED to install all of them, just install those -you need for the programs you need. +you need for your programs. - boost-iterator, boost-regex - http://www.boost.org/ - Debian/Ubuntu: libboost-dev - openSUSE: boost-devel - Homebrew: boost - - boost-program-options (for parsing command line options in some examples) - http://www.boost.org/doc/libs/1_54_0/doc/html/program_options.html - Debian/Ubuntu: libboost-program-options-dev - - Google protocol buffers (for PBF support) - http://code.google.com/p/protobuf/ (at least version 2.3.0 needed) - Debian/Ubuntu: libprotobuf-dev protobuf-compiler - openSUSE: protobuf-devel - Homebrew: protobuf - Also see http://wiki.openstreetmap.org/wiki/PBF_Format - - OSMPBF (for PBF support) - https://github.com/scrosby/OSM-binary - Debian/Ubuntu: libosmpbf-dev - (The package in Ubuntu 14.04 and older is too old, install from source - in these cases.) - Homebrew: osm-pbf - - Expat (for parsing XML files) - http://expat.sourceforge.net/ - Debian/Ubuntu: libexpat1-dev - openSUSE: libexpat-devel - Homebrew: expat - - zlib (for PBF and for gzip support when reading/writing XML) - http://www.zlib.net/ - Debian/Ubuntu: zlib1g-dev - openSUSE: zlib-devel - - bz2lib (for bzip2 support when reading/writing XML) - http://www.bzip.org/ - Debian/Ubuntu: libbz2-dev - - Google sparsehash - http://code.google.com/p/google-sparsehash/ - Debian/Ubuntu: libsparsehash-dev - openSUSE: sparsehash - Homebrew: google-sparsehash - - GDAL (for OGR support) - http://gdal.org/ - Debian/Ubuntu: libgdal1-dev - openSUSE: libgdal-devel - Homebrew: gdal - - GEOS (for GEOS support) - http://trac.osgeo.org/geos/ - Debian/Ubuntu: libgeos++-dev - openSUSE: libgeos-devel - Homebrew: geos - - libproj (for projection support) - http://trac.osgeo.org/proj/ - Debian/Ubuntu: libproj-dev - - Doxygen (to build API documentation) and tools - http://www.stack.nl/~dimitri/doxygen/ - Debian/Ubuntu: doxygen graphviz xmlstarlet - Homebrew: doxygen - -You need to either install the packages for your distribution or install those -libraries from source. Most libraries should be available in all distributions. +For details see the +[list of dependencies](https://github.com/osmcode/libosmium/wiki/Libosmium-dependencies). ## Directories -* include: C/C++ include files. All of Osmium is in those header files which - are needed for building Osmium applications. +* benchmarks: Some benchmarks checking different parts of Libosmium. + +* cmake: CMake configuration scripts. + +* doc: Config for documentation. * examples: Osmium example applications. -* test: Tests (see below). +* include: C/C++ include files. All of Libosmium is in those header files + which are needed for building Osmium applications. -* doc: Config for documentation. +* test: Tests (see below). ## Building @@ -124,61 +59,15 @@ cmake: This will build the examples and tests. Call `ctest` to run the tests. -To build the documentation you need Doxygen. If cmake can find it it will -enable the `doc` target so you can build the documentation like this: - - make doc - -If the 'cppcheck' binary is found, cmake will add another target to the -Makfile which allows you to call cppheck on all `*.cpp` and `*.hpp` files: - - make cppcheck - -For Mac users: If you have clang 3.2 or newer, use the system compiler. -If not you have to build the compiler yourself. See the instructions -on http://clang.llvm.org/ . - -Preliminary support for cmake is provided. You can use this instead of "make": +For more see the +[Libosmium Wiki](https://github.com/osmcode/libosmium/wiki/Building-Libosmium). ## Testing -### Unit Tests - -There are a few unit tests using the Catch unit test framework in the "test" -directory. Many more tests are needed, any help appreciated. - -For [Catch](https://github.com/philsquared/Catch/) only one header file is -needed which is included (`test/include/catch.hpp`). - -To compile these unit tests make sure `BUILD_UNIT_TESTS` is set in the cmake -config, then build the project and call - - ctest - -You can run tests matching a pattern by calling - - ctest -R test_name - -for instance: - - ctest basic_test_node - -will run the `basic_test_node` and `basic_test_node_ref` tests. - -### Data Tests - -In addition there are some test based on the OSM Test Data Repository at -http://osmcode.org/osm-testdata/ . Make sure `BUILD_DATA_TESTS` is set in the -cmake config, then build the project and call `ctest`. - -Some of these tests need Ruby and then 'json' gem installed. - -### Valgrind - -Running tests with valgrind: - - ctest -D ExperimentalMemCheck +See the +[Libosmium Wiki](https://github.com/osmcode/libosmium/wiki/Testing-Libosmium) +for instructions. ## Osmium on 32bit Machines @@ -198,20 +87,18 @@ Please report any issues you have and we might be able to solve them. ## Switching from the old Osmium -See `README-changes-from-old-osmium`. +If you have been using the old version of Osmium at +https://github.com/joto/osmium you might want to read about the +[changes needed](https://github.com/osmcode/libosmium/wiki/Changes-from-old-versions-of-Osmium). ## License -The Osmium Library is available under the Boost Software License. See -LICENSE.txt. +Libosmium is available under the Boost Software License. See LICENSE.txt. ## Authors -The Osmium Library was mainly written and is maintained by Jochen Topf -(jochen@topf.org). - -Other authors: -* Peter Körner (github@mazdermind.de) (PBF writer, ...) +Libosmium was mainly written and is maintained by Jochen Topf +(jochen@topf.org). See the git commit log for other authors. diff --git a/appveyor.yml b/appveyor.yml index d084b7dad..c112d4f77 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,11 +1,13 @@ +#----------------------------------------------------------------------------- # -# Configuration for appveyor.com +# Configuration for continuous integration service at appveyor.com # +#----------------------------------------------------------------------------- environment: matrix: - - configuration: Dev -# - configuration: Release + - config: Dev + - config: Release # branches to build branches: @@ -14,7 +16,7 @@ branches: - master # Operating system (build VM template) -os: Windows Server 2012 R2 +os: Visual Studio 2014 CTP4 # scripts that are called at very beginning, before repo cloning init: @@ -25,31 +27,51 @@ clone_folder: c:\projects\libosmium platform: x64 install: - # by default, all script lines are interpreted as batch + # show all availble env vars + - SET + - ECHO cmake on AppVeyor + - cmake -version + - CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 + - SET PATH=c:\projects\libosmium\cmake-3.1.0-win32-x86\bin;%PATH% + - SET LODEPSDIR=c:\projects\libosmium\libosmium-deps + - SET PROJ_LIB=%LODEPSDIR%\proj\share + - set GDAL_DATA=%LODEPSDIR%\gdal\data + #geos.dll + - SET PATH=%LODEPSDIR%\geos\lib;%PATH% + #gdal.dll + - SET PATH=%LODEPSDIR%\gdal\lib;%PATH% + #libexpat.dll + - SET PATH=%LODEPSDIR%\expat\lib;%PATH% + #libtiff.dll + - SET PATH=%LODEPSDIR%\libtiff\lib;%PATH% + #zlibwapi.dll + - SET PATH=%LODEPSDIR%\zlib\lib;%PATH% + #convert backslashes in bzip2 path to forward slashes + #cmake cannot find it otherwise + - SET LIBBZIP2=%LODEPSDIR%\bzip2\lib\libbz2.lib + - SET LIBBZIP2=%LIBBZIP2:\=/% + - ps: Start-FileDownload https://mapnik.s3.amazonaws.com/deps/cmake-3.1.0-win32-x86.7z -FileName cm.7z + - ps: Start-FileDownload https://mapnik.s3.amazonaws.com/dist/dev/libosmium-deps-win-14.0-x64.7z -FileName lodeps.7z + - 7z x cm.7z > null + - 7z x lodeps.7z > nul + - echo %LODEPSDIR% + - dir %LODEPSDIR% + - ECHO our own cmake + - cmake -version - cd c:\projects - - nuget install boost - - nuget install bzip2 - - nuget install zlib - - nuget install GDAL - - nuget install expat - - nuget install protobuf - - dir /S c:\projects - - git clone https://github.com/scrosby/OSM-binary - - cd OSM-binary - - mkdir build - - cd build - - call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64 - - cmake .. -G "Visual Studio 12 Win64" -DSEARCH_PREFIX=c:\projects -T CTP_Nov2013 - - msbuild /clp:Verbosity=minimal /nologo OSM-binary.sln + - git clone https://github.com/osmcode/osm-testdata.git build_script: - cd c:\projects\libosmium - mkdir build - cd build - - call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64 - - SET PATH=C:\Program Files (x86)\MSBuild\12.0\bin\;%PATH% - - SET P=c:/projects/libosmium - - cmake .. -G "Visual Studio 12 Win64" -DCMAKE_BUILD_TYPE=%Configuration% -DCMAKE_PREFIX_PATH=c:\projects -DBoost_USE_STATIC_LIBS=ON -T CTP_Nov2013 - - msbuild /clp:Verbosity=minimal /nologo libosmium.sln - - msbuild /clp:Verbosity=minimal /nologo tests.vcxproj + - echo %config% + - cmake .. -LA -G "Visual Studio 14 Win64" -DOsmium_DEBUG=TRUE -DCMAKE_BUILD_TYPE=%config% -DBOOST_ROOT=%LODEPSDIR%\boost -DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_57.lib -DOSMPBF_LIBRARY=%LODEPSDIR%\osmpbf\lib\osmpbf.lib -DOSMPBF_INCLUDE_DIR=%LODEPSDIR%\osmpbf\include -DPROTOBUF_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf.lib -DPROTOBUF_LITE_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf-lite.lib -DPROTOBUF_INCLUDE_DIR=%LODEPSDIR%\protobuf\include -DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib -DZLIB_INCLUDE_DIR=%LODEPSDIR%\zlib\include -DEXPAT_LIBRARY=%LODEPSDIR%\expat\lib\libexpat.lib -DEXPAT_INCLUDE_DIR=%LODEPSDIR%\expat\include -DBZIP2_LIBRARIES=%LIBBZIP2% -DBZIP2_INCLUDE_DIR=%LODEPSDIR%\bzip2\include -DGDAL_LIBRARY=%LODEPSDIR%\gdal\lib\gdal_i.lib -DGDAL_INCLUDE_DIR=%LODEPSDIR%\gdal\include -DGEOS_LIBRARY=%LODEPSDIR%\geos\lib\geos.lib -DGEOS_INCLUDE_DIR=%LODEPSDIR%\geos\include -DPROJ_LIBRARY=%LODEPSDIR%\proj\lib\proj.lib -DPROJ_INCLUDE_DIR=%LODEPSDIR%\proj\include -DSPARSEHASH_INCLUDE_DIR=%LODEPSDIR%\sparsehash\include -DGETOPT_LIBRARY=%LODEPSDIR%\wingetopt\lib\wingetopt.lib -DGETOPT_INCLUDE_DIR=%LODEPSDIR%\wingetopt\include + - msbuild libosmium.sln /p:Configuration=Release /toolsversion:14.0 /p:Platform=x64 /p:PlatformToolset=v140 + #- cmake .. -LA -G "NMake Makefiles" -DOsmium_DEBUG=TRUE -DCMAKE_BUILD_TYPE=%config% -DBOOST_ROOT=%LODEPSDIR%\boost -DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_57.lib -DOSMPBF_LIBRARY=%LODEPSDIR%\osmpbf\lib\osmpbf.lib -DOSMPBF_INCLUDE_DIR=%LODEPSDIR%\osmpbf\include -DPROTOBUF_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf.lib -DPROTOBUF_LITE_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf-lite.lib -DPROTOBUF_INCLUDE_DIR=%LODEPSDIR%\protobuf\include -DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib -DZLIB_INCLUDE_DIR=%LODEPSDIR%\zlib\include -DEXPAT_LIBRARY=%LODEPSDIR%\expat\lib\libexpat.lib -DEXPAT_INCLUDE_DIR=%LODEPSDIR%\expat\include -DBZIP2_LIBRARIES=%LIBBZIP2% -DBZIP2_INCLUDE_DIR=%LODEPSDIR%\bzip2\include -DGDAL_LIBRARY=%LODEPSDIR%\gdal\lib\gdal_i.lib -DGDAL_INCLUDE_DIR=%LODEPSDIR%\gdal\include -DGEOS_LIBRARY=%LODEPSDIR%\geos\lib\geos.lib -DGEOS_INCLUDE_DIR=%LODEPSDIR%\geos\include -DPROJ_LIBRARY=%LODEPSDIR%\proj\lib\proj.lib -DPROJ_INCLUDE_DIR=%LODEPSDIR%\proj\include -DSPARSEHASH_INCLUDE_DIR=%LODEPSDIR%\sparsehash\include -DGETOPT_LIBRARY=%LODEPSDIR%\wingetopt\lib\wingetopt.lib -DGETOPT_INCLUDE_DIR=%LODEPSDIR%\wingetopt\include + #- nmake + +test_script: + # Disable multipolygon test because it needs ruby and the 'json' gem + - ctest -V -C %config% -E testdata-multipolygon diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt new file mode 100644 index 000000000..6a4ca162d --- /dev/null +++ b/benchmarks/CMakeLists.txt @@ -0,0 +1,48 @@ +#----------------------------------------------------------------------------- +# +# CMake Config +# +# Libosmium benchmarks +# +#----------------------------------------------------------------------------- + +message(STATUS "Configuring benchmarks") + +set(BENCHMARKS + count + count_tag + index_map + static_vs_dynamic_index + CACHE STRING "Benchmark programs" +) + + +#----------------------------------------------------------------------------- +# +# Configure benchmarks +# +#----------------------------------------------------------------------------- + +message(STATUS "Configuring benchmarks - Building these benchmarks:") +foreach(benchmark ${BENCHMARKS}) + message(STATUS " - osmium_benchmark_${benchmark}") + add_executable(osmium_benchmark_${benchmark} + "osmium_benchmark_${benchmark}.cpp") + target_link_libraries(osmium_benchmark_${benchmark} + ${OSMIUM_IO_LIBRARIES} + ${BENCHMARK_LIBS_${benchmark}}) + configure_file(run_benchmark_${benchmark}.sh + ${CMAKE_CURRENT_BINARY_DIR}/run_benchmark_${benchmark}.sh + @ONLY) +endforeach() + +foreach(file setup run_benchmarks) + configure_file(${file}.sh ${CMAKE_CURRENT_BINARY_DIR}/${file}.sh @ONLY) +endforeach() + + +#----------------------------------------------------------------------------- +message(STATUS "Configuring benchmarks - done") + + +#----------------------------------------------------------------------------- diff --git a/benchmarks/README.md b/benchmarks/README.md new file mode 100644 index 000000000..f10045ca0 --- /dev/null +++ b/benchmarks/README.md @@ -0,0 +1,41 @@ + +# Benchmarks + +Benchmarks check the performance of different parts of Libosmium. + +## Preparations + +To run the benchmarks first make a directory for the data files somewhere +(outside the repository) and set the `DATA_DIR` environment variable: + + export DATA_DIR=benchmark_data + mkdir $DATA_DIR + +Then copy the OSM files you want to do the benchmarks with into this directory. +You can use the `download_data.sh` script to download a selection of OSM files +in different sizes, but you can use a different selection, too. The benchmarks +will use whatever files you have in the `DATA_DIR` directory. + +The download script will start the data files names with a number in order of +the size of the file from smallest to largest. You can use the same convention +or use a different one. Benchmarks will be run on the files in alphabetical +order. + +The files don't have to be in that directory, you can add soft links from that +directory to the real file locations if that suits you. + +## Compiling the benchmarks + +To build the benchmarks set the `BUILD_BENCHMARKS` option when configuring with +CMake and run the compilation by calling `make` (or whatever build tool you +are using). + +## Running the benchmarks + +Go to the build directory and run `benchmarks/run_benchmarks.sh`. You can also +run each benchmark on its own by calling the respective script in the +`benchmarks` directory. + +Results of the benchmarks will be printed to stdout, you might want to redirect +them into a file. + diff --git a/benchmarks/download_data.sh b/benchmarks/download_data.sh new file mode 100755 index 000000000..8a6a8ff50 --- /dev/null +++ b/benchmarks/download_data.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# +# download_data.sh +# + +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 2_bremen.osm.pbf http://download.geofabrik.de/europe/germany/bremen-latest.osm.pbf # about 13 MB +curl --location --output 3_sachsen.osm.pbf http://download.geofabrik.de/europe/germany/sachsen-latest.osm.pbf # about 120 MB +curl --location --output 4_germany.osm.pbf http://download.geofabrik.de/europe/germany-latest.osm.pbf # about 2 GB +curl --location --output 5_planet.osm.pbf http://planet.osm.org/pbf/planet-latest.osm.pbf # about 26 GB + diff --git a/benchmarks/osmium_benchmark_count.cpp b/benchmarks/osmium_benchmark_count.cpp new file mode 100644 index 000000000..701d6faec --- /dev/null +++ b/benchmarks/osmium_benchmark_count.cpp @@ -0,0 +1,54 @@ +/* + + The code in this file is released into the Public Domain. + +*/ + +#include + +#include +#include +#include + +struct CountHandler : public osmium::handler::Handler { + + int nodes = 0; + int ways = 0; + int relations = 0; + + void node(osmium::Node&) { + ++nodes; + } + + void way(osmium::Way&) { + ++ways; + } + + void relation(osmium::Relation&) { + ++relations; + } + +}; + + +int main(int argc, char* argv[]) { + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " OSMFILE\n"; + exit(1); + } + + std::string input_filename = argv[1]; + + osmium::io::Reader reader(input_filename); + + CountHandler handler; + osmium::apply(reader, handler); + reader.close(); + + std::cout << "Nodes: " << handler.nodes << "\n"; + std::cout << "Ways: " << handler.ways << "\n"; + std::cout << "Relations: " << handler.relations << "\n"; + + google::protobuf::ShutdownProtobufLibrary(); +} + diff --git a/benchmarks/osmium_benchmark_count_tag.cpp b/benchmarks/osmium_benchmark_count_tag.cpp new file mode 100644 index 000000000..4a77c3452 --- /dev/null +++ b/benchmarks/osmium_benchmark_count_tag.cpp @@ -0,0 +1,55 @@ +/* + + The code in this file is released into the Public Domain. + +*/ + +#include + +#include +#include +#include + +struct CountHandler : public osmium::handler::Handler { + + int counter = 0; + int all = 0; + + void node(osmium::Node& node) { + ++all; + const char* amenity = node.tags().get_value_by_key("amenity"); + if (amenity && !strcmp(amenity, "post_box")) { + ++counter; + } + } + + void way(osmium::Way&) { + ++all; + } + + void relation(osmium::Relation&) { + ++all; + } + +}; + + +int main(int argc, char* argv[]) { + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " OSMFILE\n"; + exit(1); + } + + std::string input_filename = argv[1]; + + osmium::io::Reader reader(input_filename); + + CountHandler handler; + osmium::apply(reader, handler); + reader.close(); + + std::cout << "r_all=" << handler.all << " r_counter=" << handler.counter << "\n"; + + google::protobuf::ShutdownProtobufLibrary(); +} + diff --git a/benchmarks/osmium_benchmark_index_map.cpp b/benchmarks/osmium_benchmark_index_map.cpp new file mode 100644 index 000000000..fa75fb2b8 --- /dev/null +++ b/benchmarks/osmium_benchmark_index_map.cpp @@ -0,0 +1,41 @@ +/* + + The code in this file is released into the Public Domain. + +*/ + +#include + +#include +#include +#include + +#include +#include + +typedef osmium::index::map::Map index_type; + +typedef osmium::handler::NodeLocationsForWays location_handler_type; + +int main(int argc, char* argv[]) { + if (argc != 3) { + std::cerr << "Usage: " << argv[0] << " OSMFILE FORMAT\n"; + exit(1); + } + + std::string input_filename = argv[1]; + std::string location_store = argv[2]; + + osmium::io::Reader reader(input_filename); + + const auto& map_factory = osmium::index::MapFactory::instance(); + std::unique_ptr index = map_factory.create_map(location_store); + location_handler_type location_handler(*index); + location_handler.ignore_errors(); + + osmium::apply(reader, location_handler); + reader.close(); + + google::protobuf::ShutdownProtobufLibrary(); +} + diff --git a/benchmarks/osmium_benchmark_static_vs_dynamic_index.cpp b/benchmarks/osmium_benchmark_static_vs_dynamic_index.cpp new file mode 100644 index 000000000..9c47c8449 --- /dev/null +++ b/benchmarks/osmium_benchmark_static_vs_dynamic_index.cpp @@ -0,0 +1,136 @@ +/* + + This benchmarks compares the run time for statically vs. dynamically + configured index maps. You can configure index maps at compile-time using + typedefs or at run-time using polymorphism. + + This will read the input file into a buffer and then run the + NodeLocationForWays handler multiple times over the complete data. The + number of runs depends on the size of the input, but is never smaller + than 10. + + Do not run this with very large input files! It will need about 10 times + as much RAM as the file size of the input file. + + The code in this file is released into the Public Domain. + +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +typedef osmium::index::map::SparseMemArray static_index_type; +const std::string location_store="sparse_mem_array"; + +typedef osmium::index::map::Map dynamic_index_type; + +typedef osmium::handler::NodeLocationsForWays static_location_handler_type; +typedef osmium::handler::NodeLocationsForWays dynamic_location_handler_type; + +int main(int argc, char* argv[]) { + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " OSMFILE\n"; + exit(1); + } + + std::string input_filename = argv[1]; + + osmium::memory::Buffer buffer = osmium::io::read_file(input_filename); + google::protobuf::ShutdownProtobufLibrary(); + + const auto& map_factory = osmium::index::MapFactory::instance(); + + const auto buffer_size = buffer.committed() / (1024*1024); // buffer size in MBytes + const int runs = std::max(10, static_cast(5000ull / buffer_size)); + + std::cout << "input: filename=" << input_filename << " buffer_size=" << buffer_size << "MBytes\n"; + std::cout << "runs: " << runs << "\n"; + + double static_min = std::numeric_limits::max(); + double static_sum = 0; + double static_max = 0; + + double dynamic_min = std::numeric_limits::max(); + double dynamic_sum = 0; + double dynamic_max = 0; + + for (int i = 0; i < runs; ++i) { + + { + // static index + osmium::memory::Buffer tmp_buffer(buffer.committed()); + for (const auto& item : buffer) { + tmp_buffer.add_item(item); + tmp_buffer.commit(); + } + + static_index_type static_index; + static_location_handler_type static_location_handler(static_index); + + auto start = std::chrono::steady_clock::now(); + osmium::apply(tmp_buffer, static_location_handler); + auto end = std::chrono::steady_clock::now(); + + double duration = std::chrono::duration(end-start).count(); + + if (duration < static_min) static_min = duration; + if (duration > static_max) static_max = duration; + static_sum += duration; + } + + { + // dynamic index + osmium::memory::Buffer tmp_buffer(buffer.committed()); + for (const auto& item : buffer) { + tmp_buffer.add_item(item); + tmp_buffer.commit(); + } + + std::unique_ptr index = map_factory.create_map(location_store); + dynamic_location_handler_type dynamic_location_handler(*index); + dynamic_location_handler.ignore_errors(); + + auto start = std::chrono::steady_clock::now(); + osmium::apply(tmp_buffer, dynamic_location_handler); + auto end = std::chrono::steady_clock::now(); + + double duration = std::chrono::duration(end-start).count(); + + if (duration < dynamic_min) dynamic_min = duration; + if (duration > dynamic_max) dynamic_max = duration; + dynamic_sum += duration; + } + } + + double static_avg = static_sum/runs; + double dynamic_avg = dynamic_sum/runs; + + std::cout << "static min=" << static_min << "ms avg=" << static_avg << "ms max=" << static_max << "ms\n"; + std::cout << "dynamic min=" << dynamic_min << "ms avg=" << dynamic_avg << "ms max=" << dynamic_max << "ms\n"; + + double rfactor = 100.0; + double diff_min = std::round((dynamic_min - static_min) * rfactor) / rfactor; + double diff_avg = std::round((dynamic_avg - static_avg) * rfactor) / rfactor; + double diff_max = std::round((dynamic_max - static_max) * rfactor) / rfactor; + + double prfactor = 10.0; + double percent_min = std::round((100.0 * diff_min / static_min) * prfactor) / prfactor; + double percent_avg = std::round((100.0 * diff_avg / static_avg) * prfactor) / prfactor; + double percent_max = std::round((100.0 * diff_max / static_max) * prfactor) / prfactor; + + std::cout << "difference:"; + std::cout << " min=" << diff_min << "ms (" << percent_min << "%)"; + std::cout << " avg=" << diff_avg << "ms (" << percent_avg << "%)"; + std::cout << " max=" << diff_max << "ms (" << percent_max << "%)\n"; +} + diff --git a/benchmarks/run_benchmark_count.sh b/benchmarks/run_benchmark_count.sh new file mode 100755 index 000000000..d71508f76 --- /dev/null +++ b/benchmarks/run_benchmark_count.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# +# run_benchmark_count.sh +# + +set -e + +BENCHMARK_NAME=count + +. @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 + diff --git a/benchmarks/run_benchmark_count_tag.sh b/benchmarks/run_benchmark_count_tag.sh new file mode 100755 index 000000000..4fa6a1068 --- /dev/null +++ b/benchmarks/run_benchmark_count_tag.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# +# run_benchmark_count_tag.sh +# + +set -e + +BENCHMARK_NAME=count_tag + +. @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 + diff --git a/benchmarks/run_benchmark_index_map.sh b/benchmarks/run_benchmark_index_map.sh new file mode 100755 index 000000000..30984d460 --- /dev/null +++ b/benchmarks/run_benchmark_index_map.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# +# run_benchmark_index_map.sh +# + +set -e + +BENCHMARK_NAME=index_map + +. @CMAKE_BINARY_DIR@/benchmarks/setup.sh + +CMD=$OB_DIR/osmium_benchmark_$BENCHMARK_NAME + +#MAPS="sparse_mem_map sparse_mem_table sparse_mem_array sparse_mmap_array sparse_file_array dense_mem_array dense_mmap_array dense_file_array" +MAPS="sparse_mem_map sparse_mem_table sparse_mem_array sparse_mmap_array sparse_file_array" + +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 map in $MAPS; do + for n in $OB_SEQ; do + $OB_TIME_CMD -f "$filename $filesize $n $OB_TIME_FORMAT" $CMD $data $map 2>&1 >/dev/null | sed -e "s%$DATA_DIR/%%" | sed -e "s%$OB_DIR/%%" + done + done +done + diff --git a/benchmarks/run_benchmark_static_vs_dynamic_index.sh b/benchmarks/run_benchmark_static_vs_dynamic_index.sh new file mode 100755 index 000000000..05e32f126 --- /dev/null +++ b/benchmarks/run_benchmark_static_vs_dynamic_index.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# +# run_benchmark_static_vs_dynamic_index.sh +# + +set -e + +BENCHMARK_NAME=static_vs_dynamic_index + +. @CMAKE_BINARY_DIR@/benchmarks/setup.sh + +CMD=$OB_DIR/osmium_benchmark_$BENCHMARK_NAME + +for data in $OB_DATA_FILES; do + filesize=`stat --format="%s" --dereference $data` + if [ $filesize -lt 500000000 ]; then + echo "========================" + $CMD $data + fi +done + diff --git a/benchmarks/run_benchmarks.sh b/benchmarks/run_benchmarks.sh new file mode 100755 index 000000000..6a20c0214 --- /dev/null +++ b/benchmarks/run_benchmarks.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# +# run_benchmarks.sh +# +# Run all benchmarks. +# + +set -e + +for benchmark in @CMAKE_BINARY_DIR@/benchmarks/run_benchmark_*.sh; do + name=`basename $benchmark` + echo "Running $name..." + $benchmark +done + diff --git a/benchmarks/setup.sh b/benchmarks/setup.sh new file mode 100755 index 000000000..9733bfe1b --- /dev/null +++ b/benchmarks/setup.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# setup.sh +# + +if [ -z $DATA_DIR ]; then + echo "Please set DATA_DIR environment variable before running benchmark" + exit 1 +fi + +OB_DIR=@CMAKE_BINARY_DIR@/benchmarks + +OB_RUNS=3 +OB_SEQ=`seq -s' ' 1 $OB_RUNS` + +OB_TIME_CMD=/usr/bin/time +OB_TIME_FORMAT="%M %e %S %U %P %C" + +OB_DATA_FILES=`find -L $DATA_DIR -mindepth 1 -maxdepth 1 -type f | sort` + +echo "BENCHMARK: $BENCHMARK_NAME" +echo "---------------------" +echo "CPU:" +grep '^model name' /proc/cpuinfo | tail -1 +grep '^cpu MHz' /proc/cpuinfo | tail -1 +grep '^cpu cores' /proc/cpuinfo | tail -1 +grep '^siblings' /proc/cpuinfo | tail -1 + +echo "---------------------" +echo "MEMORY:" +free +echo "---------------------" +echo "RESULTS:" + diff --git a/cmake/FindOsmium.cmake b/cmake/FindOsmium.cmake index 085983149..15b1e013f 100644 --- a/cmake/FindOsmium.cmake +++ b/cmake/FindOsmium.cmake @@ -9,16 +9,15 @@ # # Usage: # -# Copy this file (and OsmiumOptions.cmake) somewhere into your project -# directory, where cmake can find it. Usually this will be a directory -# called "cmake" which you can add to your module search path with the -# following line in your CMakeLists.txt: +# Copy this file somewhere into your project directory, where cmake can +# find it. Usually this will be a directory called "cmake" which you can +# add to the CMake module search path with the following line in your +# CMakeLists.txt: # # list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") # # Then add the following in your CMakeLists.txt: # -# include(OsmiumOptions) # find_package(Osmium REQUIRED COMPONENTS ) # include_directories(${OSMIUM_INCLUDE_DIRS}) # @@ -75,6 +74,8 @@ find_package_handle_standard_args(OSMIUM REQUIRED_VARS OSMIUM_INCLUDE_DIR) # Copy the results to the output variables. if(OSMIUM_FOUND) set(OSMIUM_INCLUDE_DIRS ${OSMIUM_INCLUDE_DIR}) +else() + set(OSMIUM_INCLUDE_DIRS "") endif() if(Osmium_FIND_REQUIRED AND NOT OSMIUM_FOUND) @@ -234,10 +235,22 @@ endif() #---------------------------------------------------------------------- list(REMOVE_DUPLICATES OSMIUM_INCLUDE_DIRS) -list(REMOVE_DUPLICATES OSMIUM_XML_LIBRARIES) -list(REMOVE_DUPLICATES OSMIUM_PBF_LIBRARIES) -list(REMOVE_DUPLICATES OSMIUM_IO_LIBRARIES) -list(REMOVE_DUPLICATES OSMIUM_LIBRARIES) + +if(OSMIUM_XML_LIBRARIES) + list(REMOVE_DUPLICATES OSMIUM_XML_LIBRARIES) +endif() + +if(OSMIUM_PBF_LIBRARIES) + list(REMOVE_DUPLICATES OSMIUM_PBF_LIBRARIES) +endif() + +if(OSMIUM_IO_LIBRARIES) + list(REMOVE_DUPLICATES OSMIUM_IO_LIBRARIES) +endif() + +if(OSMIUM_LIBRARIES) + list(REMOVE_DUPLICATES OSMIUM_LIBRARIES) +endif() #---------------------------------------------------------------------- # @@ -256,7 +269,14 @@ endif() add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64) if(MSVC) - add_definitions(-wd4996 -DNOMINMAX -DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_WARNINGS) + add_definitions(-wd4996) + add_definitions(-wd4068) + + # Disable warning C4715: "not all control paths return a value" because + # it generates too many false positives. + add_definitions(-wd4715) + + add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_WARNINGS) endif() if(APPLE) @@ -271,7 +291,11 @@ endif() # This is a set of recommended warning options that can be added when compiling # libosmium code. -set(OSMIUM_WARNING_OPTIONS "-Wall -Wextra -pedantic -Wredundant-decls -Wdisabled-optimization -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wsign-promo -Wold-style-cast -Wno-return-type" CACHE STRING "Recommended warning options for libosmium") +if(MSVC) + set(OSMIUM_WARNING_OPTIONS "/W3 /wd4514" CACHE STRING "Recommended warning options for libosmium") +else() + set(OSMIUM_WARNING_OPTIONS "-Wall -Wextra -pedantic -Wredundant-decls -Wdisabled-optimization -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wsign-promo -Wold-style-cast -Wno-return-type" CACHE STRING "Recommended warning options for libosmium") +endif() set(OSMIUM_DRACONIC_CLANG_OPTIONS "-Wdocumentation -Wunused-exception-parameter -Wmissing-declarations -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-unused-macros -Wno-exit-time-destructors -Wno-global-constructors -Wno-padded -Wno-switch-enum -Wno-missing-prototypes -Wno-weak-vtables -Wno-cast-align -Wno-float-equal") diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 000000000..903aad12e --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,34 @@ +#----------------------------------------------------------------------------- +# +# CMake Config +# +# Libosmium documentation +# +#----------------------------------------------------------------------------- + +message(STATUS "Configuring documentation") + +message(STATUS "Looking for doxygen") +find_package(Doxygen) + +if(DOXYGEN_FOUND) + message(STATUS "Looking for doxygen - found") + configure_file(Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) + add_custom_target(doc + ${DOXYGEN_EXECUTABLE} + ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" VERBATIM + ) +# install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html" +# DESTINATION "share/doc/libosmium-dev") +else() + message(STATUS "Looking for doxygen - not found") + message(STATUS " Disabled making of documentation.") +endif() + +#----------------------------------------------------------------------------- +message(STATUS "Configuring documentation - done") + + +#----------------------------------------------------------------------------- diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index e48d2da7e..5ce78ab59 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = "Osmium" +PROJECT_NAME = "Libosmium" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 1f8a10573..c9f59603d 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,64 +1,115 @@ -message(STATUS "Configuring examples...") +#----------------------------------------------------------------------------- +# +# CMake Config +# +# Libosmium examples +# +#----------------------------------------------------------------------------- -if(GETOPT_MISSING) - message(FATAL_ERROR "On Visual Studio the wingetopt library is needed to compile examples") -endif() +message(STATUS "Configuring examples") -set(SIMPLE_EXAMPLES - osmium_convert - osmium_count - osmium_create_node_cache - osmium_debug - osmium_read - osmium_serdump - osmium_use_node_cache +set(EXAMPLES + area_test + convert + count + create_node_cache + debug + index + read + serdump + toogr + toogr2 + toogr2_exp + use_node_cache + CACHE STRING "Example programs" ) -if(SPARSEHASH_FOUND) - list(APPEND SIMPLE_EXAMPLES osmium_area_test) + +#----------------------------------------------------------------------------- +# +# Examples depending on wingetopt +# +#----------------------------------------------------------------------------- +set(GETOPT_EXAMPLES area_test convert serdump toogr toogr2 toogr2_exp) +if(NOT GETOPT_MISSING) + foreach(example ${GETOPT_EXAMPLES}) + list(APPEND EXAMPLE_LIBS_${example} ${GETOPT_LIBRARY}) + endforeach() else() - message("Skipped osmium_area_test example - needed Google SparseHash") + message(STATUS "Configuring examples - Skipping examples because on Visual Studio the wingetopt library is needed and was not found:") + foreach(example ${GETOPT_EXAMPLES}) + message(STATUS " - osmium_${example}") + list(REMOVE_ITEM EXAMPLES ${example}) + endforeach() endif() -# In 'Dev' mode: compile with very strict warnings and turn them into errors. -if(CMAKE_BUILD_TYPE STREQUAL "Dev") - add_definitions(-Werror ${OSMIUM_WARNING_OPTIONS}) + +#----------------------------------------------------------------------------- +# +# Examples depending on SparseHash +# +#----------------------------------------------------------------------------- +if(NOT SPARSEHASH_FOUND) + list(REMOVE_ITEM EXAMPLES area_test) + message(STATUS "Configuring examples - Skipping examples because Google SparseHash not found:") + message(STATUS " - osmium_area_test") endif() -foreach(example ${SIMPLE_EXAMPLES}) - message(STATUS "Configuring example ${example}...") - add_executable(${example} "${example}.cpp") - target_link_libraries(${example} ${OSMIUM_LIBRARIES}) -endforeach(example) +#----------------------------------------------------------------------------- +# +# Examples depending on Boost Program Options +# +#----------------------------------------------------------------------------- unset(Boost_LIBRARIES) unset(Boost_FOUND) find_package(Boost 1.38 COMPONENTS program_options) if(Boost_PROGRAM_OPTIONS_FOUND) - set(example - osmium_index - ) - message(STATUS "Configuring example ${example}...") - add_executable(${example} "${example}.cpp") - target_link_libraries(${example} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${OSMIUM_LIBRARIES}) + list(APPEND EXAMPLE_LIBS_index ${Boost_PROGRAM_OPTIONS_LIBRARY}) else() - message("Can not build osmium_index example without Boost program_options") + list(REMOVE_ITEM EXAMPLES index) + message(STATUS "Configuring examples - Skipping examples because Boost program_options not found:") + message(STATUS " - osmium_index") endif() -set(OGR_EXAMPLES - osmium_toogr - osmium_toogr2 - osmium_toogr2_exp -) -if(GDAL_FOUND AND GEOS_FOUND AND SPARSEHASH_FOUND) +#----------------------------------------------------------------------------- +# +# Examples depending on GDAL/PROJ.4/SparseHash +# +#----------------------------------------------------------------------------- +set(OGR_EXAMPLES toogr toogr2 toogr2_exp) + +if(GDAL_FOUND AND PROJ_FOUND AND SPARSEHASH_FOUND) foreach(example ${OGR_EXAMPLES}) - message(STATUS "Configuring example ${example}...") - add_executable(${example} "${example}.cpp") - target_link_libraries(${example} ${OSMIUM_LIBRARIES}) - endforeach(example) + list(APPEND EXAMPLE_LIBS_${example} ${GDAL_LIBRARIES}) + list(APPEND EXAMPLE_LIBS_${example} ${PROJ_LIBRARIES}) + endforeach() else() - message("GDAL+GEOS+SparseHash not found, skipping OGR examples") + message(STATUS "Configuring examples - Skipping examples because GDAL and/or Proj.4 and/or SparseHash not found:") + foreach(example ${OGR_EXAMPLES}) + message(STATUS " - osmium_${example}") + list(REMOVE_ITEM EXAMPLES ${example}) + endforeach() endif() + +#----------------------------------------------------------------------------- +# +# Configure examples +# +#----------------------------------------------------------------------------- +message(STATUS "Configuring examples - Building these examples:") +foreach(example ${EXAMPLES}) + message(STATUS " - osmium_${example}") + add_executable(osmium_${example} "osmium_${example}.cpp") + target_link_libraries(osmium_${example} ${OSMIUM_IO_LIBRARIES} ${EXAMPLE_LIBS_${example}}) +endforeach() + + +#----------------------------------------------------------------------------- +message(STATUS "Configuring examples - done") + + +#----------------------------------------------------------------------------- diff --git a/examples/osmium_area_test.cpp b/examples/osmium_area_test.cpp index 92d4933f7..b3030a354 100644 --- a/examples/osmium_area_test.cpp +++ b/examples/osmium_area_test.cpp @@ -18,12 +18,12 @@ #include #include #include -#include +#include #include #include typedef osmium::index::map::Dummy index_neg_type; -typedef osmium::index::map::SparseTable index_pos_type; +typedef osmium::index::map::SparseMemTable index_pos_type; typedef osmium::handler::NodeLocationsForWays location_handler_type; class WKTDump : public osmium::handler::Handler { diff --git a/examples/osmium_create_node_cache.cpp b/examples/osmium_create_node_cache.cpp index 948d23021..74f7596fe 100644 --- a/examples/osmium_create_node_cache.cpp +++ b/examples/osmium_create_node_cache.cpp @@ -16,15 +16,15 @@ #include #include -#include -#include +#include +#include #include #include typedef osmium::index::map::Dummy index_neg_type; -//typedef osmium::index::map::DenseMapMmap index_pos_type; -typedef osmium::index::map::DenseMapFile index_pos_type; +//typedef osmium::index::map::DenseMmapArray index_pos_type; +typedef osmium::index::map::DenseFileArray index_pos_type; typedef osmium::handler::NodeLocationsForWays location_handler_type; diff --git a/examples/osmium_index.cpp b/examples/osmium_index.cpp index 2f7e512a5..b61214097 100644 --- a/examples/osmium_index.cpp +++ b/examples/osmium_index.cpp @@ -14,15 +14,16 @@ #include -#include +#include +#include #include #include template class IndexSearch { - typedef typename osmium::index::map::DenseMapFile dense_index_type; - typedef typename osmium::index::map::SparseMapFile sparse_index_type; + typedef typename osmium::index::map::DenseFileArray dense_index_type; + typedef typename osmium::index::map::SparseFileArray sparse_index_type; int m_fd; bool m_dense_format; @@ -186,11 +187,11 @@ public: } bool dense_format() const { - return vm.count("array"); + return vm.count("array") != 0; } bool do_dump() const { - return vm.count("dump"); + return vm.count("dump") != 0; } std::vector search_keys() const { diff --git a/examples/osmium_serdump.cpp b/examples/osmium_serdump.cpp index 0ce8c3894..a774a8dbd 100644 --- a/examples/osmium_serdump.cpp +++ b/examples/osmium_serdump.cpp @@ -24,27 +24,26 @@ #include #include -#include -#include -#include +#include +#include +#include #include // ============================================================================== // Choose the following depending on the size of the input OSM files: // ============================================================================== // for smaller OSM files (extracts) -typedef osmium::index::map::SparseMapMem offset_index_type; +typedef osmium::index::map::SparseMemArray offset_index_type; //typedef osmium::index::map::SparseMapMmap offset_index_type; //typedef osmium::index::map::SparseMapFile offset_index_type; -typedef osmium::index::multimap::SparseMultimapMem map_type; -//typedef osmium::index::multimap::StlMultimap map_type; +typedef osmium::index::multimap::SparseMemArray map_type; +//typedef osmium::index::multimap::SparseMemMultimap map_type; //typedef osmium::index::multimap::Hybrid map_type; // ============================================================================== // for very large OSM files (planet) -//typedef osmium::index::map::DenseMapMmap offset_index_type; -//typedef osmium::index::map::DenseMapMem map_type; +//typedef osmium::index::map::DenseMmapArray offset_index_type; // ============================================================================== void print_help() { diff --git a/examples/osmium_toogr.cpp b/examples/osmium_toogr.cpp index 3230eb956..6d8ab8d94 100644 --- a/examples/osmium_toogr.cpp +++ b/examples/osmium_toogr.cpp @@ -10,25 +10,7 @@ #include #include -#pragma GCC diagnostic push -#ifdef __clang__ -# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" -#endif -#pragma GCC diagnostic ignored "-Wfloat-equal" -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Wpadded" -#pragma GCC diagnostic ignored "-Wredundant-decls" -#pragma GCC diagnostic ignored "-Wshadow" -# include -# include -#pragma GCC diagnostic pop - -// usually you only need one or two of these -#include -#include -#include -#include - +#include #include #include @@ -37,10 +19,7 @@ #include typedef osmium::index::map::Dummy index_neg_type; - -//typedef osmium::index::map::StlMap index_pos_type; -//typedef osmium::index::map::SparseMapMmap index_pos_type; -typedef osmium::index::map::SparseTable index_pos_type; +typedef osmium::index::map::Map index_pos_type; typedef osmium::handler::NodeLocationsForWays location_handler_type; @@ -181,21 +160,28 @@ void print_help() { << "If INFILE is not given stdin is assumed.\n" \ << "If OUTFILE is not given 'ogr_out' is used.\n" \ << "\nOptions:\n" \ - << " -h, --help This help message\n" \ - << " -f, --format=FORMAT Output OGR format (Default: 'SQLite')\n"; + << " -h, --help This help message\n" \ + << " -l, --location_store=TYPE Set location store\n" \ + << " -f, --format=FORMAT Output OGR format (Default: 'SQLite')\n" \ + << " -L See available location stores\n"; } int main(int argc, char* argv[]) { + const auto& map_factory = osmium::index::MapFactory::instance(); + static struct option long_options[] = { - {"help", no_argument, 0, 'h'}, - {"format", required_argument, 0, 'f'}, + {"help", no_argument, 0, 'h'}, + {"format", required_argument, 0, 'f'}, + {"location_store", required_argument, 0, 'l'}, + {"list_location_stores", no_argument, 0, 'L'}, {0, 0, 0, 0} }; - std::string output_format("SQLite"); + std::string output_format { "SQLite" }; + std::string location_store { "sparse_mem_array" }; while (true) { - int c = getopt_long(argc, argv, "hf:", long_options, 0); + int c = getopt_long(argc, argv, "hf:l:L", long_options, 0); if (c == -1) { break; } @@ -207,6 +193,15 @@ int main(int argc, char* argv[]) { case 'f': output_format = optarg; break; + case 'l': + location_store = optarg; + break; + case 'L': + std::cout << "Available map types:\n"; + for (const auto& map_type : map_factory.map_types()) { + std::cout << " " << map_type << "\n"; + } + exit(0); default: exit(1); } @@ -229,9 +224,9 @@ int main(int argc, char* argv[]) { osmium::io::Reader reader(input_filename); - index_pos_type index_pos; + std::unique_ptr index_pos = map_factory.create_map(location_store); index_neg_type index_neg; - location_handler_type location_handler(index_pos, index_neg); + location_handler_type location_handler(*index_pos, index_neg); location_handler.ignore_errors(); MyOGRHandler ogr_handler(output_format, output_filename); @@ -245,7 +240,7 @@ int main(int argc, char* argv[]) { if (locations_fd < 0) { throw std::system_error(errno, std::system_category(), "Open failed"); } - index_pos.dump_as_list(locations_fd); + index_pos->dump_as_list(locations_fd); close(locations_fd); } diff --git a/examples/osmium_toogr2.cpp b/examples/osmium_toogr2.cpp index d2f46eb91..dc5c77325 100644 --- a/examples/osmium_toogr2.cpp +++ b/examples/osmium_toogr2.cpp @@ -13,24 +13,11 @@ #include #include -#pragma GCC diagnostic push -#ifdef __clang__ -# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" -#endif -#pragma GCC diagnostic ignored "-Wfloat-equal" -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Wpadded" -#pragma GCC diagnostic ignored "-Wredundant-decls" -#pragma GCC diagnostic ignored "-Wshadow" -# include -# include -#pragma GCC diagnostic pop - // usually you only need one or two of these #include -#include -#include -#include +#include +#include +#include #include #include @@ -45,9 +32,9 @@ typedef osmium::index::map::Dummy index_neg_type; -//typedef osmium::index::map::StlMap index_pos_type; -//typedef osmium::index::map::SparseMapMmap index_pos_type; -typedef osmium::index::map::SparseTable index_pos_type; +//typedef osmium::index::map::SparseMemArray index_pos_type; +//typedef osmium::index::map::SparseMmapArray index_pos_type; +typedef osmium::index::map::SparseMemTable index_pos_type; typedef osmium::handler::NodeLocationsForWays location_handler_type; diff --git a/examples/osmium_toogr2_exp.cpp b/examples/osmium_toogr2_exp.cpp index 424fe05d2..474da96d0 100644 --- a/examples/osmium_toogr2_exp.cpp +++ b/examples/osmium_toogr2_exp.cpp @@ -15,24 +15,7 @@ #include #include -#pragma GCC diagnostic push -#ifdef __clang__ -# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" -#endif -#pragma GCC diagnostic ignored "-Wfloat-equal" -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Wpadded" -#pragma GCC diagnostic ignored "-Wredundant-decls" -#pragma GCC diagnostic ignored "-Wshadow" -# include -# include -#pragma GCC diagnostic pop - -// usually you only need one or two of these -#include -#include -#include -#include +#include #include @@ -43,13 +26,8 @@ #include #include -typedef osmium::index::map::Dummy index_neg_type; - -//typedef osmium::index::map::StlMap index_pos_type; -//typedef osmium::index::map::SparseMapMmap index_pos_type; -typedef osmium::index::map::SparseTable index_pos_type; - -typedef osmium::handler::NodeLocationsForWays location_handler_type; +typedef osmium::index::map::SparseMemArray index_type; +typedef osmium::handler::NodeLocationsForWays location_handler_type; class MyOGRHandler : public osmium::handler::Handler { @@ -303,10 +281,9 @@ int main(int argc, char* argv[]) { input_filename = "-"; } - index_pos_type index_pos; - index_neg_type index_neg; - location_handler_type location_handler(index_pos, index_neg); - osmium::experimental::FlexReader exr(input_filename, osmium::osm_entity_bits::object); + index_type index_pos; + location_handler_type location_handler(index_pos); + osmium::experimental::FlexReader exr(input_filename, location_handler, osmium::osm_entity_bits::object); MyOGRHandler ogr_handler(output_format, output_filename); diff --git a/examples/osmium_use_node_cache.cpp b/examples/osmium_use_node_cache.cpp index b7ac80770..6b8f964ab 100644 --- a/examples/osmium_use_node_cache.cpp +++ b/examples/osmium_use_node_cache.cpp @@ -16,15 +16,15 @@ #include #include -#include -#include +#include +#include #include #include typedef osmium::index::map::Dummy index_neg_type; -//typedef osmium::index::map::DenseMapMmap index_pos_type; -typedef osmium::index::map::DenseMapFile index_pos_type; +//typedef osmium::index::map::DenseMmapArray index_pos_type; +typedef osmium::index::map::DenseFileArray index_pos_type; typedef osmium::handler::NodeLocationsForWays location_handler_type; diff --git a/include/mmap_for_windows.hpp b/include/mmap_for_windows.hpp index ed568a1b2..d14c81148 100644 --- a/include/mmap_for_windows.hpp +++ b/include/mmap_for_windows.hpp @@ -44,60 +44,60 @@ static void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) { - if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) - return MAP_FAILED; - if (fd == -1) { - if (!(flags & MAP_ANON) || offset) - return MAP_FAILED; - } else if (flags & MAP_ANON) - return MAP_FAILED; + if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) + return MAP_FAILED; + if (fd == -1) { + if (!(flags & MAP_ANON) || offset) + return MAP_FAILED; + } else if (flags & MAP_ANON) + return MAP_FAILED; - DWORD flProtect; - if (prot & PROT_WRITE) { - if (prot & PROT_EXEC) - flProtect = PAGE_EXECUTE_READWRITE; - else - flProtect = PAGE_READWRITE; - } else if (prot & PROT_EXEC) { - if (prot & PROT_READ) - flProtect = PAGE_EXECUTE_READ; - else if (prot & PROT_EXEC) - flProtect = PAGE_EXECUTE; - } else - flProtect = PAGE_READONLY; + DWORD flProtect; + if (prot & PROT_WRITE) { + if (prot & PROT_EXEC) + flProtect = PAGE_EXECUTE_READWRITE; + else + flProtect = PAGE_READWRITE; + } else if (prot & PROT_EXEC) { + if (prot & PROT_READ) + flProtect = PAGE_EXECUTE_READ; + else if (prot & PROT_EXEC) + flProtect = PAGE_EXECUTE; + } else + flProtect = PAGE_READONLY; - off_t end = length + offset; - HANDLE mmap_fd, h; - if (fd == -1) - mmap_fd = INVALID_HANDLE_VALUE; - else - mmap_fd = (HANDLE)_get_osfhandle(fd); - h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL); - if (h == NULL) - return MAP_FAILED; + off_t end = length + offset; + HANDLE mmap_fd, h; + if (fd == -1) + mmap_fd = INVALID_HANDLE_VALUE; + else + mmap_fd = (HANDLE)_get_osfhandle(fd); + h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL); + if (h == NULL) + return MAP_FAILED; - DWORD dwDesiredAccess; - if (prot & PROT_WRITE) - dwDesiredAccess = FILE_MAP_WRITE; - else - dwDesiredAccess = FILE_MAP_READ; - if (prot & PROT_EXEC) - dwDesiredAccess |= FILE_MAP_EXECUTE; - if (flags & MAP_PRIVATE) - dwDesiredAccess |= FILE_MAP_COPY; - void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length); - if (ret == NULL) { - CloseHandle(h); - ret = MAP_FAILED; - } - return ret; + DWORD dwDesiredAccess; + if (prot & PROT_WRITE) + dwDesiredAccess = FILE_MAP_WRITE; + else + dwDesiredAccess = FILE_MAP_READ; + if (prot & PROT_EXEC) + dwDesiredAccess |= FILE_MAP_EXECUTE; + if (flags & MAP_PRIVATE) + dwDesiredAccess |= FILE_MAP_COPY; + void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length); + if (ret == NULL) { + CloseHandle(h); + ret = MAP_FAILED; + } + return ret; } static int munmap(void *addr, size_t length) { - UnmapViewOfFile(addr); - return 0; - /* ruh-ro, we leaked handle from CreateFileMapping() ... */ + UnmapViewOfFile(addr); + return 0; + /* ruh-ro, we leaked handle from CreateFileMapping() ... */ } #undef DWORD_HI diff --git a/include/osmium/area/assembler.hpp b/include/osmium/area/assembler.hpp index 155fa24c2..db769ddf8 100644 --- a/include/osmium/area/assembler.hpp +++ b/include/osmium/area/assembler.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/area/detail/node_ref_segment.hpp b/include/osmium/area/detail/node_ref_segment.hpp index 5b251bb5b..43569a865 100644 --- a/include/osmium/area/detail/node_ref_segment.hpp +++ b/include/osmium/area/detail/node_ref_segment.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/area/detail/proto_ring.hpp b/include/osmium/area/detail/proto_ring.hpp index 759b2dc05..c0f545c98 100644 --- a/include/osmium/area/detail/proto_ring.hpp +++ b/include/osmium/area/detail/proto_ring.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/area/detail/segment_list.hpp b/include/osmium/area/detail/segment_list.hpp index a14f792e4..12ec97fa9 100644 --- a/include/osmium/area/detail/segment_list.hpp +++ b/include/osmium/area/detail/segment_list.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/area/multipolygon_collector.hpp b/include/osmium/area/multipolygon_collector.hpp index af48176d4..0bd10f78b 100644 --- a/include/osmium/area/multipolygon_collector.hpp +++ b/include/osmium/area/multipolygon_collector.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/area/problem_reporter.hpp b/include/osmium/area/problem_reporter.hpp index 5e255db50..4ae4bb23d 100644 --- a/include/osmium/area/problem_reporter.hpp +++ b/include/osmium/area/problem_reporter.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/area/problem_reporter_exception.hpp b/include/osmium/area/problem_reporter_exception.hpp index 29c7ad429..5e743c6d8 100644 --- a/include/osmium/area/problem_reporter_exception.hpp +++ b/include/osmium/area/problem_reporter_exception.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/area/problem_reporter_ogr.hpp b/include/osmium/area/problem_reporter_ogr.hpp index a567057ce..c437a3f57 100644 --- a/include/osmium/area/problem_reporter_ogr.hpp +++ b/include/osmium/area/problem_reporter_ogr.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -33,18 +33,38 @@ DEALINGS IN THE SOFTWARE. */ -#pragma GCC diagnostic push -#ifdef __clang__ -# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" +/** + * @file + * + * This file contains code for reporting problems through OGR when + * assembling multipolygons. + * + * @attention If you include this file, you'll need to link with `libgdal`. + */ + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable : 4458) +#else +# pragma GCC diagnostic push +# ifdef __clang__ +# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" +# endif +# pragma GCC diagnostic ignored "-Wfloat-equal" +# pragma GCC diagnostic ignored "-Wold-style-cast" +# pragma GCC diagnostic ignored "-Wpadded" +# pragma GCC diagnostic ignored "-Wredundant-decls" +# pragma GCC diagnostic ignored "-Wshadow" +#endif + +#include +#include + +#ifdef _MSC_VER +# pragma warning(pop) +#else +# pragma GCC diagnostic pop #endif -#pragma GCC diagnostic ignored "-Wfloat-equal" -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Wpadded" -#pragma GCC diagnostic ignored "-Wredundant-decls" -#pragma GCC diagnostic ignored "-Wshadow" -# include -# include -#pragma GCC diagnostic pop #include #include diff --git a/include/osmium/area/problem_reporter_stream.hpp b/include/osmium/area/problem_reporter_stream.hpp index 6bee56816..ddcb343e8 100644 --- a/include/osmium/area/problem_reporter_stream.hpp +++ b/include/osmium/area/problem_reporter_stream.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/builder/builder.hpp b/include/osmium/builder/builder.hpp index 30c180c0d..bf9cdccfc 100644 --- a/include/osmium/builder/builder.hpp +++ b/include/osmium/builder/builder.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -37,7 +37,9 @@ DEALINGS IN THE SOFTWARE. #include #include #include +#include #include +#include #include #include diff --git a/include/osmium/builder/builder_helper.hpp b/include/osmium/builder/builder_helper.hpp index 3e00f81c4..eebdf338c 100644 --- a/include/osmium/builder/builder_helper.hpp +++ b/include/osmium/builder/builder_helper.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/builder/osm_object_builder.hpp b/include/osmium/builder/osm_object_builder.hpp index 851eb85f8..b88765e2a 100644 --- a/include/osmium/builder/osm_object_builder.hpp +++ b/include/osmium/builder/osm_object_builder.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -36,6 +36,7 @@ DEALINGS IN THE SOFTWARE. #include #include #include +#include #include #include diff --git a/include/osmium/diff_handler.hpp b/include/osmium/diff_handler.hpp index 9864df5a1..4f9b3a1a0 100644 --- a/include/osmium/diff_handler.hpp +++ b/include/osmium/diff_handler.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/diff_iterator.hpp b/include/osmium/diff_iterator.hpp index 576834c4d..0ddf7ff7a 100644 --- a/include/osmium/diff_iterator.hpp +++ b/include/osmium/diff_iterator.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/diff_visitor.hpp b/include/osmium/diff_visitor.hpp index b8db6970b..5e72a7bb7 100644 --- a/include/osmium/diff_visitor.hpp +++ b/include/osmium/diff_visitor.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/dynamic_handler.hpp b/include/osmium/dynamic_handler.hpp index bc593131c..9d0bd66f5 100644 --- a/include/osmium/dynamic_handler.hpp +++ b/include/osmium/dynamic_handler.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/experimental/flex_reader.hpp b/include/osmium/experimental/flex_reader.hpp index 1ce4312fc..f00a5ecaf 100644 --- a/include/osmium/experimental/flex_reader.hpp +++ b/include/osmium/experimental/flex_reader.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -41,7 +41,7 @@ DEALINGS IN THE SOFTWARE. namespace osmium { /** - * @short Experimental code that is not "officially" supported. + * @brief Experimental code that is not "officially" supported. */ namespace experimental { @@ -51,9 +51,7 @@ namespace osmium { bool m_with_areas; osmium::osm_entity_bits::type m_entities; - typename TLocationHandler::index_pos_type m_index_pos; - typename TLocationHandler::index_neg_type m_index_neg; - TLocationHandler m_location_handler; + TLocationHandler& m_location_handler; osmium::io::Reader m_reader; osmium::area::Assembler::config_type m_assembler_config; @@ -61,12 +59,10 @@ namespace osmium { public: - explicit FlexReader(const osmium::io::File& file, osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::nwr) : - m_with_areas(entities & osmium::osm_entity_bits::area), + explicit FlexReader(const osmium::io::File& file, TLocationHandler& location_handler, osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::nwr) : + m_with_areas((entities & osmium::osm_entity_bits::area) != 0), m_entities((entities & ~osmium::osm_entity_bits::area) | (m_with_areas ? osmium::osm_entity_bits::node | osmium::osm_entity_bits::way : osmium::osm_entity_bits::nothing)), - m_index_pos(), - m_index_neg(), - m_location_handler(m_index_pos, m_index_neg), + m_location_handler(location_handler), m_reader(file, m_entities), m_assembler_config(), m_collector(m_assembler_config) @@ -79,21 +75,20 @@ namespace osmium { } } - explicit FlexReader(const std::string& filename, osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::nwr) : - FlexReader(osmium::io::File(filename), entities) { + explicit FlexReader(const std::string& filename, TLocationHandler& location_handler, osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::nwr) : + FlexReader(osmium::io::File(filename), location_handler, entities) { } - explicit FlexReader(const char* filename, osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::nwr) : - FlexReader(osmium::io::File(filename), entities) { + explicit FlexReader(const char* filename, TLocationHandler& location_handler, osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::nwr) : + FlexReader(osmium::io::File(filename), location_handler, entities) { } osmium::memory::Buffer read() { - std::vector area_buffers; - osmium::memory::Buffer buffer = m_reader.read(); if (buffer) { if (m_with_areas) { + std::vector area_buffers; osmium::apply(buffer, m_location_handler, m_collector.handler([&area_buffers](osmium::memory::Buffer&& area_buffer) { area_buffers.push_back(std::move(area_buffer)); })); diff --git a/include/osmium/geom/coordinates.hpp b/include/osmium/geom/coordinates.hpp index 1ff27fea4..2bad57e0d 100644 --- a/include/osmium/geom/coordinates.hpp +++ b/include/osmium/geom/coordinates.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/geom/factory.hpp b/include/osmium/geom/factory.hpp index 4097b5dac..a0a208075 100644 --- a/include/osmium/geom/factory.hpp +++ b/include/osmium/geom/factory.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/geom/geojson.hpp b/include/osmium/geom/geojson.hpp index b8bc5fde0..7d5953535 100644 --- a/include/osmium/geom/geojson.hpp +++ b/include/osmium/geom/geojson.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/geom/geos.hpp b/include/osmium/geom/geos.hpp index fffe20d3a..3c73637be 100644 --- a/include/osmium/geom/geos.hpp +++ b/include/osmium/geom/geos.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -33,6 +33,15 @@ DEALINGS IN THE SOFTWARE. */ +/** + * @file + * + * This file contains code for conversion of OSM geometries into GDAL + * geometries. + * + * @attention If you include this file, you'll need to link with `libgeos`. + */ + #include #include diff --git a/include/osmium/geom/haversine.hpp b/include/osmium/geom/haversine.hpp index b8d013492..14e18c59a 100644 --- a/include/osmium/geom/haversine.hpp +++ b/include/osmium/geom/haversine.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/geom/mercator_projection.hpp b/include/osmium/geom/mercator_projection.hpp index d17001717..a6d1d5742 100644 --- a/include/osmium/geom/mercator_projection.hpp +++ b/include/osmium/geom/mercator_projection.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/geom/ogr.hpp b/include/osmium/geom/ogr.hpp index 3770c503a..f33971c7d 100644 --- a/include/osmium/geom/ogr.hpp +++ b/include/osmium/geom/ogr.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -33,19 +33,49 @@ DEALINGS IN THE SOFTWARE. */ +/** + * @file + * + * This file contains code for conversion of OSM geometries into OGR + * geometries. + * + * @attention If you include this file, you'll need to link with `libgdal`. + */ + #include #include #include #include -#pragma GCC diagnostic push -#ifdef __clang__ -# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable : 4458) +# pragma warning(disable : 4251) +#else +# pragma GCC diagnostic push +# ifdef __clang__ +# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" +# endif +# pragma GCC diagnostic ignored "-Wfloat-equal" +# pragma GCC diagnostic ignored "-Wold-style-cast" +# pragma GCC diagnostic ignored "-Wpadded" +# pragma GCC diagnostic ignored "-Wredundant-decls" +# pragma GCC diagnostic ignored "-Wshadow" +#endif + +/* Strictly speaking the following include would be enough here, + but everybody using this file will very likely need the other includes, + so we are adding them here, so that not everybody will need all those + pragmas to disable warnings. */ +//#include +#include +#include + +#ifdef _MSC_VER +# pragma warning(pop) +#else +# pragma GCC diagnostic pop #endif -#pragma GCC diagnostic ignored "-Wfloat-equal" -#pragma GCC diagnostic ignored "-Wpadded" -# include -#pragma GCC diagnostic pop #include #include diff --git a/include/osmium/geom/projection.hpp b/include/osmium/geom/projection.hpp index 55f4eebf7..6419101f8 100644 --- a/include/osmium/geom/projection.hpp +++ b/include/osmium/geom/projection.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -33,6 +33,15 @@ DEALINGS IN THE SOFTWARE. */ +/** + * @file + * + * This file contains code for projecting OSM locations to arbitrary + * coordinate reference systems. It is based on the Proj.4 library. + * + * @attention If you include this file, you'll need to link with `libproj`. + */ + #include #include @@ -77,11 +86,11 @@ namespace osmium { } bool is_latlong() const { - return pj_is_latlong(m_crs.get()); + return pj_is_latlong(m_crs.get()) != 0; } bool is_geocent() const { - return pj_is_geocent(m_crs.get()); + return pj_is_geocent(m_crs.get()) != 0; } /** diff --git a/include/osmium/geom/relations.hpp b/include/osmium/geom/relations.hpp index e57e2f4c9..e9e2aa420 100644 --- a/include/osmium/geom/relations.hpp +++ b/include/osmium/geom/relations.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/geom/util.hpp b/include/osmium/geom/util.hpp index 1f1a50dc8..5e9f8228c 100644 --- a/include/osmium/geom/util.hpp +++ b/include/osmium/geom/util.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/geom/wkb.hpp b/include/osmium/geom/wkb.hpp index df4e25549..31fce71f9 100644 --- a/include/osmium/geom/wkb.hpp +++ b/include/osmium/geom/wkb.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/geom/wkt.hpp b/include/osmium/geom/wkt.hpp index 86ea7c039..4fea96baa 100644 --- a/include/osmium/geom/wkt.hpp +++ b/include/osmium/geom/wkt.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/handler.hpp b/include/osmium/handler.hpp index 62e59f80a..34d878511 100644 --- a/include/osmium/handler.hpp +++ b/include/osmium/handler.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/handler/chain.hpp b/include/osmium/handler/chain.hpp index 868632d7e..1af3962fd 100644 --- a/include/osmium/handler/chain.hpp +++ b/include/osmium/handler/chain.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/handler/disk_store.hpp b/include/osmium/handler/disk_store.hpp index 2b7ffcff6..ccae5962a 100644 --- a/include/osmium/handler/disk_store.hpp +++ b/include/osmium/handler/disk_store.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/handler/dump.hpp b/include/osmium/handler/dump.hpp index e62c4b071..564035c56 100644 --- a/include/osmium/handler/dump.hpp +++ b/include/osmium/handler/dump.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/handler/node_locations_for_ways.hpp b/include/osmium/handler/node_locations_for_ways.hpp index a273082b0..d1224a0d5 100644 --- a/include/osmium/handler/node_locations_for_ways.hpp +++ b/include/osmium/handler/node_locations_for_ways.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -44,6 +44,8 @@ DEALINGS IN THE SOFTWARE. #include #include +#include + namespace osmium { namespace handler { @@ -102,6 +104,9 @@ namespace osmium { NodeLocationsForWays(const NodeLocationsForWays&) = delete; NodeLocationsForWays& operator=(const NodeLocationsForWays&) = delete; + NodeLocationsForWays(NodeLocationsForWays&&) = default; + NodeLocationsForWays& operator=(NodeLocationsForWays&&) = default; + ~NodeLocationsForWays() noexcept = default; void ignore_errors() { diff --git a/include/osmium/handler/object_relations.hpp b/include/osmium/handler/object_relations.hpp index e73ce87fc..dc4aa45d8 100644 --- a/include/osmium/handler/object_relations.hpp +++ b/include/osmium/handler/object_relations.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/index/detail/create_map_with_fd.hpp b/include/osmium/index/detail/create_map_with_fd.hpp new file mode 100644 index 000000000..29dc1dc67 --- /dev/null +++ b/include/osmium/index/detail/create_map_with_fd.hpp @@ -0,0 +1,73 @@ +#ifndef OSMIUM_INDEX_DETAIL_CREATE_MAP_WITH_FD_HPP +#define OSMIUM_INDEX_DETAIL_CREATE_MAP_WITH_FD_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013-2015 Jochen Topf 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 +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace index { + + namespace detail { + + template + inline T* create_map_with_fd(const std::vector& config) { + if (config.size() == 1) { + return new T(); + } else { + assert(config.size() > 1); + const std::string& filename = config[1]; + int fd = ::open(filename.c_str(), O_CREAT | O_RDWR, 0644); + if (fd == -1) { + throw std::runtime_error(std::string("can't open file '") + filename + "': " + strerror(errno)); + } + return new T(fd); + } + } + + } // namespace detail + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_DETAIL_CREATE_MAP_WITH_FD_HPP diff --git a/include/osmium/index/detail/mmap_vector_anon.hpp b/include/osmium/index/detail/mmap_vector_anon.hpp index f06696150..0ea4f9db6 100644 --- a/include/osmium/index/detail/mmap_vector_anon.hpp +++ b/include/osmium/index/detail/mmap_vector_anon.hpp @@ -1,11 +1,11 @@ -#ifndef OSMIUM_DETAIL_MMAP_VECTOR_ANON_HPP -#define OSMIUM_DETAIL_MMAP_VECTOR_ANON_HPP +#ifndef OSMIUM_INDEX_DETAIL_MMAP_VECTOR_ANON_HPP +#define OSMIUM_INDEX_DETAIL_MMAP_VECTOR_ANON_HPP /* This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -45,8 +45,8 @@ namespace osmium { namespace detail { /** - * This class looks and behaves like STL vector, but uses mmap internally. - */ + * This class looks and behaves like STL vector, but uses mmap internally. + */ template class mmap_vector_anon : public mmap_vector_base { @@ -75,4 +75,4 @@ namespace osmium { #endif // __linux__ -#endif // OSMIUM_DETAIL_MMAP_VECTOR_ANON_HPP +#endif // OSMIUM_INDEX_DETAIL_MMAP_VECTOR_ANON_HPP diff --git a/include/osmium/index/detail/mmap_vector_base.hpp b/include/osmium/index/detail/mmap_vector_base.hpp index fc96b271a..3aff26d41 100644 --- a/include/osmium/index/detail/mmap_vector_base.hpp +++ b/include/osmium/index/detail/mmap_vector_base.hpp @@ -1,11 +1,11 @@ -#ifndef OSMIUM_DETAIL_MMAP_VECTOR_BASE_HPP -#define OSMIUM_DETAIL_MMAP_VECTOR_BASE_HPP +#ifndef OSMIUM_INDEX_DETAIL_MMAP_VECTOR_BASE_HPP +#define OSMIUM_INDEX_DETAIL_MMAP_VECTOR_BASE_HPP /* This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -38,6 +38,7 @@ DEALINGS IN THE SOFTWARE. #include #include +#include namespace osmium { @@ -180,4 +181,4 @@ namespace osmium { } // namespace osmium -#endif // OSMIUM_DETAIL_MMAP_VECTOR_BASE_HPP +#endif // OSMIUM_INDEX_DETAIL_MMAP_VECTOR_BASE_HPP diff --git a/include/osmium/index/detail/mmap_vector_file.hpp b/include/osmium/index/detail/mmap_vector_file.hpp index 421b97769..55077d18d 100644 --- a/include/osmium/index/detail/mmap_vector_file.hpp +++ b/include/osmium/index/detail/mmap_vector_file.hpp @@ -1,11 +1,11 @@ -#ifndef OSMIUM_DETAIL_MMAP_VECTOR_FILE_HPP -#define OSMIUM_DETAIL_MMAP_VECTOR_FILE_HPP +#ifndef OSMIUM_INDEX_DETAIL_MMAP_VECTOR_FILE_HPP +#define OSMIUM_INDEX_DETAIL_MMAP_VECTOR_FILE_HPP /* This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -82,4 +82,4 @@ namespace osmium { } // namespace osmium -#endif // OSMIUM_DETAIL_MMAP_VECTOR_FILE_HPP +#endif // OSMIUM_INDEX_DETAIL_MMAP_VECTOR_FILE_HPP diff --git a/include/osmium/index/detail/tmpfile.hpp b/include/osmium/index/detail/tmpfile.hpp index 3d00c5017..06cab6544 100644 --- a/include/osmium/index/detail/tmpfile.hpp +++ b/include/osmium/index/detail/tmpfile.hpp @@ -1,11 +1,11 @@ -#ifndef OSMIUM_DETAIL_TMPFILE_HPP -#define OSMIUM_DETAIL_TMPFILE_HPP +#ifndef OSMIUM_INDEX_DETAIL_TMPFILE_HPP +#define OSMIUM_INDEX_DETAIL_TMPFILE_HPP /* This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -59,4 +59,4 @@ namespace osmium { } // namespace osmium -#endif // OSMIUM_DETAIL_TMPFILE +#endif // OSMIUM_INDEX_DETAIL_TMPFILE_HPP diff --git a/include/osmium/index/detail/typed_mmap.hpp b/include/osmium/index/detail/typed_mmap.hpp index 8a952a4e0..77b065e8e 100644 --- a/include/osmium/index/detail/typed_mmap.hpp +++ b/include/osmium/index/detail/typed_mmap.hpp @@ -1,11 +1,11 @@ -#ifndef OSMIUM_DETAIL_TYPED_MMAP_HPP -#define OSMIUM_DETAIL_TYPED_MMAP_HPP +#ifndef OSMIUM_INDEX_DETAIL_TYPED_MMAP_HPP +#define OSMIUM_INDEX_DETAIL_TYPED_MMAP_HPP /* This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -226,4 +226,4 @@ namespace osmium { } // namespace osmium -#endif // OSMIUM_DETAIL_TYPED_MMAP_HPP +#endif // OSMIUM_INDEX_DETAIL_TYPED_MMAP_HPP diff --git a/include/osmium/index/map/vector.hpp b/include/osmium/index/detail/vector_map.hpp similarity index 96% rename from include/osmium/index/map/vector.hpp rename to include/osmium/index/detail/vector_map.hpp index 1ac16cab2..73c5a37a5 100644 --- a/include/osmium/index/map/vector.hpp +++ b/include/osmium/index/detail/vector_map.hpp @@ -1,11 +1,11 @@ -#ifndef OSMIUM_INDEX_MAP_VECTOR_HPP -#define OSMIUM_INDEX_MAP_VECTOR_HPP +#ifndef OSMIUM_INDEX_DETAIL_VECTOR_MAP_HPP +#define OSMIUM_INDEX_DETAIL_VECTOR_MAP_HPP /* This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -38,6 +38,7 @@ DEALINGS IN THE SOFTWARE. #include #include +#include #include #include @@ -198,7 +199,7 @@ namespace osmium { std::sort(m_vector.begin(), m_vector.end()); } - void dump_as_list(int fd) const override final { + void dump_as_list(const int fd) override final { osmium::io::detail::reliable_write(fd, reinterpret_cast(m_vector.data()), byte_size()); } @@ -234,4 +235,4 @@ namespace osmium { } // namespace osmium -#endif // OSMIUM_INDEX_MAP_VECTOR_HPP +#endif // OSMIUM_INDEX_DETAIL_VECTOR_MAP_HPP diff --git a/include/osmium/index/multimap/vector.hpp b/include/osmium/index/detail/vector_multimap.hpp similarity index 94% rename from include/osmium/index/multimap/vector.hpp rename to include/osmium/index/detail/vector_multimap.hpp index b9dae43e5..c2b2e1f29 100644 --- a/include/osmium/index/multimap/vector.hpp +++ b/include/osmium/index/detail/vector_multimap.hpp @@ -1,11 +1,11 @@ -#ifndef OSMIUM_INDEX_MULTIMAP_VECTOR_HPP -#define OSMIUM_INDEX_MULTIMAP_VECTOR_HPP +#ifndef OSMIUM_INDEX_DETAIL_VECTOR_MULTIMAP_HPP +#define OSMIUM_INDEX_DETAIL_VECTOR_MULTIMAP_HPP /* This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -37,6 +37,7 @@ DEALINGS IN THE SOFTWARE. #include #include +#include #include #include @@ -136,7 +137,7 @@ namespace osmium { ); } - void dump_as_list(int fd) const override final { + void dump_as_list(const int fd) override final { osmium::io::detail::reliable_write(fd, reinterpret_cast(m_vector.data()), byte_size()); } @@ -148,4 +149,4 @@ namespace osmium { } // namespace osmium -#endif // OSMIUM_INDEX_MULTIMAP_VECTOR_HPP +#endif // OSMIUM_INDEX_DETAIL_VECTOR_MULTIMAP_HPP diff --git a/include/osmium/index/index.hpp b/include/osmium/index/index.hpp index ece8ec444..b73b319e8 100644 --- a/include/osmium/index/index.hpp +++ b/include/osmium/index/index.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/index/map.hpp b/include/osmium/index/map.hpp index 92b880f47..a9fe0c3bd 100644 --- a/include/osmium/index/map.hpp +++ b/include/osmium/index/map.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -33,10 +33,18 @@ DEALINGS IN THE SOFTWARE. */ +#include #include +#include +#include +#include +#include +#include #include +#include -#include // IWYU pragma: export +#include +#include namespace osmium { @@ -140,7 +148,7 @@ namespace osmium { // default implementation is empty } - virtual void dump_as_list(int /*fd*/) const { + virtual void dump_as_list(const int /*fd*/) { std::runtime_error("can't dump as list"); } @@ -148,6 +156,98 @@ namespace osmium { } // namespace map + template + class MapFactory { + + public: + + typedef TId id_type; + typedef TValue value_type; + typedef osmium::index::map::Map map_type; + typedef std::function&)> create_map_func; + + private: + + std::map m_callbacks; + + MapFactory() = default; + + MapFactory(const MapFactory&) = delete; + MapFactory& operator=(const MapFactory&) = delete; + + MapFactory(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: + + static MapFactory& instance() { + static MapFactory factory; + return factory; + } + + bool register_map(const std::string& map_type_name, create_map_func func) { + return m_callbacks.emplace(map_type_name, func).second; + } + + std::vector map_types() const { + std::vector result; + + for (const auto& cb : m_callbacks) { + result.push_back(cb.first); + } + + std::sort(result.begin(), result.end()); + + return result; + } + + std::unique_ptr create_map(const std::string& config_string) const { + std::vector config = osmium::split_string(config_string, ','); + + if (config.empty()) { + throw std::runtime_error("Need non-empty map type name."); + } + + auto it = m_callbacks.find(config[0]); + if (it != m_callbacks.end()) { + return std::unique_ptr((it->second)(config)); + } + + error(config[0]); + } + + }; // class MapFactory + + namespace map { + + template class TMap> + struct create_map { + TMap* operator()(const std::vector&) { + return new TMap(); + } + }; + + } // namespace map + + template class TMap> + inline bool register_map(const std::string& name) { + return osmium::index::MapFactory::instance().register_map(name, [](const std::vector& config) { + return map::create_map()(config); + }); + } + +#define REGISTER_MAP(id, value, klass, name) \ +namespace { \ + const bool registered_index_map_##name = osmium::index::register_map(#name); \ +} + } // namespace index } // namespace osmium diff --git a/include/osmium/index/map/all.hpp b/include/osmium/index/map/all.hpp new file mode 100644 index 000000000..9ffadc0de --- /dev/null +++ b/include/osmium/index/map/all.hpp @@ -0,0 +1,46 @@ +#ifndef OSMIUM_INDEX_MAP_ALL_HPP +#define OSMIUM_INDEX_MAP_ALL_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013-2015 Jochen Topf 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 // IWYU pragma: keep +#include // IWYU pragma: keep +#include // IWYU pragma: keep +#include // IWYU pragma: keep +#include // IWYU pragma: keep +#include // IWYU pragma: keep +#include // IWYU pragma: keep +#include // IWYU pragma: keep +#include // IWYU pragma: keep + +#endif // OSMIUM_INDEX_MAP_ALL_HPP diff --git a/include/osmium/index/map/dense_file_array.hpp b/include/osmium/index/map/dense_file_array.hpp new file mode 100644 index 000000000..d209a875c --- /dev/null +++ b/include/osmium/index/map/dense_file_array.hpp @@ -0,0 +1,67 @@ +#ifndef OSMIUM_INDEX_MAP_DENSE_FILE_ARRAY_HPP +#define OSMIUM_INDEX_MAP_DENSE_FILE_ARRAY_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013-2015 Jochen Topf 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 +#include + +#include +#include +#include + +#define OSMIUM_HAS_INDEX_MAP_DENSE_FILE_ARRAY + +namespace osmium { + + namespace index { + + namespace map { + + template + using DenseFileArray = VectorBasedDenseMap, TId, TValue>; + + template + struct create_map { + DenseFileArray* operator()(const std::vector& config) { + return osmium::index::detail::create_map_with_fd>(config); + } + }; + + } // namespace map + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_MAP_DENSE_FILE_ARRAY_HPP diff --git a/include/osmium/index/map/dense_mem_array.hpp b/include/osmium/index/map/dense_mem_array.hpp new file mode 100644 index 000000000..b45eec458 --- /dev/null +++ b/include/osmium/index/map/dense_mem_array.hpp @@ -0,0 +1,57 @@ +#ifndef OSMIUM_INDEX_MAP_DENSE_MEM_ARRAY_HPP +#define OSMIUM_INDEX_MAP_DENSE_MEM_ARRAY_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013-2015 Jochen Topf 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 + +#include + +#define OSMIUM_HAS_INDEX_MAP_DENSE_MEM_ARRAY + +namespace osmium { + + namespace index { + + namespace map { + + template + using DenseMemArray = VectorBasedDenseMap, TId, TValue>; + + } // namespace map + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_MAP_DENSE_MEM_ARRAY_HPP diff --git a/include/osmium/index/map/mmap_vector_anon.hpp b/include/osmium/index/map/dense_mmap_array.hpp similarity index 77% rename from include/osmium/index/map/mmap_vector_anon.hpp rename to include/osmium/index/map/dense_mmap_array.hpp index a62e99aa6..fc60a1ef2 100644 --- a/include/osmium/index/map/mmap_vector_anon.hpp +++ b/include/osmium/index/map/dense_mmap_array.hpp @@ -1,11 +1,11 @@ -#ifndef OSMIUM_INDEX_MAP_MMAP_VECTOR_ANON_HPP -#define OSMIUM_INDEX_MAP_MMAP_VECTOR_ANON_HPP +#ifndef OSMIUM_INDEX_MAP_DENSE_MMAP_ARRAY_HPP +#define OSMIUM_INDEX_MAP_DENSE_MMAP_ARRAY_HPP /* This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -35,8 +35,10 @@ DEALINGS IN THE SOFTWARE. #ifdef __linux__ -#include #include +#include + +#define OSMIUM_HAS_INDEX_MAP_DENSE_MMAP_ARRAY namespace osmium { @@ -45,10 +47,7 @@ namespace osmium { namespace map { template - using DenseMapMmap = VectorBasedDenseMap, TId, TValue>; - - template - using SparseMapMmap = VectorBasedSparseMap; + using DenseMmapArray = VectorBasedDenseMap, TId, TValue>; } // namespace map @@ -58,4 +57,4 @@ namespace osmium { #endif // __linux__ -#endif // OSMIUM_INDEX_MAP_MMAP_VECTOR_ANON_HPP +#endif // OSMIUM_INDEX_MAP_DENSE_MMAP_ARRAY_HPP diff --git a/include/osmium/index/map/dummy.hpp b/include/osmium/index/map/dummy.hpp index bafb81008..de05d1d69 100644 --- a/include/osmium/index/map/dummy.hpp +++ b/include/osmium/index/map/dummy.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -35,6 +35,7 @@ DEALINGS IN THE SOFTWARE. #include +#include #include namespace osmium { diff --git a/include/osmium/index/map/sparse_file_array.hpp b/include/osmium/index/map/sparse_file_array.hpp new file mode 100644 index 000000000..2ba9315dd --- /dev/null +++ b/include/osmium/index/map/sparse_file_array.hpp @@ -0,0 +1,67 @@ +#ifndef OSMIUM_INDEX_MAP_SPARSE_FILE_ARRAY_HPP +#define OSMIUM_INDEX_MAP_SPARSE_FILE_ARRAY_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013-2015 Jochen Topf 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 +#include + +#include +#include +#include + +#define OSMIUM_HAS_INDEX_MAP_SPARSE_FILE_ARRAY + +namespace osmium { + + namespace index { + + namespace map { + + template + using SparseFileArray = VectorBasedSparseMap; + + template + struct create_map { + SparseFileArray* operator()(const std::vector& config) { + return osmium::index::detail::create_map_with_fd>(config); + } + }; + + } // namespace map + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_MAP_SPARSE_FILE_ARRAY_HPP diff --git a/include/osmium/index/map/stl_vector.hpp b/include/osmium/index/map/sparse_mem_array.hpp similarity index 79% rename from include/osmium/index/map/stl_vector.hpp rename to include/osmium/index/map/sparse_mem_array.hpp index 238e9afa9..9adf41f0a 100644 --- a/include/osmium/index/map/stl_vector.hpp +++ b/include/osmium/index/map/sparse_mem_array.hpp @@ -1,11 +1,11 @@ -#ifndef OSMIUM_INDEX_MAP_STL_VECTOR_HPP -#define OSMIUM_INDEX_MAP_STL_VECTOR_HPP +#ifndef OSMIUM_INDEX_MAP_SPARSE_MEM_ARRAY_HPP +#define OSMIUM_INDEX_MAP_SPARSE_MEM_ARRAY_HPP /* This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -35,7 +35,9 @@ DEALINGS IN THE SOFTWARE. #include -#include +#include + +#define OSMIUM_HAS_INDEX_MAP_SPARSE_MEM_ARRAY namespace osmium { @@ -43,14 +45,11 @@ namespace osmium { namespace map { - template - using DenseMapMem = VectorBasedDenseMap, TId, TValue>; - template using StdVectorWrap = std::vector; template - using SparseMapMem = VectorBasedSparseMap; + using SparseMemArray = VectorBasedSparseMap; } // namespace map @@ -58,4 +57,4 @@ namespace osmium { } // namespace osmium -#endif // OSMIUM_INDEX_MAP_STL_VECTOR_HPP +#endif // OSMIUM_INDEX_MAP_SPARSE_MEM_ARRAY_HPP diff --git a/include/osmium/index/map/stl_map.hpp b/include/osmium/index/map/sparse_mem_map.hpp similarity index 86% rename from include/osmium/index/map/stl_map.hpp rename to include/osmium/index/map/sparse_mem_map.hpp index d2781a7e1..d053155f0 100644 --- a/include/osmium/index/map/stl_map.hpp +++ b/include/osmium/index/map/sparse_mem_map.hpp @@ -1,11 +1,11 @@ -#ifndef OSMIUM_INDEX_MAP_STL_MAP_HPP -#define OSMIUM_INDEX_MAP_STL_MAP_HPP +#ifndef OSMIUM_INDEX_MAP_SPARSE_MEM_MAP_HPP +#define OSMIUM_INDEX_MAP_SPARSE_MEM_MAP_HPP /* This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -41,8 +41,11 @@ DEALINGS IN THE SOFTWARE. #include #include +#include #include +#define OSMIUM_HAS_INDEX_MAP_SPARSE_MEM_MAP + namespace osmium { namespace index { @@ -54,7 +57,7 @@ namespace osmium { * lot of memory, but might make sense for small maps. */ template - class StlMap : public osmium::index::map::Map { + class SparseMemMap : public osmium::index::map::Map { // This is a rough estimate for the memory needed for each // element in the map (id + value + pointers to left, right, @@ -66,9 +69,9 @@ namespace osmium { public: - StlMap() = default; + SparseMemMap() = default; - ~StlMap() override final = default; + ~SparseMemMap() override final = default; void set(const TId id, const TValue value) override final { m_elements[id] = value; @@ -94,14 +97,14 @@ namespace osmium { m_elements.clear(); } - void dump_as_list(const int fd) const override final { + void dump_as_list(const int fd) override final { typedef typename std::map::value_type t; std::vector v; std::copy(m_elements.begin(), m_elements.end(), std::back_inserter(v)); osmium::io::detail::reliable_write(fd, reinterpret_cast(v.data()), sizeof(t) * v.size()); } - }; // class StlMap + }; // class SparseMemMap } // namespace map @@ -109,4 +112,4 @@ namespace osmium { } // namespace osmium -#endif // OSMIUM_INDEX_MAP_STL_MAP_HPP +#endif // OSMIUM_INDEX_MAP_SPARSE_MEM_MAP_HPP diff --git a/include/osmium/index/map/sparse_table.hpp b/include/osmium/index/map/sparse_mem_table.hpp similarity index 86% rename from include/osmium/index/map/sparse_table.hpp rename to include/osmium/index/map/sparse_mem_table.hpp index 704e33e21..27b8f3963 100644 --- a/include/osmium/index/map/sparse_table.hpp +++ b/include/osmium/index/map/sparse_mem_table.hpp @@ -1,11 +1,11 @@ -#ifndef OSMIUM_INDEX_MAP_SPARSE_TABLE_HPP -#define OSMIUM_INDEX_MAP_SPARSE_TABLE_HPP +#ifndef OSMIUM_INDEX_MAP_SPARSE_MEM_TABLE_HPP +#define OSMIUM_INDEX_MAP_SPARSE_MEM_TABLE_HPP /* This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -34,15 +34,17 @@ DEALINGS IN THE SOFTWARE. */ #include -#include #include #include #include +#include #include #include +#define OSMIUM_HAS_INDEX_MAP_SPARSE_MEM_TABLE + namespace osmium { namespace index { @@ -50,9 +52,9 @@ namespace osmium { namespace map { /** - * The SparseTable index stores elements in a Google sparsetable, + * The SparseMemTable index stores elements in a Google sparsetable, * a data structure that can hold sparsly filled tables in a - * very space efficient way. It will resize automatically. + * space efficient way. It will resize automatically. * * Use this index if the ID space is only sparsly * populated, such as when working with smaller OSM files (like @@ -61,7 +63,7 @@ namespace osmium { * This will only work on 64 bit machines. */ template - class SparseTable : public osmium::index::map::Map { + class SparseMemTable : public osmium::index::map::Map { TId m_grow_size; @@ -79,12 +81,12 @@ namespace osmium { * The storage will grow by at least this size * every time it runs out of space. */ - explicit SparseTable(const TId grow_size=10000) : + explicit SparseMemTable(const TId grow_size=10000) : m_grow_size(grow_size), m_elements(grow_size) { } - ~SparseTable() override final = default; + ~SparseMemTable() override final = default; void set(const TId id, const TValue value) override final { if (id >= m_elements.size()) { @@ -117,7 +119,7 @@ namespace osmium { m_elements.clear(); } - void dump_as_list(const int fd) const override final { + void dump_as_list(const int fd) override final { std::vector> v; int n=0; for (const TValue value : m_elements) { @@ -129,7 +131,7 @@ namespace osmium { osmium::io::detail::reliable_write(fd, reinterpret_cast(v.data()), sizeof(std::pair) * v.size()); } - }; // class SparseTable + }; // class SparseMemTable } // namespace map @@ -137,4 +139,4 @@ namespace osmium { } // namespace osmium -#endif // OSMIUM_INDEX_BYID_SPARSE_TABLE_HPP +#endif // OSMIUM_INDEX_BYID_SPARSE_MEM_TABLE_HPP diff --git a/include/osmium/index/map/mmap_vector_file.hpp b/include/osmium/index/map/sparse_mmap_array.hpp similarity index 74% rename from include/osmium/index/map/mmap_vector_file.hpp rename to include/osmium/index/map/sparse_mmap_array.hpp index 7ea76fa6b..c85e2c938 100644 --- a/include/osmium/index/map/mmap_vector_file.hpp +++ b/include/osmium/index/map/sparse_mmap_array.hpp @@ -1,11 +1,11 @@ -#ifndef OSMIUM_INDEX_MAP_MMAP_VECTOR_FILE_HPP -#define OSMIUM_INDEX_MAP_MMAP_VECTOR_FILE_HPP +#ifndef OSMIUM_INDEX_MAP_SPARSE_MMAP_ARRAY_HPP +#define OSMIUM_INDEX_MAP_SPARSE_MMAP_ARRAY_HPP /* This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -33,8 +33,12 @@ DEALINGS IN THE SOFTWARE. */ -#include -#include +#ifdef __linux__ + +#include +#include + +#define OSMIUM_HAS_INDEX_MAP_SPARSE_MMAP_ARRAY namespace osmium { @@ -43,10 +47,7 @@ namespace osmium { namespace map { template - using DenseMapFile = VectorBasedDenseMap, TId, TValue>; - - template - using SparseMapFile = VectorBasedSparseMap; + using SparseMmapArray = VectorBasedSparseMap; } // namespace map @@ -54,4 +55,6 @@ namespace osmium { } // namespace osmium -#endif // OSMIUM_INDEX_MAP_MMAP_VECTOR_FILE_HPP +#endif // __linux__ + +#endif // OSMIUM_INDEX_MAP_SPARSE_MMAP_ARRAY_HPP diff --git a/include/osmium/index/multimap.hpp b/include/osmium/index/multimap.hpp index f76c65ddb..e5c6b4f4e 100644 --- a/include/osmium/index/multimap.hpp +++ b/include/osmium/index/multimap.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -34,11 +34,10 @@ DEALINGS IN THE SOFTWARE. */ #include +#include #include #include -#include // IWYU pragma: export - namespace osmium { namespace index { @@ -114,7 +113,7 @@ namespace osmium { // default implementation is empty } - virtual void dump_as_list(int /*fd*/) const { + virtual void dump_as_list(const int /*fd*/) { std::runtime_error("can't dump as list"); } diff --git a/include/osmium/index/multimap/all.hpp b/include/osmium/index/multimap/all.hpp new file mode 100644 index 000000000..8b0ae99f9 --- /dev/null +++ b/include/osmium/index/multimap/all.hpp @@ -0,0 +1,41 @@ +#ifndef OSMIUM_INDEX_MULTIMAP_ALL_HPP +#define OSMIUM_INDEX_MULTIMAP_ALL_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013-2015 Jochen Topf 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 // IWYU pragma: keep +#include // IWYU pragma: keep +#include // IWYU pragma: keep +#include // IWYU pragma: keep + +#endif // OSMIUM_INDEX_MULTIMAP_ALL_HPP diff --git a/include/osmium/index/multimap/hybrid.hpp b/include/osmium/index/multimap/hybrid.hpp index abaf31e95..ac2d96452 100644 --- a/include/osmium/index/multimap/hybrid.hpp +++ b/include/osmium/index/multimap/hybrid.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -36,9 +36,10 @@ DEALINGS IN THE SOFTWARE. #include #include +#include #include -#include -#include +#include +#include namespace osmium { @@ -49,8 +50,8 @@ namespace osmium { template class HybridIterator { - typedef SparseMultimapMem main_map_type; - typedef StlMultimap extra_map_type; + typedef SparseMemArray main_map_type; + typedef SparseMemMultimap extra_map_type; typedef typename std::pair element_type; @@ -117,8 +118,8 @@ namespace osmium { template class Hybrid : public Multimap { - typedef SparseMultimapMem main_map_type; - typedef StlMultimap extra_map_type; + typedef SparseMemArray main_map_type; + typedef SparseMemMultimap extra_map_type; main_map_type m_main; extra_map_type m_extra; @@ -174,7 +175,7 @@ namespace osmium { m_main.sort(); } - void dump_as_list(int fd) override final { + void dump_as_list(const int fd) override final { consolidate(); m_main.dump_as_list(fd); } diff --git a/include/osmium/index/multimap/mmap_vector_file.hpp b/include/osmium/index/multimap/sparse_file_array.hpp similarity index 81% rename from include/osmium/index/multimap/mmap_vector_file.hpp rename to include/osmium/index/multimap/sparse_file_array.hpp index 0a925b4ef..0b9ae92c5 100644 --- a/include/osmium/index/multimap/mmap_vector_file.hpp +++ b/include/osmium/index/multimap/sparse_file_array.hpp @@ -1,11 +1,11 @@ -#ifndef OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_FILE_HPP -#define OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_FILE_HPP +#ifndef OSMIUM_INDEX_MULTIMAP_SPARSE_FILE_ARRAY_HPP +#define OSMIUM_INDEX_MULTIMAP_SPARSE_FILE_ARRAY_HPP /* This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -33,8 +33,8 @@ DEALINGS IN THE SOFTWARE. */ -#include #include +#include namespace osmium { @@ -43,7 +43,7 @@ namespace osmium { namespace multimap { template - using SparseMultimapFile = VectorBasedSparseMultimap; + using SparseFileArray = VectorBasedSparseMultimap; } // namespace multimap @@ -51,4 +51,4 @@ namespace osmium { } // namespace osmium -#endif // OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_FILE_HPP +#endif // OSMIUM_INDEX_MULTIMAP_SPARSE_FILE_ARRAY_HPP diff --git a/include/osmium/index/multimap/stl_vector.hpp b/include/osmium/index/multimap/sparse_mem_array.hpp similarity index 82% rename from include/osmium/index/multimap/stl_vector.hpp rename to include/osmium/index/multimap/sparse_mem_array.hpp index 2102824d5..c4140cba0 100644 --- a/include/osmium/index/multimap/stl_vector.hpp +++ b/include/osmium/index/multimap/sparse_mem_array.hpp @@ -1,11 +1,11 @@ -#ifndef OSMIUM_INDEX_MULTIMAP_STL_VECTOR_HPP -#define OSMIUM_INDEX_MULTIMAP_STL_VECTOR_HPP +#ifndef OSMIUM_INDEX_MULTIMAP_SPARSE_MEM_ARRAY_HPP +#define OSMIUM_INDEX_MULTIMAP_SPARSE_MEM_ARRAY_HPP /* This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -35,7 +35,7 @@ DEALINGS IN THE SOFTWARE. #include -#include +#include namespace osmium { @@ -47,7 +47,7 @@ namespace osmium { using StdVectorWrap = std::vector; template - using SparseMultimapMem = VectorBasedSparseMultimap; + using SparseMemArray = VectorBasedSparseMultimap; } // namespace multimap @@ -55,4 +55,4 @@ namespace osmium { } // namespace osmium -#endif // OSMIUM_INDEX_MULTIMAP_STL_VECTOR_HPP +#endif // OSMIUM_INDEX_MULTIMAP_SPARSE_MEM_ARRAY_HPP diff --git a/include/osmium/index/multimap/stl_multimap.hpp b/include/osmium/index/multimap/sparse_mem_multimap.hpp similarity index 90% rename from include/osmium/index/multimap/stl_multimap.hpp rename to include/osmium/index/multimap/sparse_mem_multimap.hpp index 3df07abff..5b4715279 100644 --- a/include/osmium/index/multimap/stl_multimap.hpp +++ b/include/osmium/index/multimap/sparse_mem_multimap.hpp @@ -1,11 +1,11 @@ -#ifndef OSMIUM_INDEX_MULTIMAP_STL_MULTIMAP_HPP -#define OSMIUM_INDEX_MULTIMAP_STL_MULTIMAP_HPP +#ifndef OSMIUM_INDEX_MULTIMAP_SPARSE_MEM_MULTIMAP_HPP +#define OSMIUM_INDEX_MULTIMAP_SPARSE_MEM_MULTIMAP_HPP /* This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -53,7 +53,7 @@ namespace osmium { * lot of memory, but might make sense for small maps. */ template - class StlMultimap : public osmium::index::multimap::Multimap { + class SparseMemMultimap : public osmium::index::multimap::Multimap { // This is a rough estimate for the memory needed for each // element in the map (id + value + pointers to left, right, @@ -76,9 +76,9 @@ namespace osmium { public: - StlMultimap() = default; + SparseMemMultimap() = default; - ~StlMultimap() noexcept override final = default; + ~SparseMemMultimap() noexcept override final = default; void unsorted_set(const TId id, const TValue value) { m_elements.emplace(id, value); @@ -130,7 +130,7 @@ namespace osmium { // intentionally left blank } - void dump_as_list(const int fd) const override final { + void dump_as_list(const int fd) override final { std::vector v; for (const auto& element : m_elements) { v.emplace_back(element.first, element.second); @@ -140,7 +140,7 @@ namespace osmium { osmium::io::detail::reliable_write(fd, reinterpret_cast(v.data()), sizeof(element_type) * v.size()); } - }; // class StlMultimap + }; // class SparseMemMultimap } // namespace multimap @@ -148,4 +148,4 @@ namespace osmium { } // namespace osmium -#endif // OSMIUM_INDEX_MULTIMAP_STL_MULTIMAP_HPP +#endif // OSMIUM_INDEX_MULTIMAP_SPARSE_MEM_MULTIMAP_HPP diff --git a/include/osmium/index/multimap/mmap_vector_anon.hpp b/include/osmium/index/multimap/sparse_mmap_array.hpp similarity index 81% rename from include/osmium/index/multimap/mmap_vector_anon.hpp rename to include/osmium/index/multimap/sparse_mmap_array.hpp index b9de34a34..9f92555f6 100644 --- a/include/osmium/index/multimap/mmap_vector_anon.hpp +++ b/include/osmium/index/multimap/sparse_mmap_array.hpp @@ -1,11 +1,11 @@ -#ifndef OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_ANON_HPP -#define OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_ANON_HPP +#ifndef OSMIUM_INDEX_MULTIMAP_SPARSE_MMAP_ARRAY_HPP +#define OSMIUM_INDEX_MULTIMAP_SPARSE_MMAP_ARRAY_HPP /* This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -35,8 +35,8 @@ DEALINGS IN THE SOFTWARE. #ifdef __linux__ -#include #include +#include namespace osmium { @@ -45,7 +45,7 @@ namespace osmium { namespace multimap { template - using SparseMultimapMmap = VectorBasedSparseMultimap; + using SparseMmapArray = VectorBasedSparseMultimap; } // namespace multimap @@ -55,4 +55,4 @@ namespace osmium { #endif // __linux__ -#endif // OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_ANON_HPP +#endif // OSMIUM_INDEX_MULTIMAP_SPARSE_MMAP_ARRAY_HPP diff --git a/include/osmium/index/node_locations_map.hpp b/include/osmium/index/node_locations_map.hpp new file mode 100644 index 000000000..ca4b1361e --- /dev/null +++ b/include/osmium/index/node_locations_map.hpp @@ -0,0 +1,70 @@ +#ifndef OSMIUM_INDEX_NODE_LOCATIONS_MAP_HPP +#define OSMIUM_INDEX_NODE_LOCATIONS_MAP_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013-2015 Jochen Topf 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 // IWYU pragma: keep + +#ifdef OSMIUM_HAS_INDEX_MAP_DENSE_FILE_ARRAY + REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::DenseFileArray, dense_file_array) +#endif + +#ifdef OSMIUM_HAS_INDEX_MAP_DENSE_MEM_ARRAY + REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::DenseMemArray, dense_mem_array) +#endif + +#ifdef OSMIUM_HAS_INDEX_MAP_DENSE_MMAP_ARRAY + REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::DenseMmapArray, dense_mmap_array) +#endif + +#ifdef OSMIUM_HAS_INDEX_MAP_SPARSE_FILE_ARRAY + REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::SparseFileArray, sparse_file_array) +#endif + +#ifdef OSMIUM_HAS_INDEX_MAP_SPARSE_MEM_ARRAY + REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::SparseMemArray, sparse_mem_array) +#endif + +#ifdef OSMIUM_HAS_INDEX_MAP_SPARSE_MEM_MAP + REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::SparseMemMap, sparse_mem_map) +#endif + +#ifdef OSMIUM_HAS_INDEX_MAP_SPARSE_MEM_TABLE + REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::SparseMemTable, sparse_mem_table) +#endif + +#ifdef OSMIUM_HAS_INDEX_MAP_SPARSE_MMAP_ARRAY + REGISTER_MAP(osmium::unsigned_object_id_type, osmium::Location, osmium::index::map::SparseMmapArray, sparse_mmap_array) +#endif + +#endif // OSMIUM_INDEX_NODE_LOCATIONS_MAP_HPP diff --git a/include/osmium/io/any_compression.hpp b/include/osmium/io/any_compression.hpp index 03ad5ce2b..00e8ee2be 100644 --- a/include/osmium/io/any_compression.hpp +++ b/include/osmium/io/any_compression.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -33,6 +33,15 @@ DEALINGS IN THE SOFTWARE. */ +/** + * @file + * + * Include this file if you want to read or write compressed OSM XML files. + * + * @attention If you include this file, you'll need to link with `libz` + * and `libbz2`. + */ + #include // IWYU pragma: export #include // IWYU pragma: export diff --git a/include/osmium/io/any_input.hpp b/include/osmium/io/any_input.hpp index f60ff1455..633fab313 100644 --- a/include/osmium/io/any_input.hpp +++ b/include/osmium/io/any_input.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -33,6 +33,16 @@ DEALINGS IN THE SOFTWARE. */ +/** + * @file + * + * Include this file if you want to read all kinds of OSM files. + * + * @attention If you include this file, you'll need to link with + * `libprotobuf-lite`, `libosmpbf`, `ws2_32` (Windows only), + * `libexpat`, `libz`, `libbz2`, and enable multithreading. + */ + #include // IWYU pragma: export #include // IWYU pragma: export diff --git a/include/osmium/io/any_output.hpp b/include/osmium/io/any_output.hpp index 9d97d7d93..63de3ff2e 100644 --- a/include/osmium/io/any_output.hpp +++ b/include/osmium/io/any_output.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -33,6 +33,16 @@ DEALINGS IN THE SOFTWARE. */ +/** + * @file + * + * Include this file if you want to write all kinds of OSM files. + * + * @attention If you include this file, you'll need to link with + * `libprotobuf-lite`, `libosmpbf`, `ws2_32` (Windows only), + * `libz`, `libbz2`, and enable multithreading. + */ + #include // IWYU pragma: export #include // IWYU pragma: export diff --git a/include/osmium/io/bzip2_compression.hpp b/include/osmium/io/bzip2_compression.hpp index 90e5784c1..de1364c69 100644 --- a/include/osmium/io/bzip2_compression.hpp +++ b/include/osmium/io/bzip2_compression.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -33,6 +33,17 @@ DEALINGS IN THE SOFTWARE. */ +/** + * @file + * + * Include this file if you want to read or write bzip2-compressed OSM XML + * files. + * + * @attention If you include this file, you'll need to link with `libbz2`. + */ + +#include +#include #include #include #include diff --git a/include/osmium/io/compression.hpp b/include/osmium/io/compression.hpp index e83e5ba77..f5308eacb 100644 --- a/include/osmium/io/compression.hpp +++ b/include/osmium/io/compression.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/io/detail/input_format.hpp b/include/osmium/io/detail/input_format.hpp index 5a0e4e9ae..03e1190c3 100644 --- a/include/osmium/io/detail/input_format.hpp +++ b/include/osmium/io/detail/input_format.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/io/detail/opl_output_format.hpp b/include/osmium/io/detail/opl_output_format.hpp index b4f069e0d..cf92e1382 100644 --- a/include/osmium/io/detail/opl_output_format.hpp +++ b/include/osmium/io/detail/opl_output_format.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -97,9 +97,9 @@ namespace osmium { static constexpr size_t tmp_buffer_size = 100; - osmium::memory::Buffer m_input_buffer; + std::shared_ptr m_input_buffer; - std::string m_out; + std::shared_ptr m_out; char m_tmp_buffer[tmp_buffer_size+1]; @@ -114,13 +114,13 @@ namespace osmium { _snprintf(m_tmp_buffer, tmp_buffer_size, format, std::forward(args)...); #endif assert(len > 0 && static_cast(len) < tmp_buffer_size); - m_out += m_tmp_buffer; + *m_out += m_tmp_buffer; } void append_encoded_string(const std::string& data) { boost::u8_to_u32_iterator it(data.cbegin(), data.cbegin(), data.cend()); boost::u8_to_u32_iterator end(data.cend(), data.cend(), data.cend()); - boost::utf8_output_iterator> oit(std::back_inserter(m_out)); + boost::utf8_output_iterator> oit(std::back_inserter(*m_out)); for (; it != end; ++it) { uint32_t c = *it; @@ -140,7 +140,7 @@ namespace osmium { (0x00ae <= c && c <= 0x05ff)) { *oit = c; } else { - m_out += '%'; + *m_out += '%'; output_formatted("%04x", c); } } @@ -148,21 +148,21 @@ namespace osmium { void write_meta(const osmium::OSMObject& object) { output_formatted("%" PRId64 " v%d d", object.id(), object.version()); - m_out += (object.visible() ? 'V' : 'D'); + *m_out += (object.visible() ? 'V' : 'D'); output_formatted(" c%d t", object.changeset()); - m_out += object.timestamp().to_iso(); + *m_out += object.timestamp().to_iso(); output_formatted(" i%d u", object.uid()); append_encoded_string(object.user()); - m_out += " T"; + *m_out += " T"; bool first = true; for (const auto& tag : object.tags()) { if (first) { first = false; } else { - m_out += ','; + *m_out += ','; } append_encoded_string(tag.key()); - m_out += '='; + *m_out += '='; append_encoded_string(tag.value()); } } @@ -171,109 +171,103 @@ namespace osmium { if (location) { output_formatted(" %c%.7f %c%.7f", x, location.lon_without_check(), y, location.lat_without_check()); } else { - m_out += ' '; - m_out += x; - m_out += ' '; - m_out += y; + *m_out += ' '; + *m_out += x; + *m_out += ' '; + *m_out += y; } } public: explicit OPLOutputBlock(osmium::memory::Buffer&& buffer) : - m_input_buffer(std::move(buffer)), - m_out(), + m_input_buffer(std::make_shared(std::move(buffer))), + m_out(std::make_shared()), m_tmp_buffer() { } - OPLOutputBlock(const OPLOutputBlock&) = delete; - OPLOutputBlock& operator=(const OPLOutputBlock&) = delete; + OPLOutputBlock(const OPLOutputBlock&) = default; + OPLOutputBlock& operator=(const OPLOutputBlock&) = default; - OPLOutputBlock(OPLOutputBlock&& other) : - m_input_buffer(std::move(other.m_input_buffer)), - m_out(), - m_tmp_buffer() { - } + OPLOutputBlock(OPLOutputBlock&&) = default; + OPLOutputBlock& operator=(OPLOutputBlock&&) = default; - OPLOutputBlock& operator=(OPLOutputBlock&& other) { - m_input_buffer = std::move(other.m_input_buffer); - return *this; - } + ~OPLOutputBlock() = default; std::string operator()() { - osmium::apply(m_input_buffer.cbegin(), m_input_buffer.cend(), *this); + osmium::apply(m_input_buffer->cbegin(), m_input_buffer->cend(), *this); std::string out; - std::swap(out, m_out); + std::swap(out, *m_out); return out; } void node(const osmium::Node& node) { - m_out += 'n'; + *m_out += 'n'; write_meta(node); write_location(node.location(), 'x', 'y'); - m_out += '\n'; + *m_out += '\n'; } void way(const osmium::Way& way) { - m_out += 'w'; + *m_out += 'w'; write_meta(way); - m_out += " N"; + *m_out += " N"; bool first = true; for (const auto& node_ref : way.nodes()) { if (first) { first = false; } else { - m_out += ','; + *m_out += ','; } output_formatted("n%" PRId64, node_ref.ref()); } - m_out += '\n'; + *m_out += '\n'; } void relation(const osmium::Relation& relation) { - m_out += 'r'; + *m_out += 'r'; write_meta(relation); - m_out += " M"; + *m_out += " M"; bool first = true; for (const auto& member : relation.members()) { if (first) { first = false; } else { - m_out += ','; + *m_out += ','; } - m_out += item_type_to_char(member.type()); + *m_out += item_type_to_char(member.type()); output_formatted("%" PRId64 "@", member.ref()); - m_out += member.role(); + *m_out += member.role(); } - m_out += '\n'; + *m_out += '\n'; } void changeset(const osmium::Changeset& changeset) { output_formatted("c%d k%d s", changeset.id(), changeset.num_changes()); - m_out += changeset.created_at().to_iso(); - m_out += " e"; - m_out += changeset.closed_at().to_iso(); + *m_out += changeset.created_at().to_iso(); + *m_out += " e"; + *m_out += changeset.closed_at().to_iso(); output_formatted(" i%d u", changeset.uid()); append_encoded_string(changeset.user()); write_location(changeset.bounds().bottom_left(), 'x', 'y'); write_location(changeset.bounds().top_right(), 'X', 'Y'); - m_out += " T"; + *m_out += " T"; bool first = true; for (const auto& tag : changeset.tags()) { if (first) { first = false; } else { - m_out += ','; + *m_out += ','; } append_encoded_string(tag.key()); - m_out += '='; + *m_out += '='; append_encoded_string(tag.value()); } - m_out += '\n'; + *m_out += '\n'; } }; // OPLOutputBlock diff --git a/include/osmium/io/detail/output_format.hpp b/include/osmium/io/detail/output_format.hpp index ad9e70204..529a1890f 100644 --- a/include/osmium/io/detail/output_format.hpp +++ b/include/osmium/io/detail/output_format.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/io/detail/pbf.hpp b/include/osmium/io/detail/pbf.hpp index c1e59ee7f..e64e51a57 100644 --- a/include/osmium/io/detail/pbf.hpp +++ b/include/osmium/io/detail/pbf.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/io/detail/pbf_input_format.hpp b/include/osmium/io/detail/pbf_input_format.hpp index 2d85d9ff0..dc161ebab 100644 --- a/include/osmium/io/detail/pbf_input_format.hpp +++ b/include/osmium/io/detail/pbf_input_format.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/io/detail/pbf_output_format.hpp b/include/osmium/io/detail/pbf_output_format.hpp index 44f8ffb5e..73bc61673 100644 --- a/include/osmium/io/detail/pbf_output_format.hpp +++ b/include/osmium/io/detail/pbf_output_format.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/io/detail/pbf_parser.hpp b/include/osmium/io/detail/pbf_parser.hpp index e89d0196c..d99819d3d 100644 --- a/include/osmium/io/detail/pbf_parser.hpp +++ b/include/osmium/io/detail/pbf_parser.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -412,28 +412,34 @@ namespace osmium { class DataBlobParser { - std::string m_input_buffer; + std::shared_ptr m_input_buffer; osmium::osm_entity_bits::type m_read_types; public: DataBlobParser(std::string&& input_buffer, osmium::osm_entity_bits::type read_types) : - m_input_buffer(std::move(input_buffer)), + m_input_buffer(std::make_shared(std::move(input_buffer))), m_read_types(read_types) { if (input_buffer.size() > OSMPBF::max_uncompressed_blob_size) { throw osmium::pbf_error(std::string("invalid blob size: " + std::to_string(input_buffer.size()))); } } - +/* DataBlobParser(const DataBlobParser& other) : m_input_buffer(std::move(other.m_input_buffer)), m_read_types(other.m_read_types) { - } + }*/ - DataBlobParser& operator=(const DataBlobParser&) = delete; + DataBlobParser(const DataBlobParser&) = default; + DataBlobParser& operator=(const DataBlobParser&) = default; + + DataBlobParser(DataBlobParser&&) = default; + DataBlobParser& operator=(DataBlobParser&&) = default; + + ~DataBlobParser() = default; osmium::memory::Buffer operator()() { - const std::unique_ptr data = unpack_blob(m_input_buffer); + const std::unique_ptr data = unpack_blob(*m_input_buffer); PBFPrimitiveBlockParser parser(*data, m_read_types); return parser(); } diff --git a/include/osmium/io/detail/pbf_stringtable.hpp b/include/osmium/io/detail/pbf_stringtable.hpp index 6f6c54c89..c56d549de 100644 --- a/include/osmium/io/detail/pbf_stringtable.hpp +++ b/include/osmium/io/detail/pbf_stringtable.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/io/detail/read_thread.hpp b/include/osmium/io/detail/read_thread.hpp index 7c371396c..bce4f5507 100644 --- a/include/osmium/io/detail/read_thread.hpp +++ b/include/osmium/io/detail/read_thread.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/io/detail/read_write.hpp b/include/osmium/io/detail/read_write.hpp index a949296f2..564d72147 100644 --- a/include/osmium/io/detail/read_write.hpp +++ b/include/osmium/io/detail/read_write.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/io/detail/write_thread.hpp b/include/osmium/io/detail/write_thread.hpp index 49b7b5dda..fad22ed69 100644 --- a/include/osmium/io/detail/write_thread.hpp +++ b/include/osmium/io/detail/write_thread.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/io/detail/xml_input_format.hpp b/include/osmium/io/detail/xml_input_format.hpp index c42f61983..96003d874 100644 --- a/include/osmium/io/detail/xml_input_format.hpp +++ b/include/osmium/io/detail/xml_input_format.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -699,7 +699,7 @@ namespace osmium { return buffer; } - void close() { + void close() override { m_done = true; osmium::thread::wait_until_done(m_parser_future); } diff --git a/include/osmium/io/detail/xml_output_format.hpp b/include/osmium/io/detail/xml_output_format.hpp index c8c7a385e..73a7263ce 100644 --- a/include/osmium/io/detail/xml_output_format.hpp +++ b/include/osmium/io/detail/xml_output_format.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -120,9 +120,9 @@ namespace osmium { op_delete = 3 }; // enum class operation - osmium::memory::Buffer m_input_buffer; + std::shared_ptr m_input_buffer; - std::string m_out; + std::shared_ptr m_out; operation m_last_op {operation::op_none}; @@ -131,7 +131,7 @@ namespace osmium { void write_spaces(int num) { for (; num!=0; --num) { - m_out += ' '; + *m_out += ' '; } } @@ -144,33 +144,33 @@ namespace osmium { } void write_meta(const osmium::OSMObject& object) { - oprintf(m_out, " id=\"%" PRId64 "\"", object.id()); + oprintf(*m_out, " id=\"%" PRId64 "\"", object.id()); if (object.version()) { - oprintf(m_out, " version=\"%d\"", object.version()); + oprintf(*m_out, " version=\"%d\"", object.version()); } if (object.timestamp()) { - m_out += " timestamp=\""; - m_out += object.timestamp().to_iso(); - m_out += "\""; + *m_out += " timestamp=\""; + *m_out += object.timestamp().to_iso(); + *m_out += "\""; } if (!object.user_is_anonymous()) { - oprintf(m_out, " uid=\"%d\" user=\"", object.uid()); - xml_string(m_out, object.user()); - m_out += "\""; + oprintf(*m_out, " uid=\"%d\" user=\"", object.uid()); + xml_string(*m_out, object.user()); + *m_out += "\""; } if (object.changeset()) { - oprintf(m_out, " changeset=\"%d\"", object.changeset()); + oprintf(*m_out, " changeset=\"%d\"", object.changeset()); } if (m_write_visible_flag) { if (object.visible()) { - m_out += " visible=\"true\""; + *m_out += " visible=\"true\""; } else { - m_out += " visible=\"false\""; + *m_out += " visible=\"false\""; } } } @@ -178,11 +178,11 @@ namespace osmium { void write_tags(const osmium::TagList& tags) { for (const auto& tag : tags) { write_prefix(); - m_out += " \n"; + *m_out += " \n"; } } @@ -195,13 +195,13 @@ namespace osmium { case operation::op_none: break; case operation::op_create: - m_out += " \n"; + *m_out += " \n"; break; case operation::op_modify: - m_out += " \n"; + *m_out += " \n"; break; case operation::op_delete: - m_out += " \n"; + *m_out += " \n"; break; } @@ -209,13 +209,13 @@ namespace osmium { case operation::op_none: break; case operation::op_create: - m_out += " \n"; + *m_out += " \n"; break; case operation::op_modify: - m_out += " \n"; + *m_out += " \n"; break; case operation::op_delete: - m_out += " \n"; + *m_out += " \n"; break; } @@ -225,26 +225,29 @@ namespace osmium { public: explicit XMLOutputBlock(osmium::memory::Buffer&& buffer, bool write_visible_flag, bool write_change_ops) : - m_input_buffer(std::move(buffer)), + m_input_buffer(std::make_shared(std::move(buffer))), + m_out(std::make_shared()), m_write_visible_flag(write_visible_flag && !write_change_ops), m_write_change_ops(write_change_ops) { } - XMLOutputBlock(const XMLOutputBlock&) = delete; - XMLOutputBlock& operator=(const XMLOutputBlock&) = delete; + XMLOutputBlock(const XMLOutputBlock&) = default; + XMLOutputBlock& operator=(const XMLOutputBlock&) = default; XMLOutputBlock(XMLOutputBlock&&) = default; XMLOutputBlock& operator=(XMLOutputBlock&&) = default; + ~XMLOutputBlock() = default; + std::string operator()() { - osmium::apply(m_input_buffer.cbegin(), m_input_buffer.cend(), *this); + osmium::apply(m_input_buffer->cbegin(), m_input_buffer->cend(), *this); if (m_write_change_ops) { open_close_op_tag(); } std::string out; - std::swap(out, m_out); + std::swap(out, *m_out); return out; } @@ -254,29 +257,29 @@ namespace osmium { } write_prefix(); - m_out += "\n", node_ref.ref()); + oprintf(*m_out, " \n", node_ref.ref()); } write_tags(way.tags()); write_prefix(); - m_out += "\n"; + *m_out += "\n"; } void relation(const osmium::Relation& relation) { @@ -312,77 +315,77 @@ namespace osmium { } write_prefix(); - m_out += "\n"; + *m_out += " \n"; } write_tags(relation.tags()); write_prefix(); - m_out += "\n"; + *m_out += "\n"; } void changeset(const osmium::Changeset& changeset) { write_prefix(); - m_out += " and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/io/error.hpp b/include/osmium/io/error.hpp index 8fb9f05f6..07652bc59 100644 --- a/include/osmium/io/error.hpp +++ b/include/osmium/io/error.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -34,6 +34,7 @@ DEALINGS IN THE SOFTWARE. */ #include +#include namespace osmium { diff --git a/include/osmium/io/file.hpp b/include/osmium/io/file.hpp index 21469b865..5b6c02f13 100644 --- a/include/osmium/io/file.hpp +++ b/include/osmium/io/file.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -42,6 +42,7 @@ DEALINGS IN THE SOFTWARE. #include #include #include +#include namespace osmium { diff --git a/include/osmium/io/file_compression.hpp b/include/osmium/io/file_compression.hpp index c71871553..292ddcfca 100644 --- a/include/osmium/io/file_compression.hpp +++ b/include/osmium/io/file_compression.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/io/file_format.hpp b/include/osmium/io/file_format.hpp index 5a4aa5c01..1a63a5e49 100644 --- a/include/osmium/io/file_format.hpp +++ b/include/osmium/io/file_format.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/io/gzip_compression.hpp b/include/osmium/io/gzip_compression.hpp index c1f8888ba..8bc1e5a50 100644 --- a/include/osmium/io/gzip_compression.hpp +++ b/include/osmium/io/gzip_compression.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -33,6 +33,15 @@ DEALINGS IN THE SOFTWARE. */ +/** + * @file + * + * Include this file if you want to read or write gzip-compressed OSM XML + * files. + * + * @attention If you include this file, you'll need to link with `libz`. + */ + #include #include diff --git a/include/osmium/io/header.hpp b/include/osmium/io/header.hpp index 0fdbf77fc..4b0830a62 100644 --- a/include/osmium/io/header.hpp +++ b/include/osmium/io/header.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/io/input_iterator.hpp b/include/osmium/io/input_iterator.hpp index a2e3b83b3..f6197299d 100644 --- a/include/osmium/io/input_iterator.hpp +++ b/include/osmium/io/input_iterator.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -41,6 +41,7 @@ DEALINGS IN THE SOFTWARE. #include #include +#include namespace osmium { diff --git a/include/osmium/io/opl_output.hpp b/include/osmium/io/opl_output.hpp index 46a12240b..04385d968 100644 --- a/include/osmium/io/opl_output.hpp +++ b/include/osmium/io/opl_output.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/io/output_iterator.hpp b/include/osmium/io/output_iterator.hpp index e6a9cc096..608852fa9 100644 --- a/include/osmium/io/output_iterator.hpp +++ b/include/osmium/io/output_iterator.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -75,6 +75,14 @@ namespace osmium { m_buffer_wrapper(std::make_shared(buffer_size)) { } + OutputIterator(const OutputIterator&) = default; + OutputIterator(OutputIterator&&) = default; + + OutputIterator& operator=(const OutputIterator&) = default; + OutputIterator& operator=(OutputIterator&&) = default; + + ~OutputIterator() = default; + void flush() { osmium::memory::Buffer buffer(m_buffer_wrapper->buffer.capacity(), osmium::memory::Buffer::auto_grow::no); std::swap(m_buffer_wrapper->buffer, buffer); diff --git a/include/osmium/io/overwrite.hpp b/include/osmium/io/overwrite.hpp index f29a93228..e33894bd8 100644 --- a/include/osmium/io/overwrite.hpp +++ b/include/osmium/io/overwrite.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/io/pbf_input.hpp b/include/osmium/io/pbf_input.hpp index 8426f6cf6..766153ede 100644 --- a/include/osmium/io/pbf_input.hpp +++ b/include/osmium/io/pbf_input.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -33,6 +33,16 @@ DEALINGS IN THE SOFTWARE. */ +/** + * @file + * + * Include this file if you want to read OSM PBF files. + * + * @attention If you include this file, you'll need to link with + * `libprotobuf-lite`, `libosmpbf`, `ws2_32` (Windows only), + * `libz`, and enable multithreading. + */ + #include // IWYU pragma: export #include // IWYU pragma: export diff --git a/include/osmium/io/pbf_output.hpp b/include/osmium/io/pbf_output.hpp index 9fd039654..5f46ede2b 100644 --- a/include/osmium/io/pbf_output.hpp +++ b/include/osmium/io/pbf_output.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -33,6 +33,16 @@ DEALINGS IN THE SOFTWARE. */ +/** + * @file + * + * Include this file if you want to write OSM PBF files. + * + * @attention If you include this file, you'll need to link with + * `libprotobuf-lite`, `libosmpbf`, `ws2_32` (Windows only), + * `libz`, and enable multithreading. + */ + #include // IWYU pragma: export #include // IWYU pragma: export diff --git a/include/osmium/io/reader.hpp b/include/osmium/io/reader.hpp index a9b8b954d..0bb4f1cb8 100644 --- a/include/osmium/io/reader.hpp +++ b/include/osmium/io/reader.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -258,11 +258,20 @@ namespace osmium { return osmium::memory::Buffer(); } - osmium::memory::Buffer buffer = m_input->read(); - if (!buffer) { - m_input_done = true; + // m_input->read() can return an invalid buffer to signal EOF, + // or a valid buffer with or without data. A valid buffer + // without data is not an error, it just means we have to get + // keep getting the next buffer until there is one with data. + while (true) { + osmium::memory::Buffer buffer = m_input->read(); + if (!buffer) { + m_input_done = true; + return buffer; + } + if (buffer.committed() > 0) { + return buffer; + } } - return buffer; } /** diff --git a/include/osmium/io/reader_iterator.hpp b/include/osmium/io/reader_iterator.hpp index 8d71418e0..862078935 100644 --- a/include/osmium/io/reader_iterator.hpp +++ b/include/osmium/io/reader_iterator.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/io/writer.hpp b/include/osmium/io/writer.hpp index 7e9bd1383..64afe2066 100644 --- a/include/osmium/io/writer.hpp +++ b/include/osmium/io/writer.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -80,7 +80,7 @@ namespace osmium { * defaults will be used. See the default constructor * of osmium::io::Header for details. * @param allow_overwrite Allow overwriting of existing file? Can be - * osmium::io::overwrite::allow or osmium::io::overwrite::no+ + * osmium::io::overwrite::allow or osmium::io::overwrite::no * (default). * * @throws std::runtime_error If the file could not be opened. diff --git a/include/osmium/io/xml_input.hpp b/include/osmium/io/xml_input.hpp index f33d37ee2..dfcd0a9fc 100644 --- a/include/osmium/io/xml_input.hpp +++ b/include/osmium/io/xml_input.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -33,6 +33,15 @@ DEALINGS IN THE SOFTWARE. */ +/** + * @file + * + * Include this file if you want to read OSM XML files. + * + * @attention If you include this file, you'll need to link with + * `libexpat`, and enable multithreading. + */ + #include // IWYU pragma: export #include // IWYU pragma: export diff --git a/include/osmium/io/xml_output.hpp b/include/osmium/io/xml_output.hpp index d5b839f60..18a13869d 100644 --- a/include/osmium/io/xml_output.hpp +++ b/include/osmium/io/xml_output.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -33,6 +33,14 @@ DEALINGS IN THE SOFTWARE. */ +/** + * @file + * + * Include this file if you want to write OSM XML files. + * + * @attention If you include this file, you'll need to enable multithreading. + */ + #include // IWYU pragma: export #include // IWYU pragma: export diff --git a/include/osmium/memory/buffer.hpp b/include/osmium/memory/buffer.hpp index 8c05ced21..85a3a46d4 100644 --- a/include/osmium/memory/buffer.hpp +++ b/include/osmium/memory/buffer.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/memory/collection.hpp b/include/osmium/memory/collection.hpp index b25dd64ec..7deb88b45 100644 --- a/include/osmium/memory/collection.hpp +++ b/include/osmium/memory/collection.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -38,6 +38,7 @@ DEALINGS IN THE SOFTWARE. #include #include +#include namespace osmium { diff --git a/include/osmium/memory/item.hpp b/include/osmium/memory/item.hpp index 2d22f948e..df15d0133 100644 --- a/include/osmium/memory/item.hpp +++ b/include/osmium/memory/item.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/memory/item_iterator.hpp b/include/osmium/memory/item_iterator.hpp index 34ed60083..3e5b5fa8b 100644 --- a/include/osmium/memory/item_iterator.hpp +++ b/include/osmium/memory/item_iterator.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/object_pointer_collection.hpp b/include/osmium/object_pointer_collection.hpp index 22029a149..752470305 100644 --- a/include/osmium/object_pointer_collection.hpp +++ b/include/osmium/object_pointer_collection.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/osm.hpp b/include/osmium/osm.hpp index bf21c19dc..e92d9b8ef 100644 --- a/include/osmium/osm.hpp +++ b/include/osmium/osm.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/osm/area.hpp b/include/osmium/osm/area.hpp index a388de2e9..afd127ee6 100644 --- a/include/osmium/osm/area.hpp +++ b/include/osmium/osm/area.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/osm/box.hpp b/include/osmium/osm/box.hpp index 2b761fefc..37baf7e33 100644 --- a/include/osmium/osm/box.hpp +++ b/include/osmium/osm/box.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -123,7 +123,7 @@ namespace osmium { * Box are valid, ie. defined and inside usual bounds * (-180<=lon<=180, -90<=lat<=90). */ - constexpr bool valid() const noexcept { + OSMIUM_CONSTEXPR bool valid() const noexcept { return bottom_left().valid() && top_right().valid(); } diff --git a/include/osmium/osm/changeset.hpp b/include/osmium/osm/changeset.hpp index 2b79fb5cf..cc1c52d4a 100644 --- a/include/osmium/osm/changeset.hpp +++ b/include/osmium/osm/changeset.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/osm/diff_object.hpp b/include/osmium/osm/diff_object.hpp index a8f91ecd5..55a5cef68 100644 --- a/include/osmium/osm/diff_object.hpp +++ b/include/osmium/osm/diff_object.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/osm/entity.hpp b/include/osmium/osm/entity.hpp index e37ed4c94..14861a2d5 100644 --- a/include/osmium/osm/entity.hpp +++ b/include/osmium/osm/entity.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -34,6 +34,7 @@ DEALINGS IN THE SOFTWARE. */ #include +#include namespace osmium { @@ -67,6 +68,10 @@ namespace osmium { Item(size, type) { } + bool type_is_in(osmium::osm_entity_bits::type entity_bits) const { + return (osm_entity_bits::from_item_type(type()) & entity_bits) != 0; + } + }; // class OSMEntity } // namespace osmium diff --git a/include/osmium/osm/entity_bits.hpp b/include/osmium/osm/entity_bits.hpp index 2a4d96416..1c1cb8027 100644 --- a/include/osmium/osm/entity_bits.hpp +++ b/include/osmium/osm/entity_bits.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -33,6 +33,8 @@ DEALINGS IN THE SOFTWARE. */ +#include + namespace osmium { /** @@ -92,6 +94,10 @@ namespace osmium { return lhs; } + inline type from_item_type(osmium::item_type item_type) noexcept { + return static_cast(0x1 << (static_cast(item_type) - 1)); + } + } // namespace osm_entity_bits } // namespace osmium diff --git a/include/osmium/osm/item_type.hpp b/include/osmium/osm/item_type.hpp index d277e06c8..c2187a36a 100644 --- a/include/osmium/osm/item_type.hpp +++ b/include/osmium/osm/item_type.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/osm/location.hpp b/include/osmium/osm/location.hpp index cabecd50f..0d4fdc13d 100644 --- a/include/osmium/osm/location.hpp +++ b/include/osmium/osm/location.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/osm/node.hpp b/include/osmium/osm/node.hpp index 50146c568..123bfc4fa 100644 --- a/include/osmium/osm/node.hpp +++ b/include/osmium/osm/node.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/osm/node_ref.hpp b/include/osmium/osm/node_ref.hpp index ed50b9e66..1a66607a1 100644 --- a/include/osmium/osm/node_ref.hpp +++ b/include/osmium/osm/node_ref.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/osm/node_ref_list.hpp b/include/osmium/osm/node_ref_list.hpp index 321c952f4..f45bf6b59 100644 --- a/include/osmium/osm/node_ref_list.hpp +++ b/include/osmium/osm/node_ref_list.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/osm/object.hpp b/include/osmium/osm/object.hpp index 9c4d60341..d5ae48aab 100644 --- a/include/osmium/osm/object.hpp +++ b/include/osmium/osm/object.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/osm/object_comparisons.hpp b/include/osmium/osm/object_comparisons.hpp index db11b0d4c..bdf99e11c 100644 --- a/include/osmium/osm/object_comparisons.hpp +++ b/include/osmium/osm/object_comparisons.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/osm/relation.hpp b/include/osmium/osm/relation.hpp index f5d040100..6c0381539 100644 --- a/include/osmium/osm/relation.hpp +++ b/include/osmium/osm/relation.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/osm/segment.hpp b/include/osmium/osm/segment.hpp index 205036ec6..f3a82c97f 100644 --- a/include/osmium/osm/segment.hpp +++ b/include/osmium/osm/segment.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/osm/tag.hpp b/include/osmium/osm/tag.hpp index fe80de34f..2e93ede24 100644 --- a/include/osmium/osm/tag.hpp +++ b/include/osmium/osm/tag.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/osm/timestamp.hpp b/include/osmium/osm/timestamp.hpp index 23f0ec8af..f36ea36a1 100644 --- a/include/osmium/osm/timestamp.hpp +++ b/include/osmium/osm/timestamp.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -101,7 +101,7 @@ namespace osmium { tm.tm_wday = 0; tm.tm_yday = 0; tm.tm_isdst = 0; - m_timestamp = _mkgmtime(&tm); + m_timestamp = static_cast(_mkgmtime(&tm)); #endif } diff --git a/include/osmium/osm/types.hpp b/include/osmium/osm/types.hpp index 532b5497c..aea61bd37 100644 --- a/include/osmium/osm/types.hpp +++ b/include/osmium/osm/types.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/osm/undirected_segment.hpp b/include/osmium/osm/undirected_segment.hpp index 487e7bf32..654ef7d9a 100644 --- a/include/osmium/osm/undirected_segment.hpp +++ b/include/osmium/osm/undirected_segment.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/osm/way.hpp b/include/osmium/osm/way.hpp index a30cf911f..6d3e2dea0 100644 --- a/include/osmium/osm/way.hpp +++ b/include/osmium/osm/way.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/relations/collector.hpp b/include/osmium/relations/collector.hpp index 60864d308..d4af916b7 100644 --- a/include/osmium/relations/collector.hpp +++ b/include/osmium/relations/collector.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -509,7 +509,7 @@ namespace osmium { const size_t size_before = m_members_buffer.committed(); m_members_buffer.purge_removed(this); const size_t size_after = m_members_buffer.committed(); - double percent = size_before - size_after; + double percent = static_cast(size_before - size_after); percent /= size_before; percent *= 100; std::cerr << "PURGE (size before=" << size_before << " after=" << size_after << " purged=" << (size_before - size_after) << " / " << static_cast(percent) << "%)\n"; diff --git a/include/osmium/relations/detail/member_meta.hpp b/include/osmium/relations/detail/member_meta.hpp index 5463a1cb8..a45088eab 100644 --- a/include/osmium/relations/detail/member_meta.hpp +++ b/include/osmium/relations/detail/member_meta.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/relations/detail/relation_meta.hpp b/include/osmium/relations/detail/relation_meta.hpp index 77ca0c130..a48c50acc 100644 --- a/include/osmium/relations/detail/relation_meta.hpp +++ b/include/osmium/relations/detail/relation_meta.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/tags/filter.hpp b/include/osmium/tags/filter.hpp index 0a0fd3b56..3c1946c54 100644 --- a/include/osmium/tags/filter.hpp +++ b/include/osmium/tags/filter.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -135,6 +135,20 @@ namespace osmium { return m_default_result; } + /** + * Return the number of rules in this filter. + */ + size_t count() const { + return m_rules.count(); + } + + /** + * Is this filter empty, ie are there no rules defined? + */ + bool empty() const { + return m_rules.empty(); + } + }; // class Filter typedef Filter KeyValueFilter; diff --git a/include/osmium/tags/regex_filter.hpp b/include/osmium/tags/regex_filter.hpp index ae2703a30..725c42376 100644 --- a/include/osmium/tags/regex_filter.hpp +++ b/include/osmium/tags/regex_filter.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/tags/taglist.hpp b/include/osmium/tags/taglist.hpp index 41ef993a0..d7c78dc79 100644 --- a/include/osmium/tags/taglist.hpp +++ b/include/osmium/tags/taglist.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -47,17 +47,17 @@ namespace osmium { template inline bool match_any_of(const osmium::TagList& tag_list, TFilter&& filter) { - return std::any_of(tag_list.begin(), tag_list.end(), std::forward(filter)); + return std::any_of(tag_list.cbegin(), tag_list.cend(), std::forward(filter)); } template inline bool match_all_of(const osmium::TagList& tag_list, TFilter&& filter) { - return std::all_of(tag_list.begin(), tag_list.end(), std::forward(filter)); + return std::all_of(tag_list.cbegin(), tag_list.cend(), std::forward(filter)); } template inline bool match_none_of(const osmium::TagList& tag_list, TFilter&& filter) { - return std::none_of(tag_list.begin(), tag_list.end(), std::forward(filter)); + return std::none_of(tag_list.cbegin(), tag_list.cend(), std::forward(filter)); } } // namespace tags diff --git a/include/osmium/thread/function_wrapper.hpp b/include/osmium/thread/function_wrapper.hpp index dbb47ff87..fe0a49257 100644 --- a/include/osmium/thread/function_wrapper.hpp +++ b/include/osmium/thread/function_wrapper.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -94,9 +94,10 @@ namespace osmium { } function_wrapper(const function_wrapper&) = delete; - function_wrapper(function_wrapper&) = delete; function_wrapper& operator=(const function_wrapper&) = delete; + ~function_wrapper() = default; + explicit operator bool() const { return static_cast(impl); } diff --git a/include/osmium/thread/pool.hpp b/include/osmium/thread/pool.hpp index 702be66e0..bc1e9a82b 100644 --- a/include/osmium/thread/pool.hpp +++ b/include/osmium/thread/pool.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -160,11 +160,11 @@ namespace osmium { } template - std::future::type> submit(TFunction f) { + std::future::type> submit(TFunction&& func) { typedef typename std::result_of::type result_type; - std::packaged_task task(std::move(f)); + std::packaged_task task(std::forward(func)); std::future future_result(task.get_future()); m_work_queue.push(std::move(task)); diff --git a/include/osmium/thread/queue.hpp b/include/osmium/thread/queue.hpp index b01dd39bf..5c5f8e768 100644 --- a/include/osmium/thread/queue.hpp +++ b/include/osmium/thread/queue.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 @@ -39,6 +39,7 @@ DEALINGS IN THE SOFTWARE. #include #include #include +#include #include #include diff --git a/include/osmium/thread/sorted_queue.hpp b/include/osmium/thread/sorted_queue.hpp index e33dfe696..e0181eb61 100644 --- a/include/osmium/thread/sorted_queue.hpp +++ b/include/osmium/thread/sorted_queue.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/thread/util.hpp b/include/osmium/thread/util.hpp index 286ea5e06..62bb82ab5 100644 --- a/include/osmium/thread/util.hpp +++ b/include/osmium/thread/util.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/util/cast.hpp b/include/osmium/util/cast.hpp index 750326706..13e6e3a9c 100644 --- a/include/osmium/util/cast.hpp +++ b/include/osmium/util/cast.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/util/compatibility.hpp b/include/osmium/util/compatibility.hpp index 48a6db017..90d85c502 100644 --- a/include/osmium/util/compatibility.hpp +++ b/include/osmium/util/compatibility.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/util/config.hpp b/include/osmium/util/config.hpp index 4fc8f2860..3285eedbb 100644 --- a/include/osmium/util/config.hpp +++ b/include/osmium/util/config.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/util/double.hpp b/include/osmium/util/double.hpp index 67e997d9f..85a250807 100644 --- a/include/osmium/util/double.hpp +++ b/include/osmium/util/double.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/util/options.hpp b/include/osmium/util/options.hpp index fc74980d1..fea075230 100644 --- a/include/osmium/util/options.hpp +++ b/include/osmium/util/options.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/util/verbose_output.hpp b/include/osmium/util/verbose_output.hpp index 8709441af..178781e23 100644 --- a/include/osmium/util/verbose_output.hpp +++ b/include/osmium/util/verbose_output.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/include/osmium/visitor.hpp b/include/osmium/visitor.hpp index d71a2e01c..0250f11d4 100644 --- a/include/osmium/visitor.hpp +++ b/include/osmium/visitor.hpp @@ -5,7 +5,7 @@ This file is part of Osmium (http://osmcode.org/libosmium). -Copyright 2013,2014 Jochen Topf and others (see README). +Copyright 2013-2015 Jochen Topf and others (see README). Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/make_osmium_project.sh b/make_osmium_project.sh deleted file mode 100755 index ba844b85b..000000000 --- a/make_osmium_project.sh +++ /dev/null @@ -1,96 +0,0 @@ -#!/bin/sh -# -# make_osmium_project.sh PROJECTNAME -# -# Creates a subdirectory named as the project in the current directory and -# adds a skeleton of files needed to begin a new project using the Osmium -# library. -# - -if [ "x$1" = "x" ]; then - echo "Usage: $0 PROJECTNAME" - exit 1 -fi - -if [ -e "$1" ]; then - echo "Directory '$1' exists" - exit 1 -fi - -mkdir $1 -cd $1 - -sed -e "s/__PROJECTNAME__/$1/g" >Makefile <<'__EOF__' -CXXFLAGS += -O3 -#CXXFLAGS += -g -CXXFLAGS += -std=c++11 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -CXXFLAGS += -I../include - -OS:=$(shell uname -s) -ifeq ($(OS),Darwin) - CXXFLAGS += -stdlib=libc++ - LDFLAGS += -stdlib=libc++ -endif - -CXXFLAGS_WARNINGS := -Wall -Wextra -pedantic -Wredundant-decls -Wdisabled-optimization -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wsign-promo -Wold-style-cast - -LIB_EXPAT := -lexpat -LIB_PBF := -pthread -lz -lprotobuf-lite -losmpbf -LIB_GZIP := -lz -LIB_BZIP2 := -lbz2 - -LIB_IO := $(LIB_EXPAT) $(LIB_PBF) $(LIB_GZIP) $(LIB_BZIP2) - -PROGRAMS := __PROJECTNAME__ - -.PHONY: all clean - -all: $(PROGRAMS) - -__PROJECTNAME__: main.cpp - $(CXX) $(CXXFLAGS) $(CXXFLAGS_WARNINGS) -o $@ $< $(LDFLAGS) $(LIB_IO) - -clean: - rm -f *.o core $(PROGRAMS) - -__EOF__ - -cat >main.cpp <<'__EOF__' - -#include -#include -#include - -class MyHandler : public osmium::handler::Handler { - -public: - - MyHandler() : - osmium::handler::Handler() { - } - - void node(const osmium::Node& node) { - } - - void way(const osmium::Way& way) { - } - - void relation(const osmium::Relation& relation) { - } - -}; // class MyHandler - -int main(int argc, char* argv[]) { - - if (argc != 2) { - std::cerr << "Usage: " << argv[0] << " OSMFILE\n"; - exit(1); - } - - MyHandler handler; - osmium::io::Reader reader(argv[1]); - osmium::apply(reader, handler); -} - -__EOF__ - diff --git a/osmium.imp b/osmium.imp index 1f0963f11..c45794d08 100644 --- a/osmium.imp +++ b/osmium.imp @@ -1,3 +1,10 @@ +#----------------------------------------------------------------------------- +# +# Configuration for Include-What-You-Use tool +# +# https://code.google.com/p/include-what-you-use/ +# +#----------------------------------------------------------------------------- [ { "include": ["", "private", "", "public"] }, { "include": ["", "public", "", "public"] } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ebea16c11..9e27b120c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,25 +1,31 @@ -message(STATUS "Configuring unit tests...") +#----------------------------------------------------------------------------- +# +# CMake Config +# +# Libosmium unit tests +# +#----------------------------------------------------------------------------- + +message(STATUS "Configuring unit tests") -set(DART_TESTING_TIMEOUT 60) -include(Dart) include_directories(include) -# In 'Dev' mode: compile with very strict warnings and turn them into errors. -if(CMAKE_BUILD_TYPE STREQUAL "Dev") - add_definitions(-Werror ${OSMIUM_WARNING_OPTIONS} -Wno-unused-variable) -endif() - add_library(testlib STATIC test_main.cpp) -#---------------------------------------------------------------------- - set(ALL_TESTS "") -# call with parameters: -# TGROUP - test group (directory) -# TNAME - name of test -# ARGV2 - flag to enable test (optional) -# ARGV3 - libraries to add (optional) + +#----------------------------------------------------------------------------- +# +# Define function for adding tests +# +# Call with parameters: +# TGROUP - test group (directory) +# TNAME - name of test +# ARGV2 - flag to enable test (optional) +# ARGV3 - libraries to add (optional) +# +#----------------------------------------------------------------------------- function(add_unit_test TGROUP TNAME) set(ALL_TESTS "${ALL_TESTS};${TGROUP}/${TNAME}" PARENT_SCOPE) if((${ARGC} EQUAL 2) OR (${ARGV2})) @@ -36,10 +42,13 @@ function(add_unit_test TGROUP TNAME) target_link_libraries(${TESTNAME} ${ARGV3}) endif() add_test(NAME ${TESTNAME} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${TESTNAME} ) - set_tests_properties(${TESTNAME} PROPERTIES LABELS "unit;${TGROUP}") + set_tests_properties(${TESTNAME} PROPERTIES + LABELS "unit;fast;${TGROUP}" + ENVIRONMENT "OSMIUM_TEST_DATA_DIR=${CMAKE_CURRENT_SOURCE_DIR}" + ) else() message("Skipped test ${TGROUP}/${TNAME} because a dependency was not found") set(OSMIUM_SKIPPED_TESTS @@ -48,12 +57,11 @@ function(add_unit_test TGROUP TNAME) endif() endfunction() -#---------------------------------------------------------------------- +#----------------------------------------------------------------------------- # # Add all tests. # -#---------------------------------------------------------------------- - +#----------------------------------------------------------------------------- add_unit_test(area test_area_id) add_unit_test(area test_node_ref_segment) @@ -71,7 +79,7 @@ add_unit_test(basic test_way) add_unit_test(buffer test_buffer_node) add_unit_test(buffer test_buffer_purge) -if (GEOS_FOUND AND PROJ_FOUND) +if(GEOS_FOUND AND PROJ_FOUND) set(GEOS_AND_PROJ_FOUND TRUE) else() set(GEOS_AND_PROJ_FOUND FALSE) @@ -95,6 +103,7 @@ add_unit_test(index test_typed_mmap) add_unit_test(io test_bzip2 ${BZIP2_FOUND} ${BZIP2_LIBRARIES}) add_unit_test(io test_file_formats) add_unit_test(io test_reader TRUE "${OSMIUM_XML_LIBRARIES}") +add_unit_test(io test_output_iterator ${Threads_FOUND} ${CMAKE_THREAD_LIBS_INIT}) add_unit_test(tags test_filter) add_unit_test(tags test_operators) @@ -104,12 +113,12 @@ add_unit_test(util test_double) add_unit_test(util test_options) add_unit_test(util test_string) -#---------------------------------------------------------------------- + +#----------------------------------------------------------------------------- # # Check that all tests available in test/t/*/test_*.cpp are run. # -#---------------------------------------------------------------------- - +#----------------------------------------------------------------------------- file(GLOB TESTS_IN_DIR RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/t" t/*/test_*.cpp) foreach(file ${TESTS_IN_DIR}) @@ -121,3 +130,9 @@ foreach(file ${TESTS_IN_DIR}) endif() endforeach() + +#----------------------------------------------------------------------------- +message(STATUS "Configuring unit tests - done") + + +#----------------------------------------------------------------------------- diff --git a/test/README b/test/README index dc5e51222..8195824b4 100644 --- a/test/README +++ b/test/README @@ -7,6 +7,7 @@ Osmium needs a few changes to catch.hpp, they were patched in. To be able to compare with the original version, it is stored in include/catch_orig.hpp. Changes are: +* Disable more warnings in GCC * CATCH_CONFIG_CPP11_NULLPTR must be set for MSVC * Problem with test running in loop: https://github.com/philsquared/Catch/issues/271 diff --git a/test/osm-testdata/.gitignore b/test/data-tests/.gitignore similarity index 100% rename from test/osm-testdata/.gitignore rename to test/data-tests/.gitignore diff --git a/test/data-tests/CMakeLists.txt b/test/data-tests/CMakeLists.txt new file mode 100644 index 000000000..a2938e519 --- /dev/null +++ b/test/data-tests/CMakeLists.txt @@ -0,0 +1,121 @@ +#----------------------------------------------------------------------------- +# +# CMake Config +# +# Libosmium data tests +# +#----------------------------------------------------------------------------- + +message(STATUS "Configuring data tests") + +if(NOT GDAL_FOUND OR NOT EXPAT_FOUND) + message(STATUS "Sorry, building data tests needs GDAL and Expat") + message(STATUS "Configuring data tests - failed") + return() +endif() + +message(STATUS "Looking for osm-testdata") +find_path(OSM_TESTDATA grid/data/all.osm HINT ../../../osm-testdata) +if(OSM_TESTDATA STREQUAL "OSM_TESTDATA-NOTFOUND") + message(STATUS "Looking for osm-testdata - not found (data tests disabled)") + message(STATUS "Configuring data tests - failed") + return() +endif() +message(STATUS "Looking for osm-testdata - found") + + +#----------------------------------------------------------------------------- + +include_directories("include") +include_directories("../include") + + +#----------------------------------------------------------------------------- +# +# testcases +# +#----------------------------------------------------------------------------- +file(GLOB TESTCASE_CPPS testcases/*.cpp) +add_executable(testdata-testcases testdata-testcases.cpp ${TESTCASE_CPPS}) +target_link_libraries(testdata-testcases + ${OSMIUM_XML_LIBRARIES} +) +add_test(NAME testdata-testcases + COMMAND testdata-testcases +) +set_tests_properties(testdata-testcases PROPERTIES + ENVIRONMENT "TESTCASES_DIR=${OSM_TESTDATA}/grid/data" + LABELS "data;fast") + + +#----------------------------------------------------------------------------- +# +# xml +# +#----------------------------------------------------------------------------- +add_executable(testdata-xml testdata-xml.cpp) +target_link_libraries(testdata-xml + ${OSMIUM_XML_LIBRARIES} +) +add_test(NAME testdata-xml + COMMAND testdata-xml +) +set_tests_properties(testdata-xml PROPERTIES + ENVIRONMENT "TESTDIR=${OSM_TESTDATA}/xml/data" + LABELS "data;fast") + + +#----------------------------------------------------------------------------- +# +# overview +# +#----------------------------------------------------------------------------- +add_executable(testdata-overview testdata-overview.cpp) +target_link_libraries(testdata-overview + ${OSMIUM_XML_LIBRARIES} + ${GDAL_LIBRARIES} +) +add_test(NAME testdata-overview + COMMAND testdata-overview ${OSM_TESTDATA}/grid/data/all.osm +) +set_tests_properties(testdata-overview PROPERTIES + LABELS "data;slow") + + +#----------------------------------------------------------------------------- +# +# multipolygon +# +#----------------------------------------------------------------------------- +add_executable(testdata-multipolygon testdata-multipolygon.cpp) +target_link_libraries(testdata-multipolygon + ${OSMIUM_XML_LIBRARIES} + ${GDAL_LIBRARIES} +) + +if(WIN32) + set(MULTIPOLYGON_TEST_SCRIPT "run-testdata-multipolygon.bat") +else() + set(MULTIPOLYGON_TEST_SCRIPT "run-testdata-multipolygon.sh") +endif() + +if(MSVC) + set(EXE_DIR ${CMAKE_BUILD_TYPE}) +else() + set(EXE_DIR .) +endif() + +add_test(NAME testdata-multipolygon + COMMAND ${CMAKE_SOURCE_DIR}/test/data-tests/${MULTIPOLYGON_TEST_SCRIPT} + ${OSM_TESTDATA} + ${EXE_DIR} +) +set_tests_properties(testdata-multipolygon PROPERTIES + LABELS "data;slow") + + +#----------------------------------------------------------------------------- +message(STATUS "Configuring data tests - done") + + +#----------------------------------------------------------------------------- diff --git a/test/osm-testdata/README.md b/test/data-tests/README.md similarity index 100% rename from test/osm-testdata/README.md rename to test/data-tests/README.md diff --git a/test/osm-testdata/include/check_basics_handler.hpp b/test/data-tests/include/check_basics_handler.hpp similarity index 100% rename from test/osm-testdata/include/check_basics_handler.hpp rename to test/data-tests/include/check_basics_handler.hpp diff --git a/test/osm-testdata/include/check_wkt_handler.hpp b/test/data-tests/include/check_wkt_handler.hpp similarity index 100% rename from test/osm-testdata/include/check_wkt_handler.hpp rename to test/data-tests/include/check_wkt_handler.hpp diff --git a/test/osm-testdata/include/common.hpp b/test/data-tests/include/common.hpp similarity index 78% rename from test/osm-testdata/include/common.hpp rename to test/data-tests/include/common.hpp index 0f6957056..a6fd3df61 100644 --- a/test/osm-testdata/include/common.hpp +++ b/test/data-tests/include/common.hpp @@ -1,16 +1,17 @@ #ifndef COMMON_HPP #define COMMON_HPP +#include +#include + #include #include #include -#include -#include #include #include typedef osmium::index::map::Dummy index_neg_type; -typedef osmium::index::map::SparseMapMem index_pos_type; +typedef osmium::index::map::SparseMemArray index_pos_type; typedef osmium::handler::NodeLocationsForWays location_handler_type; #include "check_basics_handler.hpp" diff --git a/test/osm-testdata/include/testdata-testcases.hpp b/test/data-tests/include/testdata-testcases.hpp similarity index 100% rename from test/osm-testdata/include/testdata-testcases.hpp rename to test/data-tests/include/testdata-testcases.hpp diff --git a/test/osm-testdata/multipolygon.qgs b/test/data-tests/multipolygon.qgs similarity index 100% rename from test/osm-testdata/multipolygon.qgs rename to test/data-tests/multipolygon.qgs diff --git a/test/osm-testdata/run-testdata-multipolygon.bat b/test/data-tests/run-testdata-multipolygon.bat similarity index 100% rename from test/osm-testdata/run-testdata-multipolygon.bat rename to test/data-tests/run-testdata-multipolygon.bat diff --git a/test/osm-testdata/run-testdata-multipolygon.sh b/test/data-tests/run-testdata-multipolygon.sh similarity index 100% rename from test/osm-testdata/run-testdata-multipolygon.sh rename to test/data-tests/run-testdata-multipolygon.sh diff --git a/test/osm-testdata/testcases/test-100.cpp b/test/data-tests/testcases/test-100.cpp similarity index 100% rename from test/osm-testdata/testcases/test-100.cpp rename to test/data-tests/testcases/test-100.cpp diff --git a/test/osm-testdata/testcases/test-101.cpp b/test/data-tests/testcases/test-101.cpp similarity index 100% rename from test/osm-testdata/testcases/test-101.cpp rename to test/data-tests/testcases/test-101.cpp diff --git a/test/osm-testdata/testcases/test-110.cpp b/test/data-tests/testcases/test-110.cpp similarity index 100% rename from test/osm-testdata/testcases/test-110.cpp rename to test/data-tests/testcases/test-110.cpp diff --git a/test/osm-testdata/testdata-multipolygon.cpp b/test/data-tests/testdata-multipolygon.cpp similarity index 92% rename from test/osm-testdata/testdata-multipolygon.cpp rename to test/data-tests/testdata-multipolygon.cpp index d732566c4..0fd0d9849 100644 --- a/test/osm-testdata/testdata-multipolygon.cpp +++ b/test/data-tests/testdata-multipolygon.cpp @@ -3,18 +3,7 @@ #include #include -#pragma GCC diagnostic push -#ifdef __clang__ -# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" -#endif -#pragma GCC diagnostic ignored "-Wfloat-equal" -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Wpadded" -#pragma GCC diagnostic ignored "-Wredundant-decls" -#pragma GCC diagnostic ignored "-Wshadow" -# include -# include -#pragma GCC diagnostic pop +#include #include #include @@ -23,14 +12,12 @@ #include #include #include -#include -#include #include #include -typedef osmium::index::map::SparseMapMem index_type; +typedef osmium::index::map::SparseMemArray index_type; -typedef osmium::handler::NodeLocationsForWays location_handler_type; +typedef osmium::handler::NodeLocationsForWays location_handler_type; struct less_charptr { @@ -284,9 +271,8 @@ int main(int argc, char* argv[]) { reader1.close(); std::cerr << "Pass 1 done\n"; - index_type index_pos; - index_type index_neg; - location_handler_type location_handler(index_pos, index_neg); + index_type index; + location_handler_type location_handler(index); location_handler.ignore_errors(); TestHandler test_handler(data_source); diff --git a/test/osm-testdata/testdata-overview.cpp b/test/data-tests/testdata-overview.cpp similarity index 86% rename from test/osm-testdata/testdata-overview.cpp rename to test/data-tests/testdata-overview.cpp index b56781268..2d63dc684 100644 --- a/test/osm-testdata/testdata-overview.cpp +++ b/test/data-tests/testdata-overview.cpp @@ -2,30 +2,16 @@ #include -#pragma GCC diagnostic push -#ifdef __clang__ -# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" -#endif -#pragma GCC diagnostic ignored "-Wfloat-equal" -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Wpadded" -#pragma GCC diagnostic ignored "-Wredundant-decls" -#pragma GCC diagnostic ignored "-Wshadow" -# include -# include -#pragma GCC diagnostic pop +#include #include #include #include -#include -#include #include #include -typedef osmium::index::map::Dummy index_neg_type; -typedef osmium::index::map::SparseMapMem index_pos_type; -typedef osmium::handler::NodeLocationsForWays location_handler_type; +typedef osmium::index::map::SparseMemArray index_type; +typedef osmium::handler::NodeLocationsForWays location_handler_type; class TestOverviewHandler : public osmium::handler::Handler { @@ -199,9 +185,8 @@ int main(int argc, char* argv[]) { osmium::io::Reader reader(input_filename); - index_pos_type index_pos; - index_neg_type index_neg; - location_handler_type location_handler(index_pos, index_neg); + index_type index; + location_handler_type location_handler(index); location_handler.ignore_errors(); TestOverviewHandler handler(output_format, output_filename); diff --git a/test/osm-testdata/testdata-testcases.cpp b/test/data-tests/testdata-testcases.cpp similarity index 100% rename from test/osm-testdata/testdata-testcases.cpp rename to test/data-tests/testdata-testcases.cpp diff --git a/test/osm-testdata/testdata-xml.cpp b/test/data-tests/testdata-xml.cpp similarity index 99% rename from test/osm-testdata/testdata-xml.cpp rename to test/data-tests/testdata-xml.cpp index e4c1716d4..16133a92a 100644 --- a/test/osm-testdata/testdata-xml.cpp +++ b/test/data-tests/testdata-xml.cpp @@ -1,11 +1,7 @@ /* The code in this file is released into the Public Domain. */ #define CATCH_CONFIG_MAIN - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" #include "catch.hpp" -#pragma GCC diagnostic pop #include #include diff --git a/test/include/catch.hpp b/test/include/catch.hpp index f35378fea..bb87af296 100644 --- a/test/include/catch.hpp +++ b/test/include/catch.hpp @@ -3,8 +3,8 @@ #define CATCH_CONFIG_CPP11_NULLPTR /* - * CATCH v1.0 build 52 (master branch) - * Generated: 2014-07-10 09:17:43.994453 + * CATCH v1.0 build 53 (master branch) + * Generated: 2014-08-20 08:08:19.533804 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -30,15 +30,13 @@ #pragma clang diagnostic ignored "-Wpadded" #pragma clang diagnostic ignored "-Wc++98-compat" #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#pragma clang diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef __clang__ -# pragma GCC diagnostic ignored "-Wctor-dtor-privacy" -# pragma GCC diagnostic ignored "-Wunused-variable" -# pragma GCC diagnostic ignored "-Wreturn-type" -# pragma GCC diagnostic ignored "-Wsign-promo" -# pragma GCC diagnostic ignored "-Wparentheses" +#elif defined __GNUC__ +#pragma GCC diagnostic ignored "-Wvariadic-macros" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpadded" +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" +#pragma GCC diagnostic ignored "-Wsign-promo" #endif #ifdef CATCH_CONFIG_MAIN @@ -1175,6 +1173,8 @@ std::string toString( std::string const& value ); std::string toString( std::wstring const& value ); std::string toString( const char* const value ); std::string toString( char* const value ); +std::string toString( const wchar_t* const value ); +std::string toString( wchar_t* const value ); std::string toString( int value ); std::string toString( unsigned long value ); std::string toString( unsigned int value ); @@ -6423,7 +6423,7 @@ namespace Catch { namespace Catch { // These numbers are maintained by a script - Version libraryVersion( 1, 0, 52, "master" ); + Version libraryVersion( 1, 0, 53, "master" ); } // #included from: catch_message.hpp @@ -6909,6 +6909,16 @@ std::string toString( char* const value ) { return Catch::toString( static_cast( value ) ); } +std::string toString( const wchar_t* const value ) +{ + return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); +} + +std::string toString( wchar_t* const value ) +{ + return Catch::toString( static_cast( value ) ); +} + std::string toString( int value ) { std::ostringstream oss; oss << value; @@ -8897,8 +8907,10 @@ int main (int argc, char * const argv[]) { // "BDD-style" convenience wrappers #ifdef CATCH_CONFIG_VARIADIC_MACROS #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) #else #define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #endif #define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" ) #define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" ) @@ -8964,8 +8976,10 @@ int main (int argc, char * const argv[]) { // "BDD-style" convenience wrappers #ifdef CATCH_CONFIG_VARIADIC_MACROS #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) #else #define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #endif #define GIVEN( desc ) SECTION( " Given: " desc, "" ) #define WHEN( desc ) SECTION( " When: " desc, "" ) @@ -8981,6 +8995,8 @@ using Catch::Detail::Approx; #ifdef __clang__ #pragma clang diagnostic pop +#elif defined __GNUC__ +#pragma GCC diagnostic pop #endif #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED diff --git a/test/include/catch_orig.hpp b/test/include/catch_orig.hpp index 1fba6a34e..6b8dfb5eb 100644 --- a/test/include/catch_orig.hpp +++ b/test/include/catch_orig.hpp @@ -1,6 +1,6 @@ /* - * CATCH v1.0 build 52 (master branch) - * Generated: 2014-07-10 09:17:43.994453 + * CATCH v1.0 build 53 (master branch) + * Generated: 2014-08-20 08:08:19.533804 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -26,6 +26,11 @@ #pragma clang diagnostic ignored "-Wpadded" #pragma clang diagnostic ignored "-Wc++98-compat" #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#elif defined __GNUC__ +#pragma GCC diagnostic ignored "-Wvariadic-macros" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpadded" #endif #ifdef CATCH_CONFIG_MAIN @@ -1162,6 +1167,8 @@ std::string toString( std::string const& value ); std::string toString( std::wstring const& value ); std::string toString( const char* const value ); std::string toString( char* const value ); +std::string toString( const wchar_t* const value ); +std::string toString( wchar_t* const value ); std::string toString( int value ); std::string toString( unsigned long value ); std::string toString( unsigned int value ); @@ -6410,7 +6417,7 @@ namespace Catch { namespace Catch { // These numbers are maintained by a script - Version libraryVersion( 1, 0, 52, "master" ); + Version libraryVersion( 1, 0, 53, "master" ); } // #included from: catch_message.hpp @@ -6896,6 +6903,16 @@ std::string toString( char* const value ) { return Catch::toString( static_cast( value ) ); } +std::string toString( const wchar_t* const value ) +{ + return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); +} + +std::string toString( wchar_t* const value ) +{ + return Catch::toString( static_cast( value ) ); +} + std::string toString( int value ) { std::ostringstream oss; oss << value; @@ -8884,8 +8901,10 @@ int main (int argc, char * const argv[]) { // "BDD-style" convenience wrappers #ifdef CATCH_CONFIG_VARIADIC_MACROS #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) #else #define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #endif #define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" ) #define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" ) @@ -8951,8 +8970,10 @@ int main (int argc, char * const argv[]) { // "BDD-style" convenience wrappers #ifdef CATCH_CONFIG_VARIADIC_MACROS #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) #else #define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #endif #define GIVEN( desc ) SECTION( " Given: " desc, "" ) #define WHEN( desc ) SECTION( " When: " desc, "" ) @@ -8968,6 +8989,8 @@ using Catch::Detail::Approx; #ifdef __clang__ #pragma clang diagnostic pop +#elif defined __GNUC__ +#pragma GCC diagnostic pop #endif #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED diff --git a/test/include/utils.hpp b/test/include/utils.hpp new file mode 100644 index 000000000..662155abf --- /dev/null +++ b/test/include/utils.hpp @@ -0,0 +1,18 @@ + +#include +#include + +inline std::string with_data_dir(const char* filename) { + const char* data_dir = getenv("OSMIUM_TEST_DATA_DIR"); + + std::string result; + if (data_dir) { + result = data_dir; + result += '/'; + } + + result += filename; + + return result; +} + diff --git a/test/osm-testdata/CMakeLists.txt b/test/osm-testdata/CMakeLists.txt deleted file mode 100644 index b29510ce4..000000000 --- a/test/osm-testdata/CMakeLists.txt +++ /dev/null @@ -1,87 +0,0 @@ -message(STATUS "Configuring osm-testdata tests...") - -if(NOT GDAL_FOUND OR - NOT EXPAT_FOUND) - message("Sorry, building osm-testdata tests needs GDAL and Expat") - return() -endif() - -set(DART_TESTING_TIMEOUT 300) -include(Dart) - -include_directories("include") -include_directories("../include") - -# In 'Dev' mode: compile with very strict warnings and turn them into errors. -if(CMAKE_BUILD_TYPE STREQUAL "Dev") - add_definitions(-Werror ${OSMIUM_WARNING_OPTIONS} -Wno-unused-variable) -endif() - -get_filename_component(TESTDATA_DIR ../../../osm-testdata ABSOLUTE) -if(NOT EXISTS ${TESTDATA_DIR}) - execute_process(COMMAND git clone https://github.com/osmcode/osm-testdata.git ${TESTDATA_DIR}) -endif() - -#---------------------------------------------------------------------- - -file(GLOB TESTCASE_CPPS testcases/*.cpp) -add_executable(testdata-testcases testdata-testcases.cpp ${TESTCASE_CPPS}) -target_link_libraries(testdata-testcases - ${OSMIUM_XML_LIBRARIES} -) -add_test(NAME testdata-testcases - COMMAND testdata-testcases -) -set_tests_properties(testdata-testcases - PROPERTIES ENVIRONMENT "TESTCASES_DIR=${TESTDATA_DIR}/grid/data") - -#---------------------------------------------------------------------- - -add_executable(testdata-overview testdata-overview.cpp) -target_link_libraries(testdata-overview - ${OSMIUM_XML_LIBRARIES} - ${GDAL_LIBRARIES} -) -add_test(NAME testdata-overview - COMMAND testdata-overview ${TESTDATA_DIR}/grid/data/all.osm -) - -#---------------------------------------------------------------------- - -add_executable(testdata-xml testdata-xml.cpp) -target_link_libraries(testdata-xml - ${OSMIUM_XML_LIBRARIES} -) -add_test(NAME testdata-xml - COMMAND testdata-xml -) -set_tests_properties(testdata-xml - PROPERTIES ENVIRONMENT "TESTDIR=${TESTDATA_DIR}/xml/data") - -#---------------------------------------------------------------------- - -add_executable(testdata-multipolygon testdata-multipolygon.cpp) -target_link_libraries(testdata-multipolygon - ${OSMIUM_XML_LIBRARIES} - ${GDAL_LIBRARIES} -) - -if(WIN32) - set(MULTIPOLYGON_TEST_SCRIPT "run-testdata-multipolygon.bat") -else() - set(MULTIPOLYGON_TEST_SCRIPT "run-testdata-multipolygon.sh") -endif() - -if(MSVC) - set(EXE_DIR ${CMAKE_BUILD_TYPE}) -else() - set(EXE_DIR .) -endif() - -add_test(NAME testdata-multipolygon - COMMAND ${CMAKE_SOURCE_DIR}/test/osm-testdata/${MULTIPOLYGON_TEST_SCRIPT} - ${TESTDATA_DIR} - ${EXE_DIR} -) - -#---------------------------------------------------------------------- diff --git a/test/t/basic/test_box.cpp b/test/t/basic/test_box.cpp index 34789e815..73a45f4e2 100644 --- a/test/t/basic/test_box.cpp +++ b/test/t/basic/test_box.cpp @@ -47,7 +47,7 @@ SECTION("output_defined") { std::stringstream out; out << b; REQUIRE(out.str() == "(1.2,3.4,5.6,7.8)"); - REQUIRE((19.36 - b.size()) < 0.000001); + REQUIRE(b.size() == Approx(19.36).epsilon(0.000001)); } SECTION("output_undefined") { diff --git a/test/t/basic/test_entity_bits.cpp b/test/t/basic/test_entity_bits.cpp index b3f3e66af..a200f480b 100644 --- a/test/t/basic/test_entity_bits.cpp +++ b/test/t/basic/test_entity_bits.cpp @@ -20,6 +20,12 @@ SECTION("can_be_set_and_checked") { 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::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)); } } diff --git a/test/t/basic/test_node.cpp b/test/t/basic/test_node.cpp index d5351d96f..6c2c899bd 100644 --- a/test/t/basic/test_node.cpp +++ b/test/t/basic/test_node.cpp @@ -21,6 +21,9 @@ SECTION("node_builder") { .set_uid(21) .set_timestamp(123); + REQUIRE(osmium::item_type::node == node.type()); + REQUIRE(node.type_is_in(osmium::osm_entity_bits::node)); + REQUIRE(node.type_is_in(osmium::osm_entity_bits::nwr)); REQUIRE(17l == node.id()); REQUIRE(17ul == node.positive_id()); REQUIRE(3 == node.version()); diff --git a/test/t/basic/test_object_comparisons.cpp b/test/t/basic/test_object_comparisons.cpp index 49733ce30..ffffbccb3 100644 --- a/test/t/basic/test_object_comparisons.cpp +++ b/test/t/basic/test_object_comparisons.cpp @@ -31,20 +31,20 @@ SECTION("order") { node1.set_version(1); node2.set_id(15); node2.set_version(2); - REQUIRE(true == node1 < node2); - REQUIRE(false == node1 > node2); + REQUIRE(true == (node1 < node2)); + REQUIRE(false == (node1 > node2)); node1.set_id(20); node1.set_version(1); node2.set_id(20); node2.set_version(2); - REQUIRE(true == node1 < node2); - REQUIRE(false == node1 > node2); + REQUIRE(true == (node1 < node2)); + REQUIRE(false == (node1 > node2)); node1.set_id(-10); node1.set_version(2); node2.set_id(-15); node2.set_version(1); - REQUIRE(true == node1 < node2); - REQUIRE(false == node1 > node2); + REQUIRE(true == (node1 < node2)); + REQUIRE(false == (node1 > node2)); } SECTION("order_types") { @@ -122,11 +122,11 @@ SECTION("order_types") { const osmium::Way& way = static_cast(*(++it)); const osmium::Relation& relation = static_cast(*(++it)); - REQUIRE(true == node1 < node2); - REQUIRE(true == node2 < way); - REQUIRE(false == node2 > way); - REQUIRE(true == way < relation); - REQUIRE(true == node1 < relation); + REQUIRE(true == (node1 < node2)); + REQUIRE(true == (node2 < way)); + REQUIRE(false == (node2 > way)); + REQUIRE(true == (way < relation)); + REQUIRE(true == (node1 < relation)); REQUIRE(true == osmium::object_order_type_id_version()(node1, node2)); REQUIRE(true == osmium::object_order_type_id_reverse_version()(node2, node1)); diff --git a/test/t/basic/test_way.cpp b/test/t/basic/test_way.cpp index 6d510ab3e..9d2ba0691 100644 --- a/test/t/basic/test_way.cpp +++ b/test/t/basic/test_way.cpp @@ -22,6 +22,9 @@ SECTION("way_builder") { .set_uid(21) .set_timestamp(123); + REQUIRE(osmium::item_type::way == way.type()); + REQUIRE(way.type_is_in(osmium::osm_entity_bits::way)); + REQUIRE(way.type_is_in(osmium::osm_entity_bits::node | osmium::osm_entity_bits::way)); REQUIRE(17 == way.id()); REQUIRE(3 == way.version()); REQUIRE(true == way.visible()); diff --git a/test/t/geom/test_mercator.cpp b/test/t/geom/test_mercator.cpp index c5c663700..a6ce2ee4a 100644 --- a/test/t/geom/test_mercator.cpp +++ b/test/t/geom/test_mercator.cpp @@ -13,25 +13,25 @@ SECTION("mercator_projection") { SECTION("low_level_mercator_functions") { osmium::geom::Coordinates c1(17.839, -3.249); osmium::geom::Coordinates r1 = osmium::geom::mercator_to_lonlat(osmium::geom::lonlat_to_mercator(c1)); - REQUIRE(std::abs(c1.x - r1.x) < 0.000001); - REQUIRE(std::abs(c1.y - r1.y) < 0.000001); + REQUIRE(r1.x == Approx(c1.x).epsilon(0.000001)); + REQUIRE(r1.y == Approx(c1.y).epsilon(0.000001)); osmium::geom::Coordinates c2(-89.2, 15.915); osmium::geom::Coordinates r2 = osmium::geom::mercator_to_lonlat(osmium::geom::lonlat_to_mercator(c2)); - REQUIRE(std::abs(c2.x - r2.x) < 0.000001); - REQUIRE(std::abs(c2.y - r2.y) < 0.000001); + REQUIRE(r2.x == Approx(c2.x).epsilon(0.000001)); + REQUIRE(r2.y == Approx(c2.y).epsilon(0.000001)); osmium::geom::Coordinates c3(180.0, 85.0); osmium::geom::Coordinates r3 = osmium::geom::mercator_to_lonlat(osmium::geom::lonlat_to_mercator(c3)); - REQUIRE(std::abs(c3.x - r3.x) < 0.000001); - REQUIRE(std::abs(c3.y - r3.y) < 0.000001); + REQUIRE(r3.x == Approx(c3.x).epsilon(0.000001)); + REQUIRE(r3.y == Approx(c3.y).epsilon(0.000001)); } SECTION("mercator_bounds") { osmium::Location mmax(180.0, osmium::geom::MERCATOR_MAX_LAT); osmium::geom::Coordinates c = osmium::geom::lonlat_to_mercator(mmax); - REQUIRE((c.x - c.y) < 0.001); - REQUIRE((osmium::geom::MERCATOR_MAX_LAT - osmium::geom::detail::y_to_lat(osmium::geom::detail::lon_to_x(180.0))) < 0.0000001); + REQUIRE(c.x == Approx(c.y).epsilon(0.001)); + REQUIRE(osmium::geom::detail::y_to_lat(osmium::geom::detail::lon_to_x(180.0)) == Approx(osmium::geom::MERCATOR_MAX_LAT).epsilon(0.0000001)); } } diff --git a/test/t/geom/test_projection.cpp b/test/t/geom/test_projection.cpp index 8d14ec598..2257d7f06 100644 --- a/test/t/geom/test_projection.cpp +++ b/test/t/geom/test_projection.cpp @@ -48,26 +48,26 @@ SECTION("project_location_3857") { { const osmium::Location loc(0.0, 0.0); const osmium::geom::Coordinates c {0.0, 0.0}; - REQUIRE(std::abs(projection(loc).x - c.x) < 0.1); - REQUIRE(std::abs(projection(loc).y - c.y) < 0.1); + REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1)); + REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1)); } { const osmium::Location loc(180.0, 0.0); const osmium::geom::Coordinates c {20037508.34, 0.0}; - REQUIRE(std::abs(projection(loc).x - c.x) < 0.1); - REQUIRE(std::abs(projection(loc).y - c.y) < 0.1); + REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1)); + REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1)); } { const osmium::Location loc(180.0, 0.0); const osmium::geom::Coordinates c {20037508.34, 0.0}; - REQUIRE(std::abs(projection(loc).x - c.x) < 0.1); - REQUIRE(std::abs(projection(loc).y - c.y) < 0.1); + REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1)); + REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1)); } { const osmium::Location loc(0.0, 85.0511288); const osmium::geom::Coordinates c {0.0, 20037508.34}; - REQUIRE(std::abs(projection(loc).x - c.x) < 0.1); - REQUIRE(std::abs(projection(loc).y - c.y) < 0.1); + REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1)); + REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1)); } } @@ -77,26 +77,26 @@ SECTION("project_location_mercator") { { const osmium::Location loc(0.0, 0.0); const osmium::geom::Coordinates c {0.0, 0.0}; - REQUIRE(std::abs(projection(loc).x - c.x) < 0.1); - REQUIRE(std::abs(projection(loc).y - c.y) < 0.1); + REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1)); + REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1)); } { const osmium::Location loc(180.0, 0.0); const osmium::geom::Coordinates c {20037508.34, 0.0}; - REQUIRE(std::abs(projection(loc).x - c.x) < 0.1); - REQUIRE(std::abs(projection(loc).y - c.y) < 0.1); + REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1)); + REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1)); } { const osmium::Location loc(180.0, 0.0); const osmium::geom::Coordinates c {20037508.34, 0.0}; - REQUIRE(std::abs(projection(loc).x - c.x) < 0.1); - REQUIRE(std::abs(projection(loc).y - c.y) < 0.1); + REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1)); + REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1)); } { const osmium::Location loc(0.0, 85.0511288); const osmium::geom::Coordinates c {0.0, 20037508.34}; - REQUIRE(std::abs(projection(loc).x - c.x) < 0.1); - REQUIRE(std::abs(projection(loc).y - c.y) < 0.1); + REQUIRE(projection(loc).x == Approx(c.x).epsilon(0.1)); + REQUIRE(projection(loc).y == Approx(c.y).epsilon(0.1)); } } @@ -108,23 +108,23 @@ SECTION("compare_mercators") { { const osmium::Location loc(4.2, 27.3); - REQUIRE(std::abs(projection_merc(loc).x - projection_3857(loc).x) < 0.1); - REQUIRE(std::abs(projection_merc(loc).y - projection_3857(loc).y) < 0.1); + 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(160.789, -42.42); - REQUIRE(std::abs(projection_merc(loc).x - projection_3857(loc).x) < 0.1); - REQUIRE(std::abs(projection_merc(loc).y - projection_3857(loc).y) < 0.1); + 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(std::abs(projection_merc(loc).x - projection_3857(loc).x) < 0.1); - REQUIRE(std::abs(projection_merc(loc).y - projection_3857(loc).y) < 0.1); + 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(std::abs(projection_merc(loc).x - projection_3857(loc).x) < 0.1); - REQUIRE(std::abs(projection_merc(loc).y - projection_3857(loc).y) < 0.1); + 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)); } } diff --git a/test/t/index/test_id_to_location.cpp b/test/t/index/test_id_to_location.cpp index 4f873e1a0..bc2ec446a 100644 --- a/test/t/index/test_id_to_location.cpp +++ b/test/t/index/test_id_to_location.cpp @@ -3,12 +3,17 @@ #include #include +#include +#include +#include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include + +#include template void test_func_all(TIndex& index) { @@ -67,8 +72,8 @@ SECTION("Dummy") { REQUIRE(0 == index1.used_memory()); } -SECTION("DenseMapMem") { - typedef osmium::index::map::DenseMapMem index_type; +SECTION("DenseMemArray") { + typedef osmium::index::map::DenseMemArray index_type; index_type index1; index1.reserve(1000); @@ -80,8 +85,8 @@ SECTION("DenseMapMem") { } #ifdef __linux__ -SECTION("DenseMapMmap") { - typedef osmium::index::map::DenseMapMmap index_type; +SECTION("DenseMmapArray") { + typedef osmium::index::map::DenseMmapArray index_type; index_type index1; test_func_all(index1); @@ -90,11 +95,11 @@ SECTION("DenseMapMmap") { test_func_real(index2); } #else -# pragma message "not running 'DenseMapMmap' test case on this machine" +# pragma message("not running 'DenseMapMmap' test case on this machine") #endif -SECTION("DenseMapFile") { - typedef osmium::index::map::DenseMapFile index_type; +SECTION("DenseFileArray") { + typedef osmium::index::map::DenseFileArray index_type; index_type index1; test_func_all(index1); @@ -103,8 +108,8 @@ SECTION("DenseMapFile") { test_func_real(index2); } -SECTION("SparseTable") { - typedef osmium::index::map::SparseTable index_type; +SECTION("SparseMemTable") { + typedef osmium::index::map::SparseMemTable index_type; index_type index1; test_func_all(index1); @@ -113,8 +118,8 @@ SECTION("SparseTable") { test_func_real(index2); } -SECTION("StlMap") { - typedef osmium::index::map::StlMap index_type; +SECTION("SparseMemMap") { + typedef osmium::index::map::SparseMemMap index_type; index_type index1; test_func_all(index1); @@ -123,8 +128,8 @@ SECTION("StlMap") { test_func_real(index2); } -SECTION("SparseMapMem") { - typedef osmium::index::map::SparseMapMem index_type; +SECTION("SparseMemArray") { + typedef osmium::index::map::SparseMemArray index_type; index_type index1; @@ -139,5 +144,23 @@ SECTION("SparseMapMem") { test_func_real(index2); } +SECTION("Dynamic map choice") { + typedef osmium::index::map::Map map_type; + const auto& map_factory = osmium::index::MapFactory::instance(); + + std::vector map_type_names = map_factory.map_types(); + REQUIRE(map_type_names.size() >= 5); + + for (const auto& map_type_name : map_type_names) { + std::unique_ptr index1 = map_factory.create_map(map_type_name); + index1->reserve(1000); + test_func_all(*index1); + + std::unique_ptr index2 = map_factory.create_map(map_type_name); + index2->reserve(1000); + test_func_real(*index2); + } +} + } diff --git a/test/t/index/test_typed_mmap.cpp b/test/t/index/test_typed_mmap.cpp index 90f8f6242..745535d95 100644 --- a/test/t/index/test_typed_mmap.cpp +++ b/test/t/index/test_typed_mmap.cpp @@ -48,7 +48,7 @@ SECTION("Remap") { REQUIRE(25ul == new_data[9]); } #else -# pragma message "not running 'Remap' test case on this machine" +# pragma message("not running 'Remap' test case on this machine") #endif SECTION("FileSize") { diff --git a/test/t/io/test_bzip2.cpp b/test/t/io/test_bzip2.cpp index 143f70d36..e6342e11d 100644 --- a/test/t/io/test_bzip2.cpp +++ b/test/t/io/test_bzip2.cpp @@ -1,4 +1,5 @@ #include "catch.hpp" +#include "utils.hpp" #include #include @@ -9,7 +10,9 @@ TEST_CASE("Bzip2") { SECTION("read_compressed_file") { - int fd = ::open("t/io/data_bzip2.txt.bz2", O_RDONLY); + std::string input_file = with_data_dir("t/io/data_bzip2.txt.bz2"); + + int fd = ::open(input_file.c_str(), O_RDONLY); REQUIRE(fd > 0); size_t size = 0; diff --git a/test/t/io/test_output_iterator.cpp b/test/t/io/test_output_iterator.cpp new file mode 100644 index 000000000..7a1f57027 --- /dev/null +++ b/test/t/io/test_output_iterator.cpp @@ -0,0 +1,37 @@ +#include "catch.hpp" + +#include +#include +#include + +TEST_CASE("output iterator") { + + SECTION("should be copy constructable") { + osmium::io::Header header; + osmium::io::Writer writer("test.osm", header, osmium::io::overwrite::allow); + osmium::io::OutputIterator out1(writer); + + osmium::io::OutputIterator out2(out1); + } + + SECTION("should be copy assignable") { + osmium::io::Header header; + osmium::io::Writer writer1("test1.osm", header, osmium::io::overwrite::allow); + osmium::io::Writer writer2("test2.osm", header, osmium::io::overwrite::allow); + + osmium::io::OutputIterator out1(writer1); + osmium::io::OutputIterator out2(writer2); + + out2 = out1; + } + + SECTION("should be incrementable") { + osmium::io::Header header; + osmium::io::Writer writer("test.osm", header, osmium::io::overwrite::allow); + osmium::io::OutputIterator out(writer); + + ++out; + } + +} + diff --git a/test/t/io/test_reader.cpp b/test/t/io/test_reader.cpp index 3be842b86..22f1aa24b 100644 --- a/test/t/io/test_reader.cpp +++ b/test/t/io/test_reader.cpp @@ -1,4 +1,5 @@ #include "catch.hpp" +#include "utils.hpp" #include #include @@ -19,7 +20,7 @@ struct CountHandler : public osmium::handler::Handler { TEST_CASE("Reader") { SECTION("reader can be initialized with file") { - osmium::io::File file("t/io/data.osm"); + osmium::io::File file(with_data_dir("t/io/data.osm")); osmium::io::Reader reader(file); osmium::handler::Handler handler; @@ -27,14 +28,14 @@ TEST_CASE("Reader") { } SECTION("reader can be initialized with string") { - osmium::io::Reader reader("t/io/data.osm"); + osmium::io::Reader reader(with_data_dir("t/io/data.osm")); osmium::handler::Handler handler; osmium::apply(reader, handler); } SECTION("should return invalid buffer after eof") { - osmium::io::File file("t/io/data.osm"); + osmium::io::File file(with_data_dir("t/io/data.osm")); osmium::io::Reader reader(file); REQUIRE(!reader.eof()); @@ -50,7 +51,7 @@ TEST_CASE("Reader") { } SECTION("should not hang when apply() is called twice on reader") { - osmium::io::File file("t/io/data.osm"); + osmium::io::File file(with_data_dir("t/io/data.osm")); osmium::io::Reader reader(file); osmium::handler::Handler handler; @@ -59,7 +60,7 @@ TEST_CASE("Reader") { } SECTION("should work with a buffer with uncompressed data") { - int fd = osmium::io::detail::open_for_reading("t/io/data.osm"); + int fd = osmium::io::detail::open_for_reading(with_data_dir("t/io/data.osm")); REQUIRE(fd >= 0); const size_t buffer_size = 1000; @@ -77,7 +78,7 @@ TEST_CASE("Reader") { } SECTION("should work with a buffer with gzip-compressed data") { - int fd = osmium::io::detail::open_for_reading("t/io/data.osm.gz"); + int fd = osmium::io::detail::open_for_reading(with_data_dir("t/io/data.osm.gz")); REQUIRE(fd >= 0); const size_t buffer_size = 1000; @@ -95,7 +96,7 @@ TEST_CASE("Reader") { } SECTION("should work with a buffer with bzip2-compressed data") { - int fd = osmium::io::detail::open_for_reading("t/io/data.osm.bz2"); + int fd = osmium::io::detail::open_for_reading(with_data_dir("t/io/data.osm.bz2")); REQUIRE(fd >= 0); const size_t buffer_size = 1000; diff --git a/test/valgrind.supp b/test/valgrind.supp index aa5024a82..f6ef1f65a 100644 --- a/test/valgrind.supp +++ b/test/valgrind.supp @@ -1,3 +1,12 @@ +#----------------------------------------------------------------------------- +# +# This file describes messages that Valgrind should suppress, because they +# are about problems outside Libosmium that we can't fix anyway. +# +# See http://valgrind.org/docs/manual/manual-core.html#manual-core.suppress +# +#----------------------------------------------------------------------------- + { dl_error1 Memcheck:Cond From 275ea9b0bba12d16444732268b595e74facc8019 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 5 Feb 2015 15:20:15 +0100 Subject: [PATCH 164/360] mark GetTravelModeForEdgeID as override final --- server/data_structures/internal_datafacade.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/data_structures/internal_datafacade.hpp b/server/data_structures/internal_datafacade.hpp index 1f4b6ef8c..446104cef 100644 --- a/server/data_structures/internal_datafacade.hpp +++ b/server/data_structures/internal_datafacade.hpp @@ -370,7 +370,10 @@ template class InternalDataFacade final : public BaseDataFacad return m_turn_instruction_list.at(id); } - TravelMode GetTravelModeForEdgeID(const unsigned id) const { return m_travel_mode_list.at(id); } + TravelMode GetTravelModeForEdgeID(const unsigned id) const override final + { + return m_travel_mode_list.at(id); + } bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate, FixedPointCoordinate &result, From 328a7caf61a02a2dc284f61686fd641732ba8867 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 5 Feb 2015 17:54:32 +0100 Subject: [PATCH 165/360] rename short variable names to be more telling --- contractor/edge_based_graph_factory.cpp | 38 ++++++++++++------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/contractor/edge_based_graph_factory.cpp b/contractor/edge_based_graph_factory.cpp index 4f50b77b5..337ce06cb 100644 --- a/contractor/edge_based_graph_factory.cpp +++ b/contractor/edge_based_graph_factory.cpp @@ -551,10 +551,10 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( Percent progress(m_node_based_graph->GetNumberOfNodes()); - for (const auto u : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes())) + for (const auto node_u : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes())) { - progress.printStatus(u); - for (const EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(u)) + progress.printStatus(node_u); + for (const EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(node_u)) { if (!m_node_based_graph->GetEdgeData(e1).forward) { @@ -562,21 +562,21 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( } ++node_based_edge_counter; - const NodeID v = m_node_based_graph->GetTarget(e1); + const NodeID node_v = m_node_based_graph->GetTarget(e1); const NodeID to_node_of_only_restriction = - m_restriction_map->CheckForEmanatingIsOnlyTurn(u, v); - const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end()); + m_restriction_map->CheckForEmanatingIsOnlyTurn(node_u, node_v); + const bool is_barrier_node = (m_barrier_nodes.find(node_v) != m_barrier_nodes.end()); - for (const EdgeID e2 : m_node_based_graph->GetAdjacentEdgeRange(v)) + for (const EdgeID e2 : m_node_based_graph->GetAdjacentEdgeRange(node_v)) { if (!m_node_based_graph->GetEdgeData(e2).forward) { continue; } - const NodeID w = m_node_based_graph->GetTarget(e2); + const NodeID node_w = m_node_based_graph->GetTarget(e2); if ((to_node_of_only_restriction != SPECIAL_NODEID) && - (w != to_node_of_only_restriction)) + (node_w != to_node_of_only_restriction)) { // We are at an only_-restriction but not at the right turn. ++restricted_turns_counter; @@ -585,7 +585,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( if (is_barrier_node) { - if (u != w) + if (node_u != node_w) { ++skipped_barrier_turns_counter; continue; @@ -593,7 +593,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( } else { - if ((u == w) && (m_node_based_graph->GetOutDegree(v) > 1)) + if ((node_u == node_w) && (m_node_based_graph->GetOutDegree(node_v) > 1)) { ++skipped_uturns_counter; continue; @@ -602,9 +602,9 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( // only add an edge if turn is not a U-turn except when it is // at the end of a dead-end street - if (m_restriction_map->CheckIfTurnIsRestricted(u, v, w) && + if (m_restriction_map->CheckIfTurnIsRestricted(node_u, node_v, node_w) && (to_node_of_only_restriction == SPECIAL_NODEID) && - (w != to_node_of_only_restriction)) + (node_w != to_node_of_only_restriction)) { // We are at an only_-restriction but not at the right turn. ++restricted_turns_counter; @@ -621,7 +621,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( // the following is the core of the loop. unsigned distance = edge_data1.distance; - if (m_traffic_lights.find(v) != m_traffic_lights.end()) + if (m_traffic_lights.find(node_v) != m_traffic_lights.end()) { distance += speed_profile.traffic_signal_penalty; } @@ -630,19 +630,19 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( const auto first_coordinate = m_node_info_list[(m_geometry_compressor.HasEntryForID(e1) ? m_geometry_compressor.GetLastNodeIDOfBucket(e1) - : u)]; + : node_u)]; // unpack first node of second segment if packed const auto third_coordinate = m_node_info_list[(m_geometry_compressor.HasEntryForID(e2) ? m_geometry_compressor.GetFirstNodeIDOfBucket(e2) - : w)]; + : node_w)]; const double turn_angle = ComputeAngle::OfThreeFixedPointCoordinates( - first_coordinate, m_node_info_list[v], third_coordinate); + first_coordinate, m_node_info_list[node_v], third_coordinate); const int turn_penalty = GetTurnPenalty(turn_angle, lua_state); - TurnInstruction turn_instruction = AnalyzeTurn(u, v, w, turn_angle); + TurnInstruction turn_instruction = AnalyzeTurn(node_u, node_v, node_w, turn_angle); if (turn_instruction == TurnInstruction::UTurn) { distance += speed_profile.u_turn_penalty; @@ -657,7 +657,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( } original_edge_data_vector.emplace_back( - (edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : v), + (edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : node_v), edge_data1.nameID, turn_instruction, edge_is_compressed, edge_data2.travel_mode); From 98f85d77281b029f977627a071ac240e48cbac33 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 5 Feb 2015 18:33:21 +0100 Subject: [PATCH 166/360] remove some lint in variable names --- contractor/edge_based_graph_factory.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contractor/edge_based_graph_factory.cpp b/contractor/edge_based_graph_factory.cpp index 337ce06cb..6485863d6 100644 --- a/contractor/edge_based_graph_factory.cpp +++ b/contractor/edge_based_graph_factory.cpp @@ -563,9 +563,9 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( ++node_based_edge_counter; const NodeID node_v = m_node_based_graph->GetTarget(e1); - const NodeID to_node_of_only_restriction = + const NodeID only_restriction_to_node = m_restriction_map->CheckForEmanatingIsOnlyTurn(node_u, node_v); - const bool is_barrier_node = (m_barrier_nodes.find(node_v) != m_barrier_nodes.end()); + const bool is_barrier_node = m_barrier_nodes.find(node_v) != m_barrier_nodes.end(); for (const EdgeID e2 : m_node_based_graph->GetAdjacentEdgeRange(node_v)) { @@ -575,8 +575,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( } const NodeID node_w = m_node_based_graph->GetTarget(e2); - if ((to_node_of_only_restriction != SPECIAL_NODEID) && - (node_w != to_node_of_only_restriction)) + if ((only_restriction_to_node != SPECIAL_NODEID) && + (node_w != only_restriction_to_node)) { // We are at an only_-restriction but not at the right turn. ++restricted_turns_counter; @@ -603,8 +603,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( // only add an edge if turn is not a U-turn except when it is // at the end of a dead-end street if (m_restriction_map->CheckIfTurnIsRestricted(node_u, node_v, node_w) && - (to_node_of_only_restriction == SPECIAL_NODEID) && - (node_w != to_node_of_only_restriction)) + (only_restriction_to_node == SPECIAL_NODEID) && + (node_w != only_restriction_to_node)) { // We are at an only_-restriction but not at the right turn. ++restricted_turns_counter; From b55d35c7bbb844f8967e8063565219a53c0546b3 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 6 Feb 2015 09:54:34 +0100 Subject: [PATCH 167/360] remove a number of useless parentheses --- contractor/edge_based_graph_factory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contractor/edge_based_graph_factory.cpp b/contractor/edge_based_graph_factory.cpp index 6485863d6..8de41b905 100644 --- a/contractor/edge_based_graph_factory.cpp +++ b/contractor/edge_based_graph_factory.cpp @@ -349,7 +349,7 @@ void EdgeBasedGraphFactory::CompressGeometry() BOOST_ASSERT(0 != forward_weight2); const bool add_traffic_signal_penalty = - (m_traffic_lights.find(node_v) != m_traffic_lights.end()); + m_traffic_lights.find(node_v) != m_traffic_lights.end(); // add weight of e2's to e1 m_node_based_graph->GetEdgeData(forward_e1).distance += fwd_edge_data2.distance; @@ -503,7 +503,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes() return component_explorer.get_component_id(node_v); }(); - const bool component_is_tiny = (size_of_component < 1000); + const bool component_is_tiny = size_of_component < 1000; if (edge_data.edgeBasedNodeID == SPECIAL_NODEID) { From 2a68f9f532e6bbf34738ad2c7c8cff7a4112f6e7 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 6 Feb 2015 11:58:41 +0100 Subject: [PATCH 168/360] rename variable name --- contractor/edge_based_graph_factory.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/contractor/edge_based_graph_factory.cpp b/contractor/edge_based_graph_factory.cpp index 8de41b905..c4dc81a5b 100644 --- a/contractor/edge_based_graph_factory.cpp +++ b/contractor/edge_based_graph_factory.cpp @@ -348,13 +348,12 @@ void EdgeBasedGraphFactory::CompressGeometry() BOOST_ASSERT(0 != reverse_weight1); BOOST_ASSERT(0 != forward_weight2); - const bool add_traffic_signal_penalty = - m_traffic_lights.find(node_v) != m_traffic_lights.end(); + const bool has_node_penalty = m_traffic_lights.find(node_v) != m_traffic_lights.end(); // add weight of e2's to e1 m_node_based_graph->GetEdgeData(forward_e1).distance += fwd_edge_data2.distance; m_node_based_graph->GetEdgeData(reverse_e1).distance += rev_edge_data2.distance; - if (add_traffic_signal_penalty) + if (has_node_penalty) { m_node_based_graph->GetEdgeData(forward_e1).distance += speed_profile.traffic_signal_penalty; @@ -382,13 +381,11 @@ void EdgeBasedGraphFactory::CompressGeometry() // store compressed geometry in container m_geometry_compressor.CompressEdge( forward_e1, forward_e2, node_v, node_w, - forward_weight1 + - (add_traffic_signal_penalty ? speed_profile.traffic_signal_penalty : 0), + forward_weight1 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0), forward_weight2); m_geometry_compressor.CompressEdge( reverse_e1, reverse_e2, node_v, node_u, reverse_weight1, - reverse_weight2 + - (add_traffic_signal_penalty ? speed_profile.traffic_signal_penalty : 0)); + reverse_weight2 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0)); ++removed_node_count; BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID == From 85d8e0ac2cee40d2d7f27bcd2c502ccee44fa912 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 9 Feb 2015 09:21:44 +0100 Subject: [PATCH 169/360] minor reformat --- descriptors/descriptor_base.hpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/descriptors/descriptor_base.hpp b/descriptors/descriptor_base.hpp index 8166afb7b..815b1d5af 100644 --- a/descriptors/descriptor_base.hpp +++ b/descriptors/descriptor_base.hpp @@ -52,18 +52,16 @@ struct DescriptorTable : public std::unordered_map } }; - struct DescriptorConfig { DescriptorConfig() : instructions(true), geometry(true), encode_geometry(true), zoom_level(18) { } - template - DescriptorConfig(const OtherT &other) : instructions(other.print_instructions), - geometry(other.geometry), - encode_geometry(other.compression), - zoom_level(other.zoom_level) + template + DescriptorConfig(const OtherT &other) + : instructions(other.print_instructions), geometry(other.geometry), + encode_geometry(other.compression), zoom_level(other.zoom_level) { BOOST_ASSERT(zoom_level >= 0); } @@ -80,8 +78,8 @@ template class BaseDescriptor BaseDescriptor() {} // Maybe someone can explain the pure virtual destructor thing to me (dennis) virtual ~BaseDescriptor() {} - virtual void Run(const InternalRouteResult &, JSON::Object &) = 0; - virtual void SetConfig(const DescriptorConfig &) = 0; + virtual void Run(const InternalRouteResult &raw_route, JSON::Object &json_result) = 0; + virtual void SetConfig(const DescriptorConfig &c) = 0; }; #endif // DESCRIPTOR_BASE_HPP From 97ed6a3a4ebbabf8f6800500d02855e801bef5a3 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 9 Feb 2015 14:06:14 +0100 Subject: [PATCH 170/360] remove method stubs --- server/data_structures/datafacade_base.hpp | 2 -- server/data_structures/internal_datafacade.hpp | 3 --- 2 files changed, 5 deletions(-) diff --git a/server/data_structures/datafacade_base.hpp b/server/data_structures/datafacade_base.hpp index 0dbeef4b6..deff7c6ab 100644 --- a/server/data_structures/datafacade_base.hpp +++ b/server/data_structures/datafacade_base.hpp @@ -62,8 +62,6 @@ template class BaseDataFacade virtual NodeID GetTarget(const EdgeID e) const = 0; - // virtual EdgeDataT &GetEdgeData(const EdgeID e) = 0; - virtual const EdgeDataT &GetEdgeData(const EdgeID e) const = 0; virtual EdgeID BeginEdges(const NodeID n) const = 0; diff --git a/server/data_structures/internal_datafacade.hpp b/server/data_structures/internal_datafacade.hpp index 446104cef..93b261e83 100644 --- a/server/data_structures/internal_datafacade.hpp +++ b/server/data_structures/internal_datafacade.hpp @@ -320,9 +320,6 @@ template class InternalDataFacade final : public BaseDataFacad NodeID GetTarget(const EdgeID e) const override final { return m_query_graph->GetTarget(e); } - // EdgeDataT &GetEdgeData(const EdgeID e) override final { return m_query_graph->GetEdgeData(e); - // } - EdgeDataT &GetEdgeData(const EdgeID e) const override final { return m_query_graph->GetEdgeData(e); From 3327c32b20b79c3f6479d252a3aa8a9e6e029260 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 9 Feb 2015 14:09:09 +0100 Subject: [PATCH 171/360] remove useless parantheses --- server/request_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/request_parser.cpp b/server/request_parser.cpp index 3f7fa8145..0e9ab442f 100644 --- a/server/request_parser.cpp +++ b/server/request_parser.cpp @@ -267,7 +267,7 @@ osrm::tribool RequestParser::consume(request ¤t_request, const char input) } return osrm::tribool::no; default: // expecting_newline_3 - return (input == '\n' ? osrm::tribool::yes : osrm::tribool::no); + return input == '\n' ? osrm::tribool::yes : osrm::tribool::no; } } From 86576768d1037624e71c33f18a40aed6ab4edb41 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 9 Feb 2015 15:19:19 +0100 Subject: [PATCH 172/360] remove manually add variant dir --- third_party/variant/.gitignore | 3 - third_party/variant/.travis.yml | 22 - third_party/variant/Jamroot | 61 - third_party/variant/LICENSE | 25 - third_party/variant/Makefile | 92 - third_party/variant/README.md | 66 - third_party/variant/appveyor.yml | 27 - third_party/variant/common.gypi | 143 - third_party/variant/optional.hpp | 69 - third_party/variant/recursive_wrapper.hpp | 127 - third_party/variant/scripts/linux.sh | 40 - third_party/variant/scripts/osx.sh | 20 - third_party/variant/test/bench_variant.cpp | 204 - .../variant/test/binary_visitor_test.cpp | 135 - .../test/boost_variant_hello_world.cpp | 19 - third_party/variant/test/catch.hpp | 8683 ----------------- third_party/variant/test/optional_unit.cpp | 82 - .../variant/test/recursive_wrapper_test.cpp | 132 - third_party/variant/test/unique_ptr_test.cpp | 128 - third_party/variant/test/unit.cpp | 306 - .../variant/test/variant_hello_world.cpp | 22 - third_party/variant/variant.gyp | 21 - third_party/variant/variant.hpp | 783 -- third_party/variant/vcbuild.bat | 8 - 24 files changed, 11218 deletions(-) delete mode 100644 third_party/variant/.gitignore delete mode 100644 third_party/variant/.travis.yml delete mode 100644 third_party/variant/Jamroot delete mode 100644 third_party/variant/LICENSE delete mode 100644 third_party/variant/Makefile delete mode 100644 third_party/variant/README.md delete mode 100644 third_party/variant/appveyor.yml delete mode 100644 third_party/variant/common.gypi delete mode 100644 third_party/variant/optional.hpp delete mode 100644 third_party/variant/recursive_wrapper.hpp delete mode 100644 third_party/variant/scripts/linux.sh delete mode 100644 third_party/variant/scripts/osx.sh delete mode 100644 third_party/variant/test/bench_variant.cpp delete mode 100644 third_party/variant/test/binary_visitor_test.cpp delete mode 100644 third_party/variant/test/boost_variant_hello_world.cpp delete mode 100644 third_party/variant/test/catch.hpp delete mode 100644 third_party/variant/test/optional_unit.cpp delete mode 100644 third_party/variant/test/recursive_wrapper_test.cpp delete mode 100644 third_party/variant/test/unique_ptr_test.cpp delete mode 100644 third_party/variant/test/unit.cpp delete mode 100644 third_party/variant/test/variant_hello_world.cpp delete mode 100644 third_party/variant/variant.gyp delete mode 100644 third_party/variant/variant.hpp delete mode 100644 third_party/variant/vcbuild.bat diff --git a/third_party/variant/.gitignore b/third_party/variant/.gitignore deleted file mode 100644 index 5620e5dd1..000000000 --- a/third_party/variant/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.DS_Store -out -profiling \ No newline at end of file diff --git a/third_party/variant/.travis.yml b/third_party/variant/.travis.yml deleted file mode 100644 index cd1e65578..000000000 --- a/third_party/variant/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -language: cpp - -# http://docs.travis-ci.com/user/multi-os/ -os: - - linux - - osx - -compiler: - - clang - - gcc - -before_install: - - true - -install: - - true - -before_script: - - true - -script: - - source "scripts/${TRAVIS_OS_NAME}.sh" diff --git a/third_party/variant/Jamroot b/third_party/variant/Jamroot deleted file mode 100644 index abf312b9c..000000000 --- a/third_party/variant/Jamroot +++ /dev/null @@ -1,61 +0,0 @@ -local BOOST_DIR = "/opt/boost" ; - -#using clang : : ; - -lib system : : boost_system $(BOOST_DIR)/lib ; -lib timer : chrono : boost_timer $(BOOST_DIR)/lib ; -lib chrono : system : boost_chrono $(BOOST_DIR)/lib ; - -exe variant-test - : - test/bench_variant.cpp - .//system - .//timer - .//chrono - : - $(BOOST_DIR)/include - ./ - -std=c++11 - #SINGLE_THREADED - release:-march=native - ; - - -exe binary-visitor-test - : - test/binary_visitor_test.cpp - .//system - .//timer - .//chrono - : - $(BOOST_DIR)/include - ./ - -std=c++11 - release:-march=native - ; - -exe recursive-wrapper-test - : - test/recursive_wrapper_test.cpp - .//system - .//timer - .//chrono - : - $(BOOST_DIR)/include - ./ - -std=c++11 - release:-march=native - ; - -exe unique-ptr-test - : - test/unique_ptr_test.cpp - .//system - .//timer - .//chrono - : - $(BOOST_DIR)/include - ./ - -std=c++11 - release:-march=native - ; diff --git a/third_party/variant/LICENSE b/third_party/variant/LICENSE deleted file mode 100644 index 6c4ce40d5..000000000 --- a/third_party/variant/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) MapBox -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -- Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -- Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. -- Neither the name "MapBox" nor the names of its contributors may be - used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/third_party/variant/Makefile b/third_party/variant/Makefile deleted file mode 100644 index 0eb20b628..000000000 --- a/third_party/variant/Makefile +++ /dev/null @@ -1,92 +0,0 @@ -CXX := $(CXX) -BOOST_LIBS = -lboost_timer -lboost_system -lboost_chrono -RELEASE_FLAGS = -O3 -DNDEBUG -finline-functions -march=native -DSINGLE_THREADED -DEBUG_FLAGS = -O0 -g -DDEBUG -fno-inline-functions -COMMON_FLAGS = -Wall -Wsign-compare -Wsign-conversion -Wshadow -Wunused-parameter -pedantic -fvisibility-inlines-hidden -std=c++11 -CXXFLAGS := $(CXXFLAGS) -LDFLAGS := $(LDFLAGS) - -OS:=$(shell uname -s) -ifeq ($(OS),Darwin) - CXXFLAGS += -stdlib=libc++ - LDFLAGS += -stdlib=libc++ -F/ -framework CoreFoundation -else - BOOST_LIBS += -lrt -endif - -ifeq (sizes,$(firstword $(MAKECMDGOALS))) - RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) - $(eval $(RUN_ARGS):;@:) - ifndef RUN_ARGS - $(error sizes target requires you pass full path to boost variant.hpp) - endif - .PHONY: $(RUN_ARGS) -endif - -all: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test - -./deps/gyp: - git clone --depth 1 https://chromium.googlesource.com/external/gyp.git ./deps/gyp - -gyp: ./deps/gyp - deps/gyp/gyp --depth=. -Goutput_dir=./ --generator-output=./out -f make - make V=1 -C ./out tests - ./out/Release/tests - -out/bench-variant-debug: Makefile test/bench_variant.cpp variant.hpp - mkdir -p ./out - $(CXX) -o out/bench-variant-debug test/bench_variant.cpp -I./ $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) - -out/bench-variant: Makefile test/bench_variant.cpp variant.hpp - mkdir -p ./out - $(CXX) -o out/bench-variant test/bench_variant.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) - -out/unique_ptr_test: Makefile test/unique_ptr_test.cpp variant.hpp - mkdir -p ./out - $(CXX) -o out/unique_ptr_test test/unique_ptr_test.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) - -out/recursive_wrapper_test: Makefile test/recursive_wrapper_test.cpp variant.hpp - mkdir -p ./out - $(CXX) -o out/recursive_wrapper_test test/recursive_wrapper_test.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) - -out/binary_visitor_test: Makefile test/binary_visitor_test.cpp variant.hpp - mkdir -p ./out - $(CXX) -o out/binary_visitor_test test/binary_visitor_test.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) - -bench: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test - ./out/bench-variant 100000 - ./out/unique_ptr_test 100000 - ./out/recursive_wrapper_test 100000 - ./out/binary_visitor_test 100000 - -out/unit: Makefile test/unit.cpp test/optional_unit.cpp optional.hpp variant.hpp - mkdir -p ./out - $(CXX) -o out/unit test/unit.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) - $(CXX) -o out/optional_unit test/optional_unit.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) - -test: out/unit - ./out/unit - ./out/optional_unit - -sizes: Makefile variant.hpp - mkdir -p ./out - @$(CXX) -o ./out/variant_hello_world.out variant.hpp $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/variant_hello_world.out - @$(CXX) -o ./out/boost_variant_hello_world.out $(RUN_ARGS) $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/boost_variant_hello_world.out - @$(CXX) -o ./out/variant_hello_world ./test/variant_hello_world.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/variant_hello_world - @$(CXX) -o ./out/boost_variant_hello_world ./test/boost_variant_hello_world.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/boost_variant_hello_world - -profile: out/bench-variant-debug - mkdir -p profiling/ - rm -rf profiling/* - iprofiler -timeprofiler -d profiling/ ./out/bench-variant-debug 500000 - -clean: - rm -rf ./out - rm -rf *.dSYM - -pgo: out Makefile variant.hpp - $(CXX) -o out/bench-variant test/bench_variant.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) -pg -fprofile-generate - ./test-variant 500000 >/dev/null 2>/dev/null - $(CXX) -o out/bench-variant test/bench_variant.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) -fprofile-use - -.PHONY: sizes test diff --git a/third_party/variant/README.md b/third_party/variant/README.md deleted file mode 100644 index 018163c1c..000000000 --- a/third_party/variant/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# Mapbox Variant - -An alternative to `boost::variant` for C++11. - -[![Build Status](https://secure.travis-ci.org/mapbox/variant.svg)](https://travis-ci.org/mapbox/variant) -[![Build status](https://ci.appveyor.com/api/projects/status/v9tatx21j1k0fcgy)](https://ci.appveyor.com/project/Mapbox/variant) - -# Why use Mapbox Variant? - -Mapbox variant has the same speedy performance of `boost::variant` but is faster to compile, results in smaller binaries, and has no dependencies. - -For example on OS X 10.9 with clang++ and libc++: - -Test | Mapbox Variant | Boost Variant ----- | -------------- | ------------- -Size of pre-compiled header (release / debug) | 2.8/2.8 MB | 12/15 MB -Size of simple program linking variant (release / debug) | 8/24 K | 12/40 K -Time to compile header | 185 ms | 675 ms - - -# Depends - - - Compiler supporting `-std=c++11` - -Tested with - - - g++-4.7 - - g++-4.8 - - clang++-3.4 - - clang++-3.5 - - Visual C++ Compiler November 2013 CTP - - Visual C++ Compiler 2014 CTP 4 - -Note: get the "2013 Nov CTP" release at http://www.microsoft.com/en-us/download/details.aspx?id=41151 and the 2014 CTP at http://www.visualstudio.com/en-us/downloads/visual-studio-14-ctp-vs.aspx - -# Usage - -There is nothing to build, just include `variant.hpp` and `recursive_wrapper.hpp` in your project. - -# Tests - -The tests depend on: - - - Boost headers (for benchmarking against `boost::variant`) - - Boost built with `--with-timer` (used for benchmark timing) - -On Unix systems set your boost includes and libs locations and run `make test`: - - export LDFLAGS='-L/opt/boost/lib' - export CXXFLAGS='-I/opt/boost/include' - make test - -On windows do: - - vcbuild - -## Benchmark - -On Unix systems run the benchmark like: - - make bench - -## Check object sizes - - make sizes /path/to/boost/variant.hpp - diff --git a/third_party/variant/appveyor.yml b/third_party/variant/appveyor.yml deleted file mode 100644 index 9d7c59984..000000000 --- a/third_party/variant/appveyor.yml +++ /dev/null @@ -1,27 +0,0 @@ - -platform: - - x64 - - x86 - -configuration: - - Debug - - Release - -install: - - SET PATH=c:\python27;%PATH% - - SET PATH=C:\Program Files (x86)\MSBuild\12.0\bin\;%PATH% - - git clone --quiet --depth 1 https://chromium.googlesource.com/external/gyp.git deps/gyp - # note windows requires --generator-output to be absolute - - python deps/gyp/gyp_main.py variant.gyp --depth=. -f msvs -G msvs_version=2013 - - set MSBUILD_PLATFORM=%platform% - - if "%MSBUILD_PLATFORM%" == "x86" set MSBUILD_PLATFORM=Win32 - - msbuild variant.sln /nologo /p:Configuration=%configuration%;Platform=%MSBUILD_PLATFORM% - - .\"%configuration%"\tests.exe - -build: OFF - -test: OFF - -test_script: OFF - -deploy: OFF diff --git a/third_party/variant/common.gypi b/third_party/variant/common.gypi deleted file mode 100644 index 67e333b7e..000000000 --- a/third_party/variant/common.gypi +++ /dev/null @@ -1,143 +0,0 @@ -{ - "conditions": [ - ["OS=='win'", { - "target_defaults": { - "default_configuration": "Release_x64", - "msbuild_toolset":"CTP_Nov2013", - "msvs_settings": { - "VCCLCompilerTool": { - "ExceptionHandling": 1, # /EHsc - "RuntimeTypeInfo": "true" # /GR - } - }, - "configurations": { - "Debug_Win32": { - "msvs_configuration_platform": "Win32", - "defines": [ "DEBUG","_DEBUG"], - "msvs_settings": { - "VCCLCompilerTool": { - "RuntimeLibrary": "1", # static debug /MTd - "Optimization": 0, # /Od, no optimization - "MinimalRebuild": "false", - "OmitFramePointers": "false", - "BasicRuntimeChecks": 3 # /RTC1 - } - } - }, - "Debug_x64": { - "msvs_configuration_platform": "x64", - "defines": [ "DEBUG","_DEBUG"], - "msvs_settings": { - "VCCLCompilerTool": { - "RuntimeLibrary": "1", # static debug /MTd - "Optimization": 0, # /Od, no optimization - "MinimalRebuild": "false", - "OmitFramePointers": "false", - "BasicRuntimeChecks": 3 # /RTC1 - } - } - }, - "Release_Win32": { - "msvs_configuration_platform": "Win32", - "defines": [ "NDEBUG"], - "msvs_settings": { - "VCCLCompilerTool": { - "RuntimeLibrary": 0, # static release - "Optimization": 3, # /Ox, full optimization - "FavorSizeOrSpeed": 1, # /Ot, favour speed over size - "InlineFunctionExpansion": 2, # /Ob2, inline anything eligible - "WholeProgramOptimization": "true", # /GL, whole program optimization, needed for LTCG - "OmitFramePointers": "true", - "EnableFunctionLevelLinking": "true", - "EnableIntrinsicFunctions": "true", - "AdditionalOptions": [ - "/MP", # compile across multiple CPUs - ], - "DebugInformationFormat": "0" - }, - "VCLibrarianTool": { - "AdditionalOptions": [ - "/LTCG" # link time code generation - ], - }, - "VCLinkerTool": { - "LinkTimeCodeGeneration": 1, # link-time code generation - "OptimizeReferences": 2, # /OPT:REF - "EnableCOMDATFolding": 2, # /OPT:ICF - "LinkIncremental": 1, # disable incremental linking - "GenerateDebugInformation": "false" - } - } - }, - "Release_x64": { - "msvs_configuration_platform": "x64", - "defines": [ "NDEBUG"], - "msvs_settings": { - "VCCLCompilerTool": { - "RuntimeLibrary": 0, # static release - "Optimization": 3, # /Ox, full optimization - "FavorSizeOrSpeed": 1, # /Ot, favour speed over size - "InlineFunctionExpansion": 2, # /Ob2, inline anything eligible - "WholeProgramOptimization": "true", # /GL, whole program optimization, needed for LTCG - "OmitFramePointers": "true", - "EnableFunctionLevelLinking": "true", - "EnableIntrinsicFunctions": "true", - "AdditionalOptions": [ - "/MP", # compile across multiple CPUs - ], - "DebugInformationFormat": "0" - }, - "VCLibrarianTool": { - "AdditionalOptions": [ - "/LTCG" # link time code generation - ], - }, - "VCLinkerTool": { - "LinkTimeCodeGeneration": 1, # link-time code generation - "OptimizeReferences": 2, # /OPT:REF - "EnableCOMDATFolding": 2, # /OPT:ICF - "LinkIncremental": 1, # disable incremental linking - "GenerateDebugInformation": "false" - } - } - } - } - } - }, { - "target_defaults": { - "default_configuration": "Release", - "xcode_settings": { - "CLANG_CXX_LIBRARY": "libc++", - "CLANG_CXX_LANGUAGE_STANDARD":"c++11", - "GCC_VERSION": "com.apple.compilers.llvm.clang.1_0", - }, - "cflags_cc": ["-std=c++11"], - "configurations": { - "Debug": { - "defines": [ - "DEBUG" - ], - "xcode_settings": { - "GCC_OPTIMIZATION_LEVEL": "0", - "GCC_GENERATE_DEBUGGING_SYMBOLS": "YES", - "OTHER_CPLUSPLUSFLAGS": [ "-Wall", "-Wextra", "-pedantic", "-g", "-O0" ] - } - }, - "Release": { - "defines": [ - "NDEBUG" - ], - "xcode_settings": { - "GCC_OPTIMIZATION_LEVEL": "3", - "GCC_GENERATE_DEBUGGING_SYMBOLS": "NO", - "DEAD_CODE_STRIPPING": "YES", - "GCC_INLINES_ARE_PRIVATE_EXTERN": "YES", - "OTHER_CPLUSPLUSFLAGS": [ "-Wall", "-Wextra", "-pedantic", "-O3" ] - } - } - } - } - }] - ] -} - diff --git a/third_party/variant/optional.hpp b/third_party/variant/optional.hpp deleted file mode 100644 index 133e2c8f9..000000000 --- a/third_party/variant/optional.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef MAPBOX_UTIL_OPTIONAL_HPP -#define MAPBOX_UTIL_OPTIONAL_HPP - -#include - -#include "variant.hpp" - -namespace mapbox -{ -namespace util -{ - -template class optional -{ - static_assert(!std::is_reference::value, "optional doesn't support references"); - - struct none_type - { - }; - - variant variant_; - - public: - optional() = default; - - optional(optional const &rhs) - { - if (this != &rhs) - { // protect against invalid self-assignment - variant_ = rhs.variant_; - } - } - - optional(T const &v) { variant_ = v; } - - explicit operator bool() const noexcept { return variant_.template is(); } - - T const &get() const { return variant_.template get(); } - T &get() { return variant_.template get(); } - - T const &operator*() const { return this->get(); } - T operator*() { return this->get(); } - - optional &operator=(T const &v) - { - variant_ = v; - return *this; - } - - optional &operator=(optional const &rhs) - { - if (this != &rhs) - { - variant_ = rhs.variant_; - } - return *this; - } - - template void emplace(Args &&... args) - { - variant_ = T{std::forward(args)...}; - } - - void reset() { variant_ = none_type{}; } -}; -} -} - -#endif diff --git a/third_party/variant/recursive_wrapper.hpp b/third_party/variant/recursive_wrapper.hpp deleted file mode 100644 index 54b27634a..000000000 --- a/third_party/variant/recursive_wrapper.hpp +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP -#define MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP - -#include - -namespace mapbox { namespace util { - -template -class recursive_wrapper -{ -public: - using type = T; -private: - - T* p_; - -public: - - ~recursive_wrapper(); - recursive_wrapper(); - - recursive_wrapper(recursive_wrapper const& operand); - recursive_wrapper(T const& operand); - recursive_wrapper(recursive_wrapper&& operand); - recursive_wrapper(T&& operand); - -private: - - void assign(const T& rhs); - -public: - - inline recursive_wrapper& operator=(recursive_wrapper const& rhs) - { - assign( rhs.get() ); - return *this; - } - - inline recursive_wrapper& operator=(T const& rhs) - { - assign( rhs ); - return *this; - } - - inline void swap(recursive_wrapper& operand) noexcept - { - T* temp = operand.p_; - operand.p_ = p_; - p_ = temp; - } - - - recursive_wrapper& operator=(recursive_wrapper&& rhs) noexcept - { - swap(rhs); - return *this; - } - - recursive_wrapper& operator=(T&& rhs) - { - get() = std::move(rhs); - return *this; - } - - -public: - - T& get() { return *get_pointer(); } - const T& get() const { return *get_pointer(); } - T* get_pointer() { return p_; } - const T* get_pointer() const { return p_; } - operator T const&() const { return this->get(); } - operator T&() { return this->get(); } -}; - -template -recursive_wrapper::~recursive_wrapper() -{ - delete p_; -} - -template -recursive_wrapper::recursive_wrapper() - : p_(new T) -{ -} - -template -recursive_wrapper::recursive_wrapper(recursive_wrapper const& operand) - : p_(new T( operand.get() )) -{ -} - -template -recursive_wrapper::recursive_wrapper(T const& operand) - : p_(new T(operand)) -{ -} - -template -recursive_wrapper::recursive_wrapper(recursive_wrapper&& operand) - : p_(operand.p_) -{ - operand.p_ = nullptr; -} - -template -recursive_wrapper::recursive_wrapper(T&& operand) - : p_(new T( std::move(operand) )) -{ -} - -template -void recursive_wrapper::assign(const T& rhs) -{ - this->get() = rhs; -} - -template -inline void swap(recursive_wrapper& lhs, recursive_wrapper& rhs) noexcept -{ - lhs.swap(rhs); -} - -}} - -#endif // MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP diff --git a/third_party/variant/scripts/linux.sh b/third_party/variant/scripts/linux.sh deleted file mode 100644 index 54215d934..000000000 --- a/third_party/variant/scripts/linux.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash - -set -e -u -set -o pipefail - -# ppa for latest boost -sudo add-apt-repository -y ppa:boost-latest/ppa -# ppa for g++ 4.7 and 4.8 -sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test -sudo apt-get update -y - -# install boost headers and g++ upgrades -sudo apt-get -y -qq install boost1.55 gcc-4.8 g++-4.8 gcc-4.7 g++-4.7 - -# run tests against g++ 4.7 -export CXX="g++-4.7"; export CC="gcc-4.7" -echo 'running tests against g++ 4.7' -make test -make bench -make clean - -# run tests against g++ 4.8 -export CXX="g++-4.8"; export CC="gcc-4.8" -echo 'running tests against g++ 4.8' -make test -make bench -make clean - -# compare object sizes against boost::variant -echo 'comparing object sizes to boost::variant' -make sizes /usr/include/boost/variant.hpp -make clean - -# test building with gyp -echo 'testing build with gyp' -make gyp - -# set strictness back to normal -# to avoid tripping up travis -set +e +u diff --git a/third_party/variant/scripts/osx.sh b/third_party/variant/scripts/osx.sh deleted file mode 100644 index 14149ca04..000000000 --- a/third_party/variant/scripts/osx.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash - -set -e -u -set -o pipefail - -# install boost headers -brew unlink boost -brew install boost - -# run tests -make test -make bench -make clean - -# compare object sizes against boost::variant -make sizes `brew --prefix`/include/boost/variant.hpp -make clean - -# test building with gyp -make gyp \ No newline at end of file diff --git a/third_party/variant/test/bench_variant.cpp b/third_party/variant/test/bench_variant.cpp deleted file mode 100644 index f27124593..000000000 --- a/third_party/variant/test/bench_variant.cpp +++ /dev/null @@ -1,204 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "variant.hpp" - -#define TEXT "Testing various variant implementations with a longish string ........................................." -//#define BOOST_VARIANT_MINIMIZE_SIZE - -using namespace mapbox; - -namespace test { - -template -struct Holder -{ - typedef V value_type; - std::vector data; - - template - void append_move(T && obj) - { - data.emplace_back(std::forward(obj)); - } - - template - void append(T const& obj) - { - data.push_back(obj); - } -}; - -} // namespace test - -struct print : util::static_visitor<> -{ - template - void operator() (T const& val) const - { - std::cerr << val << ":" << typeid(T).name() << std::endl; - } -}; - - -template -struct dummy : boost::static_visitor<> -{ - dummy(V & v) - : v_(v) {} - - template - void operator() (T const& val) const - { - v_ = val; - } - V & v_; -}; - -template -struct dummy2 : util::static_visitor<> -{ - dummy2(V & v) - : v_(v) {} - - template - void operator() (T const& val) const - { - v_.template set(val); - } - V & v_; -}; - -void run_boost_test(std::size_t runs) -{ - test::Holder> h; - h.data.reserve(runs); - for (std::size_t i=0; i< runs; ++i) - { - h.append_move(std::string(TEXT)); - h.append_move(123); - h.append_move(3.14159); - } - - boost::variant v; - for (auto const& v2 : h.data) - { - dummy> d(v); - boost::apply_visitor(d, v2); - } -} - -void run_variant_test(std::size_t runs) -{ - test::Holder> h; - h.data.reserve(runs); - for (std::size_t i=0; i< runs; ++i) - { - h.append_move(std::string(TEXT)); - h.append_move(123); - h.append_move(3.14159); - } - - util::variant v; - for (auto const& v2 : h.data) - { - dummy2> d(v); - util::apply_visitor (d, v2); - } -} - -int main (int argc, char** argv) -{ - if (argc!=2) - { - std::cerr << "Usage:" << argv[0] << " " << std::endl; - return 1; - } - -#ifndef SINGLE_THREADED - const std::size_t THREADS = 4; -#endif - const std::size_t NUM_RUNS = static_cast(std::stol(argv[1])); - -#ifdef SINGLE_THREADED - { - std::cerr << "custom variant: "; - boost::timer::auto_cpu_timer t; - run_variant_test(NUM_RUNS); - } - { - std::cerr << "boost variant: "; - boost::timer::auto_cpu_timer t; - run_boost_test(NUM_RUNS); - } - { - std::cerr << "custom variant: "; - boost::timer::auto_cpu_timer t; - run_variant_test(NUM_RUNS); - } - { - std::cerr << "boost variant: "; - boost::timer::auto_cpu_timer t; - run_boost_test(NUM_RUNS); - } -#else - { - typedef std::vector> thread_group; - typedef thread_group::value_type value_type; - thread_group tg; - std::cerr << "custom variant: "; - boost::timer::auto_cpu_timer timer; - for (std::size_t i=0; ijoinable()) t->join();}); - } - - { - typedef std::vector> thread_group; - typedef thread_group::value_type value_type; - thread_group tg; - std::cerr << "boost variant: "; - boost::timer::auto_cpu_timer timer; - for (std::size_t i=0; ijoinable()) t->join();}); - } - - { - typedef std::vector> thread_group; - typedef thread_group::value_type value_type; - thread_group tg; - std::cerr << "custom variant: "; - boost::timer::auto_cpu_timer timer; - for (std::size_t i=0; ijoinable()) t->join();}); - } - - { - typedef std::vector> thread_group; - typedef thread_group::value_type value_type; - thread_group tg; - std::cerr << "boost variant: "; - boost::timer::auto_cpu_timer timer; - for (std::size_t i=0; ijoinable()) t->join();}); - } -#endif - - - return EXIT_SUCCESS; -} diff --git a/third_party/variant/test/binary_visitor_test.cpp b/third_party/variant/test/binary_visitor_test.cpp deleted file mode 100644 index b1d3ab9f8..000000000 --- a/third_party/variant/test/binary_visitor_test.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "variant.hpp" - -using namespace mapbox; - -namespace test { - -template -struct string_to_number {}; - -template <> -struct string_to_number -{ - double operator() (std::string const& str) const - { - return std::stod(str); - } -}; - -template <> -struct string_to_number -{ - std::int64_t operator() (std::string const& str) const - { - return std::stoll(str); - } -}; - -template <> -struct string_to_number -{ - std::uint64_t operator() (std::string const& str) const - { - return std::stoull(str); - } -}; - -template <> -struct string_to_number -{ - bool operator() (std::string const& str) const - { - bool result; - std::istringstream(str) >> std::boolalpha >> result; - return result; - } -}; - -struct javascript_equal_visitor : util::static_visitor -{ - template - bool operator() (T lhs, T rhs) const - { - return lhs == rhs; - } - - template ::value>::type> - bool operator() (T lhs, std::string const& rhs) const - { - return lhs == string_to_number()(rhs); - } - - template ::value>::type> - bool operator() (std::string const& lhs, T rhs) const - { - return string_to_number()(lhs) == rhs; - } - - template - bool operator() (T0 lhs, T1 rhs) const - { - return lhs == static_cast(rhs); - } -}; - -template -struct javascript_equal -{ - javascript_equal(T const& lhs) - : lhs_(lhs) {} - - bool operator() (T const& rhs) const - { - return util::apply_visitor(test::javascript_equal_visitor(), lhs_, rhs); - } - T const& lhs_; -}; - -} // namespace test - -int main (/*int argc, char** argv*/) -{ - typedef util::variant variant_type; - variant_type v0(3.14159); - variant_type v1(std::string("3.14159")); - variant_type v2(std::uint64_t(1)); - - std::cerr << v0 << " == " << v1 << " -> " - << std::boolalpha << util::apply_visitor(test::javascript_equal_visitor(), v0, v1) << std::endl; - - - std::vector vec; - - vec.emplace_back(std::string("1")); - vec.push_back(variant_type(std::uint64_t(2))); - vec.push_back(variant_type(std::uint64_t(3))); - vec.push_back(std::string("3.14159")); - vec.emplace_back(3.14159); - - //auto itr = std::find_if(vec.begin(), vec.end(), [&v0](variant_type const& val) { - // return util::apply_visitor(test::javascript_equal_visitor(), v0, val); - // }); - - auto itr = std::find_if(vec.begin(), vec.end(), test::javascript_equal(v2)); - - if (itr != std::end(vec)) - { - std::cout << "found " << *itr << std::endl; - } - else - { - std::cout << "can't find " << v2 << '\n'; - } - - return EXIT_SUCCESS; -} diff --git a/third_party/variant/test/boost_variant_hello_world.cpp b/third_party/variant/test/boost_variant_hello_world.cpp deleted file mode 100644 index 0d0925a7e..000000000 --- a/third_party/variant/test/boost_variant_hello_world.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include -#include - -struct check : boost::static_visitor<> -{ - template - void operator() (T const& val) const - { - if (val != 0) throw std::runtime_error("invalid"); - } -}; - -int main() { - typedef boost::variant variant_type; - variant_type v(0); - boost::apply_visitor(check(), v); - return 0; -} diff --git a/third_party/variant/test/catch.hpp b/third_party/variant/test/catch.hpp deleted file mode 100644 index 057c82ee0..000000000 --- a/third_party/variant/test/catch.hpp +++ /dev/null @@ -1,8683 +0,0 @@ -/* - * CATCH v1.0 build 45 (master branch) - * Generated: 2014-05-19 18:22:42.461908 - * ---------------------------------------------------------- - * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. - * - * Distributed under the Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - */ -#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED - -#define TWOBLUECUBES_CATCH_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wglobal-constructors" -#pragma clang diagnostic ignored "-Wvariadic-macros" -#pragma clang diagnostic ignored "-Wc99-extensions" -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#pragma clang diagnostic ignored "-Wc++98-compat" -#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif - -#ifdef CATCH_CONFIG_MAIN -# define CATCH_CONFIG_RUNNER -#endif - -#ifdef CATCH_CONFIG_RUNNER -# ifndef CLARA_CONFIG_MAIN -# define CLARA_CONFIG_MAIN_NOT_DEFINED -# define CLARA_CONFIG_MAIN -# endif -#endif - -// #included from: internal/catch_notimplemented_exception.h -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED - -// #included from: catch_common.h -#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED - -#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line -#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) -#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) - -#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr -#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) - -#include -#include -#include - -// #included from: catch_compiler_capabilities.h -#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED - -// Much of the following code is based on Boost (1.53) - -#ifdef __clang__ - -# if __has_feature(cxx_nullptr) -# define CATCH_CONFIG_CPP11_NULLPTR -# endif - -# if __has_feature(cxx_noexcept) -# define CATCH_CONFIG_CPP11_NOEXCEPT -# endif - -#endif // __clang__ - -//////////////////////////////////////////////////////////////////////////////// -// Borland -#ifdef __BORLANDC__ - -#if (__BORLANDC__ > 0x582 ) -//#define CATCH_CONFIG_SFINAE // Not confirmed -#endif - -#endif // __BORLANDC__ - -//////////////////////////////////////////////////////////////////////////////// -// EDG -#ifdef __EDG_VERSION__ - -#if (__EDG_VERSION__ > 238 ) -//#define CATCH_CONFIG_SFINAE // Not confirmed -#endif - -#endif // __EDG_VERSION__ - -//////////////////////////////////////////////////////////////////////////////// -// Digital Mars -#ifdef __DMC__ - -#if (__DMC__ > 0x840 ) -//#define CATCH_CONFIG_SFINAE // Not confirmed -#endif - -#endif // __DMC__ - -//////////////////////////////////////////////////////////////////////////////// -// GCC -#ifdef __GNUC__ - -#if __GNUC__ < 3 - -#if (__GNUC_MINOR__ >= 96 ) -//#define CATCH_CONFIG_SFINAE -#endif - -#elif __GNUC__ >= 3 - -// #define CATCH_CONFIG_SFINAE // Taking this out completely for now - -#endif // __GNUC__ < 3 - -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) ) - -#define CATCH_CONFIG_CPP11_NULLPTR -#endif - -#endif // __GNUC__ - -//////////////////////////////////////////////////////////////////////////////// -// Visual C++ -#ifdef _MSC_VER - -#if (_MSC_VER >= 1310 ) // (VC++ 7.0+) -//#define CATCH_CONFIG_SFINAE // Not confirmed -#endif - -#endif // _MSC_VER - -// Use variadic macros if the compiler supports them -#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ - ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ - ( defined __GNUC__ && __GNUC__ >= 3 ) || \ - ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) - -#ifndef CATCH_CONFIG_NO_VARIADIC_MACROS -#define CATCH_CONFIG_VARIADIC_MACROS -#endif - -#endif - -//////////////////////////////////////////////////////////////////////////////// -// C++ language feature support - -// detect language version: -#if (__cplusplus == 201103L) -# define CATCH_CPP11 -# define CATCH_CPP11_OR_GREATER -#elif (__cplusplus >= 201103L) -# define CATCH_CPP11_OR_GREATER -#endif - -// noexcept support: -#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) -# define CATCH_NOEXCEPT noexcept -# define CATCH_NOEXCEPT_IS(x) noexcept(x) -#else -# define CATCH_NOEXCEPT throw() -# define CATCH_NOEXCEPT_IS(x) -#endif - -namespace Catch { - - class NonCopyable { - NonCopyable( NonCopyable const& ); - void operator = ( NonCopyable const& ); - protected: - NonCopyable() {} - virtual ~NonCopyable(); - }; - - class SafeBool { - public: - typedef void (SafeBool::*type)() const; - - static type makeSafe( bool value ) { - return value ? &SafeBool::trueValue : 0; - } - private: - void trueValue() const {} - }; - - template - inline void deleteAll( ContainerT& container ) { - typename ContainerT::const_iterator it = container.begin(); - typename ContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - delete *it; - } - template - inline void deleteAllValues( AssociativeContainerT& container ) { - typename AssociativeContainerT::const_iterator it = container.begin(); - typename AssociativeContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - delete it->second; - } - - bool startsWith( std::string const& s, std::string const& prefix ); - bool endsWith( std::string const& s, std::string const& suffix ); - bool contains( std::string const& s, std::string const& infix ); - void toLowerInPlace( std::string& s ); - std::string toLower( std::string const& s ); - std::string trim( std::string const& str ); - - struct pluralise { - pluralise( std::size_t count, std::string const& label ); - - friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); - - std::size_t m_count; - std::string m_label; - }; - - struct SourceLineInfo { - - SourceLineInfo(); - SourceLineInfo( char const* _file, std::size_t _line ); - SourceLineInfo( SourceLineInfo const& other ); -# ifdef CATCH_CPP11_OR_GREATER - SourceLineInfo( SourceLineInfo && ) = default; - SourceLineInfo& operator = ( SourceLineInfo const& ) = default; - SourceLineInfo& operator = ( SourceLineInfo && ) = default; -# endif - bool empty() const; - bool operator == ( SourceLineInfo const& other ) const; - - std::string file; - std::size_t line; - }; - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); - - // This is just here to avoid compiler warnings with macro constants and boolean literals - inline bool isTrue( bool value ){ return value; } - - void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); - - // Use this in variadic streaming macros to allow - // >> +StreamEndStop - // as well as - // >> stuff +StreamEndStop - struct StreamEndStop { - std::string operator+() { - return std::string(); - } - }; - template - T const& operator + ( T const& value, StreamEndStop ) { - return value; - } -} - -#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) -#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); - -#include - -namespace Catch { - - class NotImplementedException : public std::exception - { - public: - NotImplementedException( SourceLineInfo const& lineInfo ); - - virtual ~NotImplementedException() CATCH_NOEXCEPT {} - - virtual const char* what() const CATCH_NOEXCEPT; - - private: - std::string m_what; - SourceLineInfo m_lineInfo; - }; - -} // end namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) - -// #included from: internal/catch_context.h -#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED - -// #included from: catch_interfaces_generators.h -#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED - -#include - -namespace Catch { - - struct IGeneratorInfo { - virtual ~IGeneratorInfo(); - virtual bool moveNext() = 0; - virtual std::size_t getCurrentIndex() const = 0; - }; - - struct IGeneratorsForTest { - virtual ~IGeneratorsForTest(); - - virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; - virtual bool moveNext() = 0; - }; - - IGeneratorsForTest* createGeneratorsForTest(); - -} // end namespace Catch - -// #included from: catch_ptr.hpp -#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - - // An intrusive reference counting smart pointer. - // T must implement addRef() and release() methods - // typically implementing the IShared interface - template - class Ptr { - public: - Ptr() : m_p( NULL ){} - Ptr( T* p ) : m_p( p ){ - if( m_p ) - m_p->addRef(); - } - Ptr( Ptr const& other ) : m_p( other.m_p ){ - if( m_p ) - m_p->addRef(); - } - ~Ptr(){ - if( m_p ) - m_p->release(); - } - void reset() { - if( m_p ) - m_p->release(); - m_p = NULL; - } - Ptr& operator = ( T* p ){ - Ptr temp( p ); - swap( temp ); - return *this; - } - Ptr& operator = ( Ptr const& other ){ - Ptr temp( other ); - swap( temp ); - return *this; - } - void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } - T* get() { return m_p; } - const T* get() const{ return m_p; } - T& operator*() const { return *m_p; } - T* operator->() const { return m_p; } - bool operator !() const { return m_p == NULL; } - operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); } - - private: - T* m_p; - }; - - struct IShared : NonCopyable { - virtual ~IShared(); - virtual void addRef() const = 0; - virtual void release() const = 0; - }; - - template - struct SharedImpl : T { - - SharedImpl() : m_rc( 0 ){} - - virtual void addRef() const { - ++m_rc; - } - virtual void release() const { - if( --m_rc == 0 ) - delete this; - } - - mutable unsigned int m_rc; - }; - -} // end namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#include -#include -#include - -namespace Catch { - - class TestCase; - class Stream; - struct IResultCapture; - struct IRunner; - struct IGeneratorsForTest; - struct IConfig; - - struct IContext - { - virtual ~IContext(); - - virtual IResultCapture& getResultCapture() = 0; - virtual IRunner& getRunner() = 0; - virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; - virtual bool advanceGeneratorsForCurrentTest() = 0; - virtual Ptr getConfig() const = 0; - }; - - struct IMutableContext : IContext - { - virtual ~IMutableContext(); - virtual void setResultCapture( IResultCapture* resultCapture ) = 0; - virtual void setRunner( IRunner* runner ) = 0; - virtual void setConfig( Ptr const& config ) = 0; - }; - - IContext& getCurrentContext(); - IMutableContext& getCurrentMutableContext(); - void cleanUpContext(); - Stream createStream( std::string const& streamName ); - -} - -// #included from: internal/catch_test_registry.hpp -#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED - -// #included from: catch_interfaces_testcase.h -#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED - -#include - -namespace Catch { - - class TestSpec; - - struct ITestCase : IShared { - virtual void invoke () const = 0; - protected: - virtual ~ITestCase(); - }; - - class TestCase; - struct IConfig; - - struct ITestCaseRegistry { - virtual ~ITestCaseRegistry(); - virtual std::vector const& getAllTests() const = 0; - virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases ) const = 0; - - }; -} - -namespace Catch { - -template -class MethodTestCase : public SharedImpl { - -public: - MethodTestCase( void (C::*method)() ) : m_method( method ) {} - - virtual void invoke() const { - C obj; - (obj.*m_method)(); - } - -private: - virtual ~MethodTestCase() {} - - void (C::*m_method)(); -}; - -typedef void(*TestFunction)(); - -struct NameAndDesc { - NameAndDesc( const char* _name = "", const char* _description= "" ) - : name( _name ), description( _description ) - {} - - const char* name; - const char* description; -}; - -struct AutoReg { - - AutoReg( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ); - - template - AutoReg( void (C::*method)(), - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - registerTestCase( new MethodTestCase( method ), - className, - nameAndDesc, - lineInfo ); - } - - void registerTestCase( ITestCase* testCase, - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ); - - ~AutoReg(); - -private: - AutoReg( AutoReg const& ); - void operator= ( AutoReg const& ); -}; - -} // end namespace Catch - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TESTCASE( ... ) \ - static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ - static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\ - namespace{ \ - struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ - void test(); \ - }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ - } \ - void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() - -#else - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ - static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ - static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ - namespace{ \ - struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ - void test(); \ - }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ - } \ - void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() - -#endif - -// #included from: internal/catch_capture.hpp -#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED - -// #included from: catch_expression_decomposer.hpp -#define TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED - -// #included from: catch_expression_lhs.hpp -#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED - -// #included from: catch_expressionresult_builder.h -#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_BUILDER_H_INCLUDED - -// #included from: catch_tostring.h -#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED - -// #included from: catch_sfinae.hpp -#define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED - -// Try to detect if the current compiler supports SFINAE - -namespace Catch { - - struct TrueType { - static const bool value = true; - typedef void Enable; - char sizer[1]; - }; - struct FalseType { - static const bool value = false; - typedef void Disable; - char sizer[2]; - }; - -#ifdef CATCH_CONFIG_SFINAE - - template struct NotABooleanExpression; - - template struct If : NotABooleanExpression {}; - template<> struct If : TrueType {}; - template<> struct If : FalseType {}; - - template struct SizedIf; - template<> struct SizedIf : TrueType {}; - template<> struct SizedIf : FalseType {}; - -#endif // CATCH_CONFIG_SFINAE - -} // end namespace Catch - -#include -#include -#include -#include -#include - -#ifdef __OBJC__ -// #included from: catch_objc_arc.hpp -#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED - -#import - -#ifdef __has_feature -#define CATCH_ARC_ENABLED __has_feature(objc_arc) -#else -#define CATCH_ARC_ENABLED 0 -#endif - -void arcSafeRelease( NSObject* obj ); -id performOptionalSelector( id obj, SEL sel ); - -#if !CATCH_ARC_ENABLED -inline void arcSafeRelease( NSObject* obj ) { - [obj release]; -} -inline id performOptionalSelector( id obj, SEL sel ) { - if( [obj respondsToSelector: sel] ) - return [obj performSelector: sel]; - return nil; -} -#define CATCH_UNSAFE_UNRETAINED -#define CATCH_ARC_STRONG -#else -inline void arcSafeRelease( NSObject* ){} -inline id performOptionalSelector( id obj, SEL sel ) { -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" -#endif - if( [obj respondsToSelector: sel] ) - return [obj performSelector: sel]; -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - return nil; -} -#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained -#define CATCH_ARC_STRONG __strong -#endif - -#endif - -namespace Catch { -namespace Detail { - -// SFINAE is currently disabled by default for all compilers. -// If the non SFINAE version of IsStreamInsertable is ambiguous for you -// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE -#ifdef CATCH_CONFIG_SFINAE - - template - class IsStreamInsertableHelper { - template struct TrueIfSizeable : TrueType {}; - - template - static TrueIfSizeable dummy(T2*); - static FalseType dummy(...); - - public: - typedef SizedIf type; - }; - - template - struct IsStreamInsertable : IsStreamInsertableHelper::type {}; - -#else - - struct BorgType { - template BorgType( T const& ); - }; - - TrueType& testStreamable( std::ostream& ); - FalseType testStreamable( FalseType ); - - FalseType operator<<( std::ostream const&, BorgType const& ); - - template - struct IsStreamInsertable { - static std::ostream &s; - static T const&t; - enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; - }; - -#endif - - template - struct StringMakerBase { - template - static std::string convert( T const& ) { return "{?}"; } - }; - - template<> - struct StringMakerBase { - template - static std::string convert( T const& _value ) { - std::ostringstream oss; - oss << _value; - return oss.str(); - } - }; - - struct Endianness { - enum Arch { Big, Little }; - - static Arch which() { - union _{ - int asInt; - char asChar[sizeof (int)]; - } u; - - u.asInt = 1; - return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; - } - }; - - // Writes the raw memory into a string, considering endianness - template - std::string rawMemoryToString( T value ) { - union _ { - T typedValue; - unsigned char bytes[sizeof(T)]; - } u; - - u.typedValue = value; - - std::ostringstream oss; - oss << "0x"; - - int i = 0, end = sizeof(T), inc = 1; - if( Endianness::which() == Endianness::Little ) { - i = end-1; - end = inc = -1; - } - for( ; i != end; i += inc ) - oss << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)u.bytes[i]; - return oss.str(); - } - -} // end namespace Detail - -template -std::string toString( T const& value ); - -template -struct StringMaker : - Detail::StringMakerBase::value> {}; - -template -struct StringMaker { - template - static std::string convert( U* p ) { - if( !p ) - return INTERNAL_CATCH_STRINGIFY( NULL ); - else - return Detail::rawMemoryToString( p ); - } -}; - -template -struct StringMaker { - static std::string convert( R C::* p ) { - if( !p ) - return INTERNAL_CATCH_STRINGIFY( NULL ); - else - return Detail::rawMemoryToString( p ); - } -}; - -namespace Detail { - template - std::string rangeToString( InputIterator first, InputIterator last ); -} - -template -struct StringMaker > { - static std::string convert( std::vector const& v ) { - return Detail::rangeToString( v.begin(), v.end() ); - } -}; - -namespace Detail { - template - std::string makeString( T const& value ) { - return StringMaker::convert( value ); - } -} // end namespace Detail - -/// \brief converts any type to a string -/// -/// The default template forwards on to ostringstream - except when an -/// ostringstream overload does not exist - in which case it attempts to detect -/// that and writes {?}. -/// Overload (not specialise) this template for custom typs that you don't want -/// to provide an ostream overload for. -template -std::string toString( T const& value ) { - return StringMaker::convert( value ); -} - -// Built in overloads - -std::string toString( std::string const& value ); -std::string toString( std::wstring const& value ); -std::string toString( const char* const value ); -std::string toString( char* const value ); -std::string toString( int value ); -std::string toString( unsigned long value ); -std::string toString( unsigned int value ); -std::string toString( const double value ); -std::string toString( bool value ); -std::string toString( char value ); -std::string toString( signed char value ); -std::string toString( unsigned char value ); - -#ifdef CATCH_CONFIG_CPP11_NULLPTR -std::string toString( std::nullptr_t ); -#endif - -#ifdef __OBJC__ - std::string toString( NSString const * const& nsstring ); - std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); - std::string toString( NSObject* const& nsObject ); -#endif - - namespace Detail { - template - std::string rangeToString( InputIterator first, InputIterator last ) { - std::ostringstream oss; - oss << "{ "; - if( first != last ) { - oss << toString( *first ); - for( ++first ; first != last ; ++first ) { - oss << ", " << toString( *first ); - } - } - oss << " }"; - return oss.str(); - } -} - -} // end namespace Catch - -// #included from: catch_assertionresult.h -#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED - -#include -// #included from: catch_result_type.h -#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED - -namespace Catch { - - // ResultWas::OfType enum - struct ResultWas { enum OfType { - Unknown = -1, - Ok = 0, - Info = 1, - Warning = 2, - - FailureBit = 0x10, - - ExpressionFailed = FailureBit | 1, - ExplicitFailure = FailureBit | 2, - - Exception = 0x100 | FailureBit, - - ThrewException = Exception | 1, - DidntThrowException = Exception | 2 - - }; }; - - inline bool isOk( ResultWas::OfType resultType ) { - return ( resultType & ResultWas::FailureBit ) == 0; - } - inline bool isJustInfo( int flags ) { - return flags == ResultWas::Info; - } - - // ResultAction::Value enum - struct ResultAction { enum Value { - None, - Failed = 1, // Failure - but no debug break if Debug bit not set - Debug = 2, // If this bit is set, invoke the debugger - Abort = 4 // Test run should abort - }; }; - - // ResultDisposition::Flags enum - struct ResultDisposition { enum Flags { - Normal = 0x00, - - ContinueOnFailure = 0x01, // Failures fail test, but execution continues - NegateResult = 0x02, // Prefix expressiom with ! - SuppressFail = 0x04 // Failures are reported but do not fail the test - }; }; - - inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { - return static_cast( static_cast( lhs ) | static_cast( rhs ) ); - } - - inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } - inline bool shouldNegate( int flags ) { return ( flags & ResultDisposition::NegateResult ) != 0; } - inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } - -} // end namespace Catch - - -namespace Catch { - - struct AssertionInfo - { - AssertionInfo() {} - AssertionInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - std::string const& _capturedExpression, - ResultDisposition::Flags _resultDisposition ); - - std::string macroName; - SourceLineInfo lineInfo; - std::string capturedExpression; - ResultDisposition::Flags resultDisposition; - }; - - struct AssertionResultData - { - AssertionResultData() : resultType( ResultWas::Unknown ) {} - - std::string reconstructedExpression; - std::string message; - ResultWas::OfType resultType; - }; - - class AssertionResult { - public: - AssertionResult(); - AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); - ~AssertionResult(); -# ifdef CATCH_CPP11_OR_GREATER - AssertionResult( AssertionResult const& ) = default; - AssertionResult( AssertionResult && ) = default; - AssertionResult& operator = ( AssertionResult const& ) = default; - AssertionResult& operator = ( AssertionResult && ) = default; -# endif - - bool isOk() const; - bool succeeded() const; - ResultWas::OfType getResultType() const; - bool hasExpression() const; - bool hasMessage() const; - std::string getExpression() const; - std::string getExpressionInMacro() const; - bool hasExpandedExpression() const; - std::string getExpandedExpression() const; - std::string getMessage() const; - SourceLineInfo getSourceInfo() const; - std::string getTestMacroName() const; - - protected: - AssertionInfo m_info; - AssertionResultData m_resultData; - }; - -} // end namespace Catch - -// #included from: catch_evaluate.hpp -#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4389) // '==' : signed/unsigned mismatch -#endif - -#include - -namespace Catch { -namespace Internal { - - enum Operator { - IsEqualTo, - IsNotEqualTo, - IsLessThan, - IsGreaterThan, - IsLessThanOrEqualTo, - IsGreaterThanOrEqualTo - }; - - template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; - template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; - template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; - template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; - template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; - template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; - template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; - - template - inline T& opCast(T const& t) { return const_cast(t); } - -// nullptr_t support based on pull request #154 from Konstantin Baumann -#ifdef CATCH_CONFIG_CPP11_NULLPTR - inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } -#endif // CATCH_CONFIG_CPP11_NULLPTR - - // So the compare overloads can be operator agnostic we convey the operator as a template - // enum, which is used to specialise an Evaluator for doing the comparison. - template - class Evaluator{}; - - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs) { - return opCast( lhs ) == opCast( rhs ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) != opCast( rhs ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) < opCast( rhs ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) > opCast( rhs ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) >= opCast( rhs ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) <= opCast( rhs ); - } - }; - - template - bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { - return Evaluator::evaluate( lhs, rhs ); - } - - // This level of indirection allows us to specialise for integer types - // to avoid signed/ unsigned warnings - - // "base" overload - template - bool compare( T1 const& lhs, T2 const& rhs ) { - return Evaluator::evaluate( lhs, rhs ); - } - - // unsigned X to int - template bool compare( unsigned int lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned long lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned char lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - - // unsigned X to long - template bool compare( unsigned int lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned long lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned char lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - - // int to unsigned X - template bool compare( int lhs, unsigned int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( int lhs, unsigned long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( int lhs, unsigned char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // long to unsigned X - template bool compare( long lhs, unsigned int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long lhs, unsigned long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long lhs, unsigned char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // pointer to long (when comparing against NULL) - template bool compare( long lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); - } - template bool compare( T* lhs, long rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); - } - - // pointer to int (when comparing against NULL) - template bool compare( int lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); - } - template bool compare( T* lhs, int rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); - } - -#ifdef CATCH_CONFIG_CPP11_NULLPTR - // pointer to nullptr_t (when comparing against nullptr) - template bool compare( std::nullptr_t, T* rhs ) { - return Evaluator::evaluate( NULL, rhs ); - } - template bool compare( T* lhs, std::nullptr_t ) { - return Evaluator::evaluate( lhs, NULL ); - } -#endif // CATCH_CONFIG_CPP11_NULLPTR - -} // end of namespace Internal -} // end of namespace Catch - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -namespace Catch { - -struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; - -// Wraps the (stringised versions of) the lhs, operator and rhs of an expression - as well as -// the result of evaluating it. This is used to build an AssertionResult object -class ExpressionResultBuilder { -public: - - ExpressionResultBuilder( ResultWas::OfType resultType = ResultWas::Unknown ); - ExpressionResultBuilder( ExpressionResultBuilder const& other ); - ExpressionResultBuilder& operator=(ExpressionResultBuilder const& other ); - - ExpressionResultBuilder& setResultType( ResultWas::OfType result ); - ExpressionResultBuilder& setResultType( bool result ); - ExpressionResultBuilder& setLhs( std::string const& lhs ); - ExpressionResultBuilder& setRhs( std::string const& rhs ); - ExpressionResultBuilder& setOp( std::string const& op ); - - ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition ); - - template - ExpressionResultBuilder& operator << ( T const& value ) { - m_stream << value; - return *this; - } - - std::string reconstructExpression( AssertionInfo const& info ) const; - - AssertionResult buildResult( AssertionInfo const& info ) const; - - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); - -private: - AssertionResultData m_data; - struct ExprComponents { - ExprComponents() : shouldNegate( false ) {} - bool shouldNegate; - std::string lhs, rhs, op; - } m_exprComponents; - std::ostringstream m_stream; -}; - -} // end namespace Catch - -namespace Catch { - -// Wraps the LHS of an expression and captures the operator and RHS (if any) - -// wrapping them all in an ExpressionResultBuilder object -template -class ExpressionLhs { - ExpressionLhs& operator = ( ExpressionLhs const& ); -# ifdef CATCH_CPP11_OR_GREATER - ExpressionLhs& operator = ( ExpressionLhs && ) = delete; -# endif - -public: - ExpressionLhs( T lhs ) : m_lhs( lhs ) {} -# ifdef CATCH_CPP11_OR_GREATER - ExpressionLhs( ExpressionLhs const& ) = default; - ExpressionLhs( ExpressionLhs && ) = default; -# endif - - template - ExpressionResultBuilder& operator == ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - ExpressionResultBuilder& operator != ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - ExpressionResultBuilder& operator < ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - ExpressionResultBuilder& operator > ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - ExpressionResultBuilder& operator <= ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - ExpressionResultBuilder& operator >= ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - ExpressionResultBuilder& operator == ( bool rhs ) { - return captureExpression( rhs ); - } - - ExpressionResultBuilder& operator != ( bool rhs ) { - return captureExpression( rhs ); - } - - ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition ) { - bool value = m_lhs ? true : false; - return m_result - .setLhs( Catch::toString( value ) ) - .setResultType( value ) - .endExpression( resultDisposition ); - } - - // Only simple binary expressions are allowed on the LHS. - // If more complex compositions are required then place the sub expression in parentheses - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); - -private: - template - ExpressionResultBuilder& captureExpression( RhsT const& rhs ) { - return m_result - .setResultType( Internal::compare( m_lhs, rhs ) ) - .setLhs( Catch::toString( m_lhs ) ) - .setRhs( Catch::toString( rhs ) ) - .setOp( Internal::OperatorTraits::getName() ); - } - -private: - ExpressionResultBuilder m_result; - T m_lhs; -}; - -} // end namespace Catch - -namespace Catch { - -// Captures the LHS of the expression and wraps it in an Expression Lhs object -class ExpressionDecomposer { -public: - - template - ExpressionLhs operator->* ( T const& operand ) { - return ExpressionLhs( operand ); - } - - ExpressionLhs operator->* ( bool value ) { - return ExpressionLhs( value ); - } -}; - -} // end namespace Catch - -// #included from: catch_message.h -#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED - -#include - -namespace Catch { - - struct MessageInfo { - MessageInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ); - - std::string macroName; - SourceLineInfo lineInfo; - ResultWas::OfType type; - std::string message; - unsigned int sequence; - - bool operator == ( MessageInfo const& other ) const { - return sequence == other.sequence; - } - bool operator < ( MessageInfo const& other ) const { - return sequence < other.sequence; - } - private: - static unsigned int globalCount; - }; - - struct MessageBuilder { - MessageBuilder( std::string const& macroName, - SourceLineInfo const& lineInfo, - ResultWas::OfType type ) - : m_info( macroName, lineInfo, type ) - {} - - template - MessageBuilder& operator << ( T const& value ) { - m_stream << value; - return *this; - } - - MessageInfo m_info; - std::ostringstream m_stream; - }; - - class ScopedMessage { - public: - ScopedMessage( MessageBuilder const& builder ); - ~ScopedMessage(); - - MessageInfo m_info; - }; - -} // end namespace Catch - -// #included from: catch_interfaces_capture.h -#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED - -#include - -namespace Catch { - - class TestCase; - class ExpressionResultBuilder; - class AssertionResult; - struct AssertionInfo; - struct SectionInfo; - struct MessageInfo; - class ScopedMessageBuilder; - struct Counts; - - struct IResultCapture { - - virtual ~IResultCapture(); - - virtual void assertionEnded( AssertionResult const& result ) = 0; - virtual bool sectionStarted( SectionInfo const& sectionInfo, - Counts& assertions ) = 0; - virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0; - virtual void pushScopedMessage( MessageInfo const& message ) = 0; - virtual void popScopedMessage( MessageInfo const& message ) = 0; - - virtual bool shouldDebugBreak() const = 0; - - virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) = 0; - - virtual std::string getCurrentTestName() const = 0; - virtual const AssertionResult* getLastResult() const = 0; - }; -} - -// #included from: catch_debugger.h -#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED - -// #included from: catch_platform.h -#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED - -#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) -#define CATCH_PLATFORM_MAC -#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) -#define CATCH_PLATFORM_IPHONE -#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) -#define CATCH_PLATFORM_WINDOWS -#endif - -#include - -namespace Catch{ - - bool isDebuggerActive(); - void writeToDebugConsole( std::string const& text ); -} - -#ifdef CATCH_PLATFORM_MAC - - // The following code snippet based on: - // http://cocoawithlove.com/2008/03/break-into-debugger.html - #ifdef DEBUG - #if defined(__ppc64__) || defined(__ppc__) - #define CATCH_BREAK_INTO_DEBUGGER() \ - if( Catch::isDebuggerActive() ) { \ - __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ - : : : "memory","r0","r3","r4" ); \ - } - #else - #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} - #endif - #endif - -#elif defined(_MSC_VER) - #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } -#elif defined(__MINGW32__) - extern "C" __declspec(dllimport) void __stdcall DebugBreak(); - #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } -#endif - -#ifndef CATCH_BREAK_INTO_DEBUGGER -#define CATCH_BREAK_INTO_DEBUGGER() Catch::isTrue( true ); -#endif - -// #included from: catch_interfaces_registry_hub.h -#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED - -#include - -namespace Catch { - - class TestCase; - struct ITestCaseRegistry; - struct IExceptionTranslatorRegistry; - struct IExceptionTranslator; - struct IReporterRegistry; - struct IReporterFactory; - - struct IRegistryHub { - virtual ~IRegistryHub(); - - virtual IReporterRegistry const& getReporterRegistry() const = 0; - virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; - }; - - struct IMutableRegistryHub { - virtual ~IMutableRegistryHub(); - virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0; - virtual void registerTest( TestCase const& testInfo ) = 0; - virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; - }; - - IRegistryHub& getRegistryHub(); - IMutableRegistryHub& getMutableRegistryHub(); - void cleanUp(); - std::string translateActiveException(); - -} - -// #included from: catch_interfaces_config.h -#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED - -#include -#include -#include - -namespace Catch { - - struct Verbosity { enum Level { - NoOutput = 0, - Quiet, - Normal - }; }; - - struct WarnAbout { enum What { - Nothing = 0x00, - NoAssertions = 0x01 - }; }; - - struct ShowDurations { enum OrNot { - DefaultForReporter, - Always, - Never - }; }; - - class TestSpec; - - struct IConfig : IShared { - - virtual ~IConfig(); - - virtual bool allowThrows() const = 0; - virtual std::ostream& stream() const = 0; - virtual std::string name() const = 0; - virtual bool includeSuccessfulResults() const = 0; - virtual bool shouldDebugBreak() const = 0; - virtual bool warnAboutMissingAssertions() const = 0; - virtual int abortAfter() const = 0; - virtual bool showInvisibles() const = 0; - virtual ShowDurations::OrNot showDurations() const = 0; - virtual TestSpec const& testSpec() const = 0; - }; -} - -#include - -namespace Catch { - - inline IResultCapture& getResultCapture() { - return getCurrentContext().getResultCapture(); - } - - template - ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher, - std::string const& matcherCallAsString ) { - std::string matcherAsString = matcher.toString(); - if( matcherAsString == "{?}" ) - matcherAsString = matcherCallAsString; - return ExpressionResultBuilder() - .setRhs( matcherAsString ) - .setOp( "matches" ); - } - - template - ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher, - ArgT const& arg, - std::string const& matcherCallAsString ) { - return expressionResultBuilderFromMatcher( matcher, matcherCallAsString ) - .setLhs( Catch::toString( arg ) ) - .setResultType( matcher.match( arg ) ); - } - - template - ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher, - ArgT* arg, - std::string const& matcherCallAsString ) { - return expressionResultBuilderFromMatcher( matcher, matcherCallAsString ) - .setLhs( Catch::toString( arg ) ) - .setResultType( matcher.match( arg ) ); - } - -struct TestFailureException{}; - -} // end namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \ - if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, __assertionInfo ) ) { \ - if( internal_catch_action & Catch::ResultAction::Debug ) CATCH_BREAK_INTO_DEBUGGER(); \ - if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \ - if( !Catch::shouldContinueOnFailure( resultDisposition ) ) throw Catch::TestFailureException(); \ - Catch::isTrue( false && originalExpr ); \ - } - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ - do { \ - Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - try { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \ - } catch( Catch::TestFailureException& ) { \ - throw; \ - } catch( ... ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \ - Catch::ResultDisposition::Normal, expr ); \ - } \ - } while( Catch::isTrue( false ) ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ - INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ - if( Catch::getResultCapture().getLastResult()->succeeded() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ - INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ - if( !Catch::getResultCapture().getLastResult()->succeeded() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ - do { \ - Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - try { \ - expr; \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \ - } \ - catch( ... ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), resultDisposition, false ); \ - } \ -} while( Catch::isTrue( false ) ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ - try { \ - if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \ - expr; \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \ - } \ - } \ - catch( Catch::TestFailureException& ) { \ - throw; \ - } \ - catch( exceptionType ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \ - } - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \ - do { \ - Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ - } while( Catch::isTrue( false ) ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ - do { \ - Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ - catch( ... ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \ - resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \ - } \ - } while( Catch::isTrue( false ) ) - -/////////////////////////////////////////////////////////////////////////////// -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ - do { \ - Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << __VA_ARGS__ +::Catch::StreamEndStop(), resultDisposition, true ) \ - } while( Catch::isTrue( false ) ) -#else - #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ - do { \ - Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << log, resultDisposition, true ) \ - } while( Catch::isTrue( false ) ) -#endif - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_INFO( log, macroName ) \ - Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ - do { \ - Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \ - try { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \ - } catch( Catch::TestFailureException& ) { \ - throw; \ - } catch( ... ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \ - resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \ - } \ - } while( Catch::isTrue( false ) ) - -// #included from: internal/catch_section.h -#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED - -// #included from: catch_section_info.h -#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED - -namespace Catch { - - struct SectionInfo { - SectionInfo( std::string const& _name, - std::string const& _description, - SourceLineInfo const& _lineInfo ) - : name( _name ), - description( _description ), - lineInfo( _lineInfo ) - {} - - std::string name; - std::string description; - SourceLineInfo lineInfo; - }; - -} // end namespace Catch - -// #included from: catch_totals.hpp -#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED - -#include - -namespace Catch { - - struct Counts { - Counts() : passed( 0 ), failed( 0 ) {} - - Counts operator - ( Counts const& other ) const { - Counts diff; - diff.passed = passed - other.passed; - diff.failed = failed - other.failed; - return diff; - } - Counts& operator += ( Counts const& other ) { - passed += other.passed; - failed += other.failed; - return *this; - } - - std::size_t total() const { - return passed + failed; - } - - std::size_t passed; - std::size_t failed; - }; - - struct Totals { - - Totals operator - ( Totals const& other ) const { - Totals diff; - diff.assertions = assertions - other.assertions; - diff.testCases = testCases - other.testCases; - return diff; - } - - Totals delta( Totals const& prevTotals ) const { - Totals diff = *this - prevTotals; - if( diff.assertions.failed > 0 ) - ++diff.testCases.failed; - else - ++diff.testCases.passed; - return diff; - } - - Totals& operator += ( Totals const& other ) { - assertions += other.assertions; - testCases += other.testCases; - return *this; - } - - Counts assertions; - Counts testCases; - }; -} - -// #included from: catch_timer.h -#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED - -#ifdef CATCH_PLATFORM_WINDOWS -typedef unsigned long long uint64_t; -#else -#include -#endif - -namespace Catch { - - class Timer { - public: - Timer() : m_ticks( 0 ) {} - void start(); - unsigned int getElapsedNanoseconds() const; - unsigned int getElapsedMilliseconds() const; - double getElapsedSeconds() const; - - private: - uint64_t m_ticks; - }; - -} // namespace Catch - -#include - -namespace Catch { - - class Section { - public: - Section( SourceLineInfo const& lineInfo, - std::string const& name, - std::string const& description = "" ); - ~Section(); -# ifdef CATCH_CPP11_OR_GREATER - Section( Section const& ) = default; - Section( Section && ) = default; - Section& operator = ( Section const& ) = default; - Section& operator = ( Section && ) = default; -# endif - - // This indicates whether the section should be executed or not - operator bool(); - - private: - - SectionInfo m_info; - - std::string m_name; - Counts m_assertions; - bool m_sectionIncluded; - Timer m_timer; - }; - -} // end namespace Catch - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define INTERNAL_CATCH_SECTION( ... ) \ - if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) -#else - #define INTERNAL_CATCH_SECTION( name, desc ) \ - if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, name, desc ) ) -#endif - -// #included from: internal/catch_generators.hpp -#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED - -#include -#include -#include -#include - -namespace Catch { - -template -struct IGenerator { - virtual ~IGenerator() {} - virtual T getValue( std::size_t index ) const = 0; - virtual std::size_t size () const = 0; -}; - -template -class BetweenGenerator : public IGenerator { -public: - BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} - - virtual T getValue( std::size_t index ) const { - return m_from+static_cast( index ); - } - - virtual std::size_t size() const { - return static_cast( 1+m_to-m_from ); - } - -private: - - T m_from; - T m_to; -}; - -template -class ValuesGenerator : public IGenerator { -public: - ValuesGenerator(){} - - void add( T value ) { - m_values.push_back( value ); - } - - virtual T getValue( std::size_t index ) const { - return m_values[index]; - } - - virtual std::size_t size() const { - return m_values.size(); - } - -private: - std::vector m_values; -}; - -template -class CompositeGenerator { -public: - CompositeGenerator() : m_totalSize( 0 ) {} - - // *** Move semantics, similar to auto_ptr *** - CompositeGenerator( CompositeGenerator& other ) - : m_fileInfo( other.m_fileInfo ), - m_totalSize( 0 ) - { - move( other ); - } - - CompositeGenerator& setFileInfo( const char* fileInfo ) { - m_fileInfo = fileInfo; - return *this; - } - - ~CompositeGenerator() { - deleteAll( m_composed ); - } - - operator T () const { - size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); - - typename std::vector*>::const_iterator it = m_composed.begin(); - typename std::vector*>::const_iterator itEnd = m_composed.end(); - for( size_t index = 0; it != itEnd; ++it ) - { - const IGenerator* generator = *it; - if( overallIndex >= index && overallIndex < index + generator->size() ) - { - return generator->getValue( overallIndex-index ); - } - index += generator->size(); - } - CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); - return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so - } - - void add( const IGenerator* generator ) { - m_totalSize += generator->size(); - m_composed.push_back( generator ); - } - - CompositeGenerator& then( CompositeGenerator& other ) { - move( other ); - return *this; - } - - CompositeGenerator& then( T value ) { - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( value ); - add( valuesGen ); - return *this; - } - -private: - - void move( CompositeGenerator& other ) { - std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); - m_totalSize += other.m_totalSize; - other.m_composed.clear(); - } - - std::vector*> m_composed; - std::string m_fileInfo; - size_t m_totalSize; -}; - -namespace Generators -{ - template - CompositeGenerator between( T from, T to ) { - CompositeGenerator generators; - generators.add( new BetweenGenerator( from, to ) ); - return generators; - } - - template - CompositeGenerator values( T val1, T val2 ) { - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - generators.add( valuesGen ); - return generators; - } - - template - CompositeGenerator values( T val1, T val2, T val3 ){ - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - valuesGen->add( val3 ); - generators.add( valuesGen ); - return generators; - } - - template - CompositeGenerator values( T val1, T val2, T val3, T val4 ) { - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - valuesGen->add( val3 ); - valuesGen->add( val4 ); - generators.add( valuesGen ); - return generators; - } - -} // end namespace Generators - -using namespace Generators; - -} // end namespace Catch - -#define INTERNAL_CATCH_LINESTR2( line ) #line -#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) - -#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) - -// #included from: internal/catch_interfaces_exception.h -#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED - -#include - -namespace Catch { - - typedef std::string(*exceptionTranslateFunction)(); - - struct IExceptionTranslator { - virtual ~IExceptionTranslator(); - virtual std::string translate() const = 0; - }; - - struct IExceptionTranslatorRegistry { - virtual ~IExceptionTranslatorRegistry(); - - virtual std::string translateActiveException() const = 0; - }; - - class ExceptionTranslatorRegistrar { - template - class ExceptionTranslator : public IExceptionTranslator { - public: - - ExceptionTranslator( std::string(*translateFunction)( T& ) ) - : m_translateFunction( translateFunction ) - {} - - virtual std::string translate() const { - try { - throw; - } - catch( T& ex ) { - return m_translateFunction( ex ); - } - } - - protected: - std::string(*m_translateFunction)( T& ); - }; - - public: - template - ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { - getMutableRegistryHub().registerTranslator - ( new ExceptionTranslator( translateFunction ) ); - } - }; -} - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ - static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ - namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ - static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) - -// #included from: internal/catch_approx.hpp -#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED - -#include -#include - -namespace Catch { -namespace Detail { - - class Approx { - public: - explicit Approx ( double value ) - : m_epsilon( std::numeric_limits::epsilon()*100 ), - m_scale( 1.0 ), - m_value( value ) - {} - - Approx( Approx const& other ) - : m_epsilon( other.m_epsilon ), - m_scale( other.m_scale ), - m_value( other.m_value ) - {} - - static Approx custom() { - return Approx( 0 ); - } - - Approx operator()( double value ) { - Approx approx( value ); - approx.epsilon( m_epsilon ); - approx.scale( m_scale ); - return approx; - } - - friend bool operator == ( double lhs, Approx const& rhs ) { - // Thanks to Richard Harris for his help refining this formula - return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); - } - - friend bool operator == ( Approx const& lhs, double rhs ) { - return operator==( rhs, lhs ); - } - - friend bool operator != ( double lhs, Approx const& rhs ) { - return !operator==( lhs, rhs ); - } - - friend bool operator != ( Approx const& lhs, double rhs ) { - return !operator==( rhs, lhs ); - } - - Approx& epsilon( double newEpsilon ) { - m_epsilon = newEpsilon; - return *this; - } - - Approx& scale( double newScale ) { - m_scale = newScale; - return *this; - } - - std::string toString() const { - std::ostringstream oss; - oss << "Approx( " << Catch::toString( m_value ) << " )"; - return oss.str(); - } - - private: - double m_epsilon; - double m_scale; - double m_value; - }; -} - -template<> -inline std::string toString( Detail::Approx const& value ) { - return value.toString(); -} - -} // end namespace Catch - -// #included from: internal/catch_matchers.hpp -#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED - -namespace Catch { -namespace Matchers { - namespace Impl { - - template - struct Matcher : SharedImpl - { - typedef ExpressionT ExpressionType; - - virtual ~Matcher() {} - virtual Ptr clone() const = 0; - virtual bool match( ExpressionT const& expr ) const = 0; - virtual std::string toString() const = 0; - }; - - template - struct MatcherImpl : Matcher { - - virtual Ptr > clone() const { - return Ptr >( new DerivedT( static_cast( *this ) ) ); - } - }; - - namespace Generic { - - template - class AllOf : public MatcherImpl, ExpressionT> { - public: - - AllOf() {} - AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} - - AllOf& add( Matcher const& matcher ) { - m_matchers.push_back( matcher.clone() ); - return *this; - } - virtual bool match( ExpressionT const& expr ) const - { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) - if( !m_matchers[i]->match( expr ) ) - return false; - return true; - } - virtual std::string toString() const { - std::ostringstream oss; - oss << "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - oss << " and "; - oss << m_matchers[i]->toString(); - } - oss << " )"; - return oss.str(); - } - - private: - std::vector > > m_matchers; - }; - - template - class AnyOf : public MatcherImpl, ExpressionT> { - public: - - AnyOf() {} - AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} - - AnyOf& add( Matcher const& matcher ) { - m_matchers.push_back( matcher.clone() ); - return *this; - } - virtual bool match( ExpressionT const& expr ) const - { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) - if( m_matchers[i]->match( expr ) ) - return true; - return false; - } - virtual std::string toString() const { - std::ostringstream oss; - oss << "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - oss << " or "; - oss << m_matchers[i]->toString(); - } - oss << " )"; - return oss.str(); - } - - private: - std::vector > > m_matchers; - }; - - } - - namespace StdString { - - inline std::string makeString( std::string const& str ) { return str; } - inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } - - struct Equals : MatcherImpl { - Equals( std::string const& str ) : m_str( str ){} - Equals( Equals const& other ) : m_str( other.m_str ){} - - virtual ~Equals(); - - virtual bool match( std::string const& expr ) const { - return m_str == expr; - } - virtual std::string toString() const { - return "equals: \"" + m_str + "\""; - } - - std::string m_str; - }; - - struct Contains : MatcherImpl { - Contains( std::string const& substr ) : m_substr( substr ){} - Contains( Contains const& other ) : m_substr( other.m_substr ){} - - virtual ~Contains(); - - virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) != std::string::npos; - } - virtual std::string toString() const { - return "contains: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - - struct StartsWith : MatcherImpl { - StartsWith( std::string const& substr ) : m_substr( substr ){} - StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){} - - virtual ~StartsWith(); - - virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) == 0; - } - virtual std::string toString() const { - return "starts with: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - - struct EndsWith : MatcherImpl { - EndsWith( std::string const& substr ) : m_substr( substr ){} - EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){} - - virtual ~EndsWith(); - - virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) == expr.size() - m_substr.size(); - } - virtual std::string toString() const { - return "ends with: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - } // namespace StdString - } // namespace Impl - - // The following functions create the actual matcher objects. - // This allows the types to be inferred - template - inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, - Impl::Matcher const& m2 ) { - return Impl::Generic::AllOf().add( m1 ).add( m2 ); - } - template - inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, - Impl::Matcher const& m2, - Impl::Matcher const& m3 ) { - return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); - } - template - inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, - Impl::Matcher const& m2 ) { - return Impl::Generic::AnyOf().add( m1 ).add( m2 ); - } - template - inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, - Impl::Matcher const& m2, - Impl::Matcher const& m3 ) { - return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); - } - - inline Impl::StdString::Equals Equals( std::string const& str ) { - return Impl::StdString::Equals( str ); - } - inline Impl::StdString::Equals Equals( const char* str ) { - return Impl::StdString::Equals( Impl::StdString::makeString( str ) ); - } - inline Impl::StdString::Contains Contains( std::string const& substr ) { - return Impl::StdString::Contains( substr ); - } - inline Impl::StdString::Contains Contains( const char* substr ) { - return Impl::StdString::Contains( Impl::StdString::makeString( substr ) ); - } - inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { - return Impl::StdString::StartsWith( substr ); - } - inline Impl::StdString::StartsWith StartsWith( const char* substr ) { - return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); - } - inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { - return Impl::StdString::EndsWith( substr ); - } - inline Impl::StdString::EndsWith EndsWith( const char* substr ) { - return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); - } - -} // namespace Matchers - -using namespace Matchers; - -} // namespace Catch - -// These files are included here so the single_include script doesn't put them -// in the conditionally compiled sections -// #included from: internal/catch_test_case_info.h -#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED - -#include -#include - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - - struct ITestCase; - - struct TestCaseInfo { - TestCaseInfo( std::string const& _name, - std::string const& _className, - std::string const& _description, - std::set const& _tags, - bool _isHidden, - SourceLineInfo const& _lineInfo ); - - TestCaseInfo( TestCaseInfo const& other ); - - std::string name; - std::string className; - std::string description; - std::set tags; - std::string tagsAsString; - SourceLineInfo lineInfo; - bool isHidden; - bool throws; - }; - - class TestCase : public TestCaseInfo { - public: - - TestCase( ITestCase* testCase, TestCaseInfo const& info ); - TestCase( TestCase const& other ); - - TestCase withName( std::string const& _newName ) const; - - void invoke() const; - - TestCaseInfo const& getTestCaseInfo() const; - - bool isHidden() const; - bool throws() const; - - void swap( TestCase& other ); - bool operator == ( TestCase const& other ) const; - bool operator < ( TestCase const& other ) const; - TestCase& operator = ( TestCase const& other ); - - private: - Ptr test; - }; - - TestCase makeTestCase( ITestCase* testCase, - std::string const& className, - std::string const& name, - std::string const& description, - SourceLineInfo const& lineInfo ); -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -// #included from: internal/catch_interfaces_runner.h -#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED - -namespace Catch { - class TestCase; - - struct IRunner { - virtual ~IRunner(); - }; -} - - -#ifdef __OBJC__ -// #included from: internal/catch_objc.hpp -#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED - -#import - -#include - -// NB. Any general catch headers included here must be included -// in catch.hpp first to make sure they are included by the single -// header for non obj-usage - -/////////////////////////////////////////////////////////////////////////////// -// This protocol is really only here for (self) documenting purposes, since -// all its methods are optional. -@protocol OcFixture - -@optional - --(void) setUp; --(void) tearDown; - -@end - -namespace Catch { - - class OcMethod : public SharedImpl { - - public: - OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} - - virtual void invoke() const { - id obj = [[m_cls alloc] init]; - - performOptionalSelector( obj, @selector(setUp) ); - performOptionalSelector( obj, m_sel ); - performOptionalSelector( obj, @selector(tearDown) ); - - arcSafeRelease( obj ); - } - private: - virtual ~OcMethod() {} - - Class m_cls; - SEL m_sel; - }; - - namespace Detail{ - - inline std::string getAnnotation( Class cls, - std::string const& annotationName, - std::string const& testCaseName ) { - NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; - SEL sel = NSSelectorFromString( selStr ); - arcSafeRelease( selStr ); - id value = performOptionalSelector( cls, sel ); - if( value ) - return [(NSString*)value UTF8String]; - return ""; - } - } - - inline size_t registerTestMethods() { - size_t noTestMethods = 0; - int noClasses = objc_getClassList( NULL, 0 ); - - Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); - objc_getClassList( classes, noClasses ); - - for( int c = 0; c < noClasses; c++ ) { - Class cls = classes[c]; - { - u_int count; - Method* methods = class_copyMethodList( cls, &count ); - for( u_int m = 0; m < count ; m++ ) { - SEL selector = method_getName(methods[m]); - std::string methodName = sel_getName(selector); - if( startsWith( methodName, "Catch_TestCase_" ) ) { - std::string testCaseName = methodName.substr( 15 ); - std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); - std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); - const char* className = class_getName( cls ); - - getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); - noTestMethods++; - } - } - free(methods); - } - } - return noTestMethods; - } - - namespace Matchers { - namespace Impl { - namespace NSStringMatchers { - - template - struct StringHolder : MatcherImpl{ - StringHolder( NSString* substr ) : m_substr( [substr copy] ){} - StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} - StringHolder() { - arcSafeRelease( m_substr ); - } - - NSString* m_substr; - }; - - struct Equals : StringHolder { - Equals( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return (str != nil || m_substr == nil ) && - [str isEqualToString:m_substr]; - } - - virtual std::string toString() const { - return "equals string: \"" + Catch::toString( m_substr ) + "\""; - } - }; - - struct Contains : StringHolder { - Contains( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location != NSNotFound; - } - - virtual std::string toString() const { - return "contains string: \"" + Catch::toString( m_substr ) + "\""; - } - }; - - struct StartsWith : StringHolder { - StartsWith( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location == 0; - } - - virtual std::string toString() const { - return "starts with: \"" + Catch::toString( m_substr ) + "\""; - } - }; - struct EndsWith : StringHolder { - EndsWith( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location == [str length] - [m_substr length]; - } - - virtual std::string toString() const { - return "ends with: \"" + Catch::toString( m_substr ) + "\""; - } - }; - - } // namespace NSStringMatchers - } // namespace Impl - - inline Impl::NSStringMatchers::Equals - Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } - - inline Impl::NSStringMatchers::Contains - Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } - - inline Impl::NSStringMatchers::StartsWith - StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } - - inline Impl::NSStringMatchers::EndsWith - EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } - - } // namespace Matchers - - using namespace Matchers; - -} // namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define OC_TEST_CASE( name, desc )\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ -{\ -return @ name; \ -}\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ -{ \ -return @ desc; \ -} \ --(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) - -#endif - -#ifdef CATCH_CONFIG_RUNNER -// #included from: internal/catch_impl.hpp -#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED - -// Collect all the implementation files together here -// These are the equivalent of what would usually be cpp files - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wweak-vtables" -#endif - -// #included from: catch_runner.hpp -#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED - -// #included from: internal/catch_commandline.hpp -#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED - -// #included from: catch_config.hpp -#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED - -// #included from: catch_test_spec_parser.hpp -#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -// #included from: catch_test_spec.hpp -#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -#include -#include - -namespace Catch { - - class TestSpec { - struct Pattern : SharedImpl<> { - virtual ~Pattern(); - virtual bool matches( TestCaseInfo const& testCase ) const = 0; - }; - class NamePattern : public Pattern { - enum WildcardPosition { - NoWildcard = 0, - WildcardAtStart = 1, - WildcardAtEnd = 2, - WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd - }; - - public: - NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) { - if( startsWith( m_name, "*" ) ) { - m_name = m_name.substr( 1 ); - m_wildcard = WildcardAtStart; - } - if( endsWith( m_name, "*" ) ) { - m_name = m_name.substr( 0, m_name.size()-1 ); - m_wildcard = (WildcardPosition)( m_wildcard | WildcardAtEnd ); - } - } - virtual ~NamePattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { - switch( m_wildcard ) { - case NoWildcard: - return m_name == toLower( testCase.name ); - case WildcardAtStart: - return endsWith( toLower( testCase.name ), m_name ); - case WildcardAtEnd: - return startsWith( toLower( testCase.name ), m_name ); - case WildcardAtBothEnds: - return contains( toLower( testCase.name ), m_name ); - } - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunreachable-code" -#endif - throw std::logic_error( "Unknown enum" ); -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - } - private: - std::string m_name; - WildcardPosition m_wildcard; - }; - class TagPattern : public Pattern { - public: - TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} - virtual ~TagPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { - return testCase.tags.find( m_tag ) != testCase.tags.end(); - } - private: - std::string m_tag; - }; - class ExcludedPattern : public Pattern { - public: - ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} - virtual ~ExcludedPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } - private: - Ptr m_underlyingPattern; - }; - - struct Filter { - std::vector > m_patterns; - - bool matches( TestCaseInfo const& testCase ) const { - // All patterns in a filter must match for the filter to be a match - for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) - if( !(*it)->matches( testCase ) ) - return false; - return true; - } - }; - - public: - bool hasFilters() const { - return !m_filters.empty(); - } - bool matches( TestCaseInfo const& testCase ) const { - // A TestSpec matches if any filter matches - for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) - if( it->matches( testCase ) ) - return true; - return false; - } - - private: - std::vector m_filters; - - friend class TestSpecParser; - }; -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -namespace Catch { - - class TestSpecParser { - enum Mode{ None, Name, QuotedName, Tag }; - Mode m_mode; - bool m_exclusion; - std::size_t m_start, m_pos; - std::string m_arg; - TestSpec::Filter m_currentFilter; - TestSpec m_testSpec; - - public: - TestSpecParser parse( std::string const& arg ) { - m_mode = None; - m_exclusion = false; - m_start = std::string::npos; - m_arg = arg; - for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) - visitChar( m_arg[m_pos] ); - if( m_mode == Name ) - addPattern(); - addFilter(); - return *this; - } - TestSpec testSpec() { - return m_testSpec; - } - private: - void visitChar( char c ) { - if( m_mode == None ) { - switch( c ) { - case ' ': return; - case '~': m_exclusion = true; return; - case '[': return startNewMode( Tag, ++m_pos ); - case '"': return startNewMode( QuotedName, ++m_pos ); - default: startNewMode( Name, m_pos ); break; - } - } - if( m_mode == Name ) { - if( c == ',' ) { - addPattern(); - addFilter(); - } - else if( c == '[' ) { - if( subString() == "exclude:" ) - m_exclusion = true; - else - addPattern(); - startNewMode( Tag, ++m_pos ); - } - } - else if( m_mode == QuotedName && c == '"' ) - addPattern(); - else if( m_mode == Tag && c == ']' ) - addPattern(); - } - void startNewMode( Mode mode, std::size_t start ) { - m_mode = mode; - m_start = start; - } - std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } - template - void addPattern() { - std::string token = subString(); - if( startsWith( token, "exclude:" ) ) { - m_exclusion = true; - token = token.substr( 8 ); - } - if( !token.empty() ) { - Ptr pattern = new T( token ); - if( m_exclusion ) - pattern = new TestSpec::ExcludedPattern( pattern ); - m_currentFilter.m_patterns.push_back( pattern ); - } - m_exclusion = false; - m_mode = None; - } - void addFilter() { - if( !m_currentFilter.m_patterns.empty() ) { - m_testSpec.m_filters.push_back( m_currentFilter ); - m_currentFilter = TestSpec::Filter(); - } - } - }; - inline TestSpec parseTestSpec( std::string const& arg ) { - return TestSpecParser().parse( arg ).testSpec(); - } - -} // namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -// #included from: catch_stream.h -#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED - -#include - -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - - class Stream { - public: - Stream(); - Stream( std::streambuf* _streamBuf, bool _isOwned ); - void release(); - - std::streambuf* streamBuf; - - private: - bool isOwned; - }; -} - -#include -#include -#include -#include - -#ifndef CATCH_CONFIG_CONSOLE_WIDTH -#define CATCH_CONFIG_CONSOLE_WIDTH 80 -#endif - -namespace Catch { - - struct ConfigData { - - ConfigData() - : listTests( false ), - listTags( false ), - listReporters( false ), - listTestNamesOnly( false ), - showSuccessfulTests( false ), - shouldDebugBreak( false ), - noThrow( false ), - showHelp( false ), - showInvisibles( false ), - abortAfter( -1 ), - verbosity( Verbosity::Normal ), - warnings( WarnAbout::Nothing ), - showDurations( ShowDurations::DefaultForReporter ) - {} - - bool listTests; - bool listTags; - bool listReporters; - bool listTestNamesOnly; - - bool showSuccessfulTests; - bool shouldDebugBreak; - bool noThrow; - bool showHelp; - bool showInvisibles; - - int abortAfter; - - Verbosity::Level verbosity; - WarnAbout::What warnings; - ShowDurations::OrNot showDurations; - - std::string reporterName; - std::string outputFilename; - std::string name; - std::string processName; - - std::vector testsOrTags; - }; - - class Config : public SharedImpl { - private: - Config( Config const& other ); - Config& operator = ( Config const& other ); - virtual void dummy(); - public: - - Config() - : m_os( std::cout.rdbuf() ) - {} - - Config( ConfigData const& data ) - : m_data( data ), - m_os( std::cout.rdbuf() ) - { - if( !data.testsOrTags.empty() ) { - TestSpecParser parser; - for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) - parser.parse( data.testsOrTags[i] ); - m_testSpec = parser.testSpec(); - } - } - - virtual ~Config() { - m_os.rdbuf( std::cout.rdbuf() ); - m_stream.release(); - } - - void setFilename( std::string const& filename ) { - m_data.outputFilename = filename; - } - - std::string const& getFilename() const { - return m_data.outputFilename ; - } - - bool listTests() const { return m_data.listTests; } - bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } - bool listTags() const { return m_data.listTags; } - bool listReporters() const { return m_data.listReporters; } - - std::string getProcessName() const { return m_data.processName; } - - bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } - - void setStreamBuf( std::streambuf* buf ) { - m_os.rdbuf( buf ? buf : std::cout.rdbuf() ); - } - - void useStream( std::string const& streamName ) { - Stream stream = createStream( streamName ); - setStreamBuf( stream.streamBuf ); - m_stream.release(); - m_stream = stream; - } - - std::string getReporterName() const { return m_data.reporterName; } - - int abortAfter() const { return m_data.abortAfter; } - - TestSpec const& testSpec() const { return m_testSpec; } - - bool showHelp() const { return m_data.showHelp; } - bool showInvisibles() const { return m_data.showInvisibles; } - - // IConfig interface - virtual bool allowThrows() const { return !m_data.noThrow; } - virtual std::ostream& stream() const { return m_os; } - virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } - virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } - virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } - virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } - - private: - ConfigData m_data; - - Stream m_stream; - mutable std::ostream m_os; - TestSpec m_testSpec; - }; - -} // end namespace Catch - -// #included from: catch_clara.h -#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED - -// Use Catch's value for console width (store Clara's off to the side, if present) -#ifdef CLARA_CONFIG_CONSOLE_WIDTH -#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH -#undef CLARA_CONFIG_CONSOLE_WIDTH -#endif -#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - -// Declare Clara inside the Catch namespace -#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { -// #included from: ../external/clara.h - -// Only use header guard if we are not using an outer namespace -#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) - -#ifndef STITCH_CLARA_OPEN_NAMESPACE -#define TWOBLUECUBES_CLARA_H_INCLUDED -#define STITCH_CLARA_OPEN_NAMESPACE -#define STITCH_CLARA_CLOSE_NAMESPACE -#else -#define STITCH_CLARA_CLOSE_NAMESPACE } -#endif - -#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE - -// ----------- #included from tbc_text_format.h ----------- - -// Only use header guard if we are not using an outer namespace -#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) -#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -#define TBC_TEXT_FORMAT_H_INCLUDED -#endif - -#include -#include -#include - -// Use optional outer namespace -#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { -#endif - -namespace Tbc { - -#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH - const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - struct TextAttributes { - TextAttributes() - : initialIndent( std::string::npos ), - indent( 0 ), - width( consoleWidth-1 ), - tabChar( '\t' ) - {} - - TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } - TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } - TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } - TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } - - std::size_t initialIndent; // indent of first line, or npos - std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos - std::size_t width; // maximum width of text, including indent. Longer text will wrap - char tabChar; // If this char is seen the indent is changed to current pos - }; - - class Text { - public: - Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) - : attr( _attr ) - { - std::string wrappableChars = " [({.,/|\\-"; - std::size_t indent = _attr.initialIndent != std::string::npos - ? _attr.initialIndent - : _attr.indent; - std::string remainder = _str; - - while( !remainder.empty() ) { - if( lines.size() >= 1000 ) { - lines.push_back( "... message truncated due to excessive size" ); - return; - } - std::size_t tabPos = std::string::npos; - std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); - std::size_t pos = remainder.find_first_of( '\n' ); - if( pos <= width ) { - width = pos; - } - pos = remainder.find_last_of( _attr.tabChar, width ); - if( pos != std::string::npos ) { - tabPos = pos; - if( remainder[width] == '\n' ) - width--; - remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); - } - - if( width == remainder.size() ) { - spliceLine( indent, remainder, width ); - } - else if( remainder[width] == '\n' ) { - spliceLine( indent, remainder, width ); - if( width <= 1 || remainder.size() != 1 ) - remainder = remainder.substr( 1 ); - indent = _attr.indent; - } - else { - pos = remainder.find_last_of( wrappableChars, width ); - if( pos != std::string::npos && pos > 0 ) { - spliceLine( indent, remainder, pos ); - if( remainder[0] == ' ' ) - remainder = remainder.substr( 1 ); - } - else { - spliceLine( indent, remainder, width-1 ); - lines.back() += "-"; - } - if( lines.size() == 1 ) - indent = _attr.indent; - if( tabPos != std::string::npos ) - indent += tabPos; - } - } - } - - void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { - lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); - _remainder = _remainder.substr( _pos ); - } - - typedef std::vector::const_iterator const_iterator; - - const_iterator begin() const { return lines.begin(); } - const_iterator end() const { return lines.end(); } - std::string const& last() const { return lines.back(); } - std::size_t size() const { return lines.size(); } - std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } - std::string toString() const { - std::ostringstream oss; - oss << *this; - return oss.str(); - } - - inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { - for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); - it != itEnd; ++it ) { - if( it != _text.begin() ) - _stream << "\n"; - _stream << *it; - } - return _stream; - } - - private: - std::string str; - TextAttributes attr; - std::vector lines; - }; - -} // end namespace Tbc - -#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -} // end outer namespace -#endif - -#endif // TBC_TEXT_FORMAT_H_INCLUDED - -// ----------- end of #include from tbc_text_format.h ----------- -// ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h - -#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE - -#include -#include -#include -#include - -// Use optional outer namespace -#ifdef STITCH_CLARA_OPEN_NAMESPACE -STITCH_CLARA_OPEN_NAMESPACE -#endif - -namespace Clara { - - struct UnpositionalTag {}; - - extern UnpositionalTag _; - -#ifdef CLARA_CONFIG_MAIN - UnpositionalTag _; -#endif - - namespace Detail { - -#ifdef CLARA_CONSOLE_WIDTH - const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - using namespace Tbc; - - inline bool startsWith( std::string const& str, std::string const& prefix ) { - return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; - } - - template struct RemoveConstRef{ typedef T type; }; - template struct RemoveConstRef{ typedef T type; }; - template struct RemoveConstRef{ typedef T type; }; - template struct RemoveConstRef{ typedef T type; }; - - template struct IsBool { static const bool value = false; }; - template<> struct IsBool { static const bool value = true; }; - - template - void convertInto( std::string const& _source, T& _dest ) { - std::stringstream ss; - ss << _source; - ss >> _dest; - if( ss.fail() ) - throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); - } - inline void convertInto( std::string const& _source, std::string& _dest ) { - _dest = _source; - } - inline void convertInto( std::string const& _source, bool& _dest ) { - std::string sourceLC = _source; - std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower ); - if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) - _dest = true; - else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) - _dest = false; - else - throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); - } - inline void convertInto( bool _source, bool& _dest ) { - _dest = _source; - } - template - inline void convertInto( bool, T& ) { - throw std::runtime_error( "Invalid conversion" ); - } - - template - struct IArgFunction { - virtual ~IArgFunction() {} -# ifdef CATCH_CPP11_OR_GREATER - IArgFunction() = default; - IArgFunction( IArgFunction const& ) = default; -# endif - virtual void set( ConfigT& config, std::string const& value ) const = 0; - virtual void setFlag( ConfigT& config ) const = 0; - virtual bool takesArg() const = 0; - virtual IArgFunction* clone() const = 0; - }; - - template - class BoundArgFunction { - public: - BoundArgFunction() : functionObj( NULL ) {} - BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} - BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {} - BoundArgFunction& operator = ( BoundArgFunction const& other ) { - IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL; - delete functionObj; - functionObj = newFunctionObj; - return *this; - } - ~BoundArgFunction() { delete functionObj; } - - void set( ConfigT& config, std::string const& value ) const { - functionObj->set( config, value ); - } - void setFlag( ConfigT& config ) const { - functionObj->setFlag( config ); - } - bool takesArg() const { return functionObj->takesArg(); } - - bool isSet() const { - return functionObj != NULL; - } - private: - IArgFunction* functionObj; - }; - - template - struct NullBinder : IArgFunction{ - virtual void set( C&, std::string const& ) const {} - virtual void setFlag( C& ) const {} - virtual bool takesArg() const { return true; } - virtual IArgFunction* clone() const { return new NullBinder( *this ); } - }; - - template - struct BoundDataMember : IArgFunction{ - BoundDataMember( M C::* _member ) : member( _member ) {} - virtual void set( C& p, std::string const& stringValue ) const { - convertInto( stringValue, p.*member ); - } - virtual void setFlag( C& p ) const { - convertInto( true, p.*member ); - } - virtual bool takesArg() const { return !IsBool::value; } - virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } - M C::* member; - }; - template - struct BoundUnaryMethod : IArgFunction{ - BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} - virtual void set( C& p, std::string const& stringValue ) const { - typename RemoveConstRef::type value; - convertInto( stringValue, value ); - (p.*member)( value ); - } - virtual void setFlag( C& p ) const { - typename RemoveConstRef::type value; - convertInto( true, value ); - (p.*member)( value ); - } - virtual bool takesArg() const { return !IsBool::value; } - virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } - void (C::*member)( M ); - }; - template - struct BoundNullaryMethod : IArgFunction{ - BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} - virtual void set( C& p, std::string const& stringValue ) const { - bool value; - convertInto( stringValue, value ); - if( value ) - (p.*member)(); - } - virtual void setFlag( C& p ) const { - (p.*member)(); - } - virtual bool takesArg() const { return false; } - virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } - void (C::*member)(); - }; - - template - struct BoundUnaryFunction : IArgFunction{ - BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} - virtual void set( C& obj, std::string const& stringValue ) const { - bool value; - convertInto( stringValue, value ); - if( value ) - function( obj ); - } - virtual void setFlag( C& p ) const { - function( p ); - } - virtual bool takesArg() const { return false; } - virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } - void (*function)( C& ); - }; - - template - struct BoundBinaryFunction : IArgFunction{ - BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} - virtual void set( C& obj, std::string const& stringValue ) const { - typename RemoveConstRef::type value; - convertInto( stringValue, value ); - function( obj, value ); - } - virtual void setFlag( C& obj ) const { - typename RemoveConstRef::type value; - convertInto( true, value ); - function( obj, value ); - } - virtual bool takesArg() const { return !IsBool::value; } - virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } - void (*function)( C&, T ); - }; - - } // namespace Detail - - struct Parser { - Parser() : separators( " \t=:" ) {} - - struct Token { - enum Type { Positional, ShortOpt, LongOpt }; - Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} - Type type; - std::string data; - }; - - void parseIntoTokens( int argc, char const * const * argv, std::vector& tokens ) const { - const std::string doubleDash = "--"; - for( int i = 1; i < argc && argv[i] != doubleDash; ++i ) - parseIntoTokens( argv[i] , tokens); - } - void parseIntoTokens( std::string arg, std::vector& tokens ) const { - while( !arg.empty() ) { - Parser::Token token( Parser::Token::Positional, arg ); - arg = ""; - if( token.data[0] == '-' ) { - if( token.data.size() > 1 && token.data[1] == '-' ) { - token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) ); - } - else { - token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) ); - if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) { - arg = "-" + token.data.substr( 1 ); - token.data = token.data.substr( 0, 1 ); - } - } - } - if( token.type != Parser::Token::Positional ) { - std::size_t pos = token.data.find_first_of( separators ); - if( pos != std::string::npos ) { - arg = token.data.substr( pos+1 ); - token.data = token.data.substr( 0, pos ); - } - } - tokens.push_back( token ); - } - } - std::string separators; - }; - - template - struct CommonArgProperties { - CommonArgProperties() {} - CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} - - Detail::BoundArgFunction boundField; - std::string description; - std::string detail; - std::string placeholder; // Only value if boundField takes an arg - - bool takesArg() const { - return !placeholder.empty(); - } - void validate() const { - if( !boundField.isSet() ) - throw std::logic_error( "option not bound" ); - } - }; - struct OptionArgProperties { - std::vector shortNames; - std::string longName; - - bool hasShortName( std::string const& shortName ) const { - return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); - } - bool hasLongName( std::string const& _longName ) const { - return _longName == longName; - } - }; - struct PositionalArgProperties { - PositionalArgProperties() : position( -1 ) {} - int position; // -1 means non-positional (floating) - - bool isFixedPositional() const { - return position != -1; - } - }; - - template - class CommandLine { - - struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { - Arg() {} - Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} - - using CommonArgProperties::placeholder; // !TBD - - std::string dbgName() const { - if( !longName.empty() ) - return "--" + longName; - if( !shortNames.empty() ) - return "-" + shortNames[0]; - return "positional args"; - } - std::string commands() const { - std::ostringstream oss; - bool first = true; - std::vector::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); - for(; it != itEnd; ++it ) { - if( first ) - first = false; - else - oss << ", "; - oss << "-" << *it; - } - if( !longName.empty() ) { - if( !first ) - oss << ", "; - oss << "--" << longName; - } - if( !placeholder.empty() ) - oss << " <" << placeholder << ">"; - return oss.str(); - } - }; - - // NOTE: std::auto_ptr is deprecated in c++11/c++0x -#if defined(__cplusplus) && __cplusplus > 199711L - typedef std::unique_ptr ArgAutoPtr; -#else - typedef std::auto_ptr ArgAutoPtr; -#endif - - friend void addOptName( Arg& arg, std::string const& optName ) - { - if( optName.empty() ) - return; - if( Detail::startsWith( optName, "--" ) ) { - if( !arg.longName.empty() ) - throw std::logic_error( "Only one long opt may be specified. '" - + arg.longName - + "' already specified, now attempting to add '" - + optName + "'" ); - arg.longName = optName.substr( 2 ); - } - else if( Detail::startsWith( optName, "-" ) ) - arg.shortNames.push_back( optName.substr( 1 ) ); - else - throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); - } - friend void setPositionalArg( Arg& arg, int position ) - { - arg.position = position; - } - - class ArgBuilder { - public: - ArgBuilder( Arg* arg ) : m_arg( arg ) {} - - // Bind a non-boolean data member (requires placeholder string) - template - void bind( M C::* field, std::string const& placeholder ) { - m_arg->boundField = new Detail::BoundDataMember( field ); - m_arg->placeholder = placeholder; - } - // Bind a boolean data member (no placeholder required) - template - void bind( bool C::* field ) { - m_arg->boundField = new Detail::BoundDataMember( field ); - } - - // Bind a method taking a single, non-boolean argument (requires a placeholder string) - template - void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { - m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); - m_arg->placeholder = placeholder; - } - - // Bind a method taking a single, boolean argument (no placeholder string required) - template - void bind( void (C::* unaryMethod)( bool ) ) { - m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); - } - - // Bind a method that takes no arguments (will be called if opt is present) - template - void bind( void (C::* nullaryMethod)() ) { - m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); - } - - // Bind a free function taking a single argument - the object to operate on (no placeholder string required) - template - void bind( void (* unaryFunction)( C& ) ) { - m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); - } - - // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) - template - void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { - m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); - m_arg->placeholder = placeholder; - } - - ArgBuilder& describe( std::string const& description ) { - m_arg->description = description; - return *this; - } - ArgBuilder& detail( std::string const& detail ) { - m_arg->detail = detail; - return *this; - } - - protected: - Arg* m_arg; - }; - - class OptBuilder : public ArgBuilder { - public: - OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} - OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} - - OptBuilder& operator[]( std::string const& optName ) { - addOptName( *ArgBuilder::m_arg, optName ); - return *this; - } - }; - - public: - - CommandLine() - : m_boundProcessName( new Detail::NullBinder() ), - m_highestSpecifiedArgPosition( 0 ), - m_throwOnUnrecognisedTokens( false ) - {} - CommandLine( CommandLine const& other ) - : m_boundProcessName( other.m_boundProcessName ), - m_options ( other.m_options ), - m_positionalArgs( other.m_positionalArgs ), - m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), - m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) - { - if( other.m_floatingArg.get() ) - m_floatingArg = ArgAutoPtr( new Arg( *other.m_floatingArg ) ); - } - - CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { - m_throwOnUnrecognisedTokens = shouldThrow; - return *this; - } - - OptBuilder operator[]( std::string const& optName ) { - m_options.push_back( Arg() ); - addOptName( m_options.back(), optName ); - OptBuilder builder( &m_options.back() ); - return builder; - } - - ArgBuilder operator[]( int position ) { - m_positionalArgs.insert( std::make_pair( position, Arg() ) ); - if( position > m_highestSpecifiedArgPosition ) - m_highestSpecifiedArgPosition = position; - setPositionalArg( m_positionalArgs[position], position ); - ArgBuilder builder( &m_positionalArgs[position] ); - return builder; - } - - // Invoke this with the _ instance - ArgBuilder operator[]( UnpositionalTag ) { - if( m_floatingArg.get() ) - throw std::logic_error( "Only one unpositional argument can be added" ); - m_floatingArg = ArgAutoPtr( new Arg() ); - ArgBuilder builder( m_floatingArg.get() ); - return builder; - } - - template - void bindProcessName( M C::* field ) { - m_boundProcessName = new Detail::BoundDataMember( field ); - } - template - void bindProcessName( void (C::*_unaryMethod)( M ) ) { - m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); - } - - void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { - typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; - std::size_t maxWidth = 0; - for( it = itBegin; it != itEnd; ++it ) - maxWidth = (std::max)( maxWidth, it->commands().size() ); - - for( it = itBegin; it != itEnd; ++it ) { - Detail::Text usage( it->commands(), Detail::TextAttributes() - .setWidth( maxWidth+indent ) - .setIndent( indent ) ); - Detail::Text desc( it->description, Detail::TextAttributes() - .setWidth( width - maxWidth - 3 ) ); - - for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { - std::string usageCol = i < usage.size() ? usage[i] : ""; - os << usageCol; - - if( i < desc.size() && !desc[i].empty() ) - os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) - << desc[i]; - os << "\n"; - } - } - } - std::string optUsage() const { - std::ostringstream oss; - optUsage( oss ); - return oss.str(); - } - - void argSynopsis( std::ostream& os ) const { - for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { - if( i > 1 ) - os << " "; - typename std::map::const_iterator it = m_positionalArgs.find( i ); - if( it != m_positionalArgs.end() ) - os << "<" << it->second.placeholder << ">"; - else if( m_floatingArg.get() ) - os << "<" << m_floatingArg->placeholder << ">"; - else - throw std::logic_error( "non consecutive positional arguments with no floating args" ); - } - // !TBD No indication of mandatory args - if( m_floatingArg.get() ) { - if( m_highestSpecifiedArgPosition > 1 ) - os << " "; - os << "[<" << m_floatingArg->placeholder << "> ...]"; - } - } - std::string argSynopsis() const { - std::ostringstream oss; - argSynopsis( oss ); - return oss.str(); - } - - void usage( std::ostream& os, std::string const& procName ) const { - validate(); - os << "usage:\n " << procName << " "; - argSynopsis( os ); - if( !m_options.empty() ) { - os << " [options]\n\nwhere options are: \n"; - optUsage( os, 2 ); - } - os << "\n"; - } - std::string usage( std::string const& procName ) const { - std::ostringstream oss; - usage( oss, procName ); - return oss.str(); - } - - ConfigT parse( int argc, char const * const * argv ) const { - ConfigT config; - parseInto( argc, argv, config ); - return config; - } - - std::vector parseInto( int argc, char const * const * argv, ConfigT& config ) const { - std::string processName = argv[0]; - std::size_t lastSlash = processName.find_last_of( "/\\" ); - if( lastSlash != std::string::npos ) - processName = processName.substr( lastSlash+1 ); - m_boundProcessName.set( config, processName ); - std::vector tokens; - Parser parser; - parser.parseIntoTokens( argc, argv, tokens ); - return populate( tokens, config ); - } - - std::vector populate( std::vector const& tokens, ConfigT& config ) const { - validate(); - std::vector unusedTokens = populateOptions( tokens, config ); - unusedTokens = populateFixedArgs( unusedTokens, config ); - unusedTokens = populateFloatingArgs( unusedTokens, config ); - return unusedTokens; - } - - std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { - std::vector unusedTokens; - std::vector errors; - for( std::size_t i = 0; i < tokens.size(); ++i ) { - Parser::Token const& token = tokens[i]; - typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); - for(; it != itEnd; ++it ) { - Arg const& arg = *it; - - try { - if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || - ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { - if( arg.takesArg() ) { - if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) - errors.push_back( "Expected argument to option: " + token.data ); - else - arg.boundField.set( config, tokens[++i].data ); - } - else { - arg.boundField.setFlag( config ); - } - break; - } - } - catch( std::exception& ex ) { - errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); - } - } - if( it == itEnd ) { - if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) - unusedTokens.push_back( token ); - else if( m_throwOnUnrecognisedTokens ) - errors.push_back( "unrecognised option: " + token.data ); - } - } - if( !errors.empty() ) { - std::ostringstream oss; - for( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); - it != itEnd; - ++it ) { - if( it != errors.begin() ) - oss << "\n"; - oss << *it; - } - throw std::runtime_error( oss.str() ); - } - return unusedTokens; - } - std::vector populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { - std::vector unusedTokens; - int position = 1; - for( std::size_t i = 0; i < tokens.size(); ++i ) { - Parser::Token const& token = tokens[i]; - typename std::map::const_iterator it = m_positionalArgs.find( position ); - if( it != m_positionalArgs.end() ) - it->second.boundField.set( config, token.data ); - else - unusedTokens.push_back( token ); - if( token.type == Parser::Token::Positional ) - position++; - } - return unusedTokens; - } - std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { - if( !m_floatingArg.get() ) - return tokens; - std::vector unusedTokens; - for( std::size_t i = 0; i < tokens.size(); ++i ) { - Parser::Token const& token = tokens[i]; - if( token.type == Parser::Token::Positional ) - m_floatingArg->boundField.set( config, token.data ); - else - unusedTokens.push_back( token ); - } - return unusedTokens; - } - - void validate() const - { - if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) - throw std::logic_error( "No options or arguments specified" ); - - for( typename std::vector::const_iterator it = m_options.begin(), - itEnd = m_options.end(); - it != itEnd; ++it ) - it->validate(); - } - - private: - Detail::BoundArgFunction m_boundProcessName; - std::vector m_options; - std::map m_positionalArgs; - ArgAutoPtr m_floatingArg; - int m_highestSpecifiedArgPosition; - bool m_throwOnUnrecognisedTokens; - }; - -} // end namespace Clara - -STITCH_CLARA_CLOSE_NAMESPACE -#undef STITCH_CLARA_OPEN_NAMESPACE -#undef STITCH_CLARA_CLOSE_NAMESPACE - -#endif // TWOBLUECUBES_CLARA_H_INCLUDED -#undef STITCH_CLARA_OPEN_NAMESPACE - -// Restore Clara's value for console width, if present -#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#endif - -#include - -namespace Catch { - - inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } - inline void abortAfterX( ConfigData& config, int x ) { - if( x < 1 ) - throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); - config.abortAfter = x; - } - inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } - - inline void addWarning( ConfigData& config, std::string const& _warning ) { - if( _warning == "NoAssertions" ) - config.warnings = (WarnAbout::What)( config.warnings | WarnAbout::NoAssertions ); - else - throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); - - } - inline void setVerbosity( ConfigData& config, int level ) { - // !TBD: accept strings? - config.verbosity = (Verbosity::Level)level; - } - inline void setShowDurations( ConfigData& config, bool _showDurations ) { - config.showDurations = _showDurations - ? ShowDurations::Always - : ShowDurations::Never; - } - inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { - std::ifstream f( _filename.c_str() ); - if( !f.is_open() ) - throw std::domain_error( "Unable to load input file: " + _filename ); - - std::string line; - while( std::getline( f, line ) ) { - line = trim(line); - if( !line.empty() && !startsWith( line, "#" ) ) - addTestOrTags( config, "\"" + line + "\"" ); - } - } - - inline Clara::CommandLine makeCommandLineParser() { - - using namespace Clara; - CommandLine cli; - - cli.bindProcessName( &ConfigData::processName ); - - cli["-?"]["-h"]["--help"] - .describe( "display usage information" ) - .bind( &ConfigData::showHelp ); - - cli["-l"]["--list-tests"] - .describe( "list all/matching test cases" ) - .bind( &ConfigData::listTests ); - - cli["-t"]["--list-tags"] - .describe( "list all/matching tags" ) - .bind( &ConfigData::listTags ); - - cli["-s"]["--success"] - .describe( "include successful tests in output" ) - .bind( &ConfigData::showSuccessfulTests ); - - cli["-b"]["--break"] - .describe( "break into debugger on failure" ) - .bind( &ConfigData::shouldDebugBreak ); - - cli["-e"]["--nothrow"] - .describe( "skip exception tests" ) - .bind( &ConfigData::noThrow ); - - cli["-i"]["--invisibles"] - .describe( "show invisibles (tabs, newlines)" ) - .bind( &ConfigData::showInvisibles ); - - cli["-o"]["--out"] - .describe( "output filename" ) - .bind( &ConfigData::outputFilename, "filename" ); - - cli["-r"]["--reporter"] -// .placeholder( "name[:filename]" ) - .describe( "reporter to use (defaults to console)" ) - .bind( &ConfigData::reporterName, "name" ); - - cli["-n"]["--name"] - .describe( "suite name" ) - .bind( &ConfigData::name, "name" ); - - cli["-a"]["--abort"] - .describe( "abort at first failure" ) - .bind( &abortAfterFirst ); - - cli["-x"]["--abortx"] - .describe( "abort after x failures" ) - .bind( &abortAfterX, "no. failures" ); - - cli["-w"]["--warn"] - .describe( "enable warnings" ) - .bind( &addWarning, "warning name" ); - -// - needs updating if reinstated -// cli.into( &setVerbosity ) -// .describe( "level of verbosity (0=no output)" ) -// .shortOpt( "v") -// .longOpt( "verbosity" ) -// .placeholder( "level" ); - - cli[_] - .describe( "which test or tests to use" ) - .bind( &addTestOrTags, "test name, pattern or tags" ); - - cli["-d"]["--durations"] - .describe( "show test durations" ) - .bind( &setShowDurations, "yes/no" ); - - cli["-f"]["--input-file"] - .describe( "load test names to run from a file" ) - .bind( &loadTestNamesFromFile, "filename" ); - - // Less common commands which don't have a short form - cli["--list-test-names-only"] - .describe( "list all/matching test cases names only" ) - .bind( &ConfigData::listTestNamesOnly ); - - cli["--list-reporters"] - .describe( "list all reporters" ) - .bind( &ConfigData::listReporters ); - - return cli; - } - -} // end namespace Catch - -// #included from: internal/catch_list.hpp -#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED - -// #included from: catch_text.h -#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED - -#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - -#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch -// #included from: ../external/tbc_text_format.h -// Only use header guard if we are not using an outer namespace -#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED -# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -# endif -# else -# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED -# endif -#endif -#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -#include -#include -#include - -// Use optional outer namespace -#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { -#endif - -namespace Tbc { - -#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH - const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - struct TextAttributes { - TextAttributes() - : initialIndent( std::string::npos ), - indent( 0 ), - width( consoleWidth-1 ), - tabChar( '\t' ) - {} - - TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } - TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } - TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } - TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } - - std::size_t initialIndent; // indent of first line, or npos - std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos - std::size_t width; // maximum width of text, including indent. Longer text will wrap - char tabChar; // If this char is seen the indent is changed to current pos - }; - - class Text { - public: - Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) - : attr( _attr ) - { - std::string wrappableChars = " [({.,/|\\-"; - std::size_t indent = _attr.initialIndent != std::string::npos - ? _attr.initialIndent - : _attr.indent; - std::string remainder = _str; - - while( !remainder.empty() ) { - if( lines.size() >= 1000 ) { - lines.push_back( "... message truncated due to excessive size" ); - return; - } - std::size_t tabPos = std::string::npos; - std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); - std::size_t pos = remainder.find_first_of( '\n' ); - if( pos <= width ) { - width = pos; - } - pos = remainder.find_last_of( _attr.tabChar, width ); - if( pos != std::string::npos ) { - tabPos = pos; - if( remainder[width] == '\n' ) - width--; - remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); - } - - if( width == remainder.size() ) { - spliceLine( indent, remainder, width ); - } - else if( remainder[width] == '\n' ) { - spliceLine( indent, remainder, width ); - if( width <= 1 || remainder.size() != 1 ) - remainder = remainder.substr( 1 ); - indent = _attr.indent; - } - else { - pos = remainder.find_last_of( wrappableChars, width ); - if( pos != std::string::npos && pos > 0 ) { - spliceLine( indent, remainder, pos ); - if( remainder[0] == ' ' ) - remainder = remainder.substr( 1 ); - } - else { - spliceLine( indent, remainder, width-1 ); - lines.back() += "-"; - } - if( lines.size() == 1 ) - indent = _attr.indent; - if( tabPos != std::string::npos ) - indent += tabPos; - } - } - } - - void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { - lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); - _remainder = _remainder.substr( _pos ); - } - - typedef std::vector::const_iterator const_iterator; - - const_iterator begin() const { return lines.begin(); } - const_iterator end() const { return lines.end(); } - std::string const& last() const { return lines.back(); } - std::size_t size() const { return lines.size(); } - std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } - std::string toString() const { - std::ostringstream oss; - oss << *this; - return oss.str(); - } - - inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { - for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); - it != itEnd; ++it ) { - if( it != _text.begin() ) - _stream << "\n"; - _stream << *it; - } - return _stream; - } - - private: - std::string str; - TextAttributes attr; - std::vector lines; - }; - -} // end namespace Tbc - -#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -} // end outer namespace -#endif - -#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE - -namespace Catch { - using Tbc::Text; - using Tbc::TextAttributes; -} - -// #included from: catch_console_colour.hpp -#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED - -namespace Catch { - - namespace Detail { - struct IColourImpl; - } - - struct Colour { - enum Code { - None = 0, - - White, - Red, - Green, - Blue, - Cyan, - Yellow, - Grey, - - Bright = 0x10, - - BrightRed = Bright | Red, - BrightGreen = Bright | Green, - LightGrey = Bright | Grey, - BrightWhite = Bright | White, - - // By intention - FileName = LightGrey, - ResultError = BrightRed, - ResultSuccess = BrightGreen, - - Error = BrightRed, - Success = Green, - - OriginalExpression = Cyan, - ReconstructedExpression = Yellow, - - SecondaryText = LightGrey, - Headers = White - }; - - // Use constructed object for RAII guard - Colour( Code _colourCode ); - ~Colour(); - - // Use static method for one-shot changes - static void use( Code _colourCode ); - - private: - static Detail::IColourImpl* impl(); - }; - -} // end namespace Catch - -// #included from: catch_interfaces_reporter.h -#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED - -// #included from: catch_option.hpp -#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED - -namespace Catch { - - // An optional type - template - class Option { - public: - Option() : nullableValue( NULL ) {} - Option( T const& _value ) - : nullableValue( new( storage ) T( _value ) ) - {} - Option( Option const& _other ) - : nullableValue( _other ? new( storage ) T( *_other ) : NULL ) - {} - - ~Option() { - reset(); - } - - Option& operator= ( Option const& _other ) { - if( &_other != this ) { - reset(); - if( _other ) - nullableValue = new( storage ) T( *_other ); - } - return *this; - } - Option& operator = ( T const& _value ) { - reset(); - nullableValue = new( storage ) T( _value ); - return *this; - } - - void reset() { - if( nullableValue ) - nullableValue->~T(); - nullableValue = NULL; - } - - T& operator*() { return *nullableValue; } - T const& operator*() const { return *nullableValue; } - T* operator->() { return nullableValue; } - const T* operator->() const { return nullableValue; } - - T valueOr( T const& defaultValue ) const { - return nullableValue ? *nullableValue : defaultValue; - } - - bool some() const { return nullableValue != NULL; } - bool none() const { return nullableValue == NULL; } - - bool operator !() const { return nullableValue == NULL; } - operator SafeBool::type() const { - return SafeBool::makeSafe( some() ); - } - - private: - T* nullableValue; - char storage[sizeof(T)]; - }; - -} // end namespace Catch - -#include -#include -#include -#include - -namespace Catch -{ - struct ReporterConfig { - explicit ReporterConfig( Ptr const& _fullConfig ) - : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} - - ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) - : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} - - std::ostream& stream() const { return *m_stream; } - Ptr fullConfig() const { return m_fullConfig; } - - private: - std::ostream* m_stream; - Ptr m_fullConfig; - }; - - struct ReporterPreferences { - ReporterPreferences() - : shouldRedirectStdOut( false ) - {} - - bool shouldRedirectStdOut; - }; - - template - struct LazyStat : Option { - LazyStat() : used( false ) {} - LazyStat& operator=( T const& _value ) { - Option::operator=( _value ); - used = false; - return *this; - } - void reset() { - Option::reset(); - used = false; - } - bool used; - }; - - struct TestRunInfo { - TestRunInfo( std::string const& _name ) : name( _name ) {} - std::string name; - }; - struct GroupInfo { - GroupInfo( std::string const& _name, - std::size_t _groupIndex, - std::size_t _groupsCount ) - : name( _name ), - groupIndex( _groupIndex ), - groupsCounts( _groupsCount ) - {} - - std::string name; - std::size_t groupIndex; - std::size_t groupsCounts; - }; - - struct AssertionStats { - AssertionStats( AssertionResult const& _assertionResult, - std::vector const& _infoMessages, - Totals const& _totals ) - : assertionResult( _assertionResult ), - infoMessages( _infoMessages ), - totals( _totals ) - { - if( assertionResult.hasMessage() ) { - // Copy message into messages list. - // !TBD This should have been done earlier, somewhere - MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); - builder << assertionResult.getMessage(); - builder.m_info.message = builder.m_stream.str(); - - infoMessages.push_back( builder.m_info ); - } - } - virtual ~AssertionStats(); - -# ifdef CATCH_CPP11_OR_GREATER - AssertionStats( AssertionStats const& ) = default; - AssertionStats( AssertionStats && ) = default; - AssertionStats& operator = ( AssertionStats const& ) = default; - AssertionStats& operator = ( AssertionStats && ) = default; -# endif - - AssertionResult assertionResult; - std::vector infoMessages; - Totals totals; - }; - - struct SectionStats { - SectionStats( SectionInfo const& _sectionInfo, - Counts const& _assertions, - double _durationInSeconds, - bool _missingAssertions ) - : sectionInfo( _sectionInfo ), - assertions( _assertions ), - durationInSeconds( _durationInSeconds ), - missingAssertions( _missingAssertions ) - {} - virtual ~SectionStats(); -# ifdef CATCH_CPP11_OR_GREATER - SectionStats( SectionStats const& ) = default; - SectionStats( SectionStats && ) = default; - SectionStats& operator = ( SectionStats const& ) = default; - SectionStats& operator = ( SectionStats && ) = default; -# endif - - SectionInfo sectionInfo; - Counts assertions; - double durationInSeconds; - bool missingAssertions; - }; - - struct TestCaseStats { - TestCaseStats( TestCaseInfo const& _testInfo, - Totals const& _totals, - std::string const& _stdOut, - std::string const& _stdErr, - bool _aborting ) - : testInfo( _testInfo ), - totals( _totals ), - stdOut( _stdOut ), - stdErr( _stdErr ), - aborting( _aborting ) - {} - virtual ~TestCaseStats(); - -# ifdef CATCH_CPP11_OR_GREATER - TestCaseStats( TestCaseStats const& ) = default; - TestCaseStats( TestCaseStats && ) = default; - TestCaseStats& operator = ( TestCaseStats const& ) = default; - TestCaseStats& operator = ( TestCaseStats && ) = default; -# endif - - TestCaseInfo testInfo; - Totals totals; - std::string stdOut; - std::string stdErr; - bool aborting; - }; - - struct TestGroupStats { - TestGroupStats( GroupInfo const& _groupInfo, - Totals const& _totals, - bool _aborting ) - : groupInfo( _groupInfo ), - totals( _totals ), - aborting( _aborting ) - {} - TestGroupStats( GroupInfo const& _groupInfo ) - : groupInfo( _groupInfo ), - aborting( false ) - {} - virtual ~TestGroupStats(); - -# ifdef CATCH_CPP11_OR_GREATER - TestGroupStats( TestGroupStats const& ) = default; - TestGroupStats( TestGroupStats && ) = default; - TestGroupStats& operator = ( TestGroupStats const& ) = default; - TestGroupStats& operator = ( TestGroupStats && ) = default; -# endif - - GroupInfo groupInfo; - Totals totals; - bool aborting; - }; - - struct TestRunStats { - TestRunStats( TestRunInfo const& _runInfo, - Totals const& _totals, - bool _aborting ) - : runInfo( _runInfo ), - totals( _totals ), - aborting( _aborting ) - {} - virtual ~TestRunStats(); - -# ifndef CATCH_CPP11_OR_GREATER - TestRunStats( TestRunStats const& _other ) - : runInfo( _other.runInfo ), - totals( _other.totals ), - aborting( _other.aborting ) - {} -# else - TestRunStats( TestRunStats const& ) = default; - TestRunStats( TestRunStats && ) = default; - TestRunStats& operator = ( TestRunStats const& ) = default; - TestRunStats& operator = ( TestRunStats && ) = default; -# endif - - TestRunInfo runInfo; - Totals totals; - bool aborting; - }; - - struct IStreamingReporter : IShared { - virtual ~IStreamingReporter(); - - // Implementing class must also provide the following static method: - // static std::string getDescription(); - - virtual ReporterPreferences getPreferences() const = 0; - - virtual void noMatchingTestCases( std::string const& spec ) = 0; - - virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; - virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; - - virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; - virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; - - virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; - - virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; - virtual void sectionEnded( SectionStats const& sectionStats ) = 0; - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; - virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; - }; - - struct IReporterFactory { - virtual ~IReporterFactory(); - virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; - virtual std::string getDescription() const = 0; - }; - - struct IReporterRegistry { - typedef std::map FactoryMap; - - virtual ~IReporterRegistry(); - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; - virtual FactoryMap const& getFactories() const = 0; - }; - -} - -#include -#include - -namespace Catch { - - inline std::size_t listTests( Config const& config ) { - - TestSpec testSpec = config.testSpec(); - if( config.testSpec().hasFilters() ) - std::cout << "Matching test cases:\n"; - else { - std::cout << "All available test cases:\n"; - testSpec = TestSpecParser().parse( "*" ).testSpec(); - } - - std::size_t matchedTests = 0; - TextAttributes nameAttr, tagsAttr; - nameAttr.setInitialIndent( 2 ).setIndent( 4 ); - tagsAttr.setIndent( 6 ); - - std::vector matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); - for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); - it != itEnd; - ++it ) { - matchedTests++; - TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); - Colour::Code colour = testCaseInfo.isHidden - ? Colour::SecondaryText - : Colour::None; - Colour colourGuard( colour ); - - std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl; - if( !testCaseInfo.tags.empty() ) - std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; - } - - if( !config.testSpec().hasFilters() ) - std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl; - else - std::cout << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; - return matchedTests; - } - - inline std::size_t listTestsNamesOnly( Config const& config ) { - TestSpec testSpec = config.testSpec(); - if( !config.testSpec().hasFilters() ) - testSpec = TestSpecParser().parse( "*" ).testSpec(); - std::size_t matchedTests = 0; - std::vector matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); - for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); - it != itEnd; - ++it ) { - matchedTests++; - TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); - std::cout << testCaseInfo.name << std::endl; - } - return matchedTests; - } - - inline std::size_t listTags( Config const& config ) { - TestSpec testSpec = config.testSpec(); - if( config.testSpec().hasFilters() ) - std::cout << "Tags for matching test cases:\n"; - else { - std::cout << "All available tags:\n"; - testSpec = TestSpecParser().parse( "*" ).testSpec(); - } - - std::map tagCounts; - - std::vector matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); - for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); - it != itEnd; - ++it ) { - for( std::set::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), - tagItEnd = it->getTestCaseInfo().tags.end(); - tagIt != tagItEnd; - ++tagIt ) { - std::string tagName = *tagIt; - std::map::iterator countIt = tagCounts.find( tagName ); - if( countIt == tagCounts.end() ) - tagCounts.insert( std::make_pair( tagName, 1 ) ); - else - countIt->second++; - } - } - - for( std::map::const_iterator countIt = tagCounts.begin(), - countItEnd = tagCounts.end(); - countIt != countItEnd; - ++countIt ) { - std::ostringstream oss; - oss << " " << countIt->second << " "; - Text wrapper( "[" + countIt->first + "]", TextAttributes() - .setInitialIndent( 0 ) - .setIndent( oss.str().size() ) - .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); - std::cout << oss.str() << wrapper << "\n"; - } - std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; - return tagCounts.size(); - } - - inline std::size_t listReporters( Config const& /*config*/ ) { - std::cout << "Available reports:\n"; - IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); - IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; - std::size_t maxNameLen = 0; - for(it = itBegin; it != itEnd; ++it ) - maxNameLen = (std::max)( maxNameLen, it->first.size() ); - - for(it = itBegin; it != itEnd; ++it ) { - Text wrapper( it->second->getDescription(), TextAttributes() - .setInitialIndent( 0 ) - .setIndent( 7+maxNameLen ) - .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); - std::cout << " " - << it->first - << ":" - << std::string( maxNameLen - it->first.size() + 2, ' ' ) - << wrapper << "\n"; - } - std::cout << std::endl; - return factories.size(); - } - - inline Option list( Config const& config ) { - Option listedCount; - if( config.listTests() ) - listedCount = listedCount.valueOr(0) + listTests( config ); - if( config.listTestNamesOnly() ) - listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); - if( config.listTags() ) - listedCount = listedCount.valueOr(0) + listTags( config ); - if( config.listReporters() ) - listedCount = listedCount.valueOr(0) + listReporters( config ); - return listedCount; - } - -} // end namespace Catch - -// #included from: internal/catch_runner_impl.hpp -#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED - -// #included from: catch_test_case_tracker.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED - -#include -#include -#include - -namespace Catch { -namespace SectionTracking { - - class TrackedSection { - - typedef std::map TrackedSections; - - public: - enum RunState { - NotStarted, - Executing, - ExecutingChildren, - Completed - }; - - TrackedSection( std::string const& name, TrackedSection* parent ) - : m_name( name ), m_runState( NotStarted ), m_parent( parent ) - {} - - RunState runState() const { return m_runState; } - - TrackedSection* findChild( std::string const& childName ) { - TrackedSections::iterator it = m_children.find( childName ); - return it != m_children.end() - ? &it->second - : NULL; - } - TrackedSection* acquireChild( std::string const& childName ) { - if( TrackedSection* child = findChild( childName ) ) - return child; - m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) ); - return findChild( childName ); - } - void enter() { - if( m_runState == NotStarted ) - m_runState = Executing; - } - void leave() { - for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end(); - it != itEnd; - ++it ) - if( it->second.runState() != Completed ) { - m_runState = ExecutingChildren; - return; - } - m_runState = Completed; - } - TrackedSection* getParent() { - return m_parent; - } - bool hasChildren() const { - return !m_children.empty(); - } - - private: - std::string m_name; - RunState m_runState; - TrackedSections m_children; - TrackedSection* m_parent; - - }; - - class TestCaseTracker { - public: - TestCaseTracker( std::string const& testCaseName ) - : m_testCase( testCaseName, NULL ), - m_currentSection( &m_testCase ), - m_completedASectionThisRun( false ) - {} - - bool enterSection( std::string const& name ) { - TrackedSection* child = m_currentSection->acquireChild( name ); - if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed ) - return false; - - m_currentSection = child; - m_currentSection->enter(); - return true; - } - void leaveSection() { - m_currentSection->leave(); - m_currentSection = m_currentSection->getParent(); - assert( m_currentSection != NULL ); - m_completedASectionThisRun = true; - } - - bool currentSectionHasChildren() const { - return m_currentSection->hasChildren(); - } - bool isCompleted() const { - return m_testCase.runState() == TrackedSection::Completed; - } - - class Guard { - public: - Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) { - m_tracker.enterTestCase(); - } - ~Guard() { - m_tracker.leaveTestCase(); - } - private: - Guard( Guard const& ); - void operator = ( Guard const& ); - TestCaseTracker& m_tracker; - }; - - private: - void enterTestCase() { - m_currentSection = &m_testCase; - m_completedASectionThisRun = false; - m_testCase.enter(); - } - void leaveTestCase() { - m_testCase.leave(); - } - - TrackedSection m_testCase; - TrackedSection* m_currentSection; - bool m_completedASectionThisRun; - }; - -} // namespace SectionTracking - -using SectionTracking::TestCaseTracker; - -} // namespace Catch - -#include -#include - -namespace Catch { - - class StreamRedirect { - - public: - StreamRedirect( std::ostream& stream, std::string& targetString ) - : m_stream( stream ), - m_prevBuf( stream.rdbuf() ), - m_targetString( targetString ) - { - stream.rdbuf( m_oss.rdbuf() ); - } - - ~StreamRedirect() { - m_targetString += m_oss.str(); - m_stream.rdbuf( m_prevBuf ); - } - - private: - std::ostream& m_stream; - std::streambuf* m_prevBuf; - std::ostringstream m_oss; - std::string& m_targetString; - }; - - /////////////////////////////////////////////////////////////////////////// - - class RunContext : public IResultCapture, public IRunner { - - RunContext( RunContext const& ); - void operator =( RunContext const& ); - - public: - - explicit RunContext( Ptr const& config, Ptr const& reporter ) - : m_runInfo( config->name() ), - m_context( getCurrentMutableContext() ), - m_activeTestCase( NULL ), - m_config( config ), - m_reporter( reporter ), - m_prevRunner( &m_context.getRunner() ), - m_prevResultCapture( &m_context.getResultCapture() ), - m_prevConfig( m_context.getConfig() ) - { - m_context.setRunner( this ); - m_context.setConfig( m_config ); - m_context.setResultCapture( this ); - m_reporter->testRunStarting( m_runInfo ); - } - - virtual ~RunContext() { - m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); - m_context.setRunner( m_prevRunner ); - m_context.setConfig( NULL ); - m_context.setResultCapture( m_prevResultCapture ); - m_context.setConfig( m_prevConfig ); - } - - void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { - m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); - } - void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { - m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); - } - - Totals runTest( TestCase const& testCase ) { - Totals prevTotals = m_totals; - - std::string redirectedCout; - std::string redirectedCerr; - - TestCaseInfo testInfo = testCase.getTestCaseInfo(); - - m_reporter->testCaseStarting( testInfo ); - - m_activeTestCase = &testCase; - m_testCaseTracker = TestCaseTracker( testInfo.name ); - - do { - do { - runCurrentTest( redirectedCout, redirectedCerr ); - } - while( !m_testCaseTracker->isCompleted() && !aborting() ); - } - while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); - - Totals deltaTotals = m_totals.delta( prevTotals ); - m_totals.testCases += deltaTotals.testCases; - m_reporter->testCaseEnded( TestCaseStats( testInfo, - deltaTotals, - redirectedCout, - redirectedCerr, - aborting() ) ); - - m_activeTestCase = NULL; - m_testCaseTracker.reset(); - - return deltaTotals; - } - - Ptr config() const { - return m_config; - } - - private: // IResultCapture - - virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) { - m_lastAssertionInfo = assertionInfo; - return actOnCurrentResult( assertionResult.buildResult( assertionInfo ) ); - } - - virtual void assertionEnded( AssertionResult const& result ) { - if( result.getResultType() == ResultWas::Ok ) { - m_totals.assertions.passed++; - } - else if( !result.isOk() ) { - m_totals.assertions.failed++; - } - - if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) - m_messages.clear(); - - // Reset working state - m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); - } - - virtual bool sectionStarted ( - SectionInfo const& sectionInfo, - Counts& assertions - ) - { - std::ostringstream oss; - oss << sectionInfo.name << "@" << sectionInfo.lineInfo; - - if( !m_testCaseTracker->enterSection( oss.str() ) ) - return false; - - m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; - - m_reporter->sectionStarting( sectionInfo ); - - assertions = m_totals.assertions; - - return true; - } - bool testForMissingAssertions( Counts& assertions ) { - if( assertions.total() != 0 || - !m_config->warnAboutMissingAssertions() || - m_testCaseTracker->currentSectionHasChildren() ) - return false; - m_totals.assertions.failed++; - assertions.failed++; - return true; - } - - virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) { - if( std::uncaught_exception() ) { - m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) ); - return; - } - - Counts assertions = m_totals.assertions - prevAssertions; - bool missingAssertions = testForMissingAssertions( assertions ); - - m_testCaseTracker->leaveSection(); - - m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) ); - m_messages.clear(); - } - - virtual void pushScopedMessage( MessageInfo const& message ) { - m_messages.push_back( message ); - } - - virtual void popScopedMessage( MessageInfo const& message ) { - m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); - } - - virtual bool shouldDebugBreak() const { - return m_config->shouldDebugBreak(); - } - - virtual std::string getCurrentTestName() const { - return m_activeTestCase - ? m_activeTestCase->getTestCaseInfo().name - : ""; - } - - virtual const AssertionResult* getLastResult() const { - return &m_lastResult; - } - - public: - // !TBD We need to do this another way! - bool aborting() const { - return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); - } - - private: - - ResultAction::Value actOnCurrentResult( AssertionResult const& result ) { - m_lastResult = result; - assertionEnded( m_lastResult ); - - ResultAction::Value action = ResultAction::None; - - if( !m_lastResult.isOk() ) { - action = ResultAction::Failed; - if( shouldDebugBreak() ) - action = (ResultAction::Value)( action | ResultAction::Debug ); - if( aborting() ) - action = (ResultAction::Value)( action | ResultAction::Abort ); - } - return action; - } - - void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { - TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); - SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo ); - m_reporter->sectionStarting( testCaseSection ); - Counts prevAssertions = m_totals.assertions; - double duration = 0; - try { - m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); - TestCaseTracker::Guard guard( *m_testCaseTracker ); - - Timer timer; - timer.start(); - if( m_reporter->getPreferences().shouldRedirectStdOut ) { - StreamRedirect coutRedir( std::cout, redirectedCout ); - StreamRedirect cerrRedir( std::cerr, redirectedCerr ); - m_activeTestCase->invoke(); - } - else { - m_activeTestCase->invoke(); - } - duration = timer.getElapsedSeconds(); - } - catch( TestFailureException& ) { - // This just means the test was aborted due to failure - } - catch(...) { - ExpressionResultBuilder exResult( ResultWas::ThrewException ); - exResult << translateActiveException(); - actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo ) ); - } - // If sections ended prematurely due to an exception we stored their - // infos here so we can tear them down outside the unwind process. - for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), - itEnd = m_unfinishedSections.rend(); - it != itEnd; - ++it ) - sectionEnded( it->info, it->prevAssertions, it->durationInSeconds ); - m_unfinishedSections.clear(); - m_messages.clear(); - - Counts assertions = m_totals.assertions - prevAssertions; - bool missingAssertions = testForMissingAssertions( assertions ); - - SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); - m_reporter->sectionEnded( testCaseSectionStats ); - } - - private: - struct UnfinishedSections { - UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds ) - : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) - {} - - SectionInfo info; - Counts prevAssertions; - double durationInSeconds; - }; - - TestRunInfo m_runInfo; - IMutableContext& m_context; - TestCase const* m_activeTestCase; - Option m_testCaseTracker; - AssertionResult m_lastResult; - - Ptr m_config; - Totals m_totals; - Ptr m_reporter; - std::vector m_messages; - IRunner* m_prevRunner; - IResultCapture* m_prevResultCapture; - Ptr m_prevConfig; - AssertionInfo m_lastAssertionInfo; - std::vector m_unfinishedSections; - }; - -} // end namespace Catch - -// #included from: internal/catch_version.h -#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED - -namespace Catch { - - // Versioning information - struct Version { - Version( unsigned int _majorVersion, - unsigned int _minorVersion, - unsigned int _buildNumber, - char const* const _branchName ) - : majorVersion( _majorVersion ), - minorVersion( _minorVersion ), - buildNumber( _buildNumber ), - branchName( _branchName ) - {} - - unsigned int const majorVersion; - unsigned int const minorVersion; - unsigned int const buildNumber; - char const* const branchName; - - private: - void operator=( Version const& ); - }; - - extern Version libraryVersion; -} - -#include -#include -#include - -namespace Catch { - - class Runner { - - public: - Runner( Ptr const& config ) - : m_config( config ) - { - openStream(); - makeReporter(); - } - - Totals runTests() { - - RunContext context( m_config.get(), m_reporter ); - - Totals totals; - - context.testGroupStarting( "", 1, 1 ); // deprecated? - - TestSpec testSpec = m_config->testSpec(); - if( !testSpec.hasFilters() ) - testSpec = TestSpecParser().parse( "~[.]" ).testSpec(); // All not hidden tests - - std::vector testCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases ); - - int testsRunForGroup = 0; - for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); - it != itEnd; - ++it ) { - testsRunForGroup++; - if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) { - - if( context.aborting() ) - break; - - totals += context.runTest( *it ); - m_testsAlreadyRun.insert( *it ); - } - } - context.testGroupEnded( "", totals, 1, 1 ); - return totals; - } - - private: - void openStream() { - // Open output file, if specified - if( !m_config->getFilename().empty() ) { - m_ofs.open( m_config->getFilename().c_str() ); - if( m_ofs.fail() ) { - std::ostringstream oss; - oss << "Unable to open file: '" << m_config->getFilename() << "'"; - throw std::domain_error( oss.str() ); - } - m_config->setStreamBuf( m_ofs.rdbuf() ); - } - } - void makeReporter() { - std::string reporterName = m_config->getReporterName().empty() - ? "console" - : m_config->getReporterName(); - - m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() ); - if( !m_reporter ) { - std::ostringstream oss; - oss << "No reporter registered with name: '" << reporterName << "'"; - throw std::domain_error( oss.str() ); - } - } - - private: - Ptr m_config; - std::ofstream m_ofs; - Ptr m_reporter; - std::set m_testsAlreadyRun; - }; - - class Session { - static bool alreadyInstantiated; - - public: - - struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; - - Session() - : m_cli( makeCommandLineParser() ) { - if( alreadyInstantiated ) { - std::string msg = "Only one instance of Catch::Session can ever be used"; - std::cerr << msg << std::endl; - throw std::logic_error( msg ); - } - alreadyInstantiated = true; - } - ~Session() { - Catch::cleanUp(); - } - - void showHelp( std::string const& processName ) { - std::cout << "\nCatch v" << libraryVersion.majorVersion << "." - << libraryVersion.minorVersion << " build " - << libraryVersion.buildNumber; - if( libraryVersion.branchName != std::string( "master" ) ) - std::cout << " (" << libraryVersion.branchName << " branch)"; - std::cout << "\n"; - - m_cli.usage( std::cout, processName ); - std::cout << "For more detail usage please see the project docs\n" << std::endl; - } - - int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { - try { - m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); - m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); - if( m_configData.showHelp ) - showHelp( m_configData.processName ); - m_config.reset(); - } - catch( std::exception& ex ) { - { - Colour colourGuard( Colour::Red ); - std::cerr << "\nError(s) in input:\n" - << Text( ex.what(), TextAttributes().setIndent(2) ) - << "\n\n"; - } - m_cli.usage( std::cout, m_configData.processName ); - return (std::numeric_limits::max)(); - } - return 0; - } - - void useConfigData( ConfigData const& _configData ) { - m_configData = _configData; - m_config.reset(); - } - - int run( int argc, char* const argv[] ) { - - int returnCode = applyCommandLine( argc, argv ); - if( returnCode == 0 ) - returnCode = run(); - return returnCode; - } - - int run() { - if( m_configData.showHelp ) - return 0; - - try - { - config(); // Force config to be constructed - Runner runner( m_config ); - - // Handle list request - if( Option listed = list( config() ) ) - return static_cast( *listed ); - - return static_cast( runner.runTests().assertions.failed ); - } - catch( std::exception& ex ) { - std::cerr << ex.what() << std::endl; - return (std::numeric_limits::max)(); - } - } - - Clara::CommandLine const& cli() const { - return m_cli; - } - std::vector const& unusedTokens() const { - return m_unusedTokens; - } - ConfigData& configData() { - return m_configData; - } - Config& config() { - if( !m_config ) - m_config = new Config( m_configData ); - return *m_config; - } - - private: - Clara::CommandLine m_cli; - std::vector m_unusedTokens; - ConfigData m_configData; - Ptr m_config; - }; - - bool Session::alreadyInstantiated = false; - -} // end namespace Catch - -// #included from: catch_registry_hub.hpp -#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED - -// #included from: catch_test_case_registry_impl.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED - -#include -#include -#include -#include - -namespace Catch { - - class TestRegistry : public ITestCaseRegistry { - public: - TestRegistry() : m_unnamedCount( 0 ) {} - virtual ~TestRegistry(); - - virtual void registerTest( TestCase const& testCase ) { - std::string name = testCase.getTestCaseInfo().name; - if( name == "" ) { - std::ostringstream oss; - oss << "Anonymous test case " << ++m_unnamedCount; - return registerTest( testCase.withName( oss.str() ) ); - } - - if( m_functions.find( testCase ) == m_functions.end() ) { - m_functions.insert( testCase ); - m_functionsInOrder.push_back( testCase ); - if( !testCase.isHidden() ) - m_nonHiddenFunctions.push_back( testCase ); - } - else { - TestCase const& prev = *m_functions.find( testCase ); - { - Colour colourGuard( Colour::Red ); - std::cerr << "error: TEST_CASE( \"" << name << "\" ) already defined.\n" - << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n" - << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl; - } - exit(1); - } - } - - virtual std::vector const& getAllTests() const { - return m_functionsInOrder; - } - - virtual std::vector const& getAllNonHiddenTests() const { - return m_nonHiddenFunctions; - } - - virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases ) const { - for( std::vector::const_iterator it = m_functionsInOrder.begin(), - itEnd = m_functionsInOrder.end(); - it != itEnd; - ++it ) { - if( testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ) ) - matchingTestCases.push_back( *it ); - } - } - - private: - - std::set m_functions; - std::vector m_functionsInOrder; - std::vector m_nonHiddenFunctions; - size_t m_unnamedCount; - }; - - /////////////////////////////////////////////////////////////////////////// - - class FreeFunctionTestCase : public SharedImpl { - public: - - FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} - - virtual void invoke() const { - m_fun(); - } - - private: - virtual ~FreeFunctionTestCase(); - - TestFunction m_fun; - }; - - inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { - std::string className = classOrQualifiedMethodName; - if( startsWith( className, "&" ) ) - { - std::size_t lastColons = className.rfind( "::" ); - std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); - if( penultimateColons == std::string::npos ) - penultimateColons = 1; - className = className.substr( penultimateColons, lastColons-penultimateColons ); - } - return className; - } - - /////////////////////////////////////////////////////////////////////////// - - AutoReg::AutoReg( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ) { - registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); - } - - AutoReg::~AutoReg() {} - - void AutoReg::registerTestCase( ITestCase* testCase, - char const* classOrQualifiedMethodName, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - - getMutableRegistryHub().registerTest - ( makeTestCase( testCase, - extractClassName( classOrQualifiedMethodName ), - nameAndDesc.name, - nameAndDesc.description, - lineInfo ) ); - } - -} // end namespace Catch - -// #included from: catch_reporter_registry.hpp -#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED - -#include - -namespace Catch { - - class ReporterRegistry : public IReporterRegistry { - - public: - - virtual ~ReporterRegistry() { - deleteAllValues( m_factories ); - } - - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const { - FactoryMap::const_iterator it = m_factories.find( name ); - if( it == m_factories.end() ) - return NULL; - return it->second->create( ReporterConfig( config ) ); - } - - void registerReporter( std::string const& name, IReporterFactory* factory ) { - m_factories.insert( std::make_pair( name, factory ) ); - } - - FactoryMap const& getFactories() const { - return m_factories; - } - - private: - FactoryMap m_factories; - }; -} - -// #included from: catch_exception_translator_registry.hpp -#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED - -#ifdef __OBJC__ -#import "Foundation/Foundation.h" -#endif - -namespace Catch { - - class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { - public: - ~ExceptionTranslatorRegistry() { - deleteAll( m_translators ); - } - - virtual void registerTranslator( const IExceptionTranslator* translator ) { - m_translators.push_back( translator ); - } - - virtual std::string translateActiveException() const { - try { -#ifdef __OBJC__ - // In Objective-C try objective-c exceptions first - @try { - throw; - } - @catch (NSException *exception) { - return toString( [exception description] ); - } -#else - throw; -#endif - } - catch( std::exception& ex ) { - return ex.what(); - } - catch( std::string& msg ) { - return msg; - } - catch( const char* msg ) { - return msg; - } - catch(...) { - return tryTranslators( m_translators.begin() ); - } - } - - std::string tryTranslators( std::vector::const_iterator it ) const { - if( it == m_translators.end() ) - return "Unknown exception"; - - try { - return (*it)->translate(); - } - catch(...) { - return tryTranslators( it+1 ); - } - } - - private: - std::vector m_translators; - }; -} - -namespace Catch { - - namespace { - - class RegistryHub : public IRegistryHub, public IMutableRegistryHub { - - RegistryHub( RegistryHub const& ); - void operator=( RegistryHub const& ); - - public: // IRegistryHub - RegistryHub() { - } - virtual IReporterRegistry const& getReporterRegistry() const { - return m_reporterRegistry; - } - virtual ITestCaseRegistry const& getTestCaseRegistry() const { - return m_testCaseRegistry; - } - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() { - return m_exceptionTranslatorRegistry; - } - - public: // IMutableRegistryHub - virtual void registerReporter( std::string const& name, IReporterFactory* factory ) { - m_reporterRegistry.registerReporter( name, factory ); - } - virtual void registerTest( TestCase const& testInfo ) { - m_testCaseRegistry.registerTest( testInfo ); - } - virtual void registerTranslator( const IExceptionTranslator* translator ) { - m_exceptionTranslatorRegistry.registerTranslator( translator ); - } - - private: - TestRegistry m_testCaseRegistry; - ReporterRegistry m_reporterRegistry; - ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; - }; - - // Single, global, instance - inline RegistryHub*& getTheRegistryHub() { - static RegistryHub* theRegistryHub = NULL; - if( !theRegistryHub ) - theRegistryHub = new RegistryHub(); - return theRegistryHub; - } - } - - IRegistryHub& getRegistryHub() { - return *getTheRegistryHub(); - } - IMutableRegistryHub& getMutableRegistryHub() { - return *getTheRegistryHub(); - } - void cleanUp() { - delete getTheRegistryHub(); - getTheRegistryHub() = NULL; - cleanUpContext(); - } - std::string translateActiveException() { - return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); - } - -} // end namespace Catch - -// #included from: catch_notimplemented_exception.hpp -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED - -#include - -namespace Catch { - - NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) - : m_lineInfo( lineInfo ) { - std::ostringstream oss; - oss << lineInfo << ": function "; - oss << "not implemented"; - m_what = oss.str(); - } - - const char* NotImplementedException::what() const CATCH_NOEXCEPT { - return m_what.c_str(); - } - -} // end namespace Catch - -// #included from: catch_context_impl.hpp -#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED - -// #included from: catch_stream.hpp -#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED - -// #included from: catch_streambuf.h -#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED - -#include - -namespace Catch { - - class StreamBufBase : public std::streambuf { - public: - virtual ~StreamBufBase() CATCH_NOEXCEPT; - }; -} - -#include -#include - -namespace Catch { - - template - class StreamBufImpl : public StreamBufBase { - char data[bufferSize]; - WriterF m_writer; - - public: - StreamBufImpl() { - setp( data, data + sizeof(data) ); - } - - ~StreamBufImpl() CATCH_NOEXCEPT { - sync(); - } - - private: - int overflow( int c ) { - sync(); - - if( c != EOF ) { - if( pbase() == epptr() ) - m_writer( std::string( 1, static_cast( c ) ) ); - else - sputc( static_cast( c ) ); - } - return 0; - } - - int sync() { - if( pbase() != pptr() ) { - m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); - setp( pbase(), epptr() ); - } - return 0; - } - }; - - /////////////////////////////////////////////////////////////////////////// - - struct OutputDebugWriter { - - void operator()( std::string const&str ) { - writeToDebugConsole( str ); - } - }; - - Stream::Stream() - : streamBuf( NULL ), isOwned( false ) - {} - - Stream::Stream( std::streambuf* _streamBuf, bool _isOwned ) - : streamBuf( _streamBuf ), isOwned( _isOwned ) - {} - - void Stream::release() { - if( isOwned ) { - delete streamBuf; - streamBuf = NULL; - isOwned = false; - } - } -} - -namespace Catch { - - class Context : public IMutableContext { - - Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {} - Context( Context const& ); - void operator=( Context const& ); - - public: // IContext - virtual IResultCapture& getResultCapture() { - return *m_resultCapture; - } - virtual IRunner& getRunner() { - return *m_runner; - } - virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { - return getGeneratorsForCurrentTest() - .getGeneratorInfo( fileInfo, totalSize ) - .getCurrentIndex(); - } - virtual bool advanceGeneratorsForCurrentTest() { - IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); - return generators && generators->moveNext(); - } - - virtual Ptr getConfig() const { - return m_config; - } - - public: // IMutableContext - virtual void setResultCapture( IResultCapture* resultCapture ) { - m_resultCapture = resultCapture; - } - virtual void setRunner( IRunner* runner ) { - m_runner = runner; - } - virtual void setConfig( Ptr const& config ) { - m_config = config; - } - - friend IMutableContext& getCurrentMutableContext(); - - private: - IGeneratorsForTest* findGeneratorsForCurrentTest() { - std::string testName = getResultCapture().getCurrentTestName(); - - std::map::const_iterator it = - m_generatorsByTestName.find( testName ); - return it != m_generatorsByTestName.end() - ? it->second - : NULL; - } - - IGeneratorsForTest& getGeneratorsForCurrentTest() { - IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); - if( !generators ) { - std::string testName = getResultCapture().getCurrentTestName(); - generators = createGeneratorsForTest(); - m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); - } - return *generators; - } - - private: - Ptr m_config; - IRunner* m_runner; - IResultCapture* m_resultCapture; - std::map m_generatorsByTestName; - }; - - namespace { - Context* currentContext = NULL; - } - IMutableContext& getCurrentMutableContext() { - if( !currentContext ) - currentContext = new Context(); - return *currentContext; - } - IContext& getCurrentContext() { - return getCurrentMutableContext(); - } - - Stream createStream( std::string const& streamName ) { - if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false ); - if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false ); - if( streamName == "debug" ) return Stream( new StreamBufImpl, true ); - - throw std::domain_error( "Unknown stream: " + streamName ); - } - - void cleanUpContext() { - delete currentContext; - currentContext = NULL; - } -} - -// #included from: catch_console_colour_impl.hpp -#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED - -namespace Catch { namespace Detail { - struct IColourImpl { - virtual ~IColourImpl() {} - virtual void use( Colour::Code _colourCode ) = 0; - }; -}} - -#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// - -#ifndef NOMINMAX -#define NOMINMAX -#endif - -#ifdef __AFXDLL -#include -#else -#include -#endif - -namespace Catch { -namespace { - - class Win32ColourImpl : public Detail::IColourImpl { - public: - Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) - { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); - originalAttributes = csbiInfo.wAttributes; - } - - virtual void use( Colour::Code _colourCode ) { - switch( _colourCode ) { - case Colour::None: return setTextAttribute( originalAttributes ); - case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); - case Colour::Red: return setTextAttribute( FOREGROUND_RED ); - case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); - case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); - case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); - case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); - case Colour::Grey: return setTextAttribute( 0 ); - - case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); - case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); - case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); - case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); - - case Colour::Bright: throw std::logic_error( "not a colour" ); - } - } - - private: - void setTextAttribute( WORD _textAttribute ) { - SetConsoleTextAttribute( stdoutHandle, _textAttribute ); - } - HANDLE stdoutHandle; - WORD originalAttributes; - }; - - inline bool shouldUseColourForPlatform() { - return true; - } - - static Detail::IColourImpl* platformColourInstance() { - static Win32ColourImpl s_instance; - return &s_instance; - } - -} // end anon namespace -} // end namespace Catch - -#else // Not Windows - assumed to be POSIX compatible ////////////////////////// - -#include - -namespace Catch { -namespace { - - // use POSIX/ ANSI console terminal codes - // Thanks to Adam Strzelecki for original contribution - // (http://github.com/nanoant) - // https://github.com/philsquared/Catch/pull/131 - class PosixColourImpl : public Detail::IColourImpl { - public: - virtual void use( Colour::Code _colourCode ) { - switch( _colourCode ) { - case Colour::None: - case Colour::White: return setColour( "[0m" ); - case Colour::Red: return setColour( "[0;31m" ); - case Colour::Green: return setColour( "[0;32m" ); - case Colour::Blue: return setColour( "[0:34m" ); - case Colour::Cyan: return setColour( "[0;36m" ); - case Colour::Yellow: return setColour( "[0;33m" ); - case Colour::Grey: return setColour( "[1;30m" ); - - case Colour::LightGrey: return setColour( "[0;37m" ); - case Colour::BrightRed: return setColour( "[1;31m" ); - case Colour::BrightGreen: return setColour( "[1;32m" ); - case Colour::BrightWhite: return setColour( "[1;37m" ); - - case Colour::Bright: throw std::logic_error( "not a colour" ); - } - } - private: - void setColour( const char* _escapeCode ) { - std::cout << '\033' << _escapeCode; - } - }; - - inline bool shouldUseColourForPlatform() { - return isatty(STDOUT_FILENO); - } - - static Detail::IColourImpl* platformColourInstance() { - static PosixColourImpl s_instance; - return &s_instance; - } - -} // end anon namespace -} // end namespace Catch - -#endif // not Windows - -namespace Catch { - - namespace { - struct NoColourImpl : Detail::IColourImpl { - void use( Colour::Code ) {} - - static IColourImpl* instance() { - static NoColourImpl s_instance; - return &s_instance; - } - }; - static bool shouldUseColour() { - return shouldUseColourForPlatform() && !isDebuggerActive(); - } - } - - Colour::Colour( Code _colourCode ){ use( _colourCode ); } - Colour::~Colour(){ use( None ); } - void Colour::use( Code _colourCode ) { - impl()->use( _colourCode ); - } - - Detail::IColourImpl* Colour::impl() { - return shouldUseColour() - ? platformColourInstance() - : NoColourImpl::instance(); - } - -} // end namespace Catch - -// #included from: catch_generators_impl.hpp -#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED - -#include -#include -#include - -namespace Catch { - - struct GeneratorInfo : IGeneratorInfo { - - GeneratorInfo( std::size_t size ) - : m_size( size ), - m_currentIndex( 0 ) - {} - - bool moveNext() { - if( ++m_currentIndex == m_size ) { - m_currentIndex = 0; - return false; - } - return true; - } - - std::size_t getCurrentIndex() const { - return m_currentIndex; - } - - std::size_t m_size; - std::size_t m_currentIndex; - }; - - /////////////////////////////////////////////////////////////////////////// - - class GeneratorsForTest : public IGeneratorsForTest { - - public: - ~GeneratorsForTest() { - deleteAll( m_generatorsInOrder ); - } - - IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { - std::map::const_iterator it = m_generatorsByName.find( fileInfo ); - if( it == m_generatorsByName.end() ) { - IGeneratorInfo* info = new GeneratorInfo( size ); - m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); - m_generatorsInOrder.push_back( info ); - return *info; - } - return *it->second; - } - - bool moveNext() { - std::vector::const_iterator it = m_generatorsInOrder.begin(); - std::vector::const_iterator itEnd = m_generatorsInOrder.end(); - for(; it != itEnd; ++it ) { - if( (*it)->moveNext() ) - return true; - } - return false; - } - - private: - std::map m_generatorsByName; - std::vector m_generatorsInOrder; - }; - - IGeneratorsForTest* createGeneratorsForTest() - { - return new GeneratorsForTest(); - } - -} // end namespace Catch - -// #included from: catch_assertionresult.hpp -#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED - -namespace Catch { - - AssertionInfo::AssertionInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - std::string const& _capturedExpression, - ResultDisposition::Flags _resultDisposition ) - : macroName( _macroName ), - lineInfo( _lineInfo ), - capturedExpression( _capturedExpression ), - resultDisposition( _resultDisposition ) - {} - - AssertionResult::AssertionResult() {} - - AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) - : m_info( info ), - m_resultData( data ) - {} - - AssertionResult::~AssertionResult() {} - - // Result was a success - bool AssertionResult::succeeded() const { - return Catch::isOk( m_resultData.resultType ); - } - - // Result was a success, or failure is suppressed - bool AssertionResult::isOk() const { - return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); - } - - ResultWas::OfType AssertionResult::getResultType() const { - return m_resultData.resultType; - } - - bool AssertionResult::hasExpression() const { - return !m_info.capturedExpression.empty(); - } - - bool AssertionResult::hasMessage() const { - return !m_resultData.message.empty(); - } - - std::string AssertionResult::getExpression() const { - if( shouldNegate( m_info.resultDisposition ) ) - return "!" + m_info.capturedExpression; - else - return m_info.capturedExpression; - } - std::string AssertionResult::getExpressionInMacro() const { - if( m_info.macroName.empty() ) - return m_info.capturedExpression; - else - return m_info.macroName + "( " + m_info.capturedExpression + " )"; - } - - bool AssertionResult::hasExpandedExpression() const { - return hasExpression() && getExpandedExpression() != getExpression(); - } - - std::string AssertionResult::getExpandedExpression() const { - return m_resultData.reconstructedExpression; - } - - std::string AssertionResult::getMessage() const { - return m_resultData.message; - } - SourceLineInfo AssertionResult::getSourceInfo() const { - return m_info.lineInfo; - } - - std::string AssertionResult::getTestMacroName() const { - return m_info.macroName; - } - -} // end namespace Catch - -// #included from: catch_expressionresult_builder.hpp -#define TWOBLUECUBES_CATCH_EXPRESSIONRESULT_BUILDER_HPP_INCLUDED - -#include - -namespace Catch { - - ExpressionResultBuilder::ExpressionResultBuilder( ResultWas::OfType resultType ) { - m_data.resultType = resultType; - } - ExpressionResultBuilder::ExpressionResultBuilder( ExpressionResultBuilder const& other ) - : m_data( other.m_data ), - m_exprComponents( other.m_exprComponents ) - { - m_stream << other.m_stream.str(); - } - ExpressionResultBuilder& ExpressionResultBuilder::operator=(ExpressionResultBuilder const& other ) { - m_data = other.m_data; - m_exprComponents = other.m_exprComponents; - m_stream.str(""); - m_stream << other.m_stream.str(); - return *this; - } - ExpressionResultBuilder& ExpressionResultBuilder::setResultType( ResultWas::OfType result ) { - m_data.resultType = result; - return *this; - } - ExpressionResultBuilder& ExpressionResultBuilder::setResultType( bool result ) { - m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; - return *this; - } - ExpressionResultBuilder& ExpressionResultBuilder::endExpression( ResultDisposition::Flags resultDisposition ) { - m_exprComponents.shouldNegate = shouldNegate( resultDisposition ); - return *this; - } - ExpressionResultBuilder& ExpressionResultBuilder::setLhs( std::string const& lhs ) { - m_exprComponents.lhs = lhs; - return *this; - } - ExpressionResultBuilder& ExpressionResultBuilder::setRhs( std::string const& rhs ) { - m_exprComponents.rhs = rhs; - return *this; - } - ExpressionResultBuilder& ExpressionResultBuilder::setOp( std::string const& op ) { - m_exprComponents.op = op; - return *this; - } - AssertionResult ExpressionResultBuilder::buildResult( AssertionInfo const& info ) const - { - assert( m_data.resultType != ResultWas::Unknown ); - - AssertionResultData data = m_data; - - // Flip bool results if shouldNegate is set - if( m_exprComponents.shouldNegate && data.resultType == ResultWas::Ok ) - data.resultType = ResultWas::ExpressionFailed; - else if( m_exprComponents.shouldNegate && data.resultType == ResultWas::ExpressionFailed ) - data.resultType = ResultWas::Ok; - - data.message = m_stream.str(); - data.reconstructedExpression = reconstructExpression( info ); - if( m_exprComponents.shouldNegate ) { - if( m_exprComponents.op == "" ) - data.reconstructedExpression = "!" + data.reconstructedExpression; - else - data.reconstructedExpression = "!(" + data.reconstructedExpression + ")"; - } - return AssertionResult( info, data ); - } - std::string ExpressionResultBuilder::reconstructExpression( AssertionInfo const& info ) const { - if( m_exprComponents.op == "" ) - return m_exprComponents.lhs.empty() ? info.capturedExpression : m_exprComponents.op + m_exprComponents.lhs; - else if( m_exprComponents.op == "matches" ) - return m_exprComponents.lhs + " " + m_exprComponents.rhs; - else if( m_exprComponents.op != "!" ) { - if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && - m_exprComponents.lhs.find("\n") == std::string::npos && - m_exprComponents.rhs.find("\n") == std::string::npos ) - return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; - else - return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; - } - else - return "{can't expand - use " + info.macroName + "_FALSE( " + info.capturedExpression.substr(1) + " ) instead of " + info.macroName + "( " + info.capturedExpression + " ) for better diagnostics}"; - } - -} // end namespace Catch - -// #included from: catch_test_case_info.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED - -namespace Catch { - - inline bool isSpecialTag( std::string const& tag ) { - return tag == "." || - tag == "hide" || - tag == "!hide" || - tag == "!throws"; - } - inline bool isReservedTag( std::string const& tag ) { - return !isSpecialTag( tag ) && tag.size() > 0 && !isalnum( tag[0] ); - } - inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { - if( isReservedTag( tag ) ) { - { - Colour colourGuard( Colour::Red ); - std::cerr - << "Tag name [" << tag << "] not allowed.\n" - << "Tag names starting with non alpha-numeric characters are reserved\n"; - } - { - Colour colourGuard( Colour::FileName ); - std::cerr << _lineInfo << std::endl; - } - exit(1); - } - } - - TestCase makeTestCase( ITestCase* _testCase, - std::string const& _className, - std::string const& _name, - std::string const& _descOrTags, - SourceLineInfo const& _lineInfo ) - { - bool isHidden( startsWith( _name, "./" ) ); // Legacy support - - // Parse out tags - std::set tags; - std::string desc, tag; - bool inTag = false; - for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { - char c = _descOrTags[i]; - if( !inTag ) { - if( c == '[' ) - inTag = true; - else - desc += c; - } - else { - if( c == ']' ) { - enforceNotReservedTag( tag, _lineInfo ); - - inTag = false; - if( tag == "hide" || tag == "." ) { - tags.insert( "hide" ); - tags.insert( "." ); - isHidden = true; - } - else { - tags.insert( tag ); - } - tag.clear(); - } - else - tag += c; - } - } - TestCaseInfo info( _name, _className, desc, tags, isHidden, _lineInfo ); - return TestCase( _testCase, info ); - } - - TestCaseInfo::TestCaseInfo( std::string const& _name, - std::string const& _className, - std::string const& _description, - std::set const& _tags, - bool _isHidden, - SourceLineInfo const& _lineInfo ) - : name( _name ), - className( _className ), - description( _description ), - tags( _tags ), - lineInfo( _lineInfo ), - isHidden( _isHidden ), - throws( false ) - { - std::ostringstream oss; - for( std::set::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) { - oss << "[" << *it << "]"; - if( *it == "!throws" ) - throws = true; - } - tagsAsString = oss.str(); - } - - TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) - : name( other.name ), - className( other.className ), - description( other.description ), - tags( other.tags ), - tagsAsString( other.tagsAsString ), - lineInfo( other.lineInfo ), - isHidden( other.isHidden ), - throws( other.throws ) - {} - - TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} - - TestCase::TestCase( TestCase const& other ) - : TestCaseInfo( other ), - test( other.test ) - {} - - TestCase TestCase::withName( std::string const& _newName ) const { - TestCase other( *this ); - other.name = _newName; - return other; - } - - void TestCase::invoke() const { - test->invoke(); - } - - bool TestCase::isHidden() const { - return TestCaseInfo::isHidden; - } - bool TestCase::throws() const { - return TestCaseInfo::throws; - } - - void TestCase::swap( TestCase& other ) { - test.swap( other.test ); - className.swap( other.className ); - name.swap( other.name ); - description.swap( other.description ); - std::swap( lineInfo, other.lineInfo ); - } - - bool TestCase::operator == ( TestCase const& other ) const { - return test.get() == other.test.get() && - name == other.name && - className == other.className; - } - - bool TestCase::operator < ( TestCase const& other ) const { - return name < other.name; - } - TestCase& TestCase::operator = ( TestCase const& other ) { - TestCase temp( other ); - swap( temp ); - return *this; - } - - TestCaseInfo const& TestCase::getTestCaseInfo() const - { - return *this; - } - -} // end namespace Catch - -// #included from: catch_version.hpp -#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED - -namespace Catch { - - // These numbers are maintained by a script - Version libraryVersion( 1, 0, 45, "master" ); -} - -// #included from: catch_message.hpp -#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED - -namespace Catch { - - MessageInfo::MessageInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ) - : macroName( _macroName ), - lineInfo( _lineInfo ), - type( _type ), - sequence( ++globalCount ) - {} - - // This may need protecting if threading support is added - unsigned int MessageInfo::globalCount = 0; - - //////////////////////////////////////////////////////////////////////////// - - ScopedMessage::ScopedMessage( MessageBuilder const& builder ) - : m_info( builder.m_info ) - { - m_info.message = builder.m_stream.str(); - getResultCapture().pushScopedMessage( m_info ); - } - ScopedMessage::~ScopedMessage() { - getResultCapture().popScopedMessage( m_info ); - } - -} // end namespace Catch - -// #included from: catch_legacy_reporter_adapter.hpp -#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED - -// #included from: catch_legacy_reporter_adapter.h -#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED - -namespace Catch -{ - // Deprecated - struct IReporter : IShared { - virtual ~IReporter(); - - virtual bool shouldRedirectStdout() const = 0; - - virtual void StartTesting() = 0; - virtual void EndTesting( Totals const& totals ) = 0; - virtual void StartGroup( std::string const& groupName ) = 0; - virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; - virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; - virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; - virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; - virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; - virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; - virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; - virtual void Aborted() = 0; - virtual void Result( AssertionResult const& result ) = 0; - }; - - class LegacyReporterAdapter : public SharedImpl - { - public: - LegacyReporterAdapter( Ptr const& legacyReporter ); - virtual ~LegacyReporterAdapter(); - - virtual ReporterPreferences getPreferences() const; - virtual void noMatchingTestCases( std::string const& ); - virtual void testRunStarting( TestRunInfo const& ); - virtual void testGroupStarting( GroupInfo const& groupInfo ); - virtual void testCaseStarting( TestCaseInfo const& testInfo ); - virtual void sectionStarting( SectionInfo const& sectionInfo ); - virtual void assertionStarting( AssertionInfo const& ); - virtual bool assertionEnded( AssertionStats const& assertionStats ); - virtual void sectionEnded( SectionStats const& sectionStats ); - virtual void testCaseEnded( TestCaseStats const& testCaseStats ); - virtual void testGroupEnded( TestGroupStats const& testGroupStats ); - virtual void testRunEnded( TestRunStats const& testRunStats ); - - private: - Ptr m_legacyReporter; - }; -} - -namespace Catch -{ - LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) - : m_legacyReporter( legacyReporter ) - {} - LegacyReporterAdapter::~LegacyReporterAdapter() {} - - ReporterPreferences LegacyReporterAdapter::getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); - return prefs; - } - - void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} - void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { - m_legacyReporter->StartTesting(); - } - void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { - m_legacyReporter->StartGroup( groupInfo.name ); - } - void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { - m_legacyReporter->StartTestCase( testInfo ); - } - void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { - m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); - } - void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { - // Not on legacy interface - } - - bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { - if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { - for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); - it != itEnd; - ++it ) { - if( it->type == ResultWas::Info ) { - ExpressionResultBuilder expressionBuilder( it->type ); - expressionBuilder << it->message; - AssertionInfo info( it->macroName, it->lineInfo, "", ResultDisposition::Normal ); - AssertionResult result = expressionBuilder.buildResult( info ); - m_legacyReporter->Result( result ); - } - } - } - m_legacyReporter->Result( assertionStats.assertionResult ); - return true; - } - void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { - if( sectionStats.missingAssertions ) - m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); - m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); - } - void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { - m_legacyReporter->EndTestCase - ( testCaseStats.testInfo, - testCaseStats.totals, - testCaseStats.stdOut, - testCaseStats.stdErr ); - } - void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { - if( testGroupStats.aborting ) - m_legacyReporter->Aborted(); - m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); - } - void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { - m_legacyReporter->EndTesting( testRunStats.totals ); - } -} - -// #included from: catch_timer.hpp - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wc++11-long-long" -#endif - -#ifdef CATCH_PLATFORM_WINDOWS -#include -#else -#include -#endif - -namespace Catch { - - namespace { -#ifdef CATCH_PLATFORM_WINDOWS - uint64_t getCurrentTicks() { - static uint64_t hz=0, hzo=0; - if (!hz) { - QueryPerformanceFrequency((LARGE_INTEGER*)&hz); - QueryPerformanceCounter((LARGE_INTEGER*)&hzo); - } - uint64_t t; - QueryPerformanceCounter((LARGE_INTEGER*)&t); - return ((t-hzo)*1000000)/hz; - } -#else - uint64_t getCurrentTicks() { - timeval t; - gettimeofday(&t,NULL); - return (uint64_t)t.tv_sec * 1000000ull + (uint64_t)t.tv_usec; - } -#endif - } - - void Timer::start() { - m_ticks = getCurrentTicks(); - } - unsigned int Timer::getElapsedNanoseconds() const { - return (unsigned int)(getCurrentTicks() - m_ticks); - } - unsigned int Timer::getElapsedMilliseconds() const { - return (unsigned int)((getCurrentTicks() - m_ticks)/1000); - } - double Timer::getElapsedSeconds() const { - return (getCurrentTicks() - m_ticks)/1000000.0; - } - -} // namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif -// #included from: catch_common.hpp -#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED - -namespace Catch { - - bool startsWith( std::string const& s, std::string const& prefix ) { - return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; - } - bool endsWith( std::string const& s, std::string const& suffix ) { - return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; - } - bool contains( std::string const& s, std::string const& infix ) { - return s.find( infix ) != std::string::npos; - } - void toLowerInPlace( std::string& s ) { - std::transform( s.begin(), s.end(), s.begin(), ::tolower ); - } - std::string toLower( std::string const& s ) { - std::string lc = s; - toLowerInPlace( lc ); - return lc; - } - std::string trim( std::string const& str ) { - static char const* whitespaceChars = "\n\r\t "; - std::string::size_type start = str.find_first_not_of( whitespaceChars ); - std::string::size_type end = str.find_last_not_of( whitespaceChars ); - - return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; - } - - pluralise::pluralise( std::size_t count, std::string const& label ) - : m_count( count ), - m_label( label ) - {} - - std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { - os << pluraliser.m_count << " " << pluraliser.m_label; - if( pluraliser.m_count != 1 ) - os << "s"; - return os; - } - - SourceLineInfo::SourceLineInfo() : line( 0 ){} - SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) - : file( _file ), - line( _line ) - {} - SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) - : file( other.file ), - line( other.line ) - {} - bool SourceLineInfo::empty() const { - return file.empty(); - } - bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { - return line == other.line && file == other.file; - } - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { -#ifndef __GNUG__ - os << info.file << "(" << info.line << ")"; -#else - os << info.file << ":" << info.line; -#endif - return os; - } - - void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { - std::ostringstream oss; - oss << locationInfo << ": Internal Catch error: '" << message << "'"; - if( isTrue( true )) - throw std::logic_error( oss.str() ); - } -} - -// #included from: catch_section.hpp -#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED - -namespace Catch { - - Section::Section( SourceLineInfo const& lineInfo, - std::string const& name, - std::string const& description ) - : m_info( name, description, lineInfo ), - m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( m_info, m_assertions ) ) - { - m_timer.start(); - } - - Section::~Section() { - if( m_sectionIncluded ) - getCurrentContext().getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); - } - - // This indicates whether the section should be executed or not - Section::operator bool() { - return m_sectionIncluded; - } - -} // end namespace Catch - -// #included from: catch_debugger.hpp -#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED - -#include - -#ifdef CATCH_PLATFORM_MAC - - #include - #include - #include - #include - #include - - namespace Catch{ - - // The following function is taken directly from the following technical note: - // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html - - // Returns true if the current process is being debugged (either - // running under the debugger or has a debugger attached post facto). - bool isDebuggerActive(){ - - int mib[4]; - struct kinfo_proc info; - size_t size; - - // Initialize the flags so that, if sysctl fails for some bizarre - // reason, we get a predictable result. - - info.kp_proc.p_flag = 0; - - // Initialize mib, which tells sysctl the info we want, in this case - // we're looking for information about a specific process ID. - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - - // Call sysctl. - - size = sizeof(info); - if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) { - std::cerr << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; - return false; - } - - // We're being debugged if the P_TRACED flag is set. - - return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); - } - } // namespace Catch - -#elif defined(_MSC_VER) - extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); - namespace Catch { - bool isDebuggerActive() { - return IsDebuggerPresent() != 0; - } - } -#elif defined(__MINGW32__) - extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); - namespace Catch { - bool isDebuggerActive() { - return IsDebuggerPresent() != 0; - } - } -#else - namespace Catch { - inline bool isDebuggerActive() { return false; } - } -#endif // Platform - -#ifdef CATCH_PLATFORM_WINDOWS - extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - ::OutputDebugStringA( text.c_str() ); - } - } -#else - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - // !TBD: Need a version for Mac/ XCode and other IDEs - std::cout << text; - } - } -#endif // Platform - -// #included from: catch_tostring.hpp -#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED - -namespace Catch { - -std::string toString( std::string const& value ) { - std::string s = value; - if( getCurrentContext().getConfig()->showInvisibles() ) { - for(size_t i = 0; i < s.size(); ++i ) { - std::string subs; - switch( s[i] ) { - case '\n': subs = "\\n"; break; - case '\t': subs = "\\t"; break; - default: break; - } - if( !subs.empty() ) { - s = s.substr( 0, i ) + subs + s.substr( i+1 ); - ++i; - } - } - } - return "\"" + s + "\""; -} -std::string toString( std::wstring const& value ) { - - std::string s; - s.reserve( value.size() ); - for(size_t i = 0; i < value.size(); ++i ) - s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; - return toString( s ); -} - -std::string toString( const char* const value ) { - return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); -} - -std::string toString( char* const value ) { - return Catch::toString( static_cast( value ) ); -} - -std::string toString( int value ) { - std::ostringstream oss; - oss << value; - return oss.str(); -} - -std::string toString( unsigned long value ) { - std::ostringstream oss; - if( value > 8192 ) - oss << "0x" << std::hex << value; - else - oss << value; - return oss.str(); -} - -std::string toString( unsigned int value ) { - return toString( static_cast( value ) ); -} - -std::string toString( const double value ) { - std::ostringstream oss; - oss << std::setprecision( 10 ) - << std::fixed - << value; - std::string d = oss.str(); - std::size_t i = d.find_last_not_of( '0' ); - if( i != std::string::npos && i != d.size()-1 ) { - if( d[i] == '.' ) - i++; - d = d.substr( 0, i+1 ); - } - return d; -} - -std::string toString( bool value ) { - return value ? "true" : "false"; -} - -std::string toString( char value ) { - return value < ' ' - ? toString( static_cast( value ) ) - : Detail::makeString( value ); -} - -std::string toString( signed char value ) { - return toString( static_cast( value ) ); -} - -std::string toString( unsigned char value ) { - return toString( static_cast( value ) ); -} - -#ifdef CATCH_CONFIG_CPP11_NULLPTR -std::string toString( std::nullptr_t ) { - return "nullptr"; -} -#endif - -#ifdef __OBJC__ - std::string toString( NSString const * const& nsstring ) { - if( !nsstring ) - return "nil"; - return std::string( "@\"" ) + [nsstring UTF8String] + "\""; - } - std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { - if( !nsstring ) - return "nil"; - return std::string( "@\"" ) + [nsstring UTF8String] + "\""; - } - std::string toString( NSObject* const& nsObject ) { - return toString( [nsObject description] ); - } -#endif - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_xml.hpp -#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED - -// #included from: catch_reporter_bases.hpp -#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED - -namespace Catch { - - struct StreamingReporterBase : SharedImpl { - - StreamingReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - {} - - virtual ~StreamingReporterBase(); - - virtual void noMatchingTestCases( std::string const& ) {} - - virtual void testRunStarting( TestRunInfo const& _testRunInfo ) { - currentTestRunInfo = _testRunInfo; - } - virtual void testGroupStarting( GroupInfo const& _groupInfo ) { - currentGroupInfo = _groupInfo; - } - - virtual void testCaseStarting( TestCaseInfo const& _testInfo ) { - currentTestCaseInfo = _testInfo; - } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) { - m_sectionStack.push_back( _sectionInfo ); - } - - virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) { - m_sectionStack.pop_back(); - } - virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) { - currentTestCaseInfo.reset(); - assert( m_sectionStack.empty() ); - } - virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) { - currentGroupInfo.reset(); - } - virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) { - currentTestCaseInfo.reset(); - currentGroupInfo.reset(); - currentTestRunInfo.reset(); - } - - Ptr m_config; - std::ostream& stream; - - LazyStat currentTestRunInfo; - LazyStat currentGroupInfo; - LazyStat currentTestCaseInfo; - - std::vector m_sectionStack; - }; - - struct CumulativeReporterBase : SharedImpl { - template - struct Node : SharedImpl<> { - explicit Node( T const& _value ) : value( _value ) {} - virtual ~Node() {} - - typedef std::vector > ChildNodes; - T value; - ChildNodes children; - }; - struct SectionNode : SharedImpl<> { - explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} - virtual ~SectionNode(); - - bool operator == ( SectionNode const& other ) const { - return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; - } - bool operator == ( Ptr const& other ) const { - return operator==( *other ); - } - - SectionStats stats; - typedef std::vector > ChildSections; - typedef std::vector Assertions; - ChildSections childSections; - Assertions assertions; - std::string stdOut; - std::string stdErr; - }; - - struct BySectionInfo { - BySectionInfo( SectionInfo const& other ) : m_other( other ) {} - bool operator() ( Ptr const& node ) const { - return node->stats.sectionInfo.lineInfo == m_other.lineInfo; - } - private: - BySectionInfo& operator=( BySectionInfo const& other ); // = delete; - - SectionInfo const& m_other; - }; - - typedef Node TestCaseNode; - typedef Node TestGroupNode; - typedef Node TestRunNode; - - CumulativeReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - {} - ~CumulativeReporterBase(); - - virtual void testRunStarting( TestRunInfo const& ) {} - virtual void testGroupStarting( GroupInfo const& ) {} - - virtual void testCaseStarting( TestCaseInfo const& ) {} - - virtual void sectionStarting( SectionInfo const& sectionInfo ) { - SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); - Ptr node; - if( m_sectionStack.empty() ) { - if( !m_rootSection ) - m_rootSection = new SectionNode( incompleteStats ); - node = m_rootSection; - } - else { - SectionNode& parentNode = *m_sectionStack.back(); - SectionNode::ChildSections::const_iterator it = - std::find_if( parentNode.childSections.begin(), - parentNode.childSections.end(), - BySectionInfo( sectionInfo ) ); - if( it == parentNode.childSections.end() ) { - node = new SectionNode( incompleteStats ); - parentNode.childSections.push_back( node ); - } - else - node = *it; - } - m_sectionStack.push_back( node ); - m_deepestSection = node; - } - - virtual void assertionStarting( AssertionInfo const& ) {} - - virtual bool assertionEnded( AssertionStats const& assertionStats ) { - assert( !m_sectionStack.empty() ); - SectionNode& sectionNode = *m_sectionStack.back(); - sectionNode.assertions.push_back( assertionStats ); - return true; - } - virtual void sectionEnded( SectionStats const& sectionStats ) { - assert( !m_sectionStack.empty() ); - SectionNode& node = *m_sectionStack.back(); - node.stats = sectionStats; - m_sectionStack.pop_back(); - } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { - Ptr node = new TestCaseNode( testCaseStats ); - assert( m_sectionStack.size() == 0 ); - node->children.push_back( m_rootSection ); - m_testCases.push_back( node ); - m_rootSection.reset(); - - assert( m_deepestSection ); - m_deepestSection->stdOut = testCaseStats.stdOut; - m_deepestSection->stdErr = testCaseStats.stdErr; - } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { - Ptr node = new TestGroupNode( testGroupStats ); - node->children.swap( m_testCases ); - m_testGroups.push_back( node ); - } - virtual void testRunEnded( TestRunStats const& testRunStats ) { - Ptr node = new TestRunNode( testRunStats ); - node->children.swap( m_testGroups ); - m_testRuns.push_back( node ); - testRunEndedCumulative(); - } - virtual void testRunEndedCumulative() = 0; - - Ptr m_config; - std::ostream& stream; - std::vector m_assertions; - std::vector > > m_sections; - std::vector > m_testCases; - std::vector > m_testGroups; - - std::vector > m_testRuns; - - Ptr m_rootSection; - Ptr m_deepestSection; - std::vector > m_sectionStack; - - }; - -} // end namespace Catch - -// #included from: ../internal/catch_reporter_registrars.hpp -#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED - -namespace Catch { - - template - class LegacyReporterRegistrar { - - class ReporterFactory : public IReporterFactory { - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new LegacyReporterAdapter( new T( config ) ); - } - - virtual std::string getDescription() const { - return T::getDescription(); - } - }; - - public: - - LegacyReporterRegistrar( std::string const& name ) { - getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); - } - }; - - template - class ReporterRegistrar { - - class ReporterFactory : public IReporterFactory { - - // *** Please Note ***: - // - If you end up here looking at a compiler error because it's trying to register - // your custom reporter class be aware that the native reporter interface has changed - // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via - // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. - // However please consider updating to the new interface as the old one is now - // deprecated and will probably be removed quite soon! - // Please contact me via github if you have any questions at all about this. - // In fact, ideally, please contact me anyway to let me know you've hit this - as I have - // no idea who is actually using custom reporters at all (possibly no-one!). - // The new interface is designed to minimise exposure to interface changes in the future. - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new T( config ); - } - - virtual std::string getDescription() const { - return T::getDescription(); - } - }; - - public: - - ReporterRegistrar( std::string const& name ) { - getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); - } - }; -} - -#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ - namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } -#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ - namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } - -// #included from: ../internal/catch_xmlwriter.hpp -#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED - -#include -#include -#include -#include - -namespace Catch { - - class XmlWriter { - public: - - class ScopedElement { - public: - ScopedElement( XmlWriter* writer ) - : m_writer( writer ) - {} - - ScopedElement( ScopedElement const& other ) - : m_writer( other.m_writer ){ - other.m_writer = NULL; - } - - ~ScopedElement() { - if( m_writer ) - m_writer->endElement(); - } - - ScopedElement& writeText( std::string const& text, bool indent = true ) { - m_writer->writeText( text, indent ); - return *this; - } - - template - ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { - m_writer->writeAttribute( name, attribute ); - return *this; - } - - private: - mutable XmlWriter* m_writer; - }; - - XmlWriter() - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( &std::cout ) - {} - - XmlWriter( std::ostream& os ) - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( &os ) - {} - - ~XmlWriter() { - while( !m_tags.empty() ) - endElement(); - } - -# ifndef CATCH_CPP11_OR_GREATER - XmlWriter& operator = ( XmlWriter const& other ) { - XmlWriter temp( other ); - swap( temp ); - return *this; - } -# else - XmlWriter( XmlWriter const& ) = default; - XmlWriter( XmlWriter && ) = default; - XmlWriter& operator = ( XmlWriter const& ) = default; - XmlWriter& operator = ( XmlWriter && ) = default; -# endif - - void swap( XmlWriter& other ) { - std::swap( m_tagIsOpen, other.m_tagIsOpen ); - std::swap( m_needsNewline, other.m_needsNewline ); - std::swap( m_tags, other.m_tags ); - std::swap( m_indent, other.m_indent ); - std::swap( m_os, other.m_os ); - } - - XmlWriter& startElement( std::string const& name ) { - ensureTagClosed(); - newlineIfNecessary(); - stream() << m_indent << "<" << name; - m_tags.push_back( name ); - m_indent += " "; - m_tagIsOpen = true; - return *this; - } - - ScopedElement scopedElement( std::string const& name ) { - ScopedElement scoped( this ); - startElement( name ); - return scoped; - } - - XmlWriter& endElement() { - newlineIfNecessary(); - m_indent = m_indent.substr( 0, m_indent.size()-2 ); - if( m_tagIsOpen ) { - stream() << "/>\n"; - m_tagIsOpen = false; - } - else { - stream() << m_indent << "\n"; - } - m_tags.pop_back(); - return *this; - } - - XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { - if( !name.empty() && !attribute.empty() ) { - stream() << " " << name << "=\""; - writeEncodedText( attribute ); - stream() << "\""; - } - return *this; - } - - XmlWriter& writeAttribute( std::string const& name, bool attribute ) { - stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; - return *this; - } - - template - XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { - if( !name.empty() ) - stream() << " " << name << "=\"" << attribute << "\""; - return *this; - } - - XmlWriter& writeText( std::string const& text, bool indent = true ) { - if( !text.empty() ){ - bool tagWasOpen = m_tagIsOpen; - ensureTagClosed(); - if( tagWasOpen && indent ) - stream() << m_indent; - writeEncodedText( text ); - m_needsNewline = true; - } - return *this; - } - - XmlWriter& writeComment( std::string const& text ) { - ensureTagClosed(); - stream() << m_indent << ""; - m_needsNewline = true; - return *this; - } - - XmlWriter& writeBlankLine() { - ensureTagClosed(); - stream() << "\n"; - return *this; - } - - private: - - std::ostream& stream() { - return *m_os; - } - - void ensureTagClosed() { - if( m_tagIsOpen ) { - stream() << ">\n"; - m_tagIsOpen = false; - } - } - - void newlineIfNecessary() { - if( m_needsNewline ) { - stream() << "\n"; - m_needsNewline = false; - } - } - - void writeEncodedText( std::string const& text ) { - static const char* charsToEncode = "<&\""; - std::string mtext = text; - std::string::size_type pos = mtext.find_first_of( charsToEncode ); - while( pos != std::string::npos ) { - stream() << mtext.substr( 0, pos ); - - switch( mtext[pos] ) { - case '<': - stream() << "<"; - break; - case '&': - stream() << "&"; - break; - case '\"': - stream() << """; - break; - } - mtext = mtext.substr( pos+1 ); - pos = mtext.find_first_of( charsToEncode ); - } - stream() << mtext; - } - - bool m_tagIsOpen; - bool m_needsNewline; - std::vector m_tags; - std::string m_indent; - std::ostream* m_os; - }; - -} -namespace Catch { - class XmlReporter : public SharedImpl { - public: - XmlReporter( ReporterConfig const& config ) : m_config( config ), m_sectionDepth( 0 ) {} - - static std::string getDescription() { - return "Reports test results as an XML document"; - } - virtual ~XmlReporter(); - - private: // IReporter - - virtual bool shouldRedirectStdout() const { - return true; - } - - virtual void StartTesting() { - m_xml = XmlWriter( m_config.stream() ); - m_xml.startElement( "Catch" ); - if( !m_config.fullConfig()->name().empty() ) - m_xml.writeAttribute( "name", m_config.fullConfig()->name() ); - } - - virtual void EndTesting( const Totals& totals ) { - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", totals.assertions.passed ) - .writeAttribute( "failures", totals.assertions.failed ); - m_xml.endElement(); - } - - virtual void StartGroup( const std::string& groupName ) { - m_xml.startElement( "Group" ) - .writeAttribute( "name", groupName ); - } - - virtual void EndGroup( const std::string&, const Totals& totals ) { - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", totals.assertions.passed ) - .writeAttribute( "failures", totals.assertions.failed ); - m_xml.endElement(); - } - - virtual void StartSection( const std::string& sectionName, const std::string& description ) { - if( m_sectionDepth++ > 0 ) { - m_xml.startElement( "Section" ) - .writeAttribute( "name", trim( sectionName ) ) - .writeAttribute( "description", description ); - } - } - virtual void NoAssertionsInSection( const std::string& ) {} - virtual void NoAssertionsInTestCase( const std::string& ) {} - - virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) { - if( --m_sectionDepth > 0 ) { - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", assertions.passed ) - .writeAttribute( "failures", assertions.failed ); - m_xml.endElement(); - } - } - - virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) { - m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); - m_currentTestSuccess = true; - } - - virtual void Result( const Catch::AssertionResult& assertionResult ) { - if( !m_config.fullConfig()->includeSuccessfulResults() && assertionResult.getResultType() == ResultWas::Ok ) - return; - - if( assertionResult.hasExpression() ) { - m_xml.startElement( "Expression" ) - .writeAttribute( "success", assertionResult.succeeded() ) - .writeAttribute( "filename", assertionResult.getSourceInfo().file ) - .writeAttribute( "line", assertionResult.getSourceInfo().line ); - - m_xml.scopedElement( "Original" ) - .writeText( assertionResult.getExpression() ); - m_xml.scopedElement( "Expanded" ) - .writeText( assertionResult.getExpandedExpression() ); - m_currentTestSuccess &= assertionResult.succeeded(); - } - - switch( assertionResult.getResultType() ) { - case ResultWas::ThrewException: - m_xml.scopedElement( "Exception" ) - .writeAttribute( "filename", assertionResult.getSourceInfo().file ) - .writeAttribute( "line", assertionResult.getSourceInfo().line ) - .writeText( assertionResult.getMessage() ); - m_currentTestSuccess = false; - break; - case ResultWas::Info: - m_xml.scopedElement( "Info" ) - .writeText( assertionResult.getMessage() ); - break; - case ResultWas::Warning: - m_xml.scopedElement( "Warning" ) - .writeText( assertionResult.getMessage() ); - break; - case ResultWas::ExplicitFailure: - m_xml.scopedElement( "Failure" ) - .writeText( assertionResult.getMessage() ); - m_currentTestSuccess = false; - break; - case ResultWas::Unknown: - case ResultWas::Ok: - case ResultWas::FailureBit: - case ResultWas::ExpressionFailed: - case ResultWas::Exception: - case ResultWas::DidntThrowException: - break; - } - if( assertionResult.hasExpression() ) - m_xml.endElement(); - } - - virtual void Aborted() { - // !TBD - } - - virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) { - m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess ); - m_xml.endElement(); - } - - private: - ReporterConfig m_config; - bool m_currentTestSuccess; - XmlWriter m_xml; - int m_sectionDepth; - }; - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_junit.hpp -#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED - -#include - -namespace Catch { - - class JunitReporter : public CumulativeReporterBase { - public: - JunitReporter( ReporterConfig const& _config ) - : CumulativeReporterBase( _config ), - xml( _config.stream() ) - {} - - ~JunitReporter(); - - static std::string getDescription() { - return "Reports test results in an XML format that looks like Ant's junitreport target"; - } - - virtual void noMatchingTestCases( std::string const& /*spec*/ ) {} - - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = true; - return prefs; - } - - virtual void testRunStarting( TestRunInfo const& runInfo ) { - CumulativeReporterBase::testRunStarting( runInfo ); - xml.startElement( "testsuites" ); - } - - virtual void testGroupStarting( GroupInfo const& groupInfo ) { - suiteTimer.start(); - stdOutForSuite.str(""); - stdErrForSuite.str(""); - unexpectedExceptions = 0; - CumulativeReporterBase::testGroupStarting( groupInfo ); - } - - virtual bool assertionEnded( AssertionStats const& assertionStats ) { - if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) - unexpectedExceptions++; - return CumulativeReporterBase::assertionEnded( assertionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { - stdOutForSuite << testCaseStats.stdOut; - stdErrForSuite << testCaseStats.stdErr; - CumulativeReporterBase::testCaseEnded( testCaseStats ); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { - double suiteTime = suiteTimer.getElapsedSeconds(); - CumulativeReporterBase::testGroupEnded( testGroupStats ); - writeGroup( *m_testGroups.back(), suiteTime ); - } - - virtual void testRunEndedCumulative() { - xml.endElement(); - } - - void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { - XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); - TestGroupStats const& stats = groupNode.value; - xml.writeAttribute( "name", stats.groupInfo.name ); - xml.writeAttribute( "errors", unexpectedExceptions ); - xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); - xml.writeAttribute( "tests", stats.totals.assertions.total() ); - xml.writeAttribute( "hostname", "tbd" ); // !TBD - if( m_config->showDurations() == ShowDurations::Never ) - xml.writeAttribute( "time", "" ); - else - xml.writeAttribute( "time", suiteTime ); - xml.writeAttribute( "timestamp", "tbd" ); // !TBD - - // Write test cases - for( TestGroupNode::ChildNodes::const_iterator - it = groupNode.children.begin(), itEnd = groupNode.children.end(); - it != itEnd; - ++it ) - writeTestCase( **it ); - - xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); - xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); - } - - void writeTestCase( TestCaseNode const& testCaseNode ) { - TestCaseStats const& stats = testCaseNode.value; - - // All test cases have exactly one section - which represents the - // test case itself. That section may have 0-n nested sections - assert( testCaseNode.children.size() == 1 ); - SectionNode const& rootSection = *testCaseNode.children.front(); - - std::string className = stats.testInfo.className; - - if( className.empty() ) { - if( rootSection.childSections.empty() ) - className = "global"; - } - writeSection( className, "", rootSection ); - } - - void writeSection( std::string const& className, - std::string const& rootName, - SectionNode const& sectionNode ) { - std::string name = trim( sectionNode.stats.sectionInfo.name ); - if( !rootName.empty() ) - name = rootName + "/" + name; - - if( !sectionNode.assertions.empty() || - !sectionNode.stdOut.empty() || - !sectionNode.stdErr.empty() ) { - XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); - if( className.empty() ) { - xml.writeAttribute( "classname", name ); - xml.writeAttribute( "name", "root" ); - } - else { - xml.writeAttribute( "classname", className ); - xml.writeAttribute( "name", name ); - } - xml.writeAttribute( "time", toString( sectionNode.stats.durationInSeconds ) ); - - writeAssertions( sectionNode ); - - if( !sectionNode.stdOut.empty() ) - xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); - if( !sectionNode.stdErr.empty() ) - xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); - } - for( SectionNode::ChildSections::const_iterator - it = sectionNode.childSections.begin(), - itEnd = sectionNode.childSections.end(); - it != itEnd; - ++it ) - if( className.empty() ) - writeSection( name, "", **it ); - else - writeSection( className, name, **it ); - } - - void writeAssertions( SectionNode const& sectionNode ) { - for( SectionNode::Assertions::const_iterator - it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); - it != itEnd; - ++it ) - writeAssertion( *it ); - } - void writeAssertion( AssertionStats const& stats ) { - AssertionResult const& result = stats.assertionResult; - if( !result.isOk() ) { - std::string elementName; - switch( result.getResultType() ) { - case ResultWas::ThrewException: - elementName = "error"; - break; - case ResultWas::ExplicitFailure: - elementName = "failure"; - break; - case ResultWas::ExpressionFailed: - elementName = "failure"; - break; - case ResultWas::DidntThrowException: - elementName = "failure"; - break; - - // We should never see these here: - case ResultWas::Info: - case ResultWas::Warning: - case ResultWas::Ok: - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - elementName = "internalError"; - break; - } - - XmlWriter::ScopedElement e = xml.scopedElement( elementName ); - - xml.writeAttribute( "message", result.getExpandedExpression() ); - xml.writeAttribute( "type", result.getTestMacroName() ); - - std::ostringstream oss; - if( !result.getMessage().empty() ) - oss << result.getMessage() << "\n"; - for( std::vector::const_iterator - it = stats.infoMessages.begin(), - itEnd = stats.infoMessages.end(); - it != itEnd; - ++it ) - if( it->type == ResultWas::Info ) - oss << it->message << "\n"; - - oss << "at " << result.getSourceInfo(); - xml.writeText( oss.str(), false ); - } - } - - XmlWriter xml; - Timer suiteTimer; - std::ostringstream stdOutForSuite; - std::ostringstream stdErrForSuite; - unsigned int unexpectedExceptions; - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_console.hpp -#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED - -#include - -namespace Catch { - - struct ConsoleReporter : StreamingReporterBase { - ConsoleReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ), - m_headerPrinted( false ), - m_atLeastOneTestCasePrinted( false ) - {} - - virtual ~ConsoleReporter(); - static std::string getDescription() { - return "Reports test results as plain lines of text"; - } - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = false; - return prefs; - } - - virtual void noMatchingTestCases( std::string const& spec ) { - stream << "No test cases matched '" << spec << "'" << std::endl; - } - - virtual void assertionStarting( AssertionInfo const& ) { - } - - virtual bool assertionEnded( AssertionStats const& _assertionStats ) { - AssertionResult const& result = _assertionStats.assertionResult; - - bool printInfoMessages = true; - - // Drop out if result was successful and we're not printing those - if( !m_config->includeSuccessfulResults() && result.isOk() ) { - if( result.getResultType() != ResultWas::Warning ) - return false; - printInfoMessages = false; - } - - lazyPrint(); - - AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); - printer.print(); - stream << std::endl; - return true; - } - - virtual void sectionStarting( SectionInfo const& _sectionInfo ) { - m_headerPrinted = false; - StreamingReporterBase::sectionStarting( _sectionInfo ); - } - virtual void sectionEnded( SectionStats const& _sectionStats ) { - if( _sectionStats.missingAssertions ) { - lazyPrint(); - Colour colour( Colour::ResultError ); - if( m_sectionStack.size() > 1 ) - stream << "\nNo assertions in section"; - else - stream << "\nNo assertions in test case"; - stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; - } - if( m_headerPrinted ) { - if( m_config->showDurations() == ShowDurations::Always ) - stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; - m_headerPrinted = false; - } - else { - if( m_config->showDurations() == ShowDurations::Always ) - stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; - } - StreamingReporterBase::sectionEnded( _sectionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) { - StreamingReporterBase::testCaseEnded( _testCaseStats ); - m_headerPrinted = false; - } - virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) { - if( currentGroupInfo.used ) { - printSummaryDivider(); - stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; - printTotals( _testGroupStats.totals ); - stream << "\n" << std::endl; - } - StreamingReporterBase::testGroupEnded( _testGroupStats ); - } - virtual void testRunEnded( TestRunStats const& _testRunStats ) { - if( m_atLeastOneTestCasePrinted ) - printTotalsDivider(); - printTotals( _testRunStats.totals ); - stream << "\n" << std::endl; - StreamingReporterBase::testRunEnded( _testRunStats ); - } - - private: - - class AssertionPrinter { - void operator= ( AssertionPrinter const& ); - public: - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) - : stream( _stream ), - stats( _stats ), - result( _stats.assertionResult ), - colour( Colour::None ), - message( result.getMessage() ), - messages( _stats.infoMessages ), - printInfoMessages( _printInfoMessages ) - { - switch( result.getResultType() ) { - case ResultWas::Ok: - colour = Colour::Success; - passOrFail = "PASSED"; - //if( result.hasMessage() ) - if( _stats.infoMessages.size() == 1 ) - messageLabel = "with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "with messages"; - break; - case ResultWas::ExpressionFailed: - if( result.isOk() ) { - colour = Colour::Success; - passOrFail = "FAILED - but was ok"; - } - else { - colour = Colour::Error; - passOrFail = "FAILED"; - } - if( _stats.infoMessages.size() == 1 ) - messageLabel = "with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "with messages"; - break; - case ResultWas::ThrewException: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "due to unexpected exception with message"; - break; - case ResultWas::DidntThrowException: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "because no exception was thrown where one was expected"; - break; - case ResultWas::Info: - messageLabel = "info"; - break; - case ResultWas::Warning: - messageLabel = "warning"; - break; - case ResultWas::ExplicitFailure: - passOrFail = "FAILED"; - colour = Colour::Error; - if( _stats.infoMessages.size() == 1 ) - messageLabel = "explicitly with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "explicitly with messages"; - break; - // These cases are here to prevent compiler warnings - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - passOrFail = "** internal error **"; - colour = Colour::Error; - break; - } - } - - void print() const { - printSourceInfo(); - if( stats.totals.assertions.total() > 0 ) { - if( result.isOk() ) - stream << "\n"; - printResultType(); - printOriginalExpression(); - printReconstructedExpression(); - } - else { - stream << "\n"; - } - printMessage(); - } - - private: - void printResultType() const { - if( !passOrFail.empty() ) { - Colour colourGuard( colour ); - stream << passOrFail << ":\n"; - } - } - void printOriginalExpression() const { - if( result.hasExpression() ) { - Colour colourGuard( Colour::OriginalExpression ); - stream << " "; - stream << result.getExpressionInMacro(); - stream << "\n"; - } - } - void printReconstructedExpression() const { - if( result.hasExpandedExpression() ) { - stream << "with expansion:\n"; - Colour colourGuard( Colour::ReconstructedExpression ); - stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n"; - } - } - void printMessage() const { - if( !messageLabel.empty() ) - stream << messageLabel << ":" << "\n"; - for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); - it != itEnd; - ++it ) { - // If this assertion is a warning ignore any INFO messages - if( printInfoMessages || it->type != ResultWas::Info ) - stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n"; - } - } - void printSourceInfo() const { - Colour colourGuard( Colour::FileName ); - stream << result.getSourceInfo() << ": "; - } - - std::ostream& stream; - AssertionStats const& stats; - AssertionResult const& result; - Colour::Code colour; - std::string passOrFail; - std::string messageLabel; - std::string message; - std::vector messages; - bool printInfoMessages; - }; - - void lazyPrint() { - - if( !currentTestRunInfo.used ) - lazyPrintRunInfo(); - if( !currentGroupInfo.used ) - lazyPrintGroupInfo(); - - if( !m_headerPrinted ) { - printTestCaseAndSectionHeader(); - m_headerPrinted = true; - } - m_atLeastOneTestCasePrinted = true; - } - void lazyPrintRunInfo() { - stream << "\n" << getLineOfChars<'~'>() << "\n"; - Colour colour( Colour::SecondaryText ); - stream << currentTestRunInfo->name - << " is a Catch v" << libraryVersion.majorVersion << "." - << libraryVersion.minorVersion << " b" - << libraryVersion.buildNumber; - if( libraryVersion.branchName != std::string( "master" ) ) - stream << " (" << libraryVersion.branchName << ")"; - stream << " host application.\n" - << "Run with -? for options\n\n"; - - currentTestRunInfo.used = true; - } - void lazyPrintGroupInfo() { - if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { - printClosedHeader( "Group: " + currentGroupInfo->name ); - currentGroupInfo.used = true; - } - } - void printTestCaseAndSectionHeader() { - assert( !m_sectionStack.empty() ); - printOpenHeader( currentTestCaseInfo->name ); - - if( m_sectionStack.size() > 1 ) { - Colour colourGuard( Colour::Headers ); - - std::vector::const_iterator - it = m_sectionStack.begin()+1, // Skip first section (test case) - itEnd = m_sectionStack.end(); - for( ; it != itEnd; ++it ) - printHeaderString( it->name, 2 ); - } - - SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; - - if( !lineInfo.empty() ){ - stream << getLineOfChars<'-'>() << "\n"; - Colour colourGuard( Colour::FileName ); - stream << lineInfo << "\n"; - } - stream << getLineOfChars<'.'>() << "\n" << std::endl; - } - - void printClosedHeader( std::string const& _name ) { - printOpenHeader( _name ); - stream << getLineOfChars<'.'>() << "\n"; - } - void printOpenHeader( std::string const& _name ) { - stream << getLineOfChars<'-'>() << "\n"; - { - Colour colourGuard( Colour::Headers ); - printHeaderString( _name ); - } - } - - // if string has a : in first line will set indent to follow it on - // subsequent lines - void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { - std::size_t i = _string.find( ": " ); - if( i != std::string::npos ) - i+=2; - else - i = 0; - stream << Text( _string, TextAttributes() - .setIndent( indent+i) - .setInitialIndent( indent ) ) << "\n"; - } - - void printTotals( const Totals& totals ) { - if( totals.testCases.total() == 0 ) { - stream << "No tests ran"; - } - else if( totals.assertions.total() == 0 ) { - Colour colour( Colour::Yellow ); - printCounts( "test case", totals.testCases ); - stream << " (no assertions)"; - } - else if( totals.assertions.failed ) { - Colour colour( Colour::ResultError ); - printCounts( "test case", totals.testCases ); - if( totals.testCases.failed > 0 ) { - stream << " ("; - printCounts( "assertion", totals.assertions ); - stream << ")"; - } - } - else { - Colour colour( Colour::ResultSuccess ); - stream << "All tests passed (" - << pluralise( totals.assertions.passed, "assertion" ) << " in " - << pluralise( totals.testCases.passed, "test case" ) << ")"; - } - } - void printCounts( std::string const& label, Counts const& counts ) { - if( counts.total() == 1 ) { - stream << "1 " << label << " - "; - if( counts.failed ) - stream << "failed"; - else - stream << "passed"; - } - else { - stream << counts.total() << " " << label << "s "; - if( counts.passed ) { - if( counts.failed ) - stream << "- " << counts.failed << " failed"; - else if( counts.passed == 2 ) - stream << "- both passed"; - else - stream << "- all passed"; - } - else { - if( counts.failed == 2 ) - stream << "- both failed"; - else - stream << "- all failed"; - } - } - } - - void printTotalsDivider() { - stream << getLineOfChars<'='>() << "\n"; - } - void printSummaryDivider() { - stream << getLineOfChars<'-'>() << "\n"; - } - template - static char const* getLineOfChars() { - static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; - if( !*line ) { - memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); - line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; - } - return line; - } - - private: - bool m_headerPrinted; - bool m_atLeastOneTestCasePrinted; - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_compact.hpp -#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED - -namespace Catch { - - struct CompactReporter : StreamingReporterBase { - - CompactReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ) - {} - - virtual ~CompactReporter(); - - static std::string getDescription() { - return "Reports test results on a single line, suitable for IDEs"; - } - - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = false; - return prefs; - } - - virtual void noMatchingTestCases( std::string const& spec ) { - stream << "No test cases matched '" << spec << "'" << std::endl; - } - - virtual void assertionStarting( AssertionInfo const& ) { - } - - virtual bool assertionEnded( AssertionStats const& _assertionStats ) { - AssertionResult const& result = _assertionStats.assertionResult; - - bool printInfoMessages = true; - - // Drop out if result was successful and we're not printing those - if( !m_config->includeSuccessfulResults() && result.isOk() ) { - if( result.getResultType() != ResultWas::Warning ) - return false; - printInfoMessages = false; - } - - AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); - printer.print(); - - stream << std::endl; - return true; - } - - virtual void testRunEnded( TestRunStats const& _testRunStats ) { - printTotals( _testRunStats.totals ); - stream << "\n" << std::endl; - StreamingReporterBase::testRunEnded( _testRunStats ); - } - - private: - class AssertionPrinter { - void operator= ( AssertionPrinter const& ); - public: - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) - : stream( _stream ) - , stats( _stats ) - , result( _stats.assertionResult ) - , messages( _stats.infoMessages ) - , itMessage( _stats.infoMessages.begin() ) - , printInfoMessages( _printInfoMessages ) - {} - - void print() { - printSourceInfo(); - - itMessage = messages.begin(); - - switch( result.getResultType() ) { - case ResultWas::Ok: - printResultType( Colour::ResultSuccess, passedString() ); - printOriginalExpression(); - printReconstructedExpression(); - if ( ! result.hasExpression() ) - printRemainingMessages( Colour::None ); - else - printRemainingMessages(); - break; - case ResultWas::ExpressionFailed: - if( result.isOk() ) - printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); - else - printResultType( Colour::Error, failedString() ); - printOriginalExpression(); - printReconstructedExpression(); - printRemainingMessages(); - break; - case ResultWas::ThrewException: - printResultType( Colour::Error, failedString() ); - printIssue( "unexpected exception with message:" ); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::DidntThrowException: - printResultType( Colour::Error, failedString() ); - printIssue( "expected exception, got none" ); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::Info: - printResultType( Colour::None, "info" ); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::Warning: - printResultType( Colour::None, "warning" ); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::ExplicitFailure: - printResultType( Colour::Error, failedString() ); - printIssue( "explicitly" ); - printRemainingMessages( Colour::None ); - break; - // These cases are here to prevent compiler warnings - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - printResultType( Colour::Error, "** internal error **" ); - break; - } - } - - private: - // Colour::LightGrey - - static Colour dimColour() { return Colour::FileName; } - -#ifdef CATCH_PLATFORM_MAC - static const char* failedString() { return "FAILED"; } - static const char* passedString() { return "PASSED"; } -#else - static const char* failedString() { return "failed"; } - static const char* passedString() { return "passed"; } -#endif - - void printSourceInfo() const { - Colour colourGuard( Colour::FileName ); - stream << result.getSourceInfo() << ":"; - } - - void printResultType( Colour colour, std::string passOrFail ) const { - if( !passOrFail.empty() ) { - { - Colour colourGuard( colour ); - stream << " " << passOrFail; - } - stream << ":"; - } - } - - void printIssue( std::string issue ) const { - stream << " " << issue; - } - - void printExpressionWas() { - if( result.hasExpression() ) { - stream << ";"; - { - Colour colour( dimColour() ); - stream << " expression was:"; - } - printOriginalExpression(); - } - } - - void printOriginalExpression() const { - if( result.hasExpression() ) { - stream << " " << result.getExpression(); - } - } - - void printReconstructedExpression() const { - if( result.hasExpandedExpression() ) { - { - Colour colour( dimColour() ); - stream << " for: "; - } - stream << result.getExpandedExpression(); - } - } - - void printMessage() { - if ( itMessage != messages.end() ) { - stream << " '" << itMessage->message << "'"; - ++itMessage; - } - } - - void printRemainingMessages( Colour colour = dimColour() ) { - if ( itMessage == messages.end() ) - return; - - // using messages.end() directly yields compilation error: - std::vector::const_iterator itEnd = messages.end(); - const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); - - { - Colour colourGuard( colour ); - stream << " with " << pluralise( N, "message" ) << ":"; - } - - for(; itMessage != itEnd; ) { - // If this assertion is a warning ignore any INFO messages - if( printInfoMessages || itMessage->type != ResultWas::Info ) { - stream << " '" << itMessage->message << "'"; - if ( ++itMessage != itEnd ) { - Colour colourGuard( dimColour() ); - stream << " and"; - } - } - } - } - - private: - std::ostream& stream; - AssertionStats const& stats; - AssertionResult const& result; - std::vector messages; - std::vector::const_iterator itMessage; - bool printInfoMessages; - }; - - // Colour, message variants: - // - white: No tests ran. - // - red: Failed [both/all] N test cases, failed [both/all] M assertions. - // - white: Passed [both/all] N test cases (no assertions). - // - red: Failed N tests cases, failed M assertions. - // - green: Passed [both/all] N tests cases with M assertions. - - std::string bothOrAll( std::size_t count ) const { - return count == 1 ? "" : count == 2 ? "both " : "all " ; - } - - void printTotals( const Totals& totals ) const { - if( totals.testCases.total() == 0 ) { - stream << "No tests ran."; - } - else if( totals.testCases.failed == totals.testCases.total() ) { - Colour colour( Colour::ResultError ); - const std::string qualify_assertions_failed = - totals.assertions.failed == totals.assertions.total() ? - bothOrAll( totals.assertions.failed ) : ""; - stream << - "Failed " << bothOrAll( totals.testCases.failed ) - << pluralise( totals.testCases.failed, "test case" ) << ", " - "failed " << qualify_assertions_failed << - pluralise( totals.assertions.failed, "assertion" ) << "."; - } - else if( totals.assertions.total() == 0 ) { - stream << - "Passed " << bothOrAll( totals.testCases.total() ) - << pluralise( totals.testCases.total(), "test case" ) - << " (no assertions)."; - } - else if( totals.assertions.failed ) { - Colour colour( Colour::ResultError ); - stream << - "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " - "failed " << pluralise( totals.assertions.failed, "assertion" ) << "."; - } - else { - Colour colour( Colour::ResultSuccess ); - stream << - "Passed " << bothOrAll( totals.testCases.passed ) - << pluralise( totals.testCases.passed, "test case" ) << - " with " << pluralise( totals.assertions.passed, "assertion" ) << "."; - } - } - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) - -} // end namespace Catch - -namespace Catch { - NonCopyable::~NonCopyable() {} - IShared::~IShared() {} - StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} - IContext::~IContext() {} - IResultCapture::~IResultCapture() {} - ITestCase::~ITestCase() {} - ITestCaseRegistry::~ITestCaseRegistry() {} - IRegistryHub::~IRegistryHub() {} - IMutableRegistryHub::~IMutableRegistryHub() {} - IExceptionTranslator::~IExceptionTranslator() {} - IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} - IReporter::~IReporter() {} - IReporterFactory::~IReporterFactory() {} - IReporterRegistry::~IReporterRegistry() {} - IStreamingReporter::~IStreamingReporter() {} - AssertionStats::~AssertionStats() {} - SectionStats::~SectionStats() {} - TestCaseStats::~TestCaseStats() {} - TestGroupStats::~TestGroupStats() {} - TestRunStats::~TestRunStats() {} - CumulativeReporterBase::SectionNode::~SectionNode() {} - CumulativeReporterBase::~CumulativeReporterBase() {} - - StreamingReporterBase::~StreamingReporterBase() {} - ConsoleReporter::~ConsoleReporter() {} - CompactReporter::~CompactReporter() {} - IRunner::~IRunner() {} - IMutableContext::~IMutableContext() {} - IConfig::~IConfig() {} - XmlReporter::~XmlReporter() {} - JunitReporter::~JunitReporter() {} - TestRegistry::~TestRegistry() {} - FreeFunctionTestCase::~FreeFunctionTestCase() {} - IGeneratorInfo::~IGeneratorInfo() {} - IGeneratorsForTest::~IGeneratorsForTest() {} - TestSpec::Pattern::~Pattern() {} - TestSpec::NamePattern::~NamePattern() {} - TestSpec::TagPattern::~TagPattern() {} - TestSpec::ExcludedPattern::~ExcludedPattern() {} - - Matchers::Impl::StdString::Equals::~Equals() {} - Matchers::Impl::StdString::Contains::~Contains() {} - Matchers::Impl::StdString::StartsWith::~StartsWith() {} - Matchers::Impl::StdString::EndsWith::~EndsWith() {} - - void Config::dummy() {} - - INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter ) -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#endif - -#ifdef CATCH_CONFIG_MAIN -// #included from: internal/catch_default_main.hpp -#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED - -#ifndef __OBJC__ - -// Standard C/C++ main entry point -int main (int argc, char * const argv[]) { - return Catch::Session().run( argc, argv ); -} - -#else // __OBJC__ - -// Objective-C entry point -int main (int argc, char * const argv[]) { -#if !CATCH_ARC_ENABLED - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; -#endif - - Catch::registerTestMethods(); - int result = Catch::Session().run( argc, (char* const*)argv ); - -#if !CATCH_ARC_ENABLED - [pool drain]; -#endif - - return result; -} - -#endif // __OBJC__ - -#endif - -#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED -# undef CLARA_CONFIG_MAIN -#endif - -////// - -// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ -#ifdef CATCH_CONFIG_PREFIX_ALL - -#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) -#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "CATCH_REQUIRE_FALSE" ) - -#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" ) -#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) -#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) - -#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) -#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CATCH_CHECK_FALSE" ) -#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) -#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) -#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) - -#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) -#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) -#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) - -#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) -#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) - -#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) -#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) -#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) -#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) -#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) - #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) - #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) - #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) - #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) - #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) -#else - #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) - #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) - #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) - #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) - #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) - #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) -#endif -#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) - -#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) -#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) - -#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) - -// "BDD-style" convenience wrappers -#ifdef CATCH_CONFIG_VARIADIC_MACROS -#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) -#else -#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) -#endif -#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" ) -#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" ) -#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" ) -#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" ) -#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" ) - -// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required -#else - -#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) -#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "REQUIRE_FALSE" ) - -#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "REQUIRE_THROWS" ) -#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) -#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) - -#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) -#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CHECK_FALSE" ) -#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) -#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) -#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) - -#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" ) -#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) -#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) - -#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) -#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) - -#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) -#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) -#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) -#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) -#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) - #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) - #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) - #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) - #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) - #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) -#else - #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) - #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) - #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) - #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) - #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) - #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) -#endif -#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) - -#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) -#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) - -#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) - -#endif - -#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) - -// "BDD-style" convenience wrappers -#ifdef CATCH_CONFIG_VARIADIC_MACROS -#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) -#else -#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) -#endif -#define GIVEN( desc ) SECTION( " Given: " desc, "" ) -#define WHEN( desc ) SECTION( " When: " desc, "" ) -#define AND_WHEN( desc ) SECTION( "And when: " desc, "" ) -#define THEN( desc ) SECTION( " Then: " desc, "" ) -#define AND_THEN( desc ) SECTION( " And: " desc, "" ) - -using Catch::Detail::Approx; - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED - diff --git a/third_party/variant/test/optional_unit.cpp b/third_party/variant/test/optional_unit.cpp deleted file mode 100644 index a6573ca41..000000000 --- a/third_party/variant/test/optional_unit.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#define CATCH_CONFIG_RUNNER -#include "catch.hpp" - -#include "optional.hpp" - -using namespace mapbox; - -struct dummy { - dummy(int _m_1, int _m_2) : m_1(_m_1), m_2(_m_2) {} - int m_1; - int m_2; - -}; - -int main (int argc, char* const argv[]) -{ - int result = Catch::Session().run(argc, argv); - if (!result) printf("\x1b[1;32m ✓ \x1b[0m\n"); - return result; -} - -TEST_CASE( "optional can be instantiated with a POD type", "[optiona]" ) { - mapbox::util::optional dbl_opt; - - REQUIRE(!dbl_opt); - dbl_opt = 3.1415; - REQUIRE(dbl_opt); - - REQUIRE(dbl_opt.get() == 3.1415); - REQUIRE(*dbl_opt == 3.1415); -} - -TEST_CASE( "copy c'tor", "[optiona]" ) { - mapbox::util::optional dbl_opt; - - REQUIRE(!dbl_opt); - dbl_opt = 3.1415; - REQUIRE(dbl_opt); - - mapbox::util::optional other = dbl_opt; - - REQUIRE(other.get() == 3.1415); - REQUIRE(*other == 3.1415); -} - -TEST_CASE( "const operator*, const get()", "[optiona]" ) { - mapbox::util::optional dbl_opt = 3.1415; - - REQUIRE(dbl_opt); - - const double pi1 = dbl_opt.get(); - const double pi2 = *dbl_opt; - - REQUIRE(pi1 == 3.1415); - REQUIRE(pi2 == 3.1415); -} - -TEST_CASE( "emplace initialization, reset", "[optional]" ) { - mapbox::util::optional dummy_opt; - REQUIRE(!dummy_opt); - - // rvalues, baby! - dummy_opt.emplace(1, 2); - REQUIRE(dummy_opt); - REQUIRE(dummy_opt.get().m_1 == 1); - REQUIRE((*dummy_opt).m_2 == 2); - - dummy_opt.reset(); - REQUIRE(!dummy_opt); -} - -TEST_CASE( "assignment", "[optional]") { - mapbox::util::optional a; - mapbox::util::optional b; - - a = 1; b = 3; - REQUIRE(a.get() == 1); - REQUIRE(b.get() == 3); - b = a; - REQUIRE(a.get() == b.get()); - REQUIRE(b.get() == 1); -} diff --git a/third_party/variant/test/recursive_wrapper_test.cpp b/third_party/variant/test/recursive_wrapper_test.cpp deleted file mode 100644 index 3cd79b5ce..000000000 --- a/third_party/variant/test/recursive_wrapper_test.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "variant.hpp" - -using namespace mapbox; - -namespace test { - -struct add; -struct sub; -template struct binary_op; - -typedef util::variant>, - util::recursive_wrapper> - > expression; - -template -struct binary_op -{ - expression left; // variant instantiated here... - expression right; - - binary_op(expression && lhs, expression && rhs) - : left(std::move(lhs)), right(std::move(rhs)) - { - } -}; - -struct print : util::static_visitor -{ - template - void operator() (T const& val) const - { - std::cerr << val << ":" << typeid(T).name() << std::endl; - } -}; - - -struct test : util::static_visitor -{ - template - std::string operator() (T const& obj) const - { - return std::string("TYPE_ID=") + typeid(obj).name(); - } -}; - -struct calculator : public util::static_visitor -{ -public: - - int operator()(int value) const - { - return value; - } - - int operator()(binary_op const& binary) const - { - return util::apply_visitor(calculator(), binary.left) - + util::apply_visitor(calculator(), binary.right); - } - - int operator()(binary_op const& binary) const - { - return util::apply_visitor(calculator(), binary.left) - - util::apply_visitor(calculator(), binary.right); - } -}; - -struct to_string : public util::static_visitor -{ -public: - - std::string operator()(int value) const - { - return std::to_string(value); - } - - std::string operator()(binary_op const& binary) const - { - return util::apply_visitor(to_string(), binary.left) + std::string("+") - + util::apply_visitor(to_string(), binary.right); - } - - std::string operator()(binary_op const& binary) const - { - return util::apply_visitor(to_string(), binary.left) + std::string("-") - + util::apply_visitor(to_string(), binary.right); - } - -}; - -} // namespace test - -int main (int argc, char** argv) -{ - - if (argc != 2) - { - std::cerr << "Usage" << argv[0] << " " << std::endl; - return EXIT_FAILURE; - } - - const std::size_t NUM_ITER = static_cast(std::stol(argv[1])); - - test::expression result( - test::binary_op( - test::binary_op(2, 3), 4)); - - std::cerr << "TYPE OF RESULT-> " << util::apply_visitor(test::test(), result) << std::endl; - - { - boost::timer::auto_cpu_timer t; - int total = 0; - for (std::size_t i = 0; i < NUM_ITER; ++i) - { - total += util::apply_visitor(test::calculator(), result); - } - std::cerr << "total=" << total << std::endl; - } - - std::cerr << util::apply_visitor(test::to_string(), result) << "=" << util::apply_visitor(test::calculator(), result) << std::endl; - - return EXIT_SUCCESS; -} diff --git a/third_party/variant/test/unique_ptr_test.cpp b/third_party/variant/test/unique_ptr_test.cpp deleted file mode 100644 index 2a51efef0..000000000 --- a/third_party/variant/test/unique_ptr_test.cpp +++ /dev/null @@ -1,128 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "variant.hpp" - -using namespace mapbox; - -namespace test { - -struct add; -struct sub; -template struct binary_op; - -typedef util::variant>, - std::unique_ptr> - > expression; - -template -struct binary_op -{ - expression left; // variant instantiated here... - expression right; - - binary_op(expression && lhs, expression && rhs) - : left(std::move(lhs)), right(std::move(rhs)) {} -}; - -struct print : util::static_visitor -{ - template - void operator() (T const& val) const - { - std::cerr << val << ":" << typeid(T).name() << std::endl; - } -}; - - -struct test : util::static_visitor -{ - template - std::string operator() (T const& obj) const - { - return std::string("TYPE_ID=") + typeid(obj).name(); - } -}; - -struct calculator : public util::static_visitor -{ -public: - - int operator()(int value) const - { - return value; - } - - int operator()(std::unique_ptr> const& binary) const - { - return util::apply_visitor(calculator(), binary->left) - + util::apply_visitor(calculator(), binary->right); - } - - int operator()(std::unique_ptr> const& binary) const - { - return util::apply_visitor(calculator(), binary->left) - - util::apply_visitor(calculator(), binary->right); - } -}; - -struct to_string : public util::static_visitor -{ -public: - - std::string operator()(int value) const - { - return std::to_string(value); - } - - std::string operator()(std::unique_ptr> const& binary) const - { - return util::apply_visitor(to_string(), binary->left) + std::string("+") - + util::apply_visitor(to_string(), binary->right); - } - - std::string operator()(std::unique_ptr> const& binary) const - { - return util::apply_visitor(to_string(), binary->left) + std::string("-") - + util::apply_visitor(to_string(), binary->right); - } - -}; - -} // namespace test - -int main (int argc, char** argv) -{ - if (argc != 2) - { - std::cerr << "Usage" << argv[0] << " " << std::endl; - return EXIT_FAILURE; - } - - const std::size_t NUM_ITER = static_cast(std::stol(argv[1])); - - test::expression sum(std::unique_ptr>(new test::binary_op(2, 3))); - test::expression result(std::unique_ptr>(new test::binary_op(std::move(sum), 4))); - std::cerr << "TYPE OF RESULT-> " << util::apply_visitor(test::test(), result) << std::endl; - - { - boost::timer::auto_cpu_timer t; - int total = 0; - for (std::size_t i = 0; i < NUM_ITER; ++i) - { - total += util::apply_visitor(test::calculator(), result); - } - std::cerr << "total=" << total << std::endl; - } - - std::cerr << util::apply_visitor(test::to_string(), result) << "=" << util::apply_visitor(test::calculator(), result) << std::endl; - - return EXIT_SUCCESS; -} diff --git a/third_party/variant/test/unit.cpp b/third_party/variant/test/unit.cpp deleted file mode 100644 index 53fd72423..000000000 --- a/third_party/variant/test/unit.cpp +++ /dev/null @@ -1,306 +0,0 @@ -#define CATCH_CONFIG_RUNNER -#include "catch.hpp" - -#include "variant.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace mapbox; - -template -struct mutating_visitor -{ - mutating_visitor(T & val) - : val_(val) {} - - void operator() (T & val) const - { - val = val_; - } - - template - void operator() (T1& ) const {} // no-op - - T & val_; -}; - - - -TEST_CASE( "variant version", "[variant]" ) { - unsigned int version = VARIANT_VERSION; - REQUIRE(version == 100); - #if VARIANT_VERSION == 100 - REQUIRE(true); - #else - REQUIRE(false); - #endif -} - -TEST_CASE( "variant can be moved into vector", "[variant]" ) { - typedef util::variant variant_type; - variant_type v(std::string("test")); - std::vector vec; - vec.emplace_back(std::move(v)); - REQUIRE(v.get() != std::string("test")); - REQUIRE(vec.at(0).get() == std::string("test")); -} - -TEST_CASE( "variant should support built-in types", "[variant]" ) { - SECTION( "bool" ) { - util::variant v(true); - REQUIRE(v.valid()); - REQUIRE(v.is()); - REQUIRE(v.get_type_index() == 0); - REQUIRE(v.get() == true); - v.set(false); - REQUIRE(v.get() == false); - v = true; - REQUIRE(v == util::variant(true)); - } - SECTION( "nullptr" ) { - typedef std::nullptr_t value_type; - util::variant v(nullptr); - REQUIRE(v.valid()); - REQUIRE(v.is()); - REQUIRE(v.get_type_index() == 0); - // TODO: commented since it breaks on windows: 'operator << is ambiguous' - //REQUIRE(v.get() == nullptr); - // FIXME: does not compile: ./variant.hpp:340:14: error: use of overloaded operator '<<' is ambiguous (with operand types 'std::__1::basic_ostream' and 'const nullptr_t') - // https://github.com/mapbox/variant/issues/14 - //REQUIRE(v == util::variant(nullptr)); - } - SECTION( "unique_ptr" ) { - typedef std::unique_ptr value_type; - util::variant v(value_type(new std::string("hello"))); - REQUIRE(v.valid()); - REQUIRE(v.is()); - REQUIRE(v.get_type_index() == 0); - REQUIRE(*v.get().get() == *value_type(new std::string("hello")).get()); - } - SECTION( "string" ) { - typedef std::string value_type; - util::variant v(value_type("hello")); - REQUIRE(v.valid()); - REQUIRE(v.is()); - REQUIRE(v.get_type_index() == 0); - REQUIRE(v.get() == value_type("hello")); - v.set(value_type("there")); - REQUIRE(v.get() == value_type("there")); - v = value_type("variant"); - REQUIRE(v == util::variant(value_type("variant"))); - } - SECTION( "size_t" ) { - typedef std::size_t value_type; - util::variant v(std::numeric_limits::max()); - REQUIRE(v.valid()); - REQUIRE(v.is()); - REQUIRE(v.get_type_index() == 0); - REQUIRE(v.get() == std::numeric_limits::max()); - v.set(value_type(0)); - REQUIRE(v.get() == value_type(0)); - v = value_type(1); - REQUIRE(v == util::variant(value_type(1))); - } - SECTION( "int8_t" ) { - typedef std::int8_t value_type; - util::variant v(std::numeric_limits::max()); - REQUIRE(v.valid()); - REQUIRE(v.is()); - REQUIRE(v.get_type_index() == 0); - REQUIRE(v.get() == std::numeric_limits::max()); - v.set(0); - REQUIRE(v.get() == value_type(0)); - v = value_type(1); - REQUIRE(v == util::variant(value_type(1))); - } - SECTION( "int16_t" ) { - typedef std::int16_t value_type; - util::variant v(std::numeric_limits::max()); - REQUIRE(v.valid()); - REQUIRE(v.is()); - REQUIRE(v.get_type_index() == 0); - REQUIRE(v.get() == std::numeric_limits::max()); - v.set(0); - REQUIRE(v.get() == value_type(0)); - v = value_type(1); - REQUIRE(v == util::variant(value_type(1))); - } - SECTION( "int32_t" ) { - typedef std::int32_t value_type; - util::variant v(std::numeric_limits::max()); - REQUIRE(v.valid()); - REQUIRE(v.is()); - REQUIRE(v.get_type_index() == 0); - REQUIRE(v.get() == std::numeric_limits::max()); - v.set(0); - REQUIRE(v.get() == value_type(0)); - v = value_type(1); - REQUIRE(v == util::variant(value_type(1))); - } - SECTION( "int64_t" ) { - typedef std::int64_t value_type; - util::variant v(std::numeric_limits::max()); - REQUIRE(v.valid()); - REQUIRE(v.is()); - REQUIRE(v.get_type_index() == 0); - REQUIRE(v.get() == std::numeric_limits::max()); - v.set(0); - REQUIRE(v.get() == value_type(0)); - v = value_type(1); - REQUIRE(v == util::variant(value_type(1))); - } -} - -struct MissionInteger -{ - typedef uint64_t value_type; - value_type val_; - public: - MissionInteger(uint64_t val) : - val_(val) {} - - bool operator==(MissionInteger const& rhs) const - { - return (val_ == rhs.get()); - } - - uint64_t get() const - { - return val_; - } -}; - -// TODO - remove after https://github.com/mapbox/variant/issues/14 -std::ostream& operator<<(std::ostream& os, MissionInteger const& rhs) -{ - os << rhs.get(); - return os; -} - -TEST_CASE( "variant should support custom types", "[variant]" ) { - // http://www.missionintegers.com/integer/34838300 - util::variant v(MissionInteger(34838300)); - REQUIRE(v.valid()); - REQUIRE(v.is()); - REQUIRE(v.get_type_index() == 0); - REQUIRE(v.get() == MissionInteger(34838300)); - REQUIRE(v.get().get() == MissionInteger::value_type(34838300)); - // TODO: should both of the set usages below compile? - v.set(MissionInteger::value_type(0)); - v.set(MissionInteger(0)); - REQUIRE(v.get().get() == MissionInteger::value_type(0)); - v = MissionInteger(1); - REQUIRE(v == util::variant(MissionInteger(1))); -} - -// Test internal api -TEST_CASE( "variant should correctly index types", "[variant]" ) { - typedef util::variant variant_type; - // Index is in reverse order - REQUIRE(variant_type(true).get_type_index() == 5); - REQUIRE(variant_type(std::string("test")).get_type_index() == 4); - REQUIRE(variant_type(std::uint64_t(0)).get_type_index() == 3); - REQUIRE(variant_type(std::int64_t(0)).get_type_index() == 2); - REQUIRE(variant_type(double(0.0)).get_type_index() == 1); - REQUIRE(variant_type(float(0.0)).get_type_index() == 0); -} - -TEST_CASE( "get with type not in variant type list should throw", "[variant]" ) { - typedef util::variant variant_type; - variant_type var = 5; - REQUIRE(var.get() == 5); - REQUIRE_THROWS(var.get()); // XXX shouldn't this be a compile time error? See https://github.com/mapbox/variant/issues/24 -} - -TEST_CASE( "get with wrong type (here: double) should throw", "[variant]" ) { - typedef util::variant variant_type; - variant_type var = 5; - REQUIRE(var.get() == 5); - REQUIRE_THROWS(var.get()); -} - -TEST_CASE( "get with wrong type (here: int) should throw", "[variant]" ) { - typedef util::variant variant_type; - variant_type var = 5.0; - REQUIRE(var.get() == 5.0); - REQUIRE_THROWS(var.get()); -} - -TEST_CASE( "implicit conversion", "[variant][implicit conversion]" ) { - typedef util::variant variant_type; - variant_type var(5.0); // converted to int - REQUIRE(var.get() == 5); - REQUIRE_THROWS(var.get()); - var = 6.0; // works for operator=, too - REQUIRE(var.get() == 6); -} - -TEST_CASE( "implicit conversion to first type in variant type list", "[variant][implicit conversion]" ) { - typedef util::variant variant_type; - variant_type var = 5.0; // converted to long - REQUIRE(var.get() == 5); - REQUIRE_THROWS(var.get()); - REQUIRE_THROWS(var.get()); -} - -TEST_CASE( "implicit conversion to unsigned char", "[variant][implicit conversion]" ) { - typedef util::variant variant_type; - variant_type var = 100.0; - CHECK(var.get() == static_cast(100.0)); - CHECK(var.get() == static_cast(static_cast(100.0))); -} - -struct dummy {}; - -TEST_CASE( "variant value traits", "[variant::detail]" ) { - // Users should not create variants with duplicated types - // however our type indexing should still work - // Index is in reverse order - REQUIRE((util::detail::value_traits::index == 3)); - REQUIRE((util::detail::value_traits::index == 2)); - REQUIRE((util::detail::value_traits::index == 1)); - REQUIRE((util::detail::value_traits::index == 0)); - REQUIRE((util::detail::value_traits::index == util::detail::invalid_value)); - REQUIRE((util::detail::value_traits, bool, int, double, std::string>::index == util::detail::invalid_value)); -} - -TEST_CASE( "variant default constructor", "[variant][default constructor]" ) { - // By default variant is initialised with (default constructed) first type in template parameters pack - // As a result first type in Types... must be default constructable - // NOTE: index in reverse order -> index = N - 1 - REQUIRE((util::variant().get_type_index() == 2)); - REQUIRE((util::variant(util::no_init()).get_type_index() == util::detail::invalid_value)); -} - -TEST_CASE( "variant visitation", "[visitor][unary visitor]" ) { - util::variant var(123); - REQUIRE(var.get() == 123); - int val = 456; - mutating_visitor visitor(val); - util::apply_visitor(visitor, var); - REQUIRE(var.get() == 456); -} - -TEST_CASE( "variant printer", "[visitor][unary visitor][printer]" ) { - typedef util::variant variant_type; - std::vector var = {2.1, 123, "foo", 456}; - std::stringstream out; - std::copy(var.begin(), var.end(), std::ostream_iterator(out, ",")); - out << var[2]; - REQUIRE(out.str() == "2.1,123,foo,456,foo"); -} - - -int main (int argc, char* const argv[]) -{ - int result = Catch::Session().run(argc, argv); - if (!result) printf("\x1b[1;32m ✓ \x1b[0m\n"); - return result; -} diff --git a/third_party/variant/test/variant_hello_world.cpp b/third_party/variant/test/variant_hello_world.cpp deleted file mode 100644 index b445fdbab..000000000 --- a/third_party/variant/test/variant_hello_world.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "variant.hpp" -#include -#include - -using namespace mapbox; - -struct check : util::static_visitor<> -{ - template - void operator() (T const& val) const - { - if (val != 0) throw std::runtime_error("invalid"); - } -}; - - -int main() { - typedef util::variant variant_type; - variant_type v(0); - util::apply_visitor(check(), v); - return 0; -} diff --git a/third_party/variant/variant.gyp b/third_party/variant/variant.gyp deleted file mode 100644 index 712cafed1..000000000 --- a/third_party/variant/variant.gyp +++ /dev/null @@ -1,21 +0,0 @@ -{ - "includes": [ - "common.gypi" - ], - "targets": [ - { - "target_name": "tests", - "type": "executable", - "sources": [ - "test/unit.cpp" - ], - "xcode_settings": { - "SDKROOT": "macosx", - "SUPPORTED_PLATFORMS":["macosx"] - }, - "include_dirs": [ - "./" - ] - } - ] -} \ No newline at end of file diff --git a/third_party/variant/variant.hpp b/third_party/variant/variant.hpp deleted file mode 100644 index 49d74d559..000000000 --- a/third_party/variant/variant.hpp +++ /dev/null @@ -1,783 +0,0 @@ -#ifndef MAPBOX_UTIL_VARIANT_HPP -#define MAPBOX_UTIL_VARIANT_HPP - -#include -#include -#include -#include // runtime_error -#include // operator new -#include // size_t -#include -#include - -#include "recursive_wrapper.hpp" - -#ifdef _MSC_VER - // http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx - #ifdef NDEBUG - #define VARIANT_INLINE __forceinline - #else - #define VARIANT_INLINE __declspec(noinline) - #endif -#else - #ifdef NDEBUG - #define VARIANT_INLINE inline __attribute__((always_inline)) - #else - #define VARIANT_INLINE __attribute__((noinline)) - #endif -#endif - -#define VARIANT_MAJOR_VERSION 0 -#define VARIANT_MINOR_VERSION 1 -#define VARIANT_PATCH_VERSION 0 - -// translates to 100 -#define VARIANT_VERSION (VARIANT_MAJOR_VERSION*100000) + (VARIANT_MINOR_VERSION*100) + (VARIANT_PATCH_VERSION) - -namespace mapbox { namespace util { - -// static visitor -template -struct static_visitor -{ - using result_type = R; -protected: - static_visitor() {} - ~static_visitor() {} -}; - -namespace detail { - -static constexpr std::size_t invalid_value = std::size_t(-1); - -template -struct direct_type; - -template -struct direct_type -{ - static constexpr std::size_t index = std::is_same::value - ? sizeof...(Types) : direct_type::index; -}; - -template -struct direct_type -{ - static constexpr std::size_t index = invalid_value; -}; - -template -struct convertible_type; - -template -struct convertible_type -{ - static constexpr std::size_t index = std::is_convertible::value - ? sizeof...(Types) : convertible_type::index; -}; - -template -struct convertible_type -{ - static constexpr std::size_t index = invalid_value; -}; - -template -struct value_traits -{ - static constexpr std::size_t direct_index = direct_type::index; - static constexpr std::size_t index = - (direct_index == invalid_value) ? convertible_type::index : direct_index; -}; - -template -struct is_valid_type; - -template -struct is_valid_type -{ - static constexpr bool value = std::is_convertible::value - || is_valid_type::value; -}; - -template -struct is_valid_type : std::false_type {}; - -template -struct select_type -{ - static_assert(N < sizeof...(Types), "index out of bounds"); -}; - -template -struct select_type -{ - using type = typename select_type::type; -}; - -template -struct select_type<0, T, Types...> -{ - using type = T; -}; - - -template -struct enable_if_type { using type = R; }; - -template -struct result_of_unary_visit -{ - using type = typename std::result_of::type; -}; - -template -struct result_of_unary_visit::type > -{ - using type = typename F::result_type; -}; - -template -struct result_of_binary_visit -{ - using type = typename std::result_of::type; -}; - - -template -struct result_of_binary_visit::type > -{ - using type = typename F::result_type; -}; - - -} // namespace detail - - -template -struct static_max; - -template -struct static_max -{ - static const std::size_t value = arg; -}; - -template -struct static_max -{ - static const std::size_t value = arg1 >= arg2 ? static_max::value : - static_max::value; -}; - -template -struct variant_helper; - -template -struct variant_helper -{ - VARIANT_INLINE static void destroy(const std::size_t id, void * data) - { - if (id == sizeof...(Types)) - { - reinterpret_cast(data)->~T(); - } - else - { - variant_helper::destroy(id, data); - } - } - - VARIANT_INLINE static void move(const std::size_t old_id, void * old_value, void * new_value) - { - if (old_id == sizeof...(Types)) - { - new (new_value) T(std::move(*reinterpret_cast(old_value))); - //std::memcpy(new_value, old_value, sizeof(T)); - // ^^ DANGER: this should only be considered for relocatable types e.g built-in types - // Also, I don't see any measurable performance benefit just yet - } - else - { - variant_helper::move(old_id, old_value, new_value); - } - } - - VARIANT_INLINE static void copy(const std::size_t old_id, const void * old_value, void * new_value) - { - if (old_id == sizeof...(Types)) - { - new (new_value) T(*reinterpret_cast(old_value)); - } - else - { - variant_helper::copy(old_id, old_value, new_value); - } - } -}; - -template<> struct variant_helper<> -{ - VARIANT_INLINE static void destroy(const std::size_t, void *) {} - VARIANT_INLINE static void move(const std::size_t, void *, void *) {} - VARIANT_INLINE static void copy(const std::size_t, const void *, void *) {} -}; - -namespace detail { - -template -struct unwrapper -{ - T const& operator() (T const& obj) const - { - return obj; - } - - T& operator() (T & obj) const - { - return obj; - } -}; - - -template -struct unwrapper> -{ - auto operator() (recursive_wrapper const& obj) const - -> typename recursive_wrapper::type const& - { - return obj.get(); - } -}; - - -template -struct dispatcher; - -template -struct dispatcher -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const& v, F f) - { - if (v.get_type_index() == sizeof...(Types)) - { - return f(unwrapper()(v. template get())); - } - else - { - return dispatcher::apply_const(v, f); - } - } - - VARIANT_INLINE static result_type apply(V & v, F f) - { - if (v.get_type_index() == sizeof...(Types)) - { - return f(unwrapper()(v. template get())); - } - else - { - return dispatcher::apply(v, f); - } - } -}; - -template -struct dispatcher -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const&, F) - { - throw std::runtime_error(std::string("unary dispatch: FAIL ") + typeid(V).name()); - } - - VARIANT_INLINE static result_type apply(V &, F) - { - throw std::runtime_error(std::string("unary dispatch: FAIL ") + typeid(V).name()); - } -}; - - -template -struct binary_dispatcher_rhs; - -template -struct binary_dispatcher_rhs -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f) - { - if (rhs.get_type_index() == sizeof...(Types)) // call binary functor - { - return f(unwrapper()(lhs. template get()), - unwrapper()(rhs. template get())); - } - else - { - return binary_dispatcher_rhs::apply_const(lhs, rhs, f); - } - } - - VARIANT_INLINE static result_type apply(V & lhs, V & rhs, F f) - { - if (rhs.get_type_index() == sizeof...(Types)) // call binary functor - { - return f(unwrapper()(lhs. template get()), - unwrapper()(rhs. template get())); - } - else - { - return binary_dispatcher_rhs::apply(lhs, rhs, f); - } - } - -}; - -template -struct binary_dispatcher_rhs -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const&, V const&, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } - VARIANT_INLINE static result_type apply(V &, V &, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } -}; - - -template -struct binary_dispatcher_lhs; - -template -struct binary_dispatcher_lhs -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f) - { - if (lhs.get_type_index() == sizeof...(Types)) // call binary functor - { - return f(lhs. template get(), rhs. template get()); - } - else - { - return binary_dispatcher_lhs::apply_const(lhs, rhs, f); - } - } - - VARIANT_INLINE static result_type apply(V & lhs, V & rhs, F f) - { - if (lhs.get_type_index() == sizeof...(Types)) // call binary functor - { - return f(lhs. template get(), rhs. template get()); - } - else - { - return binary_dispatcher_lhs::apply(lhs, rhs, f); - } - } - -}; - -template -struct binary_dispatcher_lhs -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const&, V const&, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } - - VARIANT_INLINE static result_type apply(V &, V &, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } -}; - -template -struct binary_dispatcher; - -template -struct binary_dispatcher -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const& v0, V const& v1, F f) - { - if (v0.get_type_index() == sizeof...(Types)) - { - if (v0.get_type_index() == v1.get_type_index()) - { - return f(v0. template get(), v1. template get()); // call binary functor - } - else - { - return binary_dispatcher_rhs::apply_const(v0, v1, f); - } - } - else if (v1.get_type_index() == sizeof...(Types)) - { - return binary_dispatcher_lhs::apply_const(v0, v1, f); - } - return binary_dispatcher::apply_const(v0, v1, f); - } - - VARIANT_INLINE static result_type apply(V & v0, V & v1, F f) - { - if (v0.get_type_index() == sizeof...(Types)) - { - if (v0.get_type_index() == v1.get_type_index()) - { - return f(v0. template get(), v1. template get()); // call binary functor - } - else - { - return binary_dispatcher_rhs::apply(v0, v1, f); - } - } - else if (v1.get_type_index() == sizeof...(Types)) - { - return binary_dispatcher_lhs::apply(v0, v1, f); - } - return binary_dispatcher::apply(v0, v1, f); - } -}; - -template -struct binary_dispatcher -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const&, V const&, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } - - VARIANT_INLINE static result_type apply(V &, V &, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } -}; - -// comparator functors -struct equal_comp -{ - template - bool operator()(T const& lhs, T const& rhs) const - { - return lhs == rhs; - } -}; - -struct less_comp -{ - template - bool operator()(T const& lhs, T const& rhs) const - { - return lhs < rhs; - } -}; - -template -class comparer -{ -public: - explicit comparer(Variant const& lhs) noexcept - : lhs_(lhs) {} - comparer& operator=(comparer const&) = delete; - // visitor - template - bool operator()(T const& rhs_content) const - { - T const& lhs_content = lhs_.template get(); - return Comp()(lhs_content, rhs_content); - } -private: - Variant const& lhs_; -}; - -// operator<< helper -template -class printer -{ -public: - explicit printer(Out & out) - : out_(out) {} - printer& operator=(printer const&) = delete; - -// visitor - template - void operator()(T const& operand) const - { - out_ << operand; - } -private: - Out & out_; -}; - -} // namespace detail - -struct no_init {}; - -template -class variant -{ -private: - - static const std::size_t data_size = static_max::value; - static const std::size_t data_align = static_max::value; - - using data_type = typename std::aligned_storage::type; - using helper_type = variant_helper; - - std::size_t type_index; - data_type data; - -public: - - VARIANT_INLINE variant() - : type_index(sizeof...(Types) - 1) - { - new (&data) typename detail::select_type<0, Types...>::type(); - } - - VARIANT_INLINE variant(no_init) - : type_index(detail::invalid_value) {} - - // http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers - template ::type, Types...>::value>::type> - VARIANT_INLINE variant(T && val) noexcept - : type_index(detail::value_traits::type, Types...>::index) - { - constexpr std::size_t index = sizeof...(Types) - detail::value_traits::type, Types...>::index - 1; - using target_type = typename detail::select_type::type; - new (&data) target_type(std::forward(val)); // nothrow - } - - VARIANT_INLINE variant(variant const& old) - : type_index(old.type_index) - { - helper_type::copy(old.type_index, &old.data, &data); - } - - VARIANT_INLINE variant(variant&& old) noexcept - : type_index(old.type_index) - { - helper_type::move(old.type_index, &old.data, &data); - } - - friend void swap(variant & first, variant & second) - { - using std::swap; //enable ADL - swap(first.type_index, second.type_index); - swap(first.data, second.data); - } - - VARIANT_INLINE variant& operator=(variant other) - { - swap(*this, other); - return *this; - } - - // conversions - // move-assign - template - VARIANT_INLINE variant& operator=(T && rhs) noexcept - { - variant temp(std::forward(rhs)); - swap(*this, temp); - return *this; - } - - // copy-assign - template - VARIANT_INLINE variant& operator=(T const& rhs) - { - variant temp(rhs); - swap(*this, temp); - return *this; - } - - template - VARIANT_INLINE bool is() const - { - return (type_index == detail::direct_type::index); - } - - VARIANT_INLINE bool valid() const - { - return (type_index != detail::invalid_value); - } - - template - VARIANT_INLINE void set(Args&&... args) - { - helper_type::destroy(type_index, &data); - new (&data) T(std::forward(args)...); - type_index = detail::direct_type::index; - } - - template - VARIANT_INLINE T& get() - { - if (type_index == detail::direct_type::index) - { - return *reinterpret_cast(&data); - } - else - { - throw std::runtime_error("in get()"); - } - } - - template - VARIANT_INLINE T const& get() const - { - if (type_index == detail::direct_type::index) - { - return *reinterpret_cast(&data); - } - else - { - throw std::runtime_error("in get()"); - } - } - - VARIANT_INLINE std::size_t get_type_index() const - { - return type_index; - } - - // visitor - // unary - template - auto VARIANT_INLINE - static visit(V const& v, F f) - -> decltype(detail::dispatcher::type>::type, Types...>::apply_const(v, f)) - { - using R = typename detail::result_of_unary_visit::type>::type; - return detail::dispatcher::apply_const(v, f); - } - // non-const - template - auto VARIANT_INLINE - static visit(V & v, F f) - -> decltype(detail::dispatcher::type>::type, Types...>::apply(v, f)) - { - using R = typename detail::result_of_unary_visit::type>::type; - return detail::dispatcher::apply(v, f); - } - - // binary - // const - template - auto VARIANT_INLINE - static binary_visit(V const& v0, V const& v1, F f) - -> decltype(detail::binary_dispatcher::type>::type, Types...>::apply_const(v0, v1, f)) - { - using R = typename detail::result_of_binary_visit::type>::type; - return detail::binary_dispatcher::apply_const(v0, v1, f); - } - // non-const - template - auto VARIANT_INLINE - static binary_visit(V& v0, V& v1, F f) - -> decltype(detail::binary_dispatcher::type>::type, Types...>::apply(v0, v1, f)) - { - using R = typename detail::result_of_binary_visit::type>::type; - return detail::binary_dispatcher::apply(v0, v1, f); - } - - ~variant() noexcept - { - helper_type::destroy(type_index, &data); - } - - // comparison operators - // equality - VARIANT_INLINE bool operator==(variant const& rhs) const - { - if (this->get_type_index() != rhs.get_type_index()) - return false; - detail::comparer visitor(*this); - return visit(rhs, visitor); - } - // less than - VARIANT_INLINE bool operator<(variant const& rhs) const - { - if (this->get_type_index() != rhs.get_type_index()) - { - return this->get_type_index() < rhs.get_type_index(); - // ^^ borrowed from boost::variant - } - detail::comparer visitor(*this); - return visit(rhs, visitor); - } -}; - -// unary visitor interface - -// const -template -auto VARIANT_INLINE static apply_visitor(F f, V const& v) -> decltype(V::visit(v, f)) -{ - return V::visit(v, f); -} -// non-const -template -auto VARIANT_INLINE static apply_visitor(F f, V & v) -> decltype(V::visit(v, f)) -{ - return V::visit(v, f); -} - -// binary visitor interface -// const -template -auto VARIANT_INLINE static apply_visitor(F f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, f)) -{ - return V::binary_visit(v0, v1, f); -} -// non-const -template -auto VARIANT_INLINE static apply_visitor(F f, V & v0, V & v1) -> decltype(V::binary_visit(v0, v1, f)) -{ - return V::binary_visit(v0, v1, f); -} - -// getter interface -template -ResultType & get(T & var) -{ - return var.template get(); -} - -template -ResultType const& get(T const& var) -{ - return var.template get(); -} - - -// operator<< -template -VARIANT_INLINE std::basic_ostream& -operator<< (std::basic_ostream& out, variant const& rhs) -{ - detail::printer> visitor(out); - apply_visitor(visitor, rhs); - return out; -} - -}} - -#endif // MAPBOX_UTIL_VARIANT_HPP diff --git a/third_party/variant/vcbuild.bat b/third_party/variant/vcbuild.bat deleted file mode 100644 index 21489a134..000000000 --- a/third_party/variant/vcbuild.bat +++ /dev/null @@ -1,8 +0,0 @@ -SET configuration=Debug -IF NOT EXIST deps\gyp\ git clone --depth 1 https://chromium.googlesource.com/external/gyp.git deps/gyp -IF EXIST %configuration% rd /s /q %configuration% -del variant.sln -del tests.vcxproj -C:\Python27\python.exe deps/gyp/gyp_main.py variant.gyp --depth=. -f msvs -G msvs_version=2013 -msbuild variant.sln /nologo /p:Configuration=%configuration%;Platform=Win32 -.\"%configuration%"\tests.exe \ No newline at end of file From 884c9986229d4228374959265905cfd7b7c90c08 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 9 Feb 2015 15:19:35 +0100 Subject: [PATCH 173/360] Squashed 'third_party/variant/' content from commit 24dcab2 git-subtree-dir: third_party/variant git-subtree-split: 24dcab23c4f70e54838e4a32a228aba8045ae17b --- .gitignore | 3 + .travis.yml | 22 + Jamroot | 61 + LICENSE | 25 + Makefile | 98 + README.md | 66 + appveyor.yml | 27 + common.gypi | 143 + optional.hpp | 69 + recursive_wrapper.hpp | 127 + scripts/linux.sh | 59 + scripts/osx.sh | 20 + test/bench_variant.cpp | 204 + test/binary_visitor_test.cpp | 136 + test/boost_variant_hello_world.cpp | 19 + test/catch.hpp | 8683 ++++++++++++++++++++++++++++ test/optional_unit.cpp | 82 + test/recursive_wrapper_test.cpp | 132 + test/unique_ptr_test.cpp | 128 + test/unit.cpp | 306 + test/variant_hello_world.cpp | 22 + variant.gyp | 21 + variant.hpp | 755 +++ variant_io.hpp | 39 + vcbuild.bat | 8 + 25 files changed, 11255 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 Jamroot create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 appveyor.yml create mode 100644 common.gypi create mode 100644 optional.hpp create mode 100644 recursive_wrapper.hpp create mode 100644 scripts/linux.sh create mode 100644 scripts/osx.sh create mode 100644 test/bench_variant.cpp create mode 100644 test/binary_visitor_test.cpp create mode 100644 test/boost_variant_hello_world.cpp create mode 100644 test/catch.hpp create mode 100644 test/optional_unit.cpp create mode 100644 test/recursive_wrapper_test.cpp create mode 100644 test/unique_ptr_test.cpp create mode 100644 test/unit.cpp create mode 100644 test/variant_hello_world.cpp create mode 100644 variant.gyp create mode 100644 variant.hpp create mode 100644 variant_io.hpp create mode 100644 vcbuild.bat diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..5620e5dd1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +out +profiling \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..cd1e65578 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,22 @@ +language: cpp + +# http://docs.travis-ci.com/user/multi-os/ +os: + - linux + - osx + +compiler: + - clang + - gcc + +before_install: + - true + +install: + - true + +before_script: + - true + +script: + - source "scripts/${TRAVIS_OS_NAME}.sh" diff --git a/Jamroot b/Jamroot new file mode 100644 index 000000000..abf312b9c --- /dev/null +++ b/Jamroot @@ -0,0 +1,61 @@ +local BOOST_DIR = "/opt/boost" ; + +#using clang : : ; + +lib system : : boost_system $(BOOST_DIR)/lib ; +lib timer : chrono : boost_timer $(BOOST_DIR)/lib ; +lib chrono : system : boost_chrono $(BOOST_DIR)/lib ; + +exe variant-test + : + test/bench_variant.cpp + .//system + .//timer + .//chrono + : + $(BOOST_DIR)/include + ./ + -std=c++11 + #SINGLE_THREADED + release:-march=native + ; + + +exe binary-visitor-test + : + test/binary_visitor_test.cpp + .//system + .//timer + .//chrono + : + $(BOOST_DIR)/include + ./ + -std=c++11 + release:-march=native + ; + +exe recursive-wrapper-test + : + test/recursive_wrapper_test.cpp + .//system + .//timer + .//chrono + : + $(BOOST_DIR)/include + ./ + -std=c++11 + release:-march=native + ; + +exe unique-ptr-test + : + test/unique_ptr_test.cpp + .//system + .//timer + .//chrono + : + $(BOOST_DIR)/include + ./ + -std=c++11 + release:-march=native + ; diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..6c4ce40d5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) MapBox +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. +- Neither the name "MapBox" nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..69761034c --- /dev/null +++ b/Makefile @@ -0,0 +1,98 @@ +CXX := $(CXX) +BOOST_LIBS = -lboost_timer -lboost_system -lboost_chrono +RELEASE_FLAGS = -O3 -DNDEBUG -finline-functions -march=native -DSINGLE_THREADED +DEBUG_FLAGS = -O0 -g -DDEBUG -fno-inline-functions +COMMON_FLAGS = -Wall -Wsign-compare -Wsign-conversion -Wshadow -Wunused-parameter -pedantic -fvisibility-inlines-hidden -std=c++11 +CXXFLAGS := $(CXXFLAGS) +LDFLAGS := $(LDFLAGS) + +OS:=$(shell uname -s) +ifeq ($(OS),Darwin) + CXXFLAGS += -stdlib=libc++ + LDFLAGS += -stdlib=libc++ -F/ -framework CoreFoundation +else + BOOST_LIBS += -lrt +endif + +ifeq (sizes,$(firstword $(MAKECMDGOALS))) + RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) + $(eval $(RUN_ARGS):;@:) + ifndef RUN_ARGS + $(error sizes target requires you pass full path to boost variant.hpp) + endif + .PHONY: $(RUN_ARGS) +endif + +all: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test + +./deps/gyp: + git clone --depth 1 https://chromium.googlesource.com/external/gyp.git ./deps/gyp + +gyp: ./deps/gyp + deps/gyp/gyp --depth=. -Goutput_dir=./ --generator-output=./out -f make + make V=1 -C ./out tests + ./out/Release/tests + +out/bench-variant-debug: Makefile test/bench_variant.cpp variant.hpp + mkdir -p ./out + $(CXX) -o out/bench-variant-debug test/bench_variant.cpp -I./ $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) + +out/bench-variant: Makefile test/bench_variant.cpp variant.hpp + mkdir -p ./out + $(CXX) -o out/bench-variant test/bench_variant.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) + +out/unique_ptr_test: Makefile test/unique_ptr_test.cpp variant.hpp + mkdir -p ./out + $(CXX) -o out/unique_ptr_test test/unique_ptr_test.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) + +out/recursive_wrapper_test: Makefile test/recursive_wrapper_test.cpp variant.hpp + mkdir -p ./out + $(CXX) -o out/recursive_wrapper_test test/recursive_wrapper_test.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) + +out/binary_visitor_test: Makefile test/binary_visitor_test.cpp variant.hpp + mkdir -p ./out + $(CXX) -o out/binary_visitor_test test/binary_visitor_test.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) + +bench: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test + ./out/bench-variant 100000 + ./out/unique_ptr_test 100000 + ./out/recursive_wrapper_test 100000 + ./out/binary_visitor_test 100000 + +out/unit: Makefile test/unit.cpp test/optional_unit.cpp optional.hpp variant.hpp + mkdir -p ./out + $(CXX) -o out/unit test/unit.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) + $(CXX) -o out/optional_unit test/optional_unit.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) + +test: out/unit + ./out/unit + ./out/optional_unit + +coverage: + mkdir -p ./out + $(CXX) -o out/cov-test --coverage test/unit.cpp -I./ $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) + +sizes: Makefile variant.hpp + mkdir -p ./out + @$(CXX) -o ./out/variant_hello_world.out variant.hpp $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/variant_hello_world.out + @$(CXX) -o ./out/boost_variant_hello_world.out $(RUN_ARGS) $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/boost_variant_hello_world.out + @$(CXX) -o ./out/variant_hello_world ./test/variant_hello_world.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/variant_hello_world + @$(CXX) -o ./out/boost_variant_hello_world ./test/boost_variant_hello_world.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/boost_variant_hello_world + +profile: out/bench-variant-debug + mkdir -p profiling/ + rm -rf profiling/* + iprofiler -timeprofiler -d profiling/ ./out/bench-variant-debug 500000 + +clean: + rm -rf ./out + rm -rf *.dSYM + rm -f unit.gc* + rm -f *gcov + +pgo: out Makefile variant.hpp + $(CXX) -o out/bench-variant test/bench_variant.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) -pg -fprofile-generate + ./test-variant 500000 >/dev/null 2>/dev/null + $(CXX) -o out/bench-variant test/bench_variant.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) -fprofile-use + +.PHONY: sizes test diff --git a/README.md b/README.md new file mode 100644 index 000000000..018163c1c --- /dev/null +++ b/README.md @@ -0,0 +1,66 @@ +# Mapbox Variant + +An alternative to `boost::variant` for C++11. + +[![Build Status](https://secure.travis-ci.org/mapbox/variant.svg)](https://travis-ci.org/mapbox/variant) +[![Build status](https://ci.appveyor.com/api/projects/status/v9tatx21j1k0fcgy)](https://ci.appveyor.com/project/Mapbox/variant) + +# Why use Mapbox Variant? + +Mapbox variant has the same speedy performance of `boost::variant` but is faster to compile, results in smaller binaries, and has no dependencies. + +For example on OS X 10.9 with clang++ and libc++: + +Test | Mapbox Variant | Boost Variant +---- | -------------- | ------------- +Size of pre-compiled header (release / debug) | 2.8/2.8 MB | 12/15 MB +Size of simple program linking variant (release / debug) | 8/24 K | 12/40 K +Time to compile header | 185 ms | 675 ms + + +# Depends + + - Compiler supporting `-std=c++11` + +Tested with + + - g++-4.7 + - g++-4.8 + - clang++-3.4 + - clang++-3.5 + - Visual C++ Compiler November 2013 CTP + - Visual C++ Compiler 2014 CTP 4 + +Note: get the "2013 Nov CTP" release at http://www.microsoft.com/en-us/download/details.aspx?id=41151 and the 2014 CTP at http://www.visualstudio.com/en-us/downloads/visual-studio-14-ctp-vs.aspx + +# Usage + +There is nothing to build, just include `variant.hpp` and `recursive_wrapper.hpp` in your project. + +# Tests + +The tests depend on: + + - Boost headers (for benchmarking against `boost::variant`) + - Boost built with `--with-timer` (used for benchmark timing) + +On Unix systems set your boost includes and libs locations and run `make test`: + + export LDFLAGS='-L/opt/boost/lib' + export CXXFLAGS='-I/opt/boost/include' + make test + +On windows do: + + vcbuild + +## Benchmark + +On Unix systems run the benchmark like: + + make bench + +## Check object sizes + + make sizes /path/to/boost/variant.hpp + diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..9d7c59984 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,27 @@ + +platform: + - x64 + - x86 + +configuration: + - Debug + - Release + +install: + - SET PATH=c:\python27;%PATH% + - SET PATH=C:\Program Files (x86)\MSBuild\12.0\bin\;%PATH% + - git clone --quiet --depth 1 https://chromium.googlesource.com/external/gyp.git deps/gyp + # note windows requires --generator-output to be absolute + - python deps/gyp/gyp_main.py variant.gyp --depth=. -f msvs -G msvs_version=2013 + - set MSBUILD_PLATFORM=%platform% + - if "%MSBUILD_PLATFORM%" == "x86" set MSBUILD_PLATFORM=Win32 + - msbuild variant.sln /nologo /p:Configuration=%configuration%;Platform=%MSBUILD_PLATFORM% + - .\"%configuration%"\tests.exe + +build: OFF + +test: OFF + +test_script: OFF + +deploy: OFF diff --git a/common.gypi b/common.gypi new file mode 100644 index 000000000..67e333b7e --- /dev/null +++ b/common.gypi @@ -0,0 +1,143 @@ +{ + "conditions": [ + ["OS=='win'", { + "target_defaults": { + "default_configuration": "Release_x64", + "msbuild_toolset":"CTP_Nov2013", + "msvs_settings": { + "VCCLCompilerTool": { + "ExceptionHandling": 1, # /EHsc + "RuntimeTypeInfo": "true" # /GR + } + }, + "configurations": { + "Debug_Win32": { + "msvs_configuration_platform": "Win32", + "defines": [ "DEBUG","_DEBUG"], + "msvs_settings": { + "VCCLCompilerTool": { + "RuntimeLibrary": "1", # static debug /MTd + "Optimization": 0, # /Od, no optimization + "MinimalRebuild": "false", + "OmitFramePointers": "false", + "BasicRuntimeChecks": 3 # /RTC1 + } + } + }, + "Debug_x64": { + "msvs_configuration_platform": "x64", + "defines": [ "DEBUG","_DEBUG"], + "msvs_settings": { + "VCCLCompilerTool": { + "RuntimeLibrary": "1", # static debug /MTd + "Optimization": 0, # /Od, no optimization + "MinimalRebuild": "false", + "OmitFramePointers": "false", + "BasicRuntimeChecks": 3 # /RTC1 + } + } + }, + "Release_Win32": { + "msvs_configuration_platform": "Win32", + "defines": [ "NDEBUG"], + "msvs_settings": { + "VCCLCompilerTool": { + "RuntimeLibrary": 0, # static release + "Optimization": 3, # /Ox, full optimization + "FavorSizeOrSpeed": 1, # /Ot, favour speed over size + "InlineFunctionExpansion": 2, # /Ob2, inline anything eligible + "WholeProgramOptimization": "true", # /GL, whole program optimization, needed for LTCG + "OmitFramePointers": "true", + "EnableFunctionLevelLinking": "true", + "EnableIntrinsicFunctions": "true", + "AdditionalOptions": [ + "/MP", # compile across multiple CPUs + ], + "DebugInformationFormat": "0" + }, + "VCLibrarianTool": { + "AdditionalOptions": [ + "/LTCG" # link time code generation + ], + }, + "VCLinkerTool": { + "LinkTimeCodeGeneration": 1, # link-time code generation + "OptimizeReferences": 2, # /OPT:REF + "EnableCOMDATFolding": 2, # /OPT:ICF + "LinkIncremental": 1, # disable incremental linking + "GenerateDebugInformation": "false" + } + } + }, + "Release_x64": { + "msvs_configuration_platform": "x64", + "defines": [ "NDEBUG"], + "msvs_settings": { + "VCCLCompilerTool": { + "RuntimeLibrary": 0, # static release + "Optimization": 3, # /Ox, full optimization + "FavorSizeOrSpeed": 1, # /Ot, favour speed over size + "InlineFunctionExpansion": 2, # /Ob2, inline anything eligible + "WholeProgramOptimization": "true", # /GL, whole program optimization, needed for LTCG + "OmitFramePointers": "true", + "EnableFunctionLevelLinking": "true", + "EnableIntrinsicFunctions": "true", + "AdditionalOptions": [ + "/MP", # compile across multiple CPUs + ], + "DebugInformationFormat": "0" + }, + "VCLibrarianTool": { + "AdditionalOptions": [ + "/LTCG" # link time code generation + ], + }, + "VCLinkerTool": { + "LinkTimeCodeGeneration": 1, # link-time code generation + "OptimizeReferences": 2, # /OPT:REF + "EnableCOMDATFolding": 2, # /OPT:ICF + "LinkIncremental": 1, # disable incremental linking + "GenerateDebugInformation": "false" + } + } + } + } + } + }, { + "target_defaults": { + "default_configuration": "Release", + "xcode_settings": { + "CLANG_CXX_LIBRARY": "libc++", + "CLANG_CXX_LANGUAGE_STANDARD":"c++11", + "GCC_VERSION": "com.apple.compilers.llvm.clang.1_0", + }, + "cflags_cc": ["-std=c++11"], + "configurations": { + "Debug": { + "defines": [ + "DEBUG" + ], + "xcode_settings": { + "GCC_OPTIMIZATION_LEVEL": "0", + "GCC_GENERATE_DEBUGGING_SYMBOLS": "YES", + "OTHER_CPLUSPLUSFLAGS": [ "-Wall", "-Wextra", "-pedantic", "-g", "-O0" ] + } + }, + "Release": { + "defines": [ + "NDEBUG" + ], + "xcode_settings": { + "GCC_OPTIMIZATION_LEVEL": "3", + "GCC_GENERATE_DEBUGGING_SYMBOLS": "NO", + "DEAD_CODE_STRIPPING": "YES", + "GCC_INLINES_ARE_PRIVATE_EXTERN": "YES", + "OTHER_CPLUSPLUSFLAGS": [ "-Wall", "-Wextra", "-pedantic", "-O3" ] + } + } + } + } + }] + ] +} + diff --git a/optional.hpp b/optional.hpp new file mode 100644 index 000000000..133e2c8f9 --- /dev/null +++ b/optional.hpp @@ -0,0 +1,69 @@ +#ifndef MAPBOX_UTIL_OPTIONAL_HPP +#define MAPBOX_UTIL_OPTIONAL_HPP + +#include + +#include "variant.hpp" + +namespace mapbox +{ +namespace util +{ + +template class optional +{ + static_assert(!std::is_reference::value, "optional doesn't support references"); + + struct none_type + { + }; + + variant variant_; + + public: + optional() = default; + + optional(optional const &rhs) + { + if (this != &rhs) + { // protect against invalid self-assignment + variant_ = rhs.variant_; + } + } + + optional(T const &v) { variant_ = v; } + + explicit operator bool() const noexcept { return variant_.template is(); } + + T const &get() const { return variant_.template get(); } + T &get() { return variant_.template get(); } + + T const &operator*() const { return this->get(); } + T operator*() { return this->get(); } + + optional &operator=(T const &v) + { + variant_ = v; + return *this; + } + + optional &operator=(optional const &rhs) + { + if (this != &rhs) + { + variant_ = rhs.variant_; + } + return *this; + } + + template void emplace(Args &&... args) + { + variant_ = T{std::forward(args)...}; + } + + void reset() { variant_ = none_type{}; } +}; +} +} + +#endif diff --git a/recursive_wrapper.hpp b/recursive_wrapper.hpp new file mode 100644 index 000000000..54b27634a --- /dev/null +++ b/recursive_wrapper.hpp @@ -0,0 +1,127 @@ +#ifndef MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP +#define MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP + +#include + +namespace mapbox { namespace util { + +template +class recursive_wrapper +{ +public: + using type = T; +private: + + T* p_; + +public: + + ~recursive_wrapper(); + recursive_wrapper(); + + recursive_wrapper(recursive_wrapper const& operand); + recursive_wrapper(T const& operand); + recursive_wrapper(recursive_wrapper&& operand); + recursive_wrapper(T&& operand); + +private: + + void assign(const T& rhs); + +public: + + inline recursive_wrapper& operator=(recursive_wrapper const& rhs) + { + assign( rhs.get() ); + return *this; + } + + inline recursive_wrapper& operator=(T const& rhs) + { + assign( rhs ); + return *this; + } + + inline void swap(recursive_wrapper& operand) noexcept + { + T* temp = operand.p_; + operand.p_ = p_; + p_ = temp; + } + + + recursive_wrapper& operator=(recursive_wrapper&& rhs) noexcept + { + swap(rhs); + return *this; + } + + recursive_wrapper& operator=(T&& rhs) + { + get() = std::move(rhs); + return *this; + } + + +public: + + T& get() { return *get_pointer(); } + const T& get() const { return *get_pointer(); } + T* get_pointer() { return p_; } + const T* get_pointer() const { return p_; } + operator T const&() const { return this->get(); } + operator T&() { return this->get(); } +}; + +template +recursive_wrapper::~recursive_wrapper() +{ + delete p_; +} + +template +recursive_wrapper::recursive_wrapper() + : p_(new T) +{ +} + +template +recursive_wrapper::recursive_wrapper(recursive_wrapper const& operand) + : p_(new T( operand.get() )) +{ +} + +template +recursive_wrapper::recursive_wrapper(T const& operand) + : p_(new T(operand)) +{ +} + +template +recursive_wrapper::recursive_wrapper(recursive_wrapper&& operand) + : p_(operand.p_) +{ + operand.p_ = nullptr; +} + +template +recursive_wrapper::recursive_wrapper(T&& operand) + : p_(new T( std::move(operand) )) +{ +} + +template +void recursive_wrapper::assign(const T& rhs) +{ + this->get() = rhs; +} + +template +inline void swap(recursive_wrapper& lhs, recursive_wrapper& rhs) noexcept +{ + lhs.swap(rhs); +} + +}} + +#endif // MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP diff --git a/scripts/linux.sh b/scripts/linux.sh new file mode 100644 index 000000000..f173db5c3 --- /dev/null +++ b/scripts/linux.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash + +set -e -u +set -o pipefail + +# ppa for latest boost +sudo add-apt-repository -y ppa:boost-latest/ppa +# ppa for g++ 4.7 and 4.8 +sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test +sudo apt-get update -y + +# install boost headers and g++ upgrades +sudo apt-get -y -qq install boost1.55 gcc-4.8 g++-4.8 gcc-4.7 g++-4.7 + +if [[ "$CXX" == "clang++" ]]; then + echo 'running tests against clang++' + make test + make bench + make clean +else + # run tests against g++ 4.7 + export CXX="g++-4.7"; export CC="gcc-4.7" + echo 'running tests against g++ 4.7' + make test + make bench + make clean + + # run tests against g++ 4.8 + export CXX="g++-4.8"; export CC="gcc-4.8" + echo 'running tests against g++ 4.8' + make test + make bench + make clean + +fi + +# compare object sizes against boost::variant +echo 'comparing object sizes to boost::variant' +make sizes /usr/include/boost/variant.hpp +make clean + +# test building with gyp +echo 'testing build with gyp' +make gyp + +# run coverage when using clang++ +if [[ $CXX == "clang++" ]]; then + make clean + make coverage + git status + ./out/cov-test + cp unit*gc* test/ + sudo pip install cpp-coveralls + coveralls -i variant.hpp -i recursive_wrapper.hpp --gcov-options '\-lp' +fi + +# set strictness back to normal +# to avoid tripping up travis +set +e +u diff --git a/scripts/osx.sh b/scripts/osx.sh new file mode 100644 index 000000000..14149ca04 --- /dev/null +++ b/scripts/osx.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +set -e -u +set -o pipefail + +# install boost headers +brew unlink boost +brew install boost + +# run tests +make test +make bench +make clean + +# compare object sizes against boost::variant +make sizes `brew --prefix`/include/boost/variant.hpp +make clean + +# test building with gyp +make gyp \ No newline at end of file diff --git a/test/bench_variant.cpp b/test/bench_variant.cpp new file mode 100644 index 000000000..f27124593 --- /dev/null +++ b/test/bench_variant.cpp @@ -0,0 +1,204 @@ +#include +#include +#include +#include +#include +#include +#include +#include "variant.hpp" + +#define TEXT "Testing various variant implementations with a longish string ........................................." +//#define BOOST_VARIANT_MINIMIZE_SIZE + +using namespace mapbox; + +namespace test { + +template +struct Holder +{ + typedef V value_type; + std::vector data; + + template + void append_move(T && obj) + { + data.emplace_back(std::forward(obj)); + } + + template + void append(T const& obj) + { + data.push_back(obj); + } +}; + +} // namespace test + +struct print : util::static_visitor<> +{ + template + void operator() (T const& val) const + { + std::cerr << val << ":" << typeid(T).name() << std::endl; + } +}; + + +template +struct dummy : boost::static_visitor<> +{ + dummy(V & v) + : v_(v) {} + + template + void operator() (T const& val) const + { + v_ = val; + } + V & v_; +}; + +template +struct dummy2 : util::static_visitor<> +{ + dummy2(V & v) + : v_(v) {} + + template + void operator() (T const& val) const + { + v_.template set(val); + } + V & v_; +}; + +void run_boost_test(std::size_t runs) +{ + test::Holder> h; + h.data.reserve(runs); + for (std::size_t i=0; i< runs; ++i) + { + h.append_move(std::string(TEXT)); + h.append_move(123); + h.append_move(3.14159); + } + + boost::variant v; + for (auto const& v2 : h.data) + { + dummy> d(v); + boost::apply_visitor(d, v2); + } +} + +void run_variant_test(std::size_t runs) +{ + test::Holder> h; + h.data.reserve(runs); + for (std::size_t i=0; i< runs; ++i) + { + h.append_move(std::string(TEXT)); + h.append_move(123); + h.append_move(3.14159); + } + + util::variant v; + for (auto const& v2 : h.data) + { + dummy2> d(v); + util::apply_visitor (d, v2); + } +} + +int main (int argc, char** argv) +{ + if (argc!=2) + { + std::cerr << "Usage:" << argv[0] << " " << std::endl; + return 1; + } + +#ifndef SINGLE_THREADED + const std::size_t THREADS = 4; +#endif + const std::size_t NUM_RUNS = static_cast(std::stol(argv[1])); + +#ifdef SINGLE_THREADED + { + std::cerr << "custom variant: "; + boost::timer::auto_cpu_timer t; + run_variant_test(NUM_RUNS); + } + { + std::cerr << "boost variant: "; + boost::timer::auto_cpu_timer t; + run_boost_test(NUM_RUNS); + } + { + std::cerr << "custom variant: "; + boost::timer::auto_cpu_timer t; + run_variant_test(NUM_RUNS); + } + { + std::cerr << "boost variant: "; + boost::timer::auto_cpu_timer t; + run_boost_test(NUM_RUNS); + } +#else + { + typedef std::vector> thread_group; + typedef thread_group::value_type value_type; + thread_group tg; + std::cerr << "custom variant: "; + boost::timer::auto_cpu_timer timer; + for (std::size_t i=0; ijoinable()) t->join();}); + } + + { + typedef std::vector> thread_group; + typedef thread_group::value_type value_type; + thread_group tg; + std::cerr << "boost variant: "; + boost::timer::auto_cpu_timer timer; + for (std::size_t i=0; ijoinable()) t->join();}); + } + + { + typedef std::vector> thread_group; + typedef thread_group::value_type value_type; + thread_group tg; + std::cerr << "custom variant: "; + boost::timer::auto_cpu_timer timer; + for (std::size_t i=0; ijoinable()) t->join();}); + } + + { + typedef std::vector> thread_group; + typedef thread_group::value_type value_type; + thread_group tg; + std::cerr << "boost variant: "; + boost::timer::auto_cpu_timer timer; + for (std::size_t i=0; ijoinable()) t->join();}); + } +#endif + + + return EXIT_SUCCESS; +} diff --git a/test/binary_visitor_test.cpp b/test/binary_visitor_test.cpp new file mode 100644 index 000000000..de2a30e6c --- /dev/null +++ b/test/binary_visitor_test.cpp @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "variant.hpp" +#include "variant_io.hpp" + +using namespace mapbox; + +namespace test { + +template +struct string_to_number {}; + +template <> +struct string_to_number +{ + double operator() (std::string const& str) const + { + return std::stod(str); + } +}; + +template <> +struct string_to_number +{ + std::int64_t operator() (std::string const& str) const + { + return std::stoll(str); + } +}; + +template <> +struct string_to_number +{ + std::uint64_t operator() (std::string const& str) const + { + return std::stoull(str); + } +}; + +template <> +struct string_to_number +{ + bool operator() (std::string const& str) const + { + bool result; + std::istringstream(str) >> std::boolalpha >> result; + return result; + } +}; + +struct javascript_equal_visitor : util::static_visitor +{ + template + bool operator() (T lhs, T rhs) const + { + return lhs == rhs; + } + + template ::value>::type> + bool operator() (T lhs, std::string const& rhs) const + { + return lhs == string_to_number()(rhs); + } + + template ::value>::type> + bool operator() (std::string const& lhs, T rhs) const + { + return string_to_number()(lhs) == rhs; + } + + template + bool operator() (T0 lhs, T1 rhs) const + { + return lhs == static_cast(rhs); + } +}; + +template +struct javascript_equal +{ + javascript_equal(T const& lhs) + : lhs_(lhs) {} + + bool operator() (T const& rhs) const + { + return util::apply_visitor(test::javascript_equal_visitor(), lhs_, rhs); + } + T const& lhs_; +}; + +} // namespace test + +int main (/*int argc, char** argv*/) +{ + typedef util::variant variant_type; + variant_type v0(3.14159); + variant_type v1(std::string("3.14159")); + variant_type v2(std::uint64_t(1)); + + std::cerr << v0 << " == " << v1 << " -> " + << std::boolalpha << util::apply_visitor(test::javascript_equal_visitor(), v0, v1) << std::endl; + + + std::vector vec; + + vec.emplace_back(std::string("1")); + vec.push_back(variant_type(std::uint64_t(2))); + vec.push_back(variant_type(std::uint64_t(3))); + vec.push_back(std::string("3.14159")); + vec.emplace_back(3.14159); + + //auto itr = std::find_if(vec.begin(), vec.end(), [&v0](variant_type const& val) { + // return util::apply_visitor(test::javascript_equal_visitor(), v0, val); + // }); + + auto itr = std::find_if(vec.begin(), vec.end(), test::javascript_equal(v2)); + + if (itr != std::end(vec)) + { + std::cout << "found " << *itr << std::endl; + } + else + { + std::cout << "can't find " << v2 << '\n'; + } + + return EXIT_SUCCESS; +} diff --git a/test/boost_variant_hello_world.cpp b/test/boost_variant_hello_world.cpp new file mode 100644 index 000000000..0d0925a7e --- /dev/null +++ b/test/boost_variant_hello_world.cpp @@ -0,0 +1,19 @@ +#include +#include +#include + +struct check : boost::static_visitor<> +{ + template + void operator() (T const& val) const + { + if (val != 0) throw std::runtime_error("invalid"); + } +}; + +int main() { + typedef boost::variant variant_type; + variant_type v(0); + boost::apply_visitor(check(), v); + return 0; +} diff --git a/test/catch.hpp b/test/catch.hpp new file mode 100644 index 000000000..057c82ee0 --- /dev/null +++ b/test/catch.hpp @@ -0,0 +1,8683 @@ +/* + * CATCH v1.0 build 45 (master branch) + * Generated: 2014-05-19 18:22:42.461908 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + +#define TWOBLUECUBES_CATCH_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wglobal-constructors" +#pragma clang diagnostic ignored "-Wvariadic-macros" +#pragma clang diagnostic ignored "-Wc99-extensions" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#pragma clang diagnostic ignored "-Wc++98-compat" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + +#ifdef CATCH_CONFIG_MAIN +# define CATCH_CONFIG_RUNNER +#endif + +#ifdef CATCH_CONFIG_RUNNER +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// #included from: internal/catch_notimplemented_exception.h +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED + +// #included from: catch_common.h +#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED + +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) + +#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr +#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) + +#include +#include +#include + +// #included from: catch_compiler_capabilities.h +#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + +// Much of the following code is based on Boost (1.53) + +#ifdef __clang__ + +# if __has_feature(cxx_nullptr) +# define CATCH_CONFIG_CPP11_NULLPTR +# endif + +# if __has_feature(cxx_noexcept) +# define CATCH_CONFIG_CPP11_NOEXCEPT +# endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Borland +#ifdef __BORLANDC__ + +#if (__BORLANDC__ > 0x582 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __BORLANDC__ + +//////////////////////////////////////////////////////////////////////////////// +// EDG +#ifdef __EDG_VERSION__ + +#if (__EDG_VERSION__ > 238 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __EDG_VERSION__ + +//////////////////////////////////////////////////////////////////////////////// +// Digital Mars +#ifdef __DMC__ + +#if (__DMC__ > 0x840 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __DMC__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +#if __GNUC__ < 3 + +#if (__GNUC_MINOR__ >= 96 ) +//#define CATCH_CONFIG_SFINAE +#endif + +#elif __GNUC__ >= 3 + +// #define CATCH_CONFIG_SFINAE // Taking this out completely for now + +#endif // __GNUC__ < 3 + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) ) + +#define CATCH_CONFIG_CPP11_NULLPTR +#endif + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1310 ) // (VC++ 7.0+) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // _MSC_VER + +// Use variadic macros if the compiler supports them +#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ + ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ + ( defined __GNUC__ && __GNUC__ >= 3 ) || \ + ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) + +#ifndef CATCH_CONFIG_NO_VARIADIC_MACROS +#define CATCH_CONFIG_VARIADIC_MACROS +#endif + +#endif + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// detect language version: +#if (__cplusplus == 201103L) +# define CATCH_CPP11 +# define CATCH_CPP11_OR_GREATER +#elif (__cplusplus >= 201103L) +# define CATCH_CPP11_OR_GREATER +#endif + +// noexcept support: +#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) +# define CATCH_NOEXCEPT noexcept +# define CATCH_NOEXCEPT_IS(x) noexcept(x) +#else +# define CATCH_NOEXCEPT throw() +# define CATCH_NOEXCEPT_IS(x) +#endif + +namespace Catch { + + class NonCopyable { + NonCopyable( NonCopyable const& ); + void operator = ( NonCopyable const& ); + protected: + NonCopyable() {} + virtual ~NonCopyable(); + }; + + class SafeBool { + public: + typedef void (SafeBool::*type)() const; + + static type makeSafe( bool value ) { + return value ? &SafeBool::trueValue : 0; + } + private: + void trueValue() const {} + }; + + template + inline void deleteAll( ContainerT& container ) { + typename ContainerT::const_iterator it = container.begin(); + typename ContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete *it; + } + template + inline void deleteAllValues( AssociativeContainerT& container ) { + typename AssociativeContainerT::const_iterator it = container.begin(); + typename AssociativeContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete it->second; + } + + bool startsWith( std::string const& s, std::string const& prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; + + struct SourceLineInfo { + + SourceLineInfo(); + SourceLineInfo( char const* _file, std::size_t _line ); + SourceLineInfo( SourceLineInfo const& other ); +# ifdef CATCH_CPP11_OR_GREATER + SourceLineInfo( SourceLineInfo && ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo& operator = ( SourceLineInfo && ) = default; +# endif + bool empty() const; + bool operator == ( SourceLineInfo const& other ) const; + + std::string file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // This is just here to avoid compiler warnings with macro constants and boolean literals + inline bool isTrue( bool value ){ return value; } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() { + return std::string(); + } + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); + +#include + +namespace Catch { + + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + + virtual ~NotImplementedException() CATCH_NOEXCEPT {} + + virtual const char* what() const CATCH_NOEXCEPT; + + private: + std::string m_what; + SourceLineInfo m_lineInfo; + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + +// #included from: internal/catch_context.h +#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED + +// #included from: catch_interfaces_generators.h +#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED + +#include + +namespace Catch { + + struct IGeneratorInfo { + virtual ~IGeneratorInfo(); + virtual bool moveNext() = 0; + virtual std::size_t getCurrentIndex() const = 0; + }; + + struct IGeneratorsForTest { + virtual ~IGeneratorsForTest(); + + virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; + virtual bool moveNext() = 0; + }; + + IGeneratorsForTest* createGeneratorsForTest(); + +} // end namespace Catch + +// #included from: catch_ptr.hpp +#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + // An intrusive reference counting smart pointer. + // T must implement addRef() and release() methods + // typically implementing the IShared interface + template + class Ptr { + public: + Ptr() : m_p( NULL ){} + Ptr( T* p ) : m_p( p ){ + if( m_p ) + m_p->addRef(); + } + Ptr( Ptr const& other ) : m_p( other.m_p ){ + if( m_p ) + m_p->addRef(); + } + ~Ptr(){ + if( m_p ) + m_p->release(); + } + void reset() { + if( m_p ) + m_p->release(); + m_p = NULL; + } + Ptr& operator = ( T* p ){ + Ptr temp( p ); + swap( temp ); + return *this; + } + Ptr& operator = ( Ptr const& other ){ + Ptr temp( other ); + swap( temp ); + return *this; + } + void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } + T* get() { return m_p; } + const T* get() const{ return m_p; } + T& operator*() const { return *m_p; } + T* operator->() const { return m_p; } + bool operator !() const { return m_p == NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); } + + private: + T* m_p; + }; + + struct IShared : NonCopyable { + virtual ~IShared(); + virtual void addRef() const = 0; + virtual void release() const = 0; + }; + + template + struct SharedImpl : T { + + SharedImpl() : m_rc( 0 ){} + + virtual void addRef() const { + ++m_rc; + } + virtual void release() const { + if( --m_rc == 0 ) + delete this; + } + + mutable unsigned int m_rc; + }; + +} // end namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#include +#include +#include + +namespace Catch { + + class TestCase; + class Stream; + struct IResultCapture; + struct IRunner; + struct IGeneratorsForTest; + struct IConfig; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture& getResultCapture() = 0; + virtual IRunner& getRunner() = 0; + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; + virtual bool advanceGeneratorsForCurrentTest() = 0; + virtual Ptr getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( Ptr const& config ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); + Stream createStream( std::string const& streamName ); + +} + +// #included from: internal/catch_test_registry.hpp +#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED + +// #included from: catch_interfaces_testcase.h +#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED + +#include + +namespace Catch { + + class TestSpec; + + struct ITestCase : IShared { + virtual void invoke () const = 0; + protected: + virtual ~ITestCase(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases ) const = 0; + + }; +} + +namespace Catch { + +template +class MethodTestCase : public SharedImpl { + +public: + MethodTestCase( void (C::*method)() ) : m_method( method ) {} + + virtual void invoke() const { + C obj; + (obj.*m_method)(); + } + +private: + virtual ~MethodTestCase() {} + + void (C::*m_method)(); +}; + +typedef void(*TestFunction)(); + +struct NameAndDesc { + NameAndDesc( const char* _name = "", const char* _description= "" ) + : name( _name ), description( _description ) + {} + + const char* name; + const char* description; +}; + +struct AutoReg { + + AutoReg( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + + template + AutoReg( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + registerTestCase( new MethodTestCase( method ), + className, + nameAndDesc, + lineInfo ); + } + + void registerTestCase( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + + ~AutoReg(); + +private: + AutoReg( AutoReg const& ); + void operator= ( AutoReg const& ); +}; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( ... ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + +#else + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + +#endif + +// #included from: internal/catch_capture.hpp +#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED + +// #included from: catch_expression_decomposer.hpp +#define TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED + +// #included from: catch_expression_lhs.hpp +#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED + +// #included from: catch_expressionresult_builder.h +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_BUILDER_H_INCLUDED + +// #included from: catch_tostring.h +#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED + +// #included from: catch_sfinae.hpp +#define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED + +// Try to detect if the current compiler supports SFINAE + +namespace Catch { + + struct TrueType { + static const bool value = true; + typedef void Enable; + char sizer[1]; + }; + struct FalseType { + static const bool value = false; + typedef void Disable; + char sizer[2]; + }; + +#ifdef CATCH_CONFIG_SFINAE + + template struct NotABooleanExpression; + + template struct If : NotABooleanExpression {}; + template<> struct If : TrueType {}; + template<> struct If : FalseType {}; + + template struct SizedIf; + template<> struct SizedIf : TrueType {}; + template<> struct SizedIf : FalseType {}; + +#endif // CATCH_CONFIG_SFINAE + +} // end namespace Catch + +#include +#include +#include +#include +#include + +#ifdef __OBJC__ +// #included from: catch_objc_arc.hpp +#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED + +#import + +#ifdef __has_feature +#define CATCH_ARC_ENABLED __has_feature(objc_arc) +#else +#define CATCH_ARC_ENABLED 0 +#endif + +void arcSafeRelease( NSObject* obj ); +id performOptionalSelector( id obj, SEL sel ); + +#if !CATCH_ARC_ENABLED +inline void arcSafeRelease( NSObject* obj ) { + [obj release]; +} +inline id performOptionalSelector( id obj, SEL sel ) { + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; + return nil; +} +#define CATCH_UNSAFE_UNRETAINED +#define CATCH_ARC_STRONG +#else +inline void arcSafeRelease( NSObject* ){} +inline id performOptionalSelector( id obj, SEL sel ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#endif + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + return nil; +} +#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained +#define CATCH_ARC_STRONG __strong +#endif + +#endif + +namespace Catch { +namespace Detail { + +// SFINAE is currently disabled by default for all compilers. +// If the non SFINAE version of IsStreamInsertable is ambiguous for you +// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE +#ifdef CATCH_CONFIG_SFINAE + + template + class IsStreamInsertableHelper { + template struct TrueIfSizeable : TrueType {}; + + template + static TrueIfSizeable dummy(T2*); + static FalseType dummy(...); + + public: + typedef SizedIf type; + }; + + template + struct IsStreamInsertable : IsStreamInsertableHelper::type {}; + +#else + + struct BorgType { + template BorgType( T const& ); + }; + + TrueType& testStreamable( std::ostream& ); + FalseType testStreamable( FalseType ); + + FalseType operator<<( std::ostream const&, BorgType const& ); + + template + struct IsStreamInsertable { + static std::ostream &s; + static T const&t; + enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; + }; + +#endif + + template + struct StringMakerBase { + template + static std::string convert( T const& ) { return "{?}"; } + }; + + template<> + struct StringMakerBase { + template + static std::string convert( T const& _value ) { + std::ostringstream oss; + oss << _value; + return oss.str(); + } + }; + + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + + // Writes the raw memory into a string, considering endianness + template + std::string rawMemoryToString( T value ) { + union _ { + T typedValue; + unsigned char bytes[sizeof(T)]; + } u; + + u.typedValue = value; + + std::ostringstream oss; + oss << "0x"; + + int i = 0, end = sizeof(T), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + for( ; i != end; i += inc ) + oss << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)u.bytes[i]; + return oss.str(); + } + +} // end namespace Detail + +template +std::string toString( T const& value ); + +template +struct StringMaker : + Detail::StringMakerBase::value> {}; + +template +struct StringMaker { + template + static std::string convert( U* p ) { + if( !p ) + return INTERNAL_CATCH_STRINGIFY( NULL ); + else + return Detail::rawMemoryToString( p ); + } +}; + +template +struct StringMaker { + static std::string convert( R C::* p ) { + if( !p ) + return INTERNAL_CATCH_STRINGIFY( NULL ); + else + return Detail::rawMemoryToString( p ); + } +}; + +namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ); +} + +template +struct StringMaker > { + static std::string convert( std::vector const& v ) { + return Detail::rangeToString( v.begin(), v.end() ); + } +}; + +namespace Detail { + template + std::string makeString( T const& value ) { + return StringMaker::convert( value ); + } +} // end namespace Detail + +/// \brief converts any type to a string +/// +/// The default template forwards on to ostringstream - except when an +/// ostringstream overload does not exist - in which case it attempts to detect +/// that and writes {?}. +/// Overload (not specialise) this template for custom typs that you don't want +/// to provide an ostream overload for. +template +std::string toString( T const& value ) { + return StringMaker::convert( value ); +} + +// Built in overloads + +std::string toString( std::string const& value ); +std::string toString( std::wstring const& value ); +std::string toString( const char* const value ); +std::string toString( char* const value ); +std::string toString( int value ); +std::string toString( unsigned long value ); +std::string toString( unsigned int value ); +std::string toString( const double value ); +std::string toString( bool value ); +std::string toString( char value ); +std::string toString( signed char value ); +std::string toString( unsigned char value ); + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ); +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); + std::string toString( NSObject* const& nsObject ); +#endif + + namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ) { + std::ostringstream oss; + oss << "{ "; + if( first != last ) { + oss << toString( *first ); + for( ++first ; first != last ; ++first ) { + oss << ", " << toString( *first ); + } + } + oss << " }"; + return oss.str(); + } +} + +} // end namespace Catch + +// #included from: catch_assertionresult.h +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED + +#include +// #included from: catch_result_type.h +#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2 + + }; }; + + inline bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + inline bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + // ResultAction::Value enum + struct ResultAction { enum Value { + None, + Failed = 1, // Failure - but no debug break if Debug bit not set + Debug = 2, // If this bit is set, invoke the debugger + Abort = 4 // Test run should abort + }; }; + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x00, + + ContinueOnFailure = 0x01, // Failures fail test, but execution continues + NegateResult = 0x02, // Prefix expressiom with ! + SuppressFail = 0x04 // Failures are reported but do not fail the test + }; }; + + inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( static_cast( lhs ) | static_cast( rhs ) ); + } + + inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } + inline bool shouldNegate( int flags ) { return ( flags & ResultDisposition::NegateResult ) != 0; } + inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + +} // end namespace Catch + + +namespace Catch { + + struct AssertionInfo + { + AssertionInfo() {} + AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ); + + std::string macroName; + SourceLineInfo lineInfo; + std::string capturedExpression; + ResultDisposition::Flags resultDisposition; + }; + + struct AssertionResultData + { + AssertionResultData() : resultType( ResultWas::Unknown ) {} + + std::string reconstructedExpression; + std::string message; + ResultWas::OfType resultType; + }; + + class AssertionResult { + public: + AssertionResult(); + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); + ~AssertionResult(); +# ifdef CATCH_CPP11_OR_GREATER + AssertionResult( AssertionResult const& ) = default; + AssertionResult( AssertionResult && ) = default; + AssertionResult& operator = ( AssertionResult const& ) = default; + AssertionResult& operator = ( AssertionResult && ) = default; +# endif + + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + std::string getMessage() const; + SourceLineInfo getSourceInfo() const; + std::string getTestMacroName() const; + + protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + +} // end namespace Catch + +// #included from: catch_evaluate.hpp +#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#endif + +#include + +namespace Catch { +namespace Internal { + + enum Operator { + IsEqualTo, + IsNotEqualTo, + IsLessThan, + IsGreaterThan, + IsLessThanOrEqualTo, + IsGreaterThanOrEqualTo + }; + + template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; + template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; + template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; + + template + inline T& opCast(T const& t) { return const_cast(t); } + +// nullptr_t support based on pull request #154 from Konstantin Baumann +#ifdef CATCH_CONFIG_CPP11_NULLPTR + inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } +#endif // CATCH_CONFIG_CPP11_NULLPTR + + // So the compare overloads can be operator agnostic we convey the operator as a template + // enum, which is used to specialise an Evaluator for doing the comparison. + template + class Evaluator{}; + + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs) { + return opCast( lhs ) == opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) != opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) < opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) > opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) >= opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) <= opCast( rhs ); + } + }; + + template + bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // This level of indirection allows us to specialise for integer types + // to avoid signed/ unsigned warnings + + // "base" overload + template + bool compare( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // unsigned X to int + template bool compare( unsigned int lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // unsigned X to long + template bool compare( unsigned int lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // int to unsigned X + template bool compare( int lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // long to unsigned X + template bool compare( long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long (when comparing against NULL) + template bool compare( long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + + // pointer to int (when comparing against NULL) + template bool compare( int lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, int rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + +#ifdef CATCH_CONFIG_CPP11_NULLPTR + // pointer to nullptr_t (when comparing against nullptr) + template bool compare( std::nullptr_t, T* rhs ) { + return Evaluator::evaluate( NULL, rhs ); + } + template bool compare( T* lhs, std::nullptr_t ) { + return Evaluator::evaluate( lhs, NULL ); + } +#endif // CATCH_CONFIG_CPP11_NULLPTR + +} // end of namespace Internal +} // end of namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +namespace Catch { + +struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; + +// Wraps the (stringised versions of) the lhs, operator and rhs of an expression - as well as +// the result of evaluating it. This is used to build an AssertionResult object +class ExpressionResultBuilder { +public: + + ExpressionResultBuilder( ResultWas::OfType resultType = ResultWas::Unknown ); + ExpressionResultBuilder( ExpressionResultBuilder const& other ); + ExpressionResultBuilder& operator=(ExpressionResultBuilder const& other ); + + ExpressionResultBuilder& setResultType( ResultWas::OfType result ); + ExpressionResultBuilder& setResultType( bool result ); + ExpressionResultBuilder& setLhs( std::string const& lhs ); + ExpressionResultBuilder& setRhs( std::string const& rhs ); + ExpressionResultBuilder& setOp( std::string const& op ); + + ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition ); + + template + ExpressionResultBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + std::string reconstructExpression( AssertionInfo const& info ) const; + + AssertionResult buildResult( AssertionInfo const& info ) const; + + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + +private: + AssertionResultData m_data; + struct ExprComponents { + ExprComponents() : shouldNegate( false ) {} + bool shouldNegate; + std::string lhs, rhs, op; + } m_exprComponents; + std::ostringstream m_stream; +}; + +} // end namespace Catch + +namespace Catch { + +// Wraps the LHS of an expression and captures the operator and RHS (if any) - +// wrapping them all in an ExpressionResultBuilder object +template +class ExpressionLhs { + ExpressionLhs& operator = ( ExpressionLhs const& ); +# ifdef CATCH_CPP11_OR_GREATER + ExpressionLhs& operator = ( ExpressionLhs && ) = delete; +# endif + +public: + ExpressionLhs( T lhs ) : m_lhs( lhs ) {} +# ifdef CATCH_CPP11_OR_GREATER + ExpressionLhs( ExpressionLhs const& ) = default; + ExpressionLhs( ExpressionLhs && ) = default; +# endif + + template + ExpressionResultBuilder& operator == ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ExpressionResultBuilder& operator != ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ExpressionResultBuilder& operator < ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ExpressionResultBuilder& operator > ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ExpressionResultBuilder& operator <= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ExpressionResultBuilder& operator >= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + ExpressionResultBuilder& operator == ( bool rhs ) { + return captureExpression( rhs ); + } + + ExpressionResultBuilder& operator != ( bool rhs ) { + return captureExpression( rhs ); + } + + ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition ) { + bool value = m_lhs ? true : false; + return m_result + .setLhs( Catch::toString( value ) ) + .setResultType( value ) + .endExpression( resultDisposition ); + } + + // Only simple binary expressions are allowed on the LHS. + // If more complex compositions are required then place the sub expression in parentheses + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + +private: + template + ExpressionResultBuilder& captureExpression( RhsT const& rhs ) { + return m_result + .setResultType( Internal::compare( m_lhs, rhs ) ) + .setLhs( Catch::toString( m_lhs ) ) + .setRhs( Catch::toString( rhs ) ) + .setOp( Internal::OperatorTraits::getName() ); + } + +private: + ExpressionResultBuilder m_result; + T m_lhs; +}; + +} // end namespace Catch + +namespace Catch { + +// Captures the LHS of the expression and wraps it in an Expression Lhs object +class ExpressionDecomposer { +public: + + template + ExpressionLhs operator->* ( T const& operand ) { + return ExpressionLhs( operand ); + } + + ExpressionLhs operator->* ( bool value ) { + return ExpressionLhs( value ); + } +}; + +} // end namespace Catch + +// #included from: catch_message.h +#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED + +#include + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + SourceLineInfo lineInfo; + ResultWas::OfType type; + std::string message; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const { + return sequence == other.sequence; + } + bool operator < ( MessageInfo const& other ) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + + struct MessageBuilder { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + : m_info( macroName, lineInfo, type ) + {} + + template + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + MessageInfo m_info; + std::ostringstream m_stream; + }; + + class ScopedMessage { + public: + ScopedMessage( MessageBuilder const& builder ); + ~ScopedMessage(); + + MessageInfo m_info; + }; + +} // end namespace Catch + +// #included from: catch_interfaces_capture.h +#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + class ExpressionResultBuilder; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct MessageInfo; + class ScopedMessageBuilder; + struct Counts; + + struct IResultCapture { + + virtual ~IResultCapture(); + + virtual void assertionEnded( AssertionResult const& result ) = 0; + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0; + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual bool shouldDebugBreak() const = 0; + + virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) = 0; + + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + }; +} + +// #included from: catch_debugger.h +#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED + +// #included from: catch_platform.h +#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED + +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_IPHONE +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CATCH_PLATFORM_WINDOWS +#endif + +#include + +namespace Catch{ + + bool isDebuggerActive(); + void writeToDebugConsole( std::string const& text ); +} + +#ifdef CATCH_PLATFORM_MAC + + // The following code snippet based on: + // http://cocoawithlove.com/2008/03/break-into-debugger.html + #ifdef DEBUG + #if defined(__ppc64__) || defined(__ppc__) + #define CATCH_BREAK_INTO_DEBUGGER() \ + if( Catch::isDebuggerActive() ) { \ + __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ + : : : "memory","r0","r3","r4" ); \ + } + #else + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} + #endif + #endif + +#elif defined(_MSC_VER) + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } +#endif + +#ifndef CATCH_BREAK_INTO_DEBUGGER +#define CATCH_BREAK_INTO_DEBUGGER() Catch::isTrue( true ); +#endif + +// #included from: catch_interfaces_registry_hub.h +#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; + + struct IRegistryHub { + virtual ~IRegistryHub(); + + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + }; + + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0; + virtual void registerTest( TestCase const& testInfo ) = 0; + virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + }; + + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + +// #included from: catch_interfaces_config.h +#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct Verbosity { enum Level { + NoOutput = 0, + Quiet, + Normal + }; }; + + struct WarnAbout { enum What { + Nothing = 0x00, + NoAssertions = 0x01 + }; }; + + struct ShowDurations { enum OrNot { + DefaultForReporter, + Always, + Never + }; }; + + class TestSpec; + + struct IConfig : IShared { + + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + }; +} + +#include + +namespace Catch { + + inline IResultCapture& getResultCapture() { + return getCurrentContext().getResultCapture(); + } + + template + ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher, + std::string const& matcherCallAsString ) { + std::string matcherAsString = matcher.toString(); + if( matcherAsString == "{?}" ) + matcherAsString = matcherCallAsString; + return ExpressionResultBuilder() + .setRhs( matcherAsString ) + .setOp( "matches" ); + } + + template + ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher, + ArgT const& arg, + std::string const& matcherCallAsString ) { + return expressionResultBuilderFromMatcher( matcher, matcherCallAsString ) + .setLhs( Catch::toString( arg ) ) + .setResultType( matcher.match( arg ) ); + } + + template + ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher, + ArgT* arg, + std::string const& matcherCallAsString ) { + return expressionResultBuilderFromMatcher( matcher, matcherCallAsString ) + .setLhs( Catch::toString( arg ) ) + .setResultType( matcher.match( arg ) ); + } + +struct TestFailureException{}; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \ + if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, __assertionInfo ) ) { \ + if( internal_catch_action & Catch::ResultAction::Debug ) CATCH_BREAK_INTO_DEBUGGER(); \ + if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \ + if( !Catch::shouldContinueOnFailure( resultDisposition ) ) throw Catch::TestFailureException(); \ + Catch::isTrue( false && originalExpr ); \ + } + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ + do { \ + Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \ + } catch( Catch::TestFailureException& ) { \ + throw; \ + } catch( ... ) { \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \ + Catch::ResultDisposition::Normal, expr ); \ + } \ + } while( Catch::isTrue( false ) ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( !Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ + do { \ + Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + expr; \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \ + } \ + catch( ... ) { \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), resultDisposition, false ); \ + } \ +} while( Catch::isTrue( false ) ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ + try { \ + if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \ + expr; \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \ + } \ + } \ + catch( Catch::TestFailureException& ) { \ + throw; \ + } \ + catch( exceptionType ) { \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \ + } + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \ + do { \ + Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ + } while( Catch::isTrue( false ) ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ + do { \ + Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ + catch( ... ) { \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \ + resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \ + } \ + } while( Catch::isTrue( false ) ) + +/////////////////////////////////////////////////////////////////////////////// +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ + do { \ + Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << __VA_ARGS__ +::Catch::StreamEndStop(), resultDisposition, true ) \ + } while( Catch::isTrue( false ) ) +#else + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ + do { \ + Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << log, resultDisposition, true ) \ + } while( Catch::isTrue( false ) ) +#endif + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( log, macroName ) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ + do { \ + Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \ + try { \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \ + } catch( Catch::TestFailureException& ) { \ + throw; \ + } catch( ... ) { \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \ + resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \ + } \ + } while( Catch::isTrue( false ) ) + +// #included from: internal/catch_section.h +#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED + +// #included from: catch_section_info.h +#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED + +namespace Catch { + + struct SectionInfo { + SectionInfo( std::string const& _name, + std::string const& _description, + SourceLineInfo const& _lineInfo ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + +} // end namespace Catch + +// #included from: catch_totals.hpp +#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED + +#include + +namespace Catch { + + struct Counts { + Counts() : passed( 0 ), failed( 0 ) {} + + Counts operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + return diff; + } + Counts& operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + return *this; + } + + std::size_t total() const { + return passed + failed; + } + + std::size_t passed; + std::size_t failed; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else + ++diff.testCases.passed; + return diff; + } + + Totals& operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Counts assertions; + Counts testCases; + }; +} + +// #included from: catch_timer.h +#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED + +#ifdef CATCH_PLATFORM_WINDOWS +typedef unsigned long long uint64_t; +#else +#include +#endif + +namespace Catch { + + class Timer { + public: + Timer() : m_ticks( 0 ) {} + void start(); + unsigned int getElapsedNanoseconds() const; + unsigned int getElapsedMilliseconds() const; + double getElapsedSeconds() const; + + private: + uint64_t m_ticks; + }; + +} // namespace Catch + +#include + +namespace Catch { + + class Section { + public: + Section( SourceLineInfo const& lineInfo, + std::string const& name, + std::string const& description = "" ); + ~Section(); +# ifdef CATCH_CPP11_OR_GREATER + Section( Section const& ) = default; + Section( Section && ) = default; + Section& operator = ( Section const& ) = default; + Section& operator = ( Section && ) = default; +# endif + + // This indicates whether the section should be executed or not + operator bool(); + + private: + + SectionInfo m_info; + + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_SECTION( ... ) \ + if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) +#else + #define INTERNAL_CATCH_SECTION( name, desc ) \ + if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, name, desc ) ) +#endif + +// #included from: internal/catch_generators.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + +template +struct IGenerator { + virtual ~IGenerator() {} + virtual T getValue( std::size_t index ) const = 0; + virtual std::size_t size () const = 0; +}; + +template +class BetweenGenerator : public IGenerator { +public: + BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} + + virtual T getValue( std::size_t index ) const { + return m_from+static_cast( index ); + } + + virtual std::size_t size() const { + return static_cast( 1+m_to-m_from ); + } + +private: + + T m_from; + T m_to; +}; + +template +class ValuesGenerator : public IGenerator { +public: + ValuesGenerator(){} + + void add( T value ) { + m_values.push_back( value ); + } + + virtual T getValue( std::size_t index ) const { + return m_values[index]; + } + + virtual std::size_t size() const { + return m_values.size(); + } + +private: + std::vector m_values; +}; + +template +class CompositeGenerator { +public: + CompositeGenerator() : m_totalSize( 0 ) {} + + // *** Move semantics, similar to auto_ptr *** + CompositeGenerator( CompositeGenerator& other ) + : m_fileInfo( other.m_fileInfo ), + m_totalSize( 0 ) + { + move( other ); + } + + CompositeGenerator& setFileInfo( const char* fileInfo ) { + m_fileInfo = fileInfo; + return *this; + } + + ~CompositeGenerator() { + deleteAll( m_composed ); + } + + operator T () const { + size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); + + typename std::vector*>::const_iterator it = m_composed.begin(); + typename std::vector*>::const_iterator itEnd = m_composed.end(); + for( size_t index = 0; it != itEnd; ++it ) + { + const IGenerator* generator = *it; + if( overallIndex >= index && overallIndex < index + generator->size() ) + { + return generator->getValue( overallIndex-index ); + } + index += generator->size(); + } + CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); + return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so + } + + void add( const IGenerator* generator ) { + m_totalSize += generator->size(); + m_composed.push_back( generator ); + } + + CompositeGenerator& then( CompositeGenerator& other ) { + move( other ); + return *this; + } + + CompositeGenerator& then( T value ) { + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( value ); + add( valuesGen ); + return *this; + } + +private: + + void move( CompositeGenerator& other ) { + std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); + m_totalSize += other.m_totalSize; + other.m_composed.clear(); + } + + std::vector*> m_composed; + std::string m_fileInfo; + size_t m_totalSize; +}; + +namespace Generators +{ + template + CompositeGenerator between( T from, T to ) { + CompositeGenerator generators; + generators.add( new BetweenGenerator( from, to ) ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3 ){ + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3, T val4 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + valuesGen->add( val4 ); + generators.add( valuesGen ); + return generators; + } + +} // end namespace Generators + +using namespace Generators; + +} // end namespace Catch + +#define INTERNAL_CATCH_LINESTR2( line ) #line +#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) + +#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) + +// #included from: internal/catch_interfaces_exception.h +#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED + +#include + +namespace Catch { + + typedef std::string(*exceptionTranslateFunction)(); + + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate() const = 0; + }; + + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + virtual std::string translate() const { + try { + throw; + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator( translateFunction ) ); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) + +// #included from: internal/catch_approx.hpp +#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED + +#include +#include + +namespace Catch { +namespace Detail { + + class Approx { + public: + explicit Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx( Approx const& other ) + : m_epsilon( other.m_epsilon ), + m_scale( other.m_scale ), + m_value( other.m_value ) + {} + + static Approx custom() { + return Approx( 0 ); + } + + Approx operator()( double value ) { + Approx approx( value ); + approx.epsilon( m_epsilon ); + approx.scale( m_scale ); + return approx; + } + + friend bool operator == ( double lhs, Approx const& rhs ) { + // Thanks to Richard Harris for his help refining this formula + return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); + } + + friend bool operator == ( Approx const& lhs, double rhs ) { + return operator==( rhs, lhs ); + } + + friend bool operator != ( double lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + friend bool operator != ( Approx const& lhs, double rhs ) { + return !operator==( rhs, lhs ); + } + + Approx& epsilon( double newEpsilon ) { + m_epsilon = newEpsilon; + return *this; + } + + Approx& scale( double newScale ) { + m_scale = newScale; + return *this; + } + + std::string toString() const { + std::ostringstream oss; + oss << "Approx( " << Catch::toString( m_value ) << " )"; + return oss.str(); + } + + private: + double m_epsilon; + double m_scale; + double m_value; + }; +} + +template<> +inline std::string toString( Detail::Approx const& value ) { + return value.toString(); +} + +} // end namespace Catch + +// #included from: internal/catch_matchers.hpp +#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED + +namespace Catch { +namespace Matchers { + namespace Impl { + + template + struct Matcher : SharedImpl + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + }; + + template + struct MatcherImpl : Matcher { + + virtual Ptr > clone() const { + return Ptr >( new DerivedT( static_cast( *this ) ) ); + } + }; + + namespace Generic { + + template + class AllOf : public MatcherImpl, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + private: + std::vector > > m_matchers; + }; + + template + class AnyOf : public MatcherImpl, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + private: + std::vector > > m_matchers; + }; + + } + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct Equals : MatcherImpl { + Equals( std::string const& str ) : m_str( str ){} + Equals( Equals const& other ) : m_str( other.m_str ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_str == expr; + } + virtual std::string toString() const { + return "equals: \"" + m_str + "\""; + } + + std::string m_str; + }; + + struct Contains : MatcherImpl { + Contains( std::string const& substr ) : m_substr( substr ){} + Contains( Contains const& other ) : m_substr( other.m_substr ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + + struct StartsWith : MatcherImpl { + StartsWith( std::string const& substr ) : m_substr( substr ){} + StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) == 0; + } + virtual std::string toString() const { + return "starts with: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + + struct EndsWith : MatcherImpl { + EndsWith( std::string const& substr ) : m_substr( substr ){} + EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) == expr.size() - m_substr.size(); + } + virtual std::string toString() const { + return "ends with: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str ) { + return Impl::StdString::Equals( str ); + } + inline Impl::StdString::Equals Equals( const char* str ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ) ); + } + inline Impl::StdString::Contains Contains( std::string const& substr ) { + return Impl::StdString::Contains( substr ); + } + inline Impl::StdString::Contains Contains( const char* substr ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + +// These files are included here so the single_include script doesn't put them +// in the conditionally compiled sections +// #included from: internal/catch_test_case_info.h +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED + +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + struct ITestCase; + + struct TestCaseInfo { + TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + bool _isHidden, + SourceLineInfo const& _lineInfo ); + + TestCaseInfo( TestCaseInfo const& other ); + + std::string name; + std::string className; + std::string description; + std::set tags; + std::string tagsAsString; + SourceLineInfo lineInfo; + bool isHidden; + bool throws; + }; + + class TestCase : public TestCaseInfo { + public: + + TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( TestCase const& other ); + + TestCase withName( std::string const& _newName ) const; + + void invoke() const; + + TestCaseInfo const& getTestCaseInfo() const; + + bool isHidden() const; + bool throws() const; + + void swap( TestCase& other ); + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + TestCase& operator = ( TestCase const& other ); + + private: + Ptr test; + }; + + TestCase makeTestCase( ITestCase* testCase, + std::string const& className, + std::string const& name, + std::string const& description, + SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// #included from: internal/catch_interfaces_runner.h +#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED + +namespace Catch { + class TestCase; + + struct IRunner { + virtual ~IRunner(); + }; +} + + +#ifdef __OBJC__ +// #included from: internal/catch_objc.hpp +#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED + +#import + +#include + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage + +/////////////////////////////////////////////////////////////////////////////// +// This protocol is really only here for (self) documenting purposes, since +// all its methods are optional. +@protocol OcFixture + +@optional + +-(void) setUp; +-(void) tearDown; + +@end + +namespace Catch { + + class OcMethod : public SharedImpl { + + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + + virtual void invoke() const { + id obj = [[m_cls alloc] init]; + + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); + + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; + }; + + namespace Detail{ + + inline std::string getAnnotation( Class cls, + std::string const& annotationName, + std::string const& testCaseName ) { + NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; + SEL sel = NSSelectorFromString( selStr ); + arcSafeRelease( selStr ); + id value = performOptionalSelector( cls, sel ); + if( value ) + return [(NSString*)value UTF8String]; + return ""; + } + } + + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( NULL, 0 ); + + Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); + objc_getClassList( classes, noClasses ); + + for( int c = 0; c < noClasses; c++ ) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList( cls, &count ); + for( u_int m = 0; m < count ; m++ ) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if( startsWith( methodName, "Catch_TestCase_" ) ) { + std::string testCaseName = methodName.substr( 15 ); + std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); + std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); + const char* className = class_getName( cls ); + + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + noTestMethods++; + } + } + free(methods); + } + } + return noTestMethods; + } + + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { + + template + struct StringHolder : MatcherImpl{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } + + NSString* m_substr; + }; + + struct Equals : StringHolder { + Equals( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_substr]; + } + + virtual std::string toString() const { + return "equals string: \"" + Catch::toString( m_substr ) + "\""; + } + }; + + struct Contains : StringHolder { + Contains( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } + + virtual std::string toString() const { + return "contains string: \"" + Catch::toString( m_substr ) + "\""; + } + }; + + struct StartsWith : StringHolder { + StartsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } + + virtual std::string toString() const { + return "starts with: \"" + Catch::toString( m_substr ) + "\""; + } + }; + struct EndsWith : StringHolder { + EndsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } + + virtual std::string toString() const { + return "ends with: \"" + Catch::toString( m_substr ) + "\""; + } + }; + + } // namespace NSStringMatchers + } // namespace Impl + + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } + + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } + + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } + + inline Impl::NSStringMatchers::EndsWith + EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } + + } // namespace Matchers + + using namespace Matchers; + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define OC_TEST_CASE( name, desc )\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ +{\ +return @ name; \ +}\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +{ \ +return @ desc; \ +} \ +-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) + +#endif + +#ifdef CATCH_CONFIG_RUNNER +// #included from: internal/catch_impl.hpp +#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED + +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// #included from: catch_runner.hpp +#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED + +// #included from: internal/catch_commandline.hpp +#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED + +// #included from: catch_config.hpp +#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED + +// #included from: catch_test_spec_parser.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_test_spec.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +#include +#include + +namespace Catch { + + class TestSpec { + struct Pattern : SharedImpl<> { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + class NamePattern : public Pattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) { + if( startsWith( m_name, "*" ) ) { + m_name = m_name.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_name, "*" ) ) { + m_name = m_name.substr( 0, m_name.size()-1 ); + m_wildcard = (WildcardPosition)( m_wildcard | WildcardAtEnd ); + } + } + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_name == toLower( testCase.name ); + case WildcardAtStart: + return endsWith( toLower( testCase.name ), m_name ); + case WildcardAtEnd: + return startsWith( toLower( testCase.name ), m_name ); + case WildcardAtBothEnds: + return contains( toLower( testCase.name ), m_name ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string m_name; + WildcardPosition m_wildcard; + }; + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + virtual ~TagPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return testCase.tags.find( m_tag ) != testCase.tags.end(); + } + private: + std::string m_tag; + }; + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr m_underlyingPattern; + }; + + struct Filter { + std::vector > m_patterns; + + bool matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) + if( !(*it)->matches( testCase ) ) + return false; + return true; + } + }; + + public: + bool hasFilters() const { + return !m_filters.empty(); + } + bool matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } + + private: + std::vector m_filters; + + friend class TestSpecParser; + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +namespace Catch { + + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag }; + Mode m_mode; + bool m_exclusion; + std::size_t m_start, m_pos; + std::string m_arg; + TestSpec::Filter m_currentFilter; + TestSpec m_testSpec; + + public: + TestSpecParser parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = arg; + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern(); + addFilter(); + return *this; + } + TestSpec testSpec() { + return m_testSpec; + } + private: + void visitChar( char c ) { + if( m_mode == None ) { + switch( c ) { + case ' ': return; + case '~': m_exclusion = true; return; + case '[': return startNewMode( Tag, ++m_pos ); + case '"': return startNewMode( QuotedName, ++m_pos ); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + startNewMode( Tag, ++m_pos ); + } + } + else if( m_mode == QuotedName && c == '"' ) + addPattern(); + else if( m_mode == Tag && c == ']' ) + addPattern(); + } + void startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + template + void addPattern() { + std::string token = subString(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr pattern = new T( token ); + if( m_exclusion ) + pattern = new TestSpec::ExcludedPattern( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + void addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + }; + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser().parse( arg ).testSpec(); + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// #included from: catch_stream.h +#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED + +#include + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + class Stream { + public: + Stream(); + Stream( std::streambuf* _streamBuf, bool _isOwned ); + void release(); + + std::streambuf* streamBuf; + + private: + bool isOwned; + }; +} + +#include +#include +#include +#include + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + + struct ConfigData { + + ConfigData() + : listTests( false ), + listTags( false ), + listReporters( false ), + listTestNamesOnly( false ), + showSuccessfulTests( false ), + shouldDebugBreak( false ), + noThrow( false ), + showHelp( false ), + showInvisibles( false ), + abortAfter( -1 ), + verbosity( Verbosity::Normal ), + warnings( WarnAbout::Nothing ), + showDurations( ShowDurations::DefaultForReporter ) + {} + + bool listTests; + bool listTags; + bool listReporters; + bool listTestNamesOnly; + + bool showSuccessfulTests; + bool shouldDebugBreak; + bool noThrow; + bool showHelp; + bool showInvisibles; + + int abortAfter; + + Verbosity::Level verbosity; + WarnAbout::What warnings; + ShowDurations::OrNot showDurations; + + std::string reporterName; + std::string outputFilename; + std::string name; + std::string processName; + + std::vector testsOrTags; + }; + + class Config : public SharedImpl { + private: + Config( Config const& other ); + Config& operator = ( Config const& other ); + virtual void dummy(); + public: + + Config() + : m_os( std::cout.rdbuf() ) + {} + + Config( ConfigData const& data ) + : m_data( data ), + m_os( std::cout.rdbuf() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser; + for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) + parser.parse( data.testsOrTags[i] ); + m_testSpec = parser.testSpec(); + } + } + + virtual ~Config() { + m_os.rdbuf( std::cout.rdbuf() ); + m_stream.release(); + } + + void setFilename( std::string const& filename ) { + m_data.outputFilename = filename; + } + + std::string const& getFilename() const { + return m_data.outputFilename ; + } + + bool listTests() const { return m_data.listTests; } + bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool listTags() const { return m_data.listTags; } + bool listReporters() const { return m_data.listReporters; } + + std::string getProcessName() const { return m_data.processName; } + + bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } + + void setStreamBuf( std::streambuf* buf ) { + m_os.rdbuf( buf ? buf : std::cout.rdbuf() ); + } + + void useStream( std::string const& streamName ) { + Stream stream = createStream( streamName ); + setStreamBuf( stream.streamBuf ); + m_stream.release(); + m_stream = stream; + } + + std::string getReporterName() const { return m_data.reporterName; } + + int abortAfter() const { return m_data.abortAfter; } + + TestSpec const& testSpec() const { return m_testSpec; } + + bool showHelp() const { return m_data.showHelp; } + bool showInvisibles() const { return m_data.showInvisibles; } + + // IConfig interface + virtual bool allowThrows() const { return !m_data.noThrow; } + virtual std::ostream& stream() const { return m_os; } + virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } + virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } + + private: + ConfigData m_data; + + Stream m_stream; + mutable std::ostream m_os; + TestSpec m_testSpec; + }; + +} // end namespace Catch + +// #included from: catch_clara.h +#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#undef CLARA_CONFIG_CONSOLE_WIDTH +#endif +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +// Declare Clara inside the Catch namespace +#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { +// #included from: ../external/clara.h + +// Only use header guard if we are not using an outer namespace +#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) + +#ifndef STITCH_CLARA_OPEN_NAMESPACE +#define TWOBLUECUBES_CLARA_H_INCLUDED +#define STITCH_CLARA_OPEN_NAMESPACE +#define STITCH_CLARA_CLOSE_NAMESPACE +#else +#define STITCH_CLARA_CLOSE_NAMESPACE } +#endif + +#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE + +// ----------- #included from tbc_text_format.h ----------- + +// Only use header guard if we are not using an outer namespace +#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) +#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +#define TBC_TEXT_FORMAT_H_INCLUDED +#endif + +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TBC_TEXT_FORMAT_H_INCLUDED + +// ----------- end of #include from tbc_text_format.h ----------- +// ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h + +#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE + +#include +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_CLARA_OPEN_NAMESPACE +STITCH_CLARA_OPEN_NAMESPACE +#endif + +namespace Clara { + + struct UnpositionalTag {}; + + extern UnpositionalTag _; + +#ifdef CLARA_CONFIG_MAIN + UnpositionalTag _; +#endif + + namespace Detail { + +#ifdef CLARA_CONSOLE_WIDTH + const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + using namespace Tbc; + + inline bool startsWith( std::string const& str, std::string const& prefix ) { + return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; + } + + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + + template struct IsBool { static const bool value = false; }; + template<> struct IsBool { static const bool value = true; }; + + template + void convertInto( std::string const& _source, T& _dest ) { + std::stringstream ss; + ss << _source; + ss >> _dest; + if( ss.fail() ) + throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); + } + inline void convertInto( std::string const& _source, std::string& _dest ) { + _dest = _source; + } + inline void convertInto( std::string const& _source, bool& _dest ) { + std::string sourceLC = _source; + std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower ); + if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) + _dest = true; + else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) + _dest = false; + else + throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); + } + inline void convertInto( bool _source, bool& _dest ) { + _dest = _source; + } + template + inline void convertInto( bool, T& ) { + throw std::runtime_error( "Invalid conversion" ); + } + + template + struct IArgFunction { + virtual ~IArgFunction() {} +# ifdef CATCH_CPP11_OR_GREATER + IArgFunction() = default; + IArgFunction( IArgFunction const& ) = default; +# endif + virtual void set( ConfigT& config, std::string const& value ) const = 0; + virtual void setFlag( ConfigT& config ) const = 0; + virtual bool takesArg() const = 0; + virtual IArgFunction* clone() const = 0; + }; + + template + class BoundArgFunction { + public: + BoundArgFunction() : functionObj( NULL ) {} + BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {} + BoundArgFunction& operator = ( BoundArgFunction const& other ) { + IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL; + delete functionObj; + functionObj = newFunctionObj; + return *this; + } + ~BoundArgFunction() { delete functionObj; } + + void set( ConfigT& config, std::string const& value ) const { + functionObj->set( config, value ); + } + void setFlag( ConfigT& config ) const { + functionObj->setFlag( config ); + } + bool takesArg() const { return functionObj->takesArg(); } + + bool isSet() const { + return functionObj != NULL; + } + private: + IArgFunction* functionObj; + }; + + template + struct NullBinder : IArgFunction{ + virtual void set( C&, std::string const& ) const {} + virtual void setFlag( C& ) const {} + virtual bool takesArg() const { return true; } + virtual IArgFunction* clone() const { return new NullBinder( *this ); } + }; + + template + struct BoundDataMember : IArgFunction{ + BoundDataMember( M C::* _member ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + convertInto( stringValue, p.*member ); + } + virtual void setFlag( C& p ) const { + convertInto( true, p.*member ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } + M C::* member; + }; + template + struct BoundUnaryMethod : IArgFunction{ + BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + (p.*member)( value ); + } + virtual void setFlag( C& p ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + (p.*member)( value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } + void (C::*member)( M ); + }; + template + struct BoundNullaryMethod : IArgFunction{ + BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + (p.*member)(); + } + virtual void setFlag( C& p ) const { + (p.*member)(); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } + void (C::*member)(); + }; + + template + struct BoundUnaryFunction : IArgFunction{ + BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + function( obj ); + } + virtual void setFlag( C& p ) const { + function( p ); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } + void (*function)( C& ); + }; + + template + struct BoundBinaryFunction : IArgFunction{ + BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + function( obj, value ); + } + virtual void setFlag( C& obj ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + function( obj, value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } + void (*function)( C&, T ); + }; + + } // namespace Detail + + struct Parser { + Parser() : separators( " \t=:" ) {} + + struct Token { + enum Type { Positional, ShortOpt, LongOpt }; + Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} + Type type; + std::string data; + }; + + void parseIntoTokens( int argc, char const * const * argv, std::vector& tokens ) const { + const std::string doubleDash = "--"; + for( int i = 1; i < argc && argv[i] != doubleDash; ++i ) + parseIntoTokens( argv[i] , tokens); + } + void parseIntoTokens( std::string arg, std::vector& tokens ) const { + while( !arg.empty() ) { + Parser::Token token( Parser::Token::Positional, arg ); + arg = ""; + if( token.data[0] == '-' ) { + if( token.data.size() > 1 && token.data[1] == '-' ) { + token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) ); + } + else { + token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) ); + if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) { + arg = "-" + token.data.substr( 1 ); + token.data = token.data.substr( 0, 1 ); + } + } + } + if( token.type != Parser::Token::Positional ) { + std::size_t pos = token.data.find_first_of( separators ); + if( pos != std::string::npos ) { + arg = token.data.substr( pos+1 ); + token.data = token.data.substr( 0, pos ); + } + } + tokens.push_back( token ); + } + } + std::string separators; + }; + + template + struct CommonArgProperties { + CommonArgProperties() {} + CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} + + Detail::BoundArgFunction boundField; + std::string description; + std::string detail; + std::string placeholder; // Only value if boundField takes an arg + + bool takesArg() const { + return !placeholder.empty(); + } + void validate() const { + if( !boundField.isSet() ) + throw std::logic_error( "option not bound" ); + } + }; + struct OptionArgProperties { + std::vector shortNames; + std::string longName; + + bool hasShortName( std::string const& shortName ) const { + return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); + } + bool hasLongName( std::string const& _longName ) const { + return _longName == longName; + } + }; + struct PositionalArgProperties { + PositionalArgProperties() : position( -1 ) {} + int position; // -1 means non-positional (floating) + + bool isFixedPositional() const { + return position != -1; + } + }; + + template + class CommandLine { + + struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { + Arg() {} + Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} + + using CommonArgProperties::placeholder; // !TBD + + std::string dbgName() const { + if( !longName.empty() ) + return "--" + longName; + if( !shortNames.empty() ) + return "-" + shortNames[0]; + return "positional args"; + } + std::string commands() const { + std::ostringstream oss; + bool first = true; + std::vector::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); + for(; it != itEnd; ++it ) { + if( first ) + first = false; + else + oss << ", "; + oss << "-" << *it; + } + if( !longName.empty() ) { + if( !first ) + oss << ", "; + oss << "--" << longName; + } + if( !placeholder.empty() ) + oss << " <" << placeholder << ">"; + return oss.str(); + } + }; + + // NOTE: std::auto_ptr is deprecated in c++11/c++0x +#if defined(__cplusplus) && __cplusplus > 199711L + typedef std::unique_ptr ArgAutoPtr; +#else + typedef std::auto_ptr ArgAutoPtr; +#endif + + friend void addOptName( Arg& arg, std::string const& optName ) + { + if( optName.empty() ) + return; + if( Detail::startsWith( optName, "--" ) ) { + if( !arg.longName.empty() ) + throw std::logic_error( "Only one long opt may be specified. '" + + arg.longName + + "' already specified, now attempting to add '" + + optName + "'" ); + arg.longName = optName.substr( 2 ); + } + else if( Detail::startsWith( optName, "-" ) ) + arg.shortNames.push_back( optName.substr( 1 ) ); + else + throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); + } + friend void setPositionalArg( Arg& arg, int position ) + { + arg.position = position; + } + + class ArgBuilder { + public: + ArgBuilder( Arg* arg ) : m_arg( arg ) {} + + // Bind a non-boolean data member (requires placeholder string) + template + void bind( M C::* field, std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + m_arg->placeholder = placeholder; + } + // Bind a boolean data member (no placeholder required) + template + void bind( bool C::* field ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + } + + // Bind a method taking a single, non-boolean argument (requires a placeholder string) + template + void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + m_arg->placeholder = placeholder; + } + + // Bind a method taking a single, boolean argument (no placeholder string required) + template + void bind( void (C::* unaryMethod)( bool ) ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + } + + // Bind a method that takes no arguments (will be called if opt is present) + template + void bind( void (C::* nullaryMethod)() ) { + m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); + } + + // Bind a free function taking a single argument - the object to operate on (no placeholder string required) + template + void bind( void (* unaryFunction)( C& ) ) { + m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); + } + + // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) + template + void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); + m_arg->placeholder = placeholder; + } + + ArgBuilder& describe( std::string const& description ) { + m_arg->description = description; + return *this; + } + ArgBuilder& detail( std::string const& detail ) { + m_arg->detail = detail; + return *this; + } + + protected: + Arg* m_arg; + }; + + class OptBuilder : public ArgBuilder { + public: + OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} + OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} + + OptBuilder& operator[]( std::string const& optName ) { + addOptName( *ArgBuilder::m_arg, optName ); + return *this; + } + }; + + public: + + CommandLine() + : m_boundProcessName( new Detail::NullBinder() ), + m_highestSpecifiedArgPosition( 0 ), + m_throwOnUnrecognisedTokens( false ) + {} + CommandLine( CommandLine const& other ) + : m_boundProcessName( other.m_boundProcessName ), + m_options ( other.m_options ), + m_positionalArgs( other.m_positionalArgs ), + m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), + m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) + { + if( other.m_floatingArg.get() ) + m_floatingArg = ArgAutoPtr( new Arg( *other.m_floatingArg ) ); + } + + CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { + m_throwOnUnrecognisedTokens = shouldThrow; + return *this; + } + + OptBuilder operator[]( std::string const& optName ) { + m_options.push_back( Arg() ); + addOptName( m_options.back(), optName ); + OptBuilder builder( &m_options.back() ); + return builder; + } + + ArgBuilder operator[]( int position ) { + m_positionalArgs.insert( std::make_pair( position, Arg() ) ); + if( position > m_highestSpecifiedArgPosition ) + m_highestSpecifiedArgPosition = position; + setPositionalArg( m_positionalArgs[position], position ); + ArgBuilder builder( &m_positionalArgs[position] ); + return builder; + } + + // Invoke this with the _ instance + ArgBuilder operator[]( UnpositionalTag ) { + if( m_floatingArg.get() ) + throw std::logic_error( "Only one unpositional argument can be added" ); + m_floatingArg = ArgAutoPtr( new Arg() ); + ArgBuilder builder( m_floatingArg.get() ); + return builder; + } + + template + void bindProcessName( M C::* field ) { + m_boundProcessName = new Detail::BoundDataMember( field ); + } + template + void bindProcessName( void (C::*_unaryMethod)( M ) ) { + m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); + } + + void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { + typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; + std::size_t maxWidth = 0; + for( it = itBegin; it != itEnd; ++it ) + maxWidth = (std::max)( maxWidth, it->commands().size() ); + + for( it = itBegin; it != itEnd; ++it ) { + Detail::Text usage( it->commands(), Detail::TextAttributes() + .setWidth( maxWidth+indent ) + .setIndent( indent ) ); + Detail::Text desc( it->description, Detail::TextAttributes() + .setWidth( width - maxWidth - 3 ) ); + + for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { + std::string usageCol = i < usage.size() ? usage[i] : ""; + os << usageCol; + + if( i < desc.size() && !desc[i].empty() ) + os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) + << desc[i]; + os << "\n"; + } + } + } + std::string optUsage() const { + std::ostringstream oss; + optUsage( oss ); + return oss.str(); + } + + void argSynopsis( std::ostream& os ) const { + for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { + if( i > 1 ) + os << " "; + typename std::map::const_iterator it = m_positionalArgs.find( i ); + if( it != m_positionalArgs.end() ) + os << "<" << it->second.placeholder << ">"; + else if( m_floatingArg.get() ) + os << "<" << m_floatingArg->placeholder << ">"; + else + throw std::logic_error( "non consecutive positional arguments with no floating args" ); + } + // !TBD No indication of mandatory args + if( m_floatingArg.get() ) { + if( m_highestSpecifiedArgPosition > 1 ) + os << " "; + os << "[<" << m_floatingArg->placeholder << "> ...]"; + } + } + std::string argSynopsis() const { + std::ostringstream oss; + argSynopsis( oss ); + return oss.str(); + } + + void usage( std::ostream& os, std::string const& procName ) const { + validate(); + os << "usage:\n " << procName << " "; + argSynopsis( os ); + if( !m_options.empty() ) { + os << " [options]\n\nwhere options are: \n"; + optUsage( os, 2 ); + } + os << "\n"; + } + std::string usage( std::string const& procName ) const { + std::ostringstream oss; + usage( oss, procName ); + return oss.str(); + } + + ConfigT parse( int argc, char const * const * argv ) const { + ConfigT config; + parseInto( argc, argv, config ); + return config; + } + + std::vector parseInto( int argc, char const * const * argv, ConfigT& config ) const { + std::string processName = argv[0]; + std::size_t lastSlash = processName.find_last_of( "/\\" ); + if( lastSlash != std::string::npos ) + processName = processName.substr( lastSlash+1 ); + m_boundProcessName.set( config, processName ); + std::vector tokens; + Parser parser; + parser.parseIntoTokens( argc, argv, tokens ); + return populate( tokens, config ); + } + + std::vector populate( std::vector const& tokens, ConfigT& config ) const { + validate(); + std::vector unusedTokens = populateOptions( tokens, config ); + unusedTokens = populateFixedArgs( unusedTokens, config ); + unusedTokens = populateFloatingArgs( unusedTokens, config ); + return unusedTokens; + } + + std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + std::vector errors; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); + for(; it != itEnd; ++it ) { + Arg const& arg = *it; + + try { + if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || + ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { + if( arg.takesArg() ) { + if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) + errors.push_back( "Expected argument to option: " + token.data ); + else + arg.boundField.set( config, tokens[++i].data ); + } + else { + arg.boundField.setFlag( config ); + } + break; + } + } + catch( std::exception& ex ) { + errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); + } + } + if( it == itEnd ) { + if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) + unusedTokens.push_back( token ); + else if( m_throwOnUnrecognisedTokens ) + errors.push_back( "unrecognised option: " + token.data ); + } + } + if( !errors.empty() ) { + std::ostringstream oss; + for( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); + it != itEnd; + ++it ) { + if( it != errors.begin() ) + oss << "\n"; + oss << *it; + } + throw std::runtime_error( oss.str() ); + } + return unusedTokens; + } + std::vector populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + int position = 1; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::map::const_iterator it = m_positionalArgs.find( position ); + if( it != m_positionalArgs.end() ) + it->second.boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + if( token.type == Parser::Token::Positional ) + position++; + } + return unusedTokens; + } + std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { + if( !m_floatingArg.get() ) + return tokens; + std::vector unusedTokens; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + if( token.type == Parser::Token::Positional ) + m_floatingArg->boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + } + return unusedTokens; + } + + void validate() const + { + if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) + throw std::logic_error( "No options or arguments specified" ); + + for( typename std::vector::const_iterator it = m_options.begin(), + itEnd = m_options.end(); + it != itEnd; ++it ) + it->validate(); + } + + private: + Detail::BoundArgFunction m_boundProcessName; + std::vector m_options; + std::map m_positionalArgs; + ArgAutoPtr m_floatingArg; + int m_highestSpecifiedArgPosition; + bool m_throwOnUnrecognisedTokens; + }; + +} // end namespace Clara + +STITCH_CLARA_CLOSE_NAMESPACE +#undef STITCH_CLARA_OPEN_NAMESPACE +#undef STITCH_CLARA_CLOSE_NAMESPACE + +#endif // TWOBLUECUBES_CLARA_H_INCLUDED +#undef STITCH_CLARA_OPEN_NAMESPACE + +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +#include + +namespace Catch { + + inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } + inline void abortAfterX( ConfigData& config, int x ) { + if( x < 1 ) + throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); + config.abortAfter = x; + } + inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + + inline void addWarning( ConfigData& config, std::string const& _warning ) { + if( _warning == "NoAssertions" ) + config.warnings = (WarnAbout::What)( config.warnings | WarnAbout::NoAssertions ); + else + throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); + + } + inline void setVerbosity( ConfigData& config, int level ) { + // !TBD: accept strings? + config.verbosity = (Verbosity::Level)level; + } + inline void setShowDurations( ConfigData& config, bool _showDurations ) { + config.showDurations = _showDurations + ? ShowDurations::Always + : ShowDurations::Never; + } + inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { + std::ifstream f( _filename.c_str() ); + if( !f.is_open() ) + throw std::domain_error( "Unable to load input file: " + _filename ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, "#" ) ) + addTestOrTags( config, "\"" + line + "\"" ); + } + } + + inline Clara::CommandLine makeCommandLineParser() { + + using namespace Clara; + CommandLine cli; + + cli.bindProcessName( &ConfigData::processName ); + + cli["-?"]["-h"]["--help"] + .describe( "display usage information" ) + .bind( &ConfigData::showHelp ); + + cli["-l"]["--list-tests"] + .describe( "list all/matching test cases" ) + .bind( &ConfigData::listTests ); + + cli["-t"]["--list-tags"] + .describe( "list all/matching tags" ) + .bind( &ConfigData::listTags ); + + cli["-s"]["--success"] + .describe( "include successful tests in output" ) + .bind( &ConfigData::showSuccessfulTests ); + + cli["-b"]["--break"] + .describe( "break into debugger on failure" ) + .bind( &ConfigData::shouldDebugBreak ); + + cli["-e"]["--nothrow"] + .describe( "skip exception tests" ) + .bind( &ConfigData::noThrow ); + + cli["-i"]["--invisibles"] + .describe( "show invisibles (tabs, newlines)" ) + .bind( &ConfigData::showInvisibles ); + + cli["-o"]["--out"] + .describe( "output filename" ) + .bind( &ConfigData::outputFilename, "filename" ); + + cli["-r"]["--reporter"] +// .placeholder( "name[:filename]" ) + .describe( "reporter to use (defaults to console)" ) + .bind( &ConfigData::reporterName, "name" ); + + cli["-n"]["--name"] + .describe( "suite name" ) + .bind( &ConfigData::name, "name" ); + + cli["-a"]["--abort"] + .describe( "abort at first failure" ) + .bind( &abortAfterFirst ); + + cli["-x"]["--abortx"] + .describe( "abort after x failures" ) + .bind( &abortAfterX, "no. failures" ); + + cli["-w"]["--warn"] + .describe( "enable warnings" ) + .bind( &addWarning, "warning name" ); + +// - needs updating if reinstated +// cli.into( &setVerbosity ) +// .describe( "level of verbosity (0=no output)" ) +// .shortOpt( "v") +// .longOpt( "verbosity" ) +// .placeholder( "level" ); + + cli[_] + .describe( "which test or tests to use" ) + .bind( &addTestOrTags, "test name, pattern or tags" ); + + cli["-d"]["--durations"] + .describe( "show test durations" ) + .bind( &setShowDurations, "yes/no" ); + + cli["-f"]["--input-file"] + .describe( "load test names to run from a file" ) + .bind( &loadTestNamesFromFile, "filename" ); + + // Less common commands which don't have a short form + cli["--list-test-names-only"] + .describe( "list all/matching test cases names only" ) + .bind( &ConfigData::listTestNamesOnly ); + + cli["--list-reporters"] + .describe( "list all reporters" ) + .bind( &ConfigData::listReporters ); + + return cli; + } + +} // end namespace Catch + +// #included from: internal/catch_list.hpp +#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED + +// #included from: catch_text.h +#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED + +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +// #included from: ../external/tbc_text_format.h +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# endif +# else +# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include +#include +#include + +// Use optional outer namespace +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE + +namespace Catch { + using Tbc::Text; + using Tbc::TextAttributes; +} + +// #included from: catch_console_colour.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED + +namespace Catch { + + namespace Detail { + struct IColourImpl; + } + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + + // By intention + FileName = LightGrey, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + static Detail::IColourImpl* impl(); + }; + +} // end namespace Catch + +// #included from: catch_interfaces_reporter.h +#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED + +// #included from: catch_option.hpp +#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED + +namespace Catch { + + // An optional type + template + class Option { + public: + Option() : nullableValue( NULL ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : NULL ) + {} + + ~Option() { + reset(); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = NULL; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != NULL; } + bool none() const { return nullableValue == NULL; } + + bool operator !() const { return nullableValue == NULL; } + operator SafeBool::type() const { + return SafeBool::makeSafe( some() ); + } + + private: + T* nullableValue; + char storage[sizeof(T)]; + }; + +} // end namespace Catch + +#include +#include +#include +#include + +namespace Catch +{ + struct ReporterConfig { + explicit ReporterConfig( Ptr const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) + : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + + std::ostream& stream() const { return *m_stream; } + Ptr fullConfig() const { return m_fullConfig; } + + private: + std::ostream* m_stream; + Ptr m_fullConfig; + }; + + struct ReporterPreferences { + ReporterPreferences() + : shouldRedirectStdOut( false ) + {} + + bool shouldRedirectStdOut; + }; + + template + struct LazyStat : Option { + LazyStat() : used( false ) {} + LazyStat& operator=( T const& _value ) { + Option::operator=( _value ); + used = false; + return *this; + } + void reset() { + Option::reset(); + used = false; + } + bool used; + }; + + struct TestRunInfo { + TestRunInfo( std::string const& _name ) : name( _name ) {} + std::string name; + }; + struct GroupInfo { + GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) + {} + + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; + + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) + { + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); + + infoMessages.push_back( builder.m_info ); + } + } + virtual ~AssertionStats(); + +# ifdef CATCH_CPP11_OR_GREATER + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; +# endif + + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; + }; + + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + virtual ~SectionStats(); +# ifdef CATCH_CPP11_OR_GREATER + SectionStats( SectionStats const& ) = default; + SectionStats( SectionStats && ) = default; + SectionStats& operator = ( SectionStats const& ) = default; + SectionStats& operator = ( SectionStats && ) = default; +# endif + + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; + }; + + struct TestCaseStats { + TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ) + : testInfo( _testInfo ), + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + virtual ~TestCaseStats(); + +# ifdef CATCH_CPP11_OR_GREATER + TestCaseStats( TestCaseStats const& ) = default; + TestCaseStats( TestCaseStats && ) = default; + TestCaseStats& operator = ( TestCaseStats const& ) = default; + TestCaseStats& operator = ( TestCaseStats && ) = default; +# endif + + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; + + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + virtual ~TestGroupStats(); + +# ifdef CATCH_CPP11_OR_GREATER + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; +# endif + + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; + + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + virtual ~TestRunStats(); + +# ifndef CATCH_CPP11_OR_GREATER + TestRunStats( TestRunStats const& _other ) + : runInfo( _other.runInfo ), + totals( _other.totals ), + aborting( _other.aborting ) + {} +# else + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; +# endif + + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; + + struct IStreamingReporter : IShared { + virtual ~IStreamingReporter(); + + // Implementing class must also provide the following static method: + // static std::string getDescription(); + + virtual ReporterPreferences getPreferences() const = 0; + + virtual void noMatchingTestCases( std::string const& spec ) = 0; + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; + virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + + virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; + virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + }; + + struct IReporterFactory { + virtual ~IReporterFactory(); + virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; + + struct IReporterRegistry { + typedef std::map FactoryMap; + + virtual ~IReporterRegistry(); + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + }; + +} + +#include +#include + +namespace Catch { + + inline std::size_t listTests( Config const& config ) { + + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + std::cout << "Matching test cases:\n"; + else { + std::cout << "All available test cases:\n"; + testSpec = TestSpecParser().parse( "*" ).testSpec(); + } + + std::size_t matchedTests = 0; + TextAttributes nameAttr, tagsAttr; + nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + tagsAttr.setIndent( 6 ); + + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Colour::Code colour = testCaseInfo.isHidden + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard( colour ); + + std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl; + if( !testCaseInfo.tags.empty() ) + std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; + } + + if( !config.testSpec().hasFilters() ) + std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl; + else + std::cout << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; + return matchedTests; + } + + inline std::size_t listTestsNamesOnly( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( !config.testSpec().hasFilters() ) + testSpec = TestSpecParser().parse( "*" ).testSpec(); + std::size_t matchedTests = 0; + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + std::cout << testCaseInfo.name << std::endl; + } + return matchedTests; + } + + inline std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + std::cout << "Tags for matching test cases:\n"; + else { + std::cout << "All available tags:\n"; + testSpec = TestSpecParser().parse( "*" ).testSpec(); + } + + std::map tagCounts; + + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + for( std::set::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), + tagItEnd = it->getTestCaseInfo().tags.end(); + tagIt != tagItEnd; + ++tagIt ) { + std::string tagName = *tagIt; + std::map::iterator countIt = tagCounts.find( tagName ); + if( countIt == tagCounts.end() ) + tagCounts.insert( std::make_pair( tagName, 1 ) ); + else + countIt->second++; + } + } + + for( std::map::const_iterator countIt = tagCounts.begin(), + countItEnd = tagCounts.end(); + countIt != countItEnd; + ++countIt ) { + std::ostringstream oss; + oss << " " << countIt->second << " "; + Text wrapper( "[" + countIt->first + "]", TextAttributes() + .setInitialIndent( 0 ) + .setIndent( oss.str().size() ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); + std::cout << oss.str() << wrapper << "\n"; + } + std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; + return tagCounts.size(); + } + + inline std::size_t listReporters( Config const& /*config*/ ) { + std::cout << "Available reports:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; + std::size_t maxNameLen = 0; + for(it = itBegin; it != itEnd; ++it ) + maxNameLen = (std::max)( maxNameLen, it->first.size() ); + + for(it = itBegin; it != itEnd; ++it ) { + Text wrapper( it->second->getDescription(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( 7+maxNameLen ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); + std::cout << " " + << it->first + << ":" + << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << wrapper << "\n"; + } + std::cout << std::endl; + return factories.size(); + } + + inline Option list( Config const& config ) { + Option listedCount; + if( config.listTests() ) + listedCount = listedCount.valueOr(0) + listTests( config ); + if( config.listTestNamesOnly() ) + listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); + if( config.listTags() ) + listedCount = listedCount.valueOr(0) + listTags( config ); + if( config.listReporters() ) + listedCount = listedCount.valueOr(0) + listReporters( config ); + return listedCount; + } + +} // end namespace Catch + +// #included from: internal/catch_runner_impl.hpp +#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED + +// #included from: catch_test_case_tracker.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { +namespace SectionTracking { + + class TrackedSection { + + typedef std::map TrackedSections; + + public: + enum RunState { + NotStarted, + Executing, + ExecutingChildren, + Completed + }; + + TrackedSection( std::string const& name, TrackedSection* parent ) + : m_name( name ), m_runState( NotStarted ), m_parent( parent ) + {} + + RunState runState() const { return m_runState; } + + TrackedSection* findChild( std::string const& childName ) { + TrackedSections::iterator it = m_children.find( childName ); + return it != m_children.end() + ? &it->second + : NULL; + } + TrackedSection* acquireChild( std::string const& childName ) { + if( TrackedSection* child = findChild( childName ) ) + return child; + m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) ); + return findChild( childName ); + } + void enter() { + if( m_runState == NotStarted ) + m_runState = Executing; + } + void leave() { + for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end(); + it != itEnd; + ++it ) + if( it->second.runState() != Completed ) { + m_runState = ExecutingChildren; + return; + } + m_runState = Completed; + } + TrackedSection* getParent() { + return m_parent; + } + bool hasChildren() const { + return !m_children.empty(); + } + + private: + std::string m_name; + RunState m_runState; + TrackedSections m_children; + TrackedSection* m_parent; + + }; + + class TestCaseTracker { + public: + TestCaseTracker( std::string const& testCaseName ) + : m_testCase( testCaseName, NULL ), + m_currentSection( &m_testCase ), + m_completedASectionThisRun( false ) + {} + + bool enterSection( std::string const& name ) { + TrackedSection* child = m_currentSection->acquireChild( name ); + if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed ) + return false; + + m_currentSection = child; + m_currentSection->enter(); + return true; + } + void leaveSection() { + m_currentSection->leave(); + m_currentSection = m_currentSection->getParent(); + assert( m_currentSection != NULL ); + m_completedASectionThisRun = true; + } + + bool currentSectionHasChildren() const { + return m_currentSection->hasChildren(); + } + bool isCompleted() const { + return m_testCase.runState() == TrackedSection::Completed; + } + + class Guard { + public: + Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) { + m_tracker.enterTestCase(); + } + ~Guard() { + m_tracker.leaveTestCase(); + } + private: + Guard( Guard const& ); + void operator = ( Guard const& ); + TestCaseTracker& m_tracker; + }; + + private: + void enterTestCase() { + m_currentSection = &m_testCase; + m_completedASectionThisRun = false; + m_testCase.enter(); + } + void leaveTestCase() { + m_testCase.leave(); + } + + TrackedSection m_testCase; + TrackedSection* m_currentSection; + bool m_completedASectionThisRun; + }; + +} // namespace SectionTracking + +using SectionTracking::TestCaseTracker; + +} // namespace Catch + +#include +#include + +namespace Catch { + + class StreamRedirect { + + public: + StreamRedirect( std::ostream& stream, std::string& targetString ) + : m_stream( stream ), + m_prevBuf( stream.rdbuf() ), + m_targetString( targetString ) + { + stream.rdbuf( m_oss.rdbuf() ); + } + + ~StreamRedirect() { + m_targetString += m_oss.str(); + m_stream.rdbuf( m_prevBuf ); + } + + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + RunContext( RunContext const& ); + void operator =( RunContext const& ); + + public: + + explicit RunContext( Ptr const& config, Ptr const& reporter ) + : m_runInfo( config->name() ), + m_context( getCurrentMutableContext() ), + m_activeTestCase( NULL ), + m_config( config ), + m_reporter( reporter ), + m_prevRunner( &m_context.getRunner() ), + m_prevResultCapture( &m_context.getResultCapture() ), + m_prevConfig( m_context.getConfig() ) + { + m_context.setRunner( this ); + m_context.setConfig( m_config ); + m_context.setResultCapture( this ); + m_reporter->testRunStarting( m_runInfo ); + } + + virtual ~RunContext() { + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); + m_context.setRunner( m_prevRunner ); + m_context.setConfig( NULL ); + m_context.setResultCapture( m_prevResultCapture ); + m_context.setConfig( m_prevConfig ); + } + + void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); + } + void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); + } + + Totals runTest( TestCase const& testCase ) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + TestCaseInfo testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting( testInfo ); + + m_activeTestCase = &testCase; + m_testCaseTracker = TestCaseTracker( testInfo.name ); + + do { + do { + runCurrentTest( redirectedCout, redirectedCerr ); + } + while( !m_testCaseTracker->isCompleted() && !aborting() ); + } + while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); + + Totals deltaTotals = m_totals.delta( prevTotals ); + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting() ) ); + + m_activeTestCase = NULL; + m_testCaseTracker.reset(); + + return deltaTotals; + } + + Ptr config() const { + return m_config; + } + + private: // IResultCapture + + virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) { + m_lastAssertionInfo = assertionInfo; + return actOnCurrentResult( assertionResult.buildResult( assertionInfo ) ); + } + + virtual void assertionEnded( AssertionResult const& result ) { + if( result.getResultType() == ResultWas::Ok ) { + m_totals.assertions.passed++; + } + else if( !result.isOk() ) { + m_totals.assertions.failed++; + } + + if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) + m_messages.clear(); + + // Reset working state + m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + } + + virtual bool sectionStarted ( + SectionInfo const& sectionInfo, + Counts& assertions + ) + { + std::ostringstream oss; + oss << sectionInfo.name << "@" << sectionInfo.lineInfo; + + if( !m_testCaseTracker->enterSection( oss.str() ) ) + return false; + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting( sectionInfo ); + + assertions = m_totals.assertions; + + return true; + } + bool testForMissingAssertions( Counts& assertions ) { + if( assertions.total() != 0 || + !m_config->warnAboutMissingAssertions() || + m_testCaseTracker->currentSectionHasChildren() ) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) { + if( std::uncaught_exception() ) { + m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) ); + return; + } + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + m_testCaseTracker->leaveSection(); + + m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) ); + m_messages.clear(); + } + + virtual void pushScopedMessage( MessageInfo const& message ) { + m_messages.push_back( message ); + } + + virtual void popScopedMessage( MessageInfo const& message ) { + m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); + } + + virtual bool shouldDebugBreak() const { + return m_config->shouldDebugBreak(); + } + + virtual std::string getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : ""; + } + + virtual const AssertionResult* getLastResult() const { + return &m_lastResult; + } + + public: + // !TBD We need to do this another way! + bool aborting() const { + return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); + } + + private: + + ResultAction::Value actOnCurrentResult( AssertionResult const& result ) { + m_lastResult = result; + assertionEnded( m_lastResult ); + + ResultAction::Value action = ResultAction::None; + + if( !m_lastResult.isOk() ) { + action = ResultAction::Failed; + if( shouldDebugBreak() ) + action = (ResultAction::Value)( action | ResultAction::Debug ); + if( aborting() ) + action = (ResultAction::Value)( action | ResultAction::Abort ); + } + return action; + } + + void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo ); + m_reporter->sectionStarting( testCaseSection ); + Counts prevAssertions = m_totals.assertions; + double duration = 0; + try { + m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); + TestCaseTracker::Guard guard( *m_testCaseTracker ); + + Timer timer; + timer.start(); + if( m_reporter->getPreferences().shouldRedirectStdOut ) { + StreamRedirect coutRedir( std::cout, redirectedCout ); + StreamRedirect cerrRedir( std::cerr, redirectedCerr ); + m_activeTestCase->invoke(); + } + else { + m_activeTestCase->invoke(); + } + duration = timer.getElapsedSeconds(); + } + catch( TestFailureException& ) { + // This just means the test was aborted due to failure + } + catch(...) { + ExpressionResultBuilder exResult( ResultWas::ThrewException ); + exResult << translateActiveException(); + actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo ) ); + } + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it ) + sectionEnded( it->info, it->prevAssertions, it->durationInSeconds ); + m_unfinishedSections.clear(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); + m_reporter->sectionEnded( testCaseSectionStats ); + } + + private: + struct UnfinishedSections { + UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds ) + : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo info; + Counts prevAssertions; + double durationInSeconds; + }; + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase; + Option m_testCaseTracker; + AssertionResult m_lastResult; + + Ptr m_config; + Totals m_totals; + Ptr m_reporter; + std::vector m_messages; + IRunner* m_prevRunner; + IResultCapture* m_prevResultCapture; + Ptr m_prevConfig; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + }; + +} // end namespace Catch + +// #included from: internal/catch_version.h +#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED + +namespace Catch { + + // Versioning information + struct Version { + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _buildNumber, + char const* const _branchName ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + buildNumber( _buildNumber ), + branchName( _branchName ) + {} + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const buildNumber; + char const* const branchName; + + private: + void operator=( Version const& ); + }; + + extern Version libraryVersion; +} + +#include +#include +#include + +namespace Catch { + + class Runner { + + public: + Runner( Ptr const& config ) + : m_config( config ) + { + openStream(); + makeReporter(); + } + + Totals runTests() { + + RunContext context( m_config.get(), m_reporter ); + + Totals totals; + + context.testGroupStarting( "", 1, 1 ); // deprecated? + + TestSpec testSpec = m_config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser().parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector testCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases ); + + int testsRunForGroup = 0; + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) { + testsRunForGroup++; + if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) { + + if( context.aborting() ) + break; + + totals += context.runTest( *it ); + m_testsAlreadyRun.insert( *it ); + } + } + context.testGroupEnded( "", totals, 1, 1 ); + return totals; + } + + private: + void openStream() { + // Open output file, if specified + if( !m_config->getFilename().empty() ) { + m_ofs.open( m_config->getFilename().c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << m_config->getFilename() << "'"; + throw std::domain_error( oss.str() ); + } + m_config->setStreamBuf( m_ofs.rdbuf() ); + } + } + void makeReporter() { + std::string reporterName = m_config->getReporterName().empty() + ? "console" + : m_config->getReporterName(); + + m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() ); + if( !m_reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); + } + } + + private: + Ptr m_config; + std::ofstream m_ofs; + Ptr m_reporter; + std::set m_testsAlreadyRun; + }; + + class Session { + static bool alreadyInstantiated; + + public: + + struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; + + Session() + : m_cli( makeCommandLineParser() ) { + if( alreadyInstantiated ) { + std::string msg = "Only one instance of Catch::Session can ever be used"; + std::cerr << msg << std::endl; + throw std::logic_error( msg ); + } + alreadyInstantiated = true; + } + ~Session() { + Catch::cleanUp(); + } + + void showHelp( std::string const& processName ) { + std::cout << "\nCatch v" << libraryVersion.majorVersion << "." + << libraryVersion.minorVersion << " build " + << libraryVersion.buildNumber; + if( libraryVersion.branchName != std::string( "master" ) ) + std::cout << " (" << libraryVersion.branchName << " branch)"; + std::cout << "\n"; + + m_cli.usage( std::cout, processName ); + std::cout << "For more detail usage please see the project docs\n" << std::endl; + } + + int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + try { + m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); + m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); + if( m_configData.showHelp ) + showHelp( m_configData.processName ); + m_config.reset(); + } + catch( std::exception& ex ) { + { + Colour colourGuard( Colour::Red ); + std::cerr << "\nError(s) in input:\n" + << Text( ex.what(), TextAttributes().setIndent(2) ) + << "\n\n"; + } + m_cli.usage( std::cout, m_configData.processName ); + return (std::numeric_limits::max)(); + } + return 0; + } + + void useConfigData( ConfigData const& _configData ) { + m_configData = _configData; + m_config.reset(); + } + + int run( int argc, char* const argv[] ) { + + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + + int run() { + if( m_configData.showHelp ) + return 0; + + try + { + config(); // Force config to be constructed + Runner runner( m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + return static_cast( runner.runTests().assertions.failed ); + } + catch( std::exception& ex ) { + std::cerr << ex.what() << std::endl; + return (std::numeric_limits::max)(); + } + } + + Clara::CommandLine const& cli() const { + return m_cli; + } + std::vector const& unusedTokens() const { + return m_unusedTokens; + } + ConfigData& configData() { + return m_configData; + } + Config& config() { + if( !m_config ) + m_config = new Config( m_configData ); + return *m_config; + } + + private: + Clara::CommandLine m_cli; + std::vector m_unusedTokens; + ConfigData m_configData; + Ptr m_config; + }; + + bool Session::alreadyInstantiated = false; + +} // end namespace Catch + +// #included from: catch_registry_hub.hpp +#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED + +// #included from: catch_test_case_registry_impl.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + class TestRegistry : public ITestCaseRegistry { + public: + TestRegistry() : m_unnamedCount( 0 ) {} + virtual ~TestRegistry(); + + virtual void registerTest( TestCase const& testCase ) { + std::string name = testCase.getTestCaseInfo().name; + if( name == "" ) { + std::ostringstream oss; + oss << "Anonymous test case " << ++m_unnamedCount; + return registerTest( testCase.withName( oss.str() ) ); + } + + if( m_functions.find( testCase ) == m_functions.end() ) { + m_functions.insert( testCase ); + m_functionsInOrder.push_back( testCase ); + if( !testCase.isHidden() ) + m_nonHiddenFunctions.push_back( testCase ); + } + else { + TestCase const& prev = *m_functions.find( testCase ); + { + Colour colourGuard( Colour::Red ); + std::cerr << "error: TEST_CASE( \"" << name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl; + } + exit(1); + } + } + + virtual std::vector const& getAllTests() const { + return m_functionsInOrder; + } + + virtual std::vector const& getAllNonHiddenTests() const { + return m_nonHiddenFunctions; + } + + virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases ) const { + for( std::vector::const_iterator it = m_functionsInOrder.begin(), + itEnd = m_functionsInOrder.end(); + it != itEnd; + ++it ) { + if( testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ) ) + matchingTestCases.push_back( *it ); + } + } + + private: + + std::set m_functions; + std::vector m_functionsInOrder; + std::vector m_nonHiddenFunctions; + size_t m_unnamedCount; + }; + + /////////////////////////////////////////////////////////////////////////// + + class FreeFunctionTestCase : public SharedImpl { + public: + + FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} + + virtual void invoke() const { + m_fun(); + } + + private: + virtual ~FreeFunctionTestCase(); + + TestFunction m_fun; + }; + + inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { + std::string className = classOrQualifiedMethodName; + if( startsWith( className, "&" ) ) + { + std::size_t lastColons = className.rfind( "::" ); + std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); + if( penultimateColons == std::string::npos ) + penultimateColons = 1; + className = className.substr( penultimateColons, lastColons-penultimateColons ); + } + return className; + } + + /////////////////////////////////////////////////////////////////////////// + + AutoReg::AutoReg( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + } + + AutoReg::~AutoReg() {} + + void AutoReg::registerTestCase( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + getMutableRegistryHub().registerTest + ( makeTestCase( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + +} // end namespace Catch + +// #included from: catch_reporter_registry.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED + +#include + +namespace Catch { + + class ReporterRegistry : public IReporterRegistry { + + public: + + virtual ~ReporterRegistry() { + deleteAllValues( m_factories ); + } + + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const { + FactoryMap::const_iterator it = m_factories.find( name ); + if( it == m_factories.end() ) + return NULL; + return it->second->create( ReporterConfig( config ) ); + } + + void registerReporter( std::string const& name, IReporterFactory* factory ) { + m_factories.insert( std::make_pair( name, factory ) ); + } + + FactoryMap const& getFactories() const { + return m_factories; + } + + private: + FactoryMap m_factories; + }; +} + +// #included from: catch_exception_translator_registry.hpp +#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED + +#ifdef __OBJC__ +#import "Foundation/Foundation.h" +#endif + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry() { + deleteAll( m_translators ); + } + + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( translator ); + } + + virtual std::string translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + throw; + } + @catch (NSException *exception) { + return toString( [exception description] ); + } +#else + throw; +#endif + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return tryTranslators( m_translators.begin() ); + } + } + + std::string tryTranslators( std::vector::const_iterator it ) const { + if( it == m_translators.end() ) + return "Unknown exception"; + + try { + return (*it)->translate(); + } + catch(...) { + return tryTranslators( it+1 ); + } + } + + private: + std::vector m_translators; + }; +} + +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub { + + RegistryHub( RegistryHub const& ); + void operator=( RegistryHub const& ); + + public: // IRegistryHub + RegistryHub() { + } + virtual IReporterRegistry const& getReporterRegistry() const { + return m_reporterRegistry; + } + virtual ITestCaseRegistry const& getTestCaseRegistry() const { + return m_testCaseRegistry; + } + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() { + return m_exceptionTranslatorRegistry; + } + + public: // IMutableRegistryHub + virtual void registerReporter( std::string const& name, IReporterFactory* factory ) { + m_reporterRegistry.registerReporter( name, factory ); + } + virtual void registerTest( TestCase const& testInfo ) { + m_testCaseRegistry.registerTest( testInfo ); + } + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + }; + + // Single, global, instance + inline RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = NULL; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = NULL; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + +} // end namespace Catch + +// #included from: catch_notimplemented_exception.hpp +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED + +#include + +namespace Catch { + + NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) + : m_lineInfo( lineInfo ) { + std::ostringstream oss; + oss << lineInfo << ": function "; + oss << "not implemented"; + m_what = oss.str(); + } + + const char* NotImplementedException::what() const CATCH_NOEXCEPT { + return m_what.c_str(); + } + +} // end namespace Catch + +// #included from: catch_context_impl.hpp +#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED + +// #included from: catch_stream.hpp +#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED + +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED + +#include + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() CATCH_NOEXCEPT; + }; +} + +#include +#include + +namespace Catch { + + template + class StreamBufImpl : public StreamBufBase { + char data[bufferSize]; + WriterF m_writer; + + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); + } + + ~StreamBufImpl() CATCH_NOEXCEPT { + sync(); + } + + private: + int overflow( int c ) { + sync(); + + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast( c ) ) ); + else + sputc( static_cast( c ) ); + } + return 0; + } + + int sync() { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + Stream::Stream() + : streamBuf( NULL ), isOwned( false ) + {} + + Stream::Stream( std::streambuf* _streamBuf, bool _isOwned ) + : streamBuf( _streamBuf ), isOwned( _isOwned ) + {} + + void Stream::release() { + if( isOwned ) { + delete streamBuf; + streamBuf = NULL; + isOwned = false; + } + } +} + +namespace Catch { + + class Context : public IMutableContext { + + Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {} + Context( Context const& ); + void operator=( Context const& ); + + public: // IContext + virtual IResultCapture& getResultCapture() { + return *m_resultCapture; + } + virtual IRunner& getRunner() { + return *m_runner; + } + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { + return getGeneratorsForCurrentTest() + .getGeneratorInfo( fileInfo, totalSize ) + .getCurrentIndex(); + } + virtual bool advanceGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + return generators && generators->moveNext(); + } + + virtual Ptr getConfig() const { + return m_config; + } + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ) { + m_resultCapture = resultCapture; + } + virtual void setRunner( IRunner* runner ) { + m_runner = runner; + } + virtual void setConfig( Ptr const& config ) { + m_config = config; + } + + friend IMutableContext& getCurrentMutableContext(); + + private: + IGeneratorsForTest* findGeneratorsForCurrentTest() { + std::string testName = getResultCapture().getCurrentTestName(); + + std::map::const_iterator it = + m_generatorsByTestName.find( testName ); + return it != m_generatorsByTestName.end() + ? it->second + : NULL; + } + + IGeneratorsForTest& getGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + if( !generators ) { + std::string testName = getResultCapture().getCurrentTestName(); + generators = createGeneratorsForTest(); + m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); + } + return *generators; + } + + private: + Ptr m_config; + IRunner* m_runner; + IResultCapture* m_resultCapture; + std::map m_generatorsByTestName; + }; + + namespace { + Context* currentContext = NULL; + } + IMutableContext& getCurrentMutableContext() { + if( !currentContext ) + currentContext = new Context(); + return *currentContext; + } + IContext& getCurrentContext() { + return getCurrentMutableContext(); + } + + Stream createStream( std::string const& streamName ) { + if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false ); + if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false ); + if( streamName == "debug" ) return Stream( new StreamBufImpl, true ); + + throw std::domain_error( "Unknown stream: " + streamName ); + } + + void cleanUpContext() { + delete currentContext; + currentContext = NULL; + } +} + +// #included from: catch_console_colour_impl.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED + +namespace Catch { namespace Detail { + struct IColourImpl { + virtual ~IColourImpl() {} + virtual void use( Colour::Code _colourCode ) = 0; + }; +}} + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +namespace Catch { +namespace { + + class Win32ColourImpl : public Detail::IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalAttributes = csbiInfo.wAttributes; + } + + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalAttributes ); + case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::Red: return setTextAttribute( FOREGROUND_RED ); + case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); + case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); + case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); + case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::Grey: return setTextAttribute( 0 ); + + case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); + case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); + case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); + case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + + private: + void setTextAttribute( WORD _textAttribute ) { + SetConsoleTextAttribute( stdoutHandle, _textAttribute ); + } + HANDLE stdoutHandle; + WORD originalAttributes; + }; + + inline bool shouldUseColourForPlatform() { + return true; + } + + static Detail::IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + return &s_instance; + } + +} // end anon namespace +} // end namespace Catch + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +#include + +namespace Catch { +namespace { + + // use POSIX/ ANSI console terminal codes + // Thanks to Adam Strzelecki for original contribution + // (http://github.com/nanoant) + // https://github.com/philsquared/Catch/pull/131 + class PosixColourImpl : public Detail::IColourImpl { + public: + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: + case Colour::White: return setColour( "[0m" ); + case Colour::Red: return setColour( "[0;31m" ); + case Colour::Green: return setColour( "[0;32m" ); + case Colour::Blue: return setColour( "[0:34m" ); + case Colour::Cyan: return setColour( "[0;36m" ); + case Colour::Yellow: return setColour( "[0;33m" ); + case Colour::Grey: return setColour( "[1;30m" ); + + case Colour::LightGrey: return setColour( "[0;37m" ); + case Colour::BrightRed: return setColour( "[1;31m" ); + case Colour::BrightGreen: return setColour( "[1;32m" ); + case Colour::BrightWhite: return setColour( "[1;37m" ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + private: + void setColour( const char* _escapeCode ) { + std::cout << '\033' << _escapeCode; + } + }; + + inline bool shouldUseColourForPlatform() { + return isatty(STDOUT_FILENO); + } + + static Detail::IColourImpl* platformColourInstance() { + static PosixColourImpl s_instance; + return &s_instance; + } + +} // end anon namespace +} // end namespace Catch + +#endif // not Windows + +namespace Catch { + + namespace { + struct NoColourImpl : Detail::IColourImpl { + void use( Colour::Code ) {} + + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + static bool shouldUseColour() { + return shouldUseColourForPlatform() && !isDebuggerActive(); + } + } + + Colour::Colour( Code _colourCode ){ use( _colourCode ); } + Colour::~Colour(){ use( None ); } + void Colour::use( Code _colourCode ) { + impl()->use( _colourCode ); + } + + Detail::IColourImpl* Colour::impl() { + return shouldUseColour() + ? platformColourInstance() + : NoColourImpl::instance(); + } + +} // end namespace Catch + +// #included from: catch_generators_impl.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct GeneratorInfo : IGeneratorInfo { + + GeneratorInfo( std::size_t size ) + : m_size( size ), + m_currentIndex( 0 ) + {} + + bool moveNext() { + if( ++m_currentIndex == m_size ) { + m_currentIndex = 0; + return false; + } + return true; + } + + std::size_t getCurrentIndex() const { + return m_currentIndex; + } + + std::size_t m_size; + std::size_t m_currentIndex; + }; + + /////////////////////////////////////////////////////////////////////////// + + class GeneratorsForTest : public IGeneratorsForTest { + + public: + ~GeneratorsForTest() { + deleteAll( m_generatorsInOrder ); + } + + IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { + std::map::const_iterator it = m_generatorsByName.find( fileInfo ); + if( it == m_generatorsByName.end() ) { + IGeneratorInfo* info = new GeneratorInfo( size ); + m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); + m_generatorsInOrder.push_back( info ); + return *info; + } + return *it->second; + } + + bool moveNext() { + std::vector::const_iterator it = m_generatorsInOrder.begin(); + std::vector::const_iterator itEnd = m_generatorsInOrder.end(); + for(; it != itEnd; ++it ) { + if( (*it)->moveNext() ) + return true; + } + return false; + } + + private: + std::map m_generatorsByName; + std::vector m_generatorsInOrder; + }; + + IGeneratorsForTest* createGeneratorsForTest() + { + return new GeneratorsForTest(); + } + +} // end namespace Catch + +// #included from: catch_assertionresult.hpp +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED + +namespace Catch { + + AssertionInfo::AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + capturedExpression( _capturedExpression ), + resultDisposition( _resultDisposition ) + {} + + AssertionResult::AssertionResult() {} + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + AssertionResult::~AssertionResult() {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return !m_info.capturedExpression.empty(); + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if( shouldNegate( m_info.resultDisposition ) ) + return "!" + m_info.capturedExpression; + else + return m_info.capturedExpression; + } + std::string AssertionResult::getExpressionInMacro() const { + if( m_info.macroName.empty() ) + return m_info.capturedExpression; + else + return m_info.macroName + "( " + m_info.capturedExpression + " )"; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + return m_resultData.reconstructedExpression; + } + + std::string AssertionResult::getMessage() const { + return m_resultData.message; + } + SourceLineInfo AssertionResult::getSourceInfo() const { + return m_info.lineInfo; + } + + std::string AssertionResult::getTestMacroName() const { + return m_info.macroName; + } + +} // end namespace Catch + +// #included from: catch_expressionresult_builder.hpp +#define TWOBLUECUBES_CATCH_EXPRESSIONRESULT_BUILDER_HPP_INCLUDED + +#include + +namespace Catch { + + ExpressionResultBuilder::ExpressionResultBuilder( ResultWas::OfType resultType ) { + m_data.resultType = resultType; + } + ExpressionResultBuilder::ExpressionResultBuilder( ExpressionResultBuilder const& other ) + : m_data( other.m_data ), + m_exprComponents( other.m_exprComponents ) + { + m_stream << other.m_stream.str(); + } + ExpressionResultBuilder& ExpressionResultBuilder::operator=(ExpressionResultBuilder const& other ) { + m_data = other.m_data; + m_exprComponents = other.m_exprComponents; + m_stream.str(""); + m_stream << other.m_stream.str(); + return *this; + } + ExpressionResultBuilder& ExpressionResultBuilder::setResultType( ResultWas::OfType result ) { + m_data.resultType = result; + return *this; + } + ExpressionResultBuilder& ExpressionResultBuilder::setResultType( bool result ) { + m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; + return *this; + } + ExpressionResultBuilder& ExpressionResultBuilder::endExpression( ResultDisposition::Flags resultDisposition ) { + m_exprComponents.shouldNegate = shouldNegate( resultDisposition ); + return *this; + } + ExpressionResultBuilder& ExpressionResultBuilder::setLhs( std::string const& lhs ) { + m_exprComponents.lhs = lhs; + return *this; + } + ExpressionResultBuilder& ExpressionResultBuilder::setRhs( std::string const& rhs ) { + m_exprComponents.rhs = rhs; + return *this; + } + ExpressionResultBuilder& ExpressionResultBuilder::setOp( std::string const& op ) { + m_exprComponents.op = op; + return *this; + } + AssertionResult ExpressionResultBuilder::buildResult( AssertionInfo const& info ) const + { + assert( m_data.resultType != ResultWas::Unknown ); + + AssertionResultData data = m_data; + + // Flip bool results if shouldNegate is set + if( m_exprComponents.shouldNegate && data.resultType == ResultWas::Ok ) + data.resultType = ResultWas::ExpressionFailed; + else if( m_exprComponents.shouldNegate && data.resultType == ResultWas::ExpressionFailed ) + data.resultType = ResultWas::Ok; + + data.message = m_stream.str(); + data.reconstructedExpression = reconstructExpression( info ); + if( m_exprComponents.shouldNegate ) { + if( m_exprComponents.op == "" ) + data.reconstructedExpression = "!" + data.reconstructedExpression; + else + data.reconstructedExpression = "!(" + data.reconstructedExpression + ")"; + } + return AssertionResult( info, data ); + } + std::string ExpressionResultBuilder::reconstructExpression( AssertionInfo const& info ) const { + if( m_exprComponents.op == "" ) + return m_exprComponents.lhs.empty() ? info.capturedExpression : m_exprComponents.op + m_exprComponents.lhs; + else if( m_exprComponents.op == "matches" ) + return m_exprComponents.lhs + " " + m_exprComponents.rhs; + else if( m_exprComponents.op != "!" ) { + if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && + m_exprComponents.lhs.find("\n") == std::string::npos && + m_exprComponents.rhs.find("\n") == std::string::npos ) + return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; + else + return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; + } + else + return "{can't expand - use " + info.macroName + "_FALSE( " + info.capturedExpression.substr(1) + " ) instead of " + info.macroName + "( " + info.capturedExpression + " ) for better diagnostics}"; + } + +} // end namespace Catch + +// #included from: catch_test_case_info.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED + +namespace Catch { + + inline bool isSpecialTag( std::string const& tag ) { + return tag == "." || + tag == "hide" || + tag == "!hide" || + tag == "!throws"; + } + inline bool isReservedTag( std::string const& tag ) { + return !isSpecialTag( tag ) && tag.size() > 0 && !isalnum( tag[0] ); + } + inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + if( isReservedTag( tag ) ) { + { + Colour colourGuard( Colour::Red ); + std::cerr + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n"; + } + { + Colour colourGuard( Colour::FileName ); + std::cerr << _lineInfo << std::endl; + } + exit(1); + } + } + + TestCase makeTestCase( ITestCase* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden( startsWith( _name, "./" ) ); // Legacy support + + // Parse out tags + std::set tags; + std::string desc, tag; + bool inTag = false; + for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { + char c = _descOrTags[i]; + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; + } + else { + if( c == ']' ) { + enforceNotReservedTag( tag, _lineInfo ); + + inTag = false; + if( tag == "hide" || tag == "." ) { + tags.insert( "hide" ); + tags.insert( "." ); + isHidden = true; + } + else { + tags.insert( tag ); + } + tag.clear(); + } + else + tag += c; + } + } + TestCaseInfo info( _name, _className, desc, tags, isHidden, _lineInfo ); + return TestCase( _testCase, info ); + } + + TestCaseInfo::TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + bool _isHidden, + SourceLineInfo const& _lineInfo ) + : name( _name ), + className( _className ), + description( _description ), + tags( _tags ), + lineInfo( _lineInfo ), + isHidden( _isHidden ), + throws( false ) + { + std::ostringstream oss; + for( std::set::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + if( *it == "!throws" ) + throws = true; + } + tagsAsString = oss.str(); + } + + TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) + : name( other.name ), + className( other.className ), + description( other.description ), + tags( other.tags ), + tagsAsString( other.tagsAsString ), + lineInfo( other.lineInfo ), + isHidden( other.isHidden ), + throws( other.throws ) + {} + + TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + + TestCase::TestCase( TestCase const& other ) + : TestCaseInfo( other ), + test( other.test ) + {} + + TestCase TestCase::withName( std::string const& _newName ) const { + TestCase other( *this ); + other.name = _newName; + return other; + } + + void TestCase::invoke() const { + test->invoke(); + } + + bool TestCase::isHidden() const { + return TestCaseInfo::isHidden; + } + bool TestCase::throws() const { + return TestCaseInfo::throws; + } + + void TestCase::swap( TestCase& other ) { + test.swap( other.test ); + className.swap( other.className ); + name.swap( other.name ); + description.swap( other.description ); + std::swap( lineInfo, other.lineInfo ); + } + + bool TestCase::operator == ( TestCase const& other ) const { + return test.get() == other.test.get() && + name == other.name && + className == other.className; + } + + bool TestCase::operator < ( TestCase const& other ) const { + return name < other.name; + } + TestCase& TestCase::operator = ( TestCase const& other ) { + TestCase temp( other ); + swap( temp ); + return *this; + } + + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } + +} // end namespace Catch + +// #included from: catch_version.hpp +#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED + +namespace Catch { + + // These numbers are maintained by a script + Version libraryVersion( 1, 0, 45, "master" ); +} + +// #included from: catch_message.hpp +#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + ScopedMessage::~ScopedMessage() { + getResultCapture().popScopedMessage( m_info ); + } + +} // end namespace Catch + +// #included from: catch_legacy_reporter_adapter.hpp +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED + +// #included from: catch_legacy_reporter_adapter.h +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED + +namespace Catch +{ + // Deprecated + struct IReporter : IShared { + virtual ~IReporter(); + + virtual bool shouldRedirectStdout() const = 0; + + virtual void StartTesting() = 0; + virtual void EndTesting( Totals const& totals ) = 0; + virtual void StartGroup( std::string const& groupName ) = 0; + virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; + virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; + virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; + virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; + virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; + virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; + virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; + virtual void Aborted() = 0; + virtual void Result( AssertionResult const& result ) = 0; + }; + + class LegacyReporterAdapter : public SharedImpl + { + public: + LegacyReporterAdapter( Ptr const& legacyReporter ); + virtual ~LegacyReporterAdapter(); + + virtual ReporterPreferences getPreferences() const; + virtual void noMatchingTestCases( std::string const& ); + virtual void testRunStarting( TestRunInfo const& ); + virtual void testGroupStarting( GroupInfo const& groupInfo ); + virtual void testCaseStarting( TestCaseInfo const& testInfo ); + virtual void sectionStarting( SectionInfo const& sectionInfo ); + virtual void assertionStarting( AssertionInfo const& ); + virtual bool assertionEnded( AssertionStats const& assertionStats ); + virtual void sectionEnded( SectionStats const& sectionStats ); + virtual void testCaseEnded( TestCaseStats const& testCaseStats ); + virtual void testGroupEnded( TestGroupStats const& testGroupStats ); + virtual void testRunEnded( TestRunStats const& testRunStats ); + + private: + Ptr m_legacyReporter; + }; +} + +namespace Catch +{ + LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) + : m_legacyReporter( legacyReporter ) + {} + LegacyReporterAdapter::~LegacyReporterAdapter() {} + + ReporterPreferences LegacyReporterAdapter::getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); + return prefs; + } + + void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} + void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { + m_legacyReporter->StartTesting(); + } + void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { + m_legacyReporter->StartGroup( groupInfo.name ); + } + void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { + m_legacyReporter->StartTestCase( testInfo ); + } + void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { + m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); + } + void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { + // Not on legacy interface + } + + bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + ExpressionResultBuilder expressionBuilder( it->type ); + expressionBuilder << it->message; + AssertionInfo info( it->macroName, it->lineInfo, "", ResultDisposition::Normal ); + AssertionResult result = expressionBuilder.buildResult( info ); + m_legacyReporter->Result( result ); + } + } + } + m_legacyReporter->Result( assertionStats.assertionResult ); + return true; + } + void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { + if( sectionStats.missingAssertions ) + m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); + m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); + } + void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { + m_legacyReporter->EndTestCase + ( testCaseStats.testInfo, + testCaseStats.totals, + testCaseStats.stdOut, + testCaseStats.stdErr ); + } + void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { + if( testGroupStats.aborting ) + m_legacyReporter->Aborted(); + m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); + } + void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { + m_legacyReporter->EndTesting( testRunStats.totals ); + } +} + +// #included from: catch_timer.hpp + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-long-long" +#endif + +#ifdef CATCH_PLATFORM_WINDOWS +#include +#else +#include +#endif + +namespace Catch { + + namespace { +#ifdef CATCH_PLATFORM_WINDOWS + uint64_t getCurrentTicks() { + static uint64_t hz=0, hzo=0; + if (!hz) { + QueryPerformanceFrequency((LARGE_INTEGER*)&hz); + QueryPerformanceCounter((LARGE_INTEGER*)&hzo); + } + uint64_t t; + QueryPerformanceCounter((LARGE_INTEGER*)&t); + return ((t-hzo)*1000000)/hz; + } +#else + uint64_t getCurrentTicks() { + timeval t; + gettimeofday(&t,NULL); + return (uint64_t)t.tv_sec * 1000000ull + (uint64_t)t.tv_usec; + } +#endif + } + + void Timer::start() { + m_ticks = getCurrentTicks(); + } + unsigned int Timer::getElapsedNanoseconds() const { + return (unsigned int)(getCurrentTicks() - m_ticks); + } + unsigned int Timer::getElapsedMilliseconds() const { + return (unsigned int)((getCurrentTicks() - m_ticks)/1000); + } + double Timer::getElapsedSeconds() const { + return (getCurrentTicks() - m_ticks)/1000000.0; + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +// #included from: catch_common.hpp +#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), ::tolower ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << " " << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << "s"; + return os; + } + + SourceLineInfo::SourceLineInfo() : line( 0 ){} + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) + : file( _file ), + line( _line ) + {} + SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) + : file( other.file ), + line( other.line ) + {} + bool SourceLineInfo::empty() const { + return file.empty(); + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { + return line == other.line && file == other.file; + } + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { +#ifndef __GNUG__ + os << info.file << "(" << info.line << ")"; +#else + os << info.file << ":" << info.line; +#endif + return os; + } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { + std::ostringstream oss; + oss << locationInfo << ": Internal Catch error: '" << message << "'"; + if( isTrue( true )) + throw std::logic_error( oss.str() ); + } +} + +// #included from: catch_section.hpp +#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED + +namespace Catch { + + Section::Section( SourceLineInfo const& lineInfo, + std::string const& name, + std::string const& description ) + : m_info( name, description, lineInfo ), + m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( m_info, m_assertions ) ) + { + m_timer.start(); + } + + Section::~Section() { + if( m_sectionIncluded ) + getCurrentContext().getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); + } + + // This indicates whether the section should be executed or not + Section::operator bool() { + return m_sectionIncluded; + } + +} // end namespace Catch + +// #included from: catch_debugger.hpp +#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED + +#include + +#ifdef CATCH_PLATFORM_MAC + + #include + #include + #include + #include + #include + + namespace Catch{ + + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive(){ + + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) { + std::cerr << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; + return false; + } + + // We're being debugged if the P_TRACED flag is set. + + return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + } + } // namespace Catch + +#elif defined(_MSC_VER) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#else + namespace Catch { + inline bool isDebuggerActive() { return false; } + } +#endif // Platform + +#ifdef CATCH_PLATFORM_WINDOWS + extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + std::cout << text; + } + } +#endif // Platform + +// #included from: catch_tostring.hpp +#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED + +namespace Catch { + +std::string toString( std::string const& value ) { + std::string s = value; + if( getCurrentContext().getConfig()->showInvisibles() ) { + for(size_t i = 0; i < s.size(); ++i ) { + std::string subs; + switch( s[i] ) { + case '\n': subs = "\\n"; break; + case '\t': subs = "\\t"; break; + default: break; + } + if( !subs.empty() ) { + s = s.substr( 0, i ) + subs + s.substr( i+1 ); + ++i; + } + } + } + return "\"" + s + "\""; +} +std::string toString( std::wstring const& value ) { + + std::string s; + s.reserve( value.size() ); + for(size_t i = 0; i < value.size(); ++i ) + s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; + return toString( s ); +} + +std::string toString( const char* const value ) { + return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); +} + +std::string toString( char* const value ) { + return Catch::toString( static_cast( value ) ); +} + +std::string toString( int value ) { + std::ostringstream oss; + oss << value; + return oss.str(); +} + +std::string toString( unsigned long value ) { + std::ostringstream oss; + if( value > 8192 ) + oss << "0x" << std::hex << value; + else + oss << value; + return oss.str(); +} + +std::string toString( unsigned int value ) { + return toString( static_cast( value ) ); +} + +std::string toString( const double value ) { + std::ostringstream oss; + oss << std::setprecision( 10 ) + << std::fixed + << value; + std::string d = oss.str(); + std::size_t i = d.find_last_not_of( '0' ); + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) + i++; + d = d.substr( 0, i+1 ); + } + return d; +} + +std::string toString( bool value ) { + return value ? "true" : "false"; +} + +std::string toString( char value ) { + return value < ' ' + ? toString( static_cast( value ) ) + : Detail::makeString( value ); +} + +std::string toString( signed char value ) { + return toString( static_cast( value ) ); +} + +std::string toString( unsigned char value ) { + return toString( static_cast( value ) ); +} + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ) { + return "nullptr"; +} +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ) { + if( !nsstring ) + return "nil"; + return std::string( "@\"" ) + [nsstring UTF8String] + "\""; + } + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { + if( !nsstring ) + return "nil"; + return std::string( "@\"" ) + [nsstring UTF8String] + "\""; + } + std::string toString( NSObject* const& nsObject ) { + return toString( [nsObject description] ); + } +#endif + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_xml.hpp +#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED + +// #included from: catch_reporter_bases.hpp +#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED + +namespace Catch { + + struct StreamingReporterBase : SharedImpl { + + StreamingReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + {} + + virtual ~StreamingReporterBase(); + + virtual void noMatchingTestCases( std::string const& ) {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) { + currentTestRunInfo = _testRunInfo; + } + virtual void testGroupStarting( GroupInfo const& _groupInfo ) { + currentGroupInfo = _groupInfo; + } + + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) { + currentTestCaseInfo = _testInfo; + } + virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + m_sectionStack.push_back( _sectionInfo ); + } + + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) { + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) { + currentTestCaseInfo.reset(); + assert( m_sectionStack.empty() ); + } + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) { + currentGroupInfo.reset(); + } + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + Ptr m_config; + std::ostream& stream; + + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; + + std::vector m_sectionStack; + }; + + struct CumulativeReporterBase : SharedImpl { + template + struct Node : SharedImpl<> { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} + + typedef std::vector > ChildNodes; + T value; + ChildNodes children; + }; + struct SectionNode : SharedImpl<> { + explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} + virtual ~SectionNode(); + + bool operator == ( SectionNode const& other ) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + bool operator == ( Ptr const& other ) const { + return operator==( *other ); + } + + SectionStats stats; + typedef std::vector > ChildSections; + typedef std::vector Assertions; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + + struct BySectionInfo { + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + bool operator() ( Ptr const& node ) const { + return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + } + private: + BySectionInfo& operator=( BySectionInfo const& other ); // = delete; + + SectionInfo const& m_other; + }; + + typedef Node TestCaseNode; + typedef Node TestGroupNode; + typedef Node TestRunNode; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + {} + ~CumulativeReporterBase(); + + virtual void testRunStarting( TestRunInfo const& ) {} + virtual void testGroupStarting( GroupInfo const& ) {} + + virtual void testCaseStarting( TestCaseInfo const& ) {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + Ptr node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = new SectionNode( incompleteStats ); + node = m_rootSection; + } + else { + SectionNode& parentNode = *m_sectionStack.back(); + SectionNode::ChildSections::const_iterator it = + std::find_if( parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo( sectionInfo ) ); + if( it == parentNode.childSections.end() ) { + node = new SectionNode( incompleteStats ); + parentNode.childSections.push_back( node ); + } + else + node = *it; + } + m_sectionStack.push_back( node ); + m_deepestSection = node; + } + + virtual void assertionStarting( AssertionInfo const& ) {} + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back( assertionStats ); + return true; + } + virtual void sectionEnded( SectionStats const& sectionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + Ptr node = new TestCaseNode( testCaseStats ); + assert( m_sectionStack.size() == 0 ); + node->children.push_back( m_rootSection ); + m_testCases.push_back( node ); + m_rootSection.reset(); + + assert( m_deepestSection ); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + Ptr node = new TestGroupNode( testGroupStats ); + node->children.swap( m_testCases ); + m_testGroups.push_back( node ); + } + virtual void testRunEnded( TestRunStats const& testRunStats ) { + Ptr node = new TestRunNode( testRunStats ); + node->children.swap( m_testGroups ); + m_testRuns.push_back( node ); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + Ptr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector > > m_sections; + std::vector > m_testCases; + std::vector > m_testGroups; + + std::vector > m_testRuns; + + Ptr m_rootSection; + Ptr m_deepestSection; + std::vector > m_sectionStack; + + }; + +} // end namespace Catch + +// #included from: ../internal/catch_reporter_registrars.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED + +namespace Catch { + + template + class LegacyReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new LegacyReporterAdapter( new T( config ) ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + LegacyReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + class ReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + + // *** Please Note ***: + // - If you end up here looking at a compiler error because it's trying to register + // your custom reporter class be aware that the native reporter interface has changed + // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via + // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. + // However please consider updating to the new interface as the old one is now + // deprecated and will probably be removed quite soon! + // Please contact me via github if you have any questions at all about this. + // In fact, ideally, please contact me anyway to let me know you've hit this - as I have + // no idea who is actually using custom reporters at all (possibly no-one!). + // The new interface is designed to minimise exposure to interface changes in the future. + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; +} + +#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ + namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +// #included from: ../internal/catch_xmlwriter.hpp +#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = NULL; + } + + ~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + ScopedElement& writeText( std::string const& text, bool indent = true ) { + m_writer->writeText( text, indent ); + return *this; + } + + template + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer; + }; + + XmlWriter() + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &std::cout ) + {} + + XmlWriter( std::ostream& os ) + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &os ) + {} + + ~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + +# ifndef CATCH_CPP11_OR_GREATER + XmlWriter& operator = ( XmlWriter const& other ) { + XmlWriter temp( other ); + swap( temp ); + return *this; + } +# else + XmlWriter( XmlWriter const& ) = default; + XmlWriter( XmlWriter && ) = default; + XmlWriter& operator = ( XmlWriter const& ) = default; + XmlWriter& operator = ( XmlWriter && ) = default; +# endif + + void swap( XmlWriter& other ) { + std::swap( m_tagIsOpen, other.m_tagIsOpen ); + std::swap( m_needsNewline, other.m_needsNewline ); + std::swap( m_tags, other.m_tags ); + std::swap( m_indent, other.m_indent ); + std::swap( m_os, other.m_os ); + } + + XmlWriter& startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + stream() << m_indent << "<" << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + ScopedElement scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + stream() << "/>\n"; + m_tagIsOpen = false; + } + else { + stream() << m_indent << "\n"; + } + m_tags.pop_back(); + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) { + stream() << " " << name << "=\""; + writeEncodedText( attribute ); + stream() << "\""; + } + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, bool attribute ) { + stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; + return *this; + } + + template + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + if( !name.empty() ) + stream() << " " << name << "=\"" << attribute << "\""; + return *this; + } + + XmlWriter& writeText( std::string const& text, bool indent = true ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + stream() << m_indent; + writeEncodedText( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& writeComment( std::string const& text ) { + ensureTagClosed(); + stream() << m_indent << ""; + m_needsNewline = true; + return *this; + } + + XmlWriter& writeBlankLine() { + ensureTagClosed(); + stream() << "\n"; + return *this; + } + + private: + + std::ostream& stream() { + return *m_os; + } + + void ensureTagClosed() { + if( m_tagIsOpen ) { + stream() << ">\n"; + m_tagIsOpen = false; + } + } + + void newlineIfNecessary() { + if( m_needsNewline ) { + stream() << "\n"; + m_needsNewline = false; + } + } + + void writeEncodedText( std::string const& text ) { + static const char* charsToEncode = "<&\""; + std::string mtext = text; + std::string::size_type pos = mtext.find_first_of( charsToEncode ); + while( pos != std::string::npos ) { + stream() << mtext.substr( 0, pos ); + + switch( mtext[pos] ) { + case '<': + stream() << "<"; + break; + case '&': + stream() << "&"; + break; + case '\"': + stream() << """; + break; + } + mtext = mtext.substr( pos+1 ); + pos = mtext.find_first_of( charsToEncode ); + } + stream() << mtext; + } + + bool m_tagIsOpen; + bool m_needsNewline; + std::vector m_tags; + std::string m_indent; + std::ostream* m_os; + }; + +} +namespace Catch { + class XmlReporter : public SharedImpl { + public: + XmlReporter( ReporterConfig const& config ) : m_config( config ), m_sectionDepth( 0 ) {} + + static std::string getDescription() { + return "Reports test results as an XML document"; + } + virtual ~XmlReporter(); + + private: // IReporter + + virtual bool shouldRedirectStdout() const { + return true; + } + + virtual void StartTesting() { + m_xml = XmlWriter( m_config.stream() ); + m_xml.startElement( "Catch" ); + if( !m_config.fullConfig()->name().empty() ) + m_xml.writeAttribute( "name", m_config.fullConfig()->name() ); + } + + virtual void EndTesting( const Totals& totals ) { + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", totals.assertions.passed ) + .writeAttribute( "failures", totals.assertions.failed ); + m_xml.endElement(); + } + + virtual void StartGroup( const std::string& groupName ) { + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupName ); + } + + virtual void EndGroup( const std::string&, const Totals& totals ) { + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", totals.assertions.passed ) + .writeAttribute( "failures", totals.assertions.failed ); + m_xml.endElement(); + } + + virtual void StartSection( const std::string& sectionName, const std::string& description ) { + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionName ) ) + .writeAttribute( "description", description ); + } + } + virtual void NoAssertionsInSection( const std::string& ) {} + virtual void NoAssertionsInTestCase( const std::string& ) {} + + virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) { + if( --m_sectionDepth > 0 ) { + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", assertions.passed ) + .writeAttribute( "failures", assertions.failed ); + m_xml.endElement(); + } + } + + virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) { + m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); + m_currentTestSuccess = true; + } + + virtual void Result( const Catch::AssertionResult& assertionResult ) { + if( !m_config.fullConfig()->includeSuccessfulResults() && assertionResult.getResultType() == ResultWas::Ok ) + return; + + if( assertionResult.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", assertionResult.succeeded() ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ); + + m_xml.scopedElement( "Original" ) + .writeText( assertionResult.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( assertionResult.getExpandedExpression() ); + m_currentTestSuccess &= assertionResult.succeeded(); + } + + switch( assertionResult.getResultType() ) { + case ResultWas::ThrewException: + m_xml.scopedElement( "Exception" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + m_currentTestSuccess = false; + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Warning: + m_xml.scopedElement( "Warning" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::ExplicitFailure: + m_xml.scopedElement( "Failure" ) + .writeText( assertionResult.getMessage() ); + m_currentTestSuccess = false; + break; + case ResultWas::Unknown: + case ResultWas::Ok: + case ResultWas::FailureBit: + case ResultWas::ExpressionFailed: + case ResultWas::Exception: + case ResultWas::DidntThrowException: + break; + } + if( assertionResult.hasExpression() ) + m_xml.endElement(); + } + + virtual void Aborted() { + // !TBD + } + + virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) { + m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess ); + m_xml.endElement(); + } + + private: + ReporterConfig m_config; + bool m_currentTestSuccess; + XmlWriter m_xml; + int m_sectionDepth; + }; + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_junit.hpp +#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED + +#include + +namespace Catch { + + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter( ReporterConfig const& _config ) + : CumulativeReporterBase( _config ), + xml( _config.stream() ) + {} + + ~JunitReporter(); + + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + virtual void noMatchingTestCases( std::string const& /*spec*/ ) {} + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = true; + return prefs; + } + + virtual void testRunStarting( TestRunInfo const& runInfo ) { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + virtual void testRunEndedCumulative() { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", "tbd" ); // !TBD + + // Write test cases + for( TestGroupNode::ChildNodes::const_iterator + it = groupNode.children.begin(), itEnd = groupNode.children.end(); + it != itEnd; + ++it ) + writeTestCase( **it ); + + xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); + xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); + } + + void writeTestCase( TestCaseNode const& testCaseNode ) { + TestCaseStats const& stats = testCaseNode.value; + + // All test cases have exactly one section - which represents the + // test case itself. That section may have 0-n nested sections + assert( testCaseNode.children.size() == 1 ); + SectionNode const& rootSection = *testCaseNode.children.front(); + + std::string className = stats.testInfo.className; + + if( className.empty() ) { + if( rootSection.childSections.empty() ) + className = "global"; + } + writeSection( className, "", rootSection ); + } + + void writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode ) { + std::string name = trim( sectionNode.stats.sectionInfo.name ); + if( !rootName.empty() ) + name = rootName + "/" + name; + + if( !sectionNode.assertions.empty() || + !sectionNode.stdOut.empty() || + !sectionNode.stdErr.empty() ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); + if( className.empty() ) { + xml.writeAttribute( "classname", name ); + xml.writeAttribute( "name", "root" ); + } + else { + xml.writeAttribute( "classname", className ); + xml.writeAttribute( "name", name ); + } + xml.writeAttribute( "time", toString( sectionNode.stats.durationInSeconds ) ); + + writeAssertions( sectionNode ); + + if( !sectionNode.stdOut.empty() ) + xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); + if( !sectionNode.stdErr.empty() ) + xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); + } + for( SectionNode::ChildSections::const_iterator + it = sectionNode.childSections.begin(), + itEnd = sectionNode.childSections.end(); + it != itEnd; + ++it ) + if( className.empty() ) + writeSection( name, "", **it ); + else + writeSection( className, name, **it ); + } + + void writeAssertions( SectionNode const& sectionNode ) { + for( SectionNode::Assertions::const_iterator + it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); + it != itEnd; + ++it ) + writeAssertion( *it ); + } + void writeAssertion( AssertionStats const& stats ) { + AssertionResult const& result = stats.assertionResult; + if( !result.isOk() ) { + std::string elementName; + switch( result.getResultType() ) { + case ResultWas::ThrewException: + elementName = "error"; + break; + case ResultWas::ExplicitFailure: + elementName = "failure"; + break; + case ResultWas::ExpressionFailed: + elementName = "failure"; + break; + case ResultWas::DidntThrowException: + elementName = "failure"; + break; + + // We should never see these here: + case ResultWas::Info: + case ResultWas::Warning: + case ResultWas::Ok: + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + elementName = "internalError"; + break; + } + + XmlWriter::ScopedElement e = xml.scopedElement( elementName ); + + xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "type", result.getTestMacroName() ); + + std::ostringstream oss; + if( !result.getMessage().empty() ) + oss << result.getMessage() << "\n"; + for( std::vector::const_iterator + it = stats.infoMessages.begin(), + itEnd = stats.infoMessages.end(); + it != itEnd; + ++it ) + if( it->type == ResultWas::Info ) + oss << it->message << "\n"; + + oss << "at " << result.getSourceInfo(); + xml.writeText( oss.str(), false ); + } + } + + XmlWriter xml; + Timer suiteTimer; + std::ostringstream stdOutForSuite; + std::ostringstream stdErrForSuite; + unsigned int unexpectedExceptions; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_console.hpp +#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED + +#include + +namespace Catch { + + struct ConsoleReporter : StreamingReporterBase { + ConsoleReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_headerPrinted( false ), + m_atLeastOneTestCasePrinted( false ) + {} + + virtual ~ConsoleReporter(); + static std::string getDescription() { + return "Reports test results as plain lines of text"; + } + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + lazyPrint(); + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + stream << std::endl; + return true; + } + + virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting( _sectionInfo ); + } + virtual void sectionEnded( SectionStats const& _sectionStats ) { + if( _sectionStats.missingAssertions ) { + lazyPrint(); + Colour colour( Colour::ResultError ); + if( m_sectionStack.size() > 1 ) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if( m_headerPrinted ) { + if( m_config->showDurations() == ShowDurations::Always ) + stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + m_headerPrinted = false; + } + else { + if( m_config->showDurations() == ShowDurations::Always ) + stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + } + StreamingReporterBase::sectionEnded( _sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) { + StreamingReporterBase::testCaseEnded( _testCaseStats ); + m_headerPrinted = false; + } + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) { + if( currentGroupInfo.used ) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals( _testGroupStats.totals ); + stream << "\n" << std::endl; + } + StreamingReporterBase::testGroupEnded( _testGroupStats ); + } + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + if( m_atLeastOneTestCasePrinted ) + printTotalsDivider(); + printTotals( _testRunStats.totals ); + stream << "\n" << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ), + stats( _stats ), + result( _stats.assertionResult ), + colour( Colour::None ), + message( result.getMessage() ), + messages( _stats.infoMessages ), + printInfoMessages( _printInfoMessages ) + { + switch( result.getResultType() ) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + //if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; + } + else { + colour = Colour::Error; + passOrFail = "FAILED"; + } + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with message"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if( _stats.infoMessages.size() == 1 ) + messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; + } + } + + void print() const { + printSourceInfo(); + if( stats.totals.assertions.total() > 0 ) { + if( result.isOk() ) + stream << "\n"; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } + else { + stream << "\n"; + } + printMessage(); + } + + private: + void printResultType() const { + if( !passOrFail.empty() ) { + Colour colourGuard( colour ); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if( result.hasExpression() ) { + Colour colourGuard( Colour::OriginalExpression ); + stream << " "; + stream << result.getExpressionInMacro(); + stream << "\n"; + } + } + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + stream << "with expansion:\n"; + Colour colourGuard( Colour::ReconstructedExpression ); + stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n"; + } + } + void printMessage() const { + if( !messageLabel.empty() ) + stream << messageLabel << ":" << "\n"; + for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); + it != itEnd; + ++it ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || it->type != ResultWas::Info ) + stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n"; + } + } + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector messages; + bool printInfoMessages; + }; + + void lazyPrint() { + + if( !currentTestRunInfo.used ) + lazyPrintRunInfo(); + if( !currentGroupInfo.used ) + lazyPrintGroupInfo(); + + if( !m_headerPrinted ) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } + m_atLeastOneTestCasePrinted = true; + } + void lazyPrintRunInfo() { + stream << "\n" << getLineOfChars<'~'>() << "\n"; + Colour colour( Colour::SecondaryText ); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion.majorVersion << "." + << libraryVersion.minorVersion << " b" + << libraryVersion.buildNumber; + if( libraryVersion.branchName != std::string( "master" ) ) + stream << " (" << libraryVersion.branchName << ")"; + stream << " host application.\n" + << "Run with -? for options\n\n"; + + currentTestRunInfo.used = true; + } + void lazyPrintGroupInfo() { + if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { + printClosedHeader( "Group: " + currentGroupInfo->name ); + currentGroupInfo.used = true; + } + } + void printTestCaseAndSectionHeader() { + assert( !m_sectionStack.empty() ); + printOpenHeader( currentTestCaseInfo->name ); + + if( m_sectionStack.size() > 1 ) { + Colour colourGuard( Colour::Headers ); + + std::vector::const_iterator + it = m_sectionStack.begin()+1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for( ; it != itEnd; ++it ) + printHeaderString( it->name, 2 ); + } + + SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; + + if( !lineInfo.empty() ){ + stream << getLineOfChars<'-'>() << "\n"; + Colour colourGuard( Colour::FileName ); + stream << lineInfo << "\n"; + } + stream << getLineOfChars<'.'>() << "\n" << std::endl; + } + + void printClosedHeader( std::string const& _name ) { + printOpenHeader( _name ); + stream << getLineOfChars<'.'>() << "\n"; + } + void printOpenHeader( std::string const& _name ) { + stream << getLineOfChars<'-'>() << "\n"; + { + Colour colourGuard( Colour::Headers ); + printHeaderString( _name ); + } + } + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { + std::size_t i = _string.find( ": " ); + if( i != std::string::npos ) + i+=2; + else + i = 0; + stream << Text( _string, TextAttributes() + .setIndent( indent+i) + .setInitialIndent( indent ) ) << "\n"; + } + + void printTotals( const Totals& totals ) { + if( totals.testCases.total() == 0 ) { + stream << "No tests ran"; + } + else if( totals.assertions.total() == 0 ) { + Colour colour( Colour::Yellow ); + printCounts( "test case", totals.testCases ); + stream << " (no assertions)"; + } + else if( totals.assertions.failed ) { + Colour colour( Colour::ResultError ); + printCounts( "test case", totals.testCases ); + if( totals.testCases.failed > 0 ) { + stream << " ("; + printCounts( "assertion", totals.assertions ); + stream << ")"; + } + } + else { + Colour colour( Colour::ResultSuccess ); + stream << "All tests passed (" + << pluralise( totals.assertions.passed, "assertion" ) << " in " + << pluralise( totals.testCases.passed, "test case" ) << ")"; + } + } + void printCounts( std::string const& label, Counts const& counts ) { + if( counts.total() == 1 ) { + stream << "1 " << label << " - "; + if( counts.failed ) + stream << "failed"; + else + stream << "passed"; + } + else { + stream << counts.total() << " " << label << "s "; + if( counts.passed ) { + if( counts.failed ) + stream << "- " << counts.failed << " failed"; + else if( counts.passed == 2 ) + stream << "- both passed"; + else + stream << "- all passed"; + } + else { + if( counts.failed == 2 ) + stream << "- both failed"; + else + stream << "- all failed"; + } + } + } + + void printTotalsDivider() { + stream << getLineOfChars<'='>() << "\n"; + } + void printSummaryDivider() { + stream << getLineOfChars<'-'>() << "\n"; + } + template + static char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; + } + + private: + bool m_headerPrinted; + bool m_atLeastOneTestCasePrinted; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_compact.hpp +#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + CompactReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual ~CompactReporter(); + + static std::string getDescription() { + return "Reports test results on a single line, suitable for IDEs"; + } + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; + } + + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotals( _testRunStats.totals ); + stream << "\n" << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , stats( _stats ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + + switch( result.getResultType() ) { + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType( Colour::None, "warning" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType( Colour::Error, failedString() ); + printIssue( "explicitly" ); + printRemainingMessages( Colour::None ); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType( Colour::Error, "** internal error **" ); + break; + } + } + + private: + // Colour::LightGrey + + static Colour dimColour() { return Colour::FileName; } + +#ifdef CATCH_PLATFORM_MAC + static const char* failedString() { return "FAILED"; } + static const char* passedString() { return "PASSED"; } +#else + static const char* failedString() { return "failed"; } + static const char* passedString() { return "passed"; } +#endif + + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ":"; + } + + void printResultType( Colour colour, std::string passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << " " << passOrFail; + } + stream << ":"; + } + } + + void printIssue( std::string issue ) const { + stream << " " << issue; + } + + void printExpressionWas() { + if( result.hasExpression() ) { + stream << ";"; + { + Colour colour( dimColour() ); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if( result.hasExpression() ) { + stream << " " << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + { + Colour colour( dimColour() ); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if ( itMessage != messages.end() ) { + stream << " '" << itMessage->message << "'"; + ++itMessage; + } + } + + void printRemainingMessages( Colour colour = dimColour() ) { + if ( itMessage == messages.end() ) + return; + + // using messages.end() directly yields compilation error: + std::vector::const_iterator itEnd = messages.end(); + const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); + + { + Colour colourGuard( colour ); + stream << " with " << pluralise( N, "message" ) << ":"; + } + + for(; itMessage != itEnd; ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || itMessage->type != ResultWas::Info ) { + stream << " '" << itMessage->message << "'"; + if ( ++itMessage != itEnd ) { + Colour colourGuard( dimColour() ); + stream << " and"; + } + } + } + } + + private: + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + std::vector messages; + std::vector::const_iterator itMessage; + bool printInfoMessages; + }; + + // Colour, message variants: + // - white: No tests ran. + // - red: Failed [both/all] N test cases, failed [both/all] M assertions. + // - white: Passed [both/all] N test cases (no assertions). + // - red: Failed N tests cases, failed M assertions. + // - green: Passed [both/all] N tests cases with M assertions. + + std::string bothOrAll( std::size_t count ) const { + return count == 1 ? "" : count == 2 ? "both " : "all " ; + } + + void printTotals( const Totals& totals ) const { + if( totals.testCases.total() == 0 ) { + stream << "No tests ran."; + } + else if( totals.testCases.failed == totals.testCases.total() ) { + Colour colour( Colour::ResultError ); + const std::string qualify_assertions_failed = + totals.assertions.failed == totals.assertions.total() ? + bothOrAll( totals.assertions.failed ) : ""; + stream << + "Failed " << bothOrAll( totals.testCases.failed ) + << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << qualify_assertions_failed << + pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else if( totals.assertions.total() == 0 ) { + stream << + "Passed " << bothOrAll( totals.testCases.total() ) + << pluralise( totals.testCases.total(), "test case" ) + << " (no assertions)."; + } + else if( totals.assertions.failed ) { + Colour colour( Colour::ResultError ); + stream << + "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else { + Colour colour( Colour::ResultSuccess ); + stream << + "Passed " << bothOrAll( totals.testCases.passed ) + << pluralise( totals.testCases.passed, "test case" ) << + " with " << pluralise( totals.assertions.passed, "assertion" ) << "."; + } + } + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch + +namespace Catch { + NonCopyable::~NonCopyable() {} + IShared::~IShared() {} + StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} + IContext::~IContext() {} + IResultCapture::~IResultCapture() {} + ITestCase::~ITestCase() {} + ITestCaseRegistry::~ITestCaseRegistry() {} + IRegistryHub::~IRegistryHub() {} + IMutableRegistryHub::~IMutableRegistryHub() {} + IExceptionTranslator::~IExceptionTranslator() {} + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} + IReporter::~IReporter() {} + IReporterFactory::~IReporterFactory() {} + IReporterRegistry::~IReporterRegistry() {} + IStreamingReporter::~IStreamingReporter() {} + AssertionStats::~AssertionStats() {} + SectionStats::~SectionStats() {} + TestCaseStats::~TestCaseStats() {} + TestGroupStats::~TestGroupStats() {} + TestRunStats::~TestRunStats() {} + CumulativeReporterBase::SectionNode::~SectionNode() {} + CumulativeReporterBase::~CumulativeReporterBase() {} + + StreamingReporterBase::~StreamingReporterBase() {} + ConsoleReporter::~ConsoleReporter() {} + CompactReporter::~CompactReporter() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + XmlReporter::~XmlReporter() {} + JunitReporter::~JunitReporter() {} + TestRegistry::~TestRegistry() {} + FreeFunctionTestCase::~FreeFunctionTestCase() {} + IGeneratorInfo::~IGeneratorInfo() {} + IGeneratorsForTest::~IGeneratorsForTest() {} + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} + + Matchers::Impl::StdString::Equals::~Equals() {} + Matchers::Impl::StdString::Contains::~Contains() {} + Matchers::Impl::StdString::StartsWith::~StartsWith() {} + Matchers::Impl::StdString::EndsWith::~EndsWith() {} + + void Config::dummy() {} + + INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter ) +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif + +#ifdef CATCH_CONFIG_MAIN +// #included from: internal/catch_default_main.hpp +#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED + +#ifndef __OBJC__ + +// Standard C/C++ main entry point +int main (int argc, char * const argv[]) { + return Catch::Session().run( argc, argv ); +} + +#else // __OBJC__ + +// Objective-C entry point +int main (int argc, char * const argv[]) { +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int result = Catch::Session().run( argc, (char* const*)argv ); + +#if !CATCH_ARC_ENABLED + [pool drain]; +#endif + + return result; +} + +#endif // __OBJC__ + +#endif + +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +# undef CLARA_CONFIG_MAIN +#endif + +////// + +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) +#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "CATCH_REQUIRE_FALSE" ) + +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) + +#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) +#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CATCH_CHECK_FALSE" ) +#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) +#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) +#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) + +#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) + +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) +#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) +#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) + #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) +#else + #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) + #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) +#endif +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#else +#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#endif +#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) +#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "REQUIRE_FALSE" ) + +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "REQUIRE_THROWS" ) +#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) + +#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) +#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CHECK_FALSE" ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) +#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) + +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" ) +#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) + +#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) +#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) +#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) + #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) +#else + #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) + #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) +#endif +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#else +#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#endif +#define GIVEN( desc ) SECTION( " Given: " desc, "" ) +#define WHEN( desc ) SECTION( " When: " desc, "" ) +#define AND_WHEN( desc ) SECTION( "And when: " desc, "" ) +#define THEN( desc ) SECTION( " Then: " desc, "" ) +#define AND_THEN( desc ) SECTION( " And: " desc, "" ) + +using Catch::Detail::Approx; + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + diff --git a/test/optional_unit.cpp b/test/optional_unit.cpp new file mode 100644 index 000000000..a6573ca41 --- /dev/null +++ b/test/optional_unit.cpp @@ -0,0 +1,82 @@ +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" + +#include "optional.hpp" + +using namespace mapbox; + +struct dummy { + dummy(int _m_1, int _m_2) : m_1(_m_1), m_2(_m_2) {} + int m_1; + int m_2; + +}; + +int main (int argc, char* const argv[]) +{ + int result = Catch::Session().run(argc, argv); + if (!result) printf("\x1b[1;32m ✓ \x1b[0m\n"); + return result; +} + +TEST_CASE( "optional can be instantiated with a POD type", "[optiona]" ) { + mapbox::util::optional dbl_opt; + + REQUIRE(!dbl_opt); + dbl_opt = 3.1415; + REQUIRE(dbl_opt); + + REQUIRE(dbl_opt.get() == 3.1415); + REQUIRE(*dbl_opt == 3.1415); +} + +TEST_CASE( "copy c'tor", "[optiona]" ) { + mapbox::util::optional dbl_opt; + + REQUIRE(!dbl_opt); + dbl_opt = 3.1415; + REQUIRE(dbl_opt); + + mapbox::util::optional other = dbl_opt; + + REQUIRE(other.get() == 3.1415); + REQUIRE(*other == 3.1415); +} + +TEST_CASE( "const operator*, const get()", "[optiona]" ) { + mapbox::util::optional dbl_opt = 3.1415; + + REQUIRE(dbl_opt); + + const double pi1 = dbl_opt.get(); + const double pi2 = *dbl_opt; + + REQUIRE(pi1 == 3.1415); + REQUIRE(pi2 == 3.1415); +} + +TEST_CASE( "emplace initialization, reset", "[optional]" ) { + mapbox::util::optional dummy_opt; + REQUIRE(!dummy_opt); + + // rvalues, baby! + dummy_opt.emplace(1, 2); + REQUIRE(dummy_opt); + REQUIRE(dummy_opt.get().m_1 == 1); + REQUIRE((*dummy_opt).m_2 == 2); + + dummy_opt.reset(); + REQUIRE(!dummy_opt); +} + +TEST_CASE( "assignment", "[optional]") { + mapbox::util::optional a; + mapbox::util::optional b; + + a = 1; b = 3; + REQUIRE(a.get() == 1); + REQUIRE(b.get() == 3); + b = a; + REQUIRE(a.get() == b.get()); + REQUIRE(b.get() == 1); +} diff --git a/test/recursive_wrapper_test.cpp b/test/recursive_wrapper_test.cpp new file mode 100644 index 000000000..3cd79b5ce --- /dev/null +++ b/test/recursive_wrapper_test.cpp @@ -0,0 +1,132 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "variant.hpp" + +using namespace mapbox; + +namespace test { + +struct add; +struct sub; +template struct binary_op; + +typedef util::variant>, + util::recursive_wrapper> + > expression; + +template +struct binary_op +{ + expression left; // variant instantiated here... + expression right; + + binary_op(expression && lhs, expression && rhs) + : left(std::move(lhs)), right(std::move(rhs)) + { + } +}; + +struct print : util::static_visitor +{ + template + void operator() (T const& val) const + { + std::cerr << val << ":" << typeid(T).name() << std::endl; + } +}; + + +struct test : util::static_visitor +{ + template + std::string operator() (T const& obj) const + { + return std::string("TYPE_ID=") + typeid(obj).name(); + } +}; + +struct calculator : public util::static_visitor +{ +public: + + int operator()(int value) const + { + return value; + } + + int operator()(binary_op const& binary) const + { + return util::apply_visitor(calculator(), binary.left) + + util::apply_visitor(calculator(), binary.right); + } + + int operator()(binary_op const& binary) const + { + return util::apply_visitor(calculator(), binary.left) + - util::apply_visitor(calculator(), binary.right); + } +}; + +struct to_string : public util::static_visitor +{ +public: + + std::string operator()(int value) const + { + return std::to_string(value); + } + + std::string operator()(binary_op const& binary) const + { + return util::apply_visitor(to_string(), binary.left) + std::string("+") + + util::apply_visitor(to_string(), binary.right); + } + + std::string operator()(binary_op const& binary) const + { + return util::apply_visitor(to_string(), binary.left) + std::string("-") + + util::apply_visitor(to_string(), binary.right); + } + +}; + +} // namespace test + +int main (int argc, char** argv) +{ + + if (argc != 2) + { + std::cerr << "Usage" << argv[0] << " " << std::endl; + return EXIT_FAILURE; + } + + const std::size_t NUM_ITER = static_cast(std::stol(argv[1])); + + test::expression result( + test::binary_op( + test::binary_op(2, 3), 4)); + + std::cerr << "TYPE OF RESULT-> " << util::apply_visitor(test::test(), result) << std::endl; + + { + boost::timer::auto_cpu_timer t; + int total = 0; + for (std::size_t i = 0; i < NUM_ITER; ++i) + { + total += util::apply_visitor(test::calculator(), result); + } + std::cerr << "total=" << total << std::endl; + } + + std::cerr << util::apply_visitor(test::to_string(), result) << "=" << util::apply_visitor(test::calculator(), result) << std::endl; + + return EXIT_SUCCESS; +} diff --git a/test/unique_ptr_test.cpp b/test/unique_ptr_test.cpp new file mode 100644 index 000000000..2a51efef0 --- /dev/null +++ b/test/unique_ptr_test.cpp @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "variant.hpp" + +using namespace mapbox; + +namespace test { + +struct add; +struct sub; +template struct binary_op; + +typedef util::variant>, + std::unique_ptr> + > expression; + +template +struct binary_op +{ + expression left; // variant instantiated here... + expression right; + + binary_op(expression && lhs, expression && rhs) + : left(std::move(lhs)), right(std::move(rhs)) {} +}; + +struct print : util::static_visitor +{ + template + void operator() (T const& val) const + { + std::cerr << val << ":" << typeid(T).name() << std::endl; + } +}; + + +struct test : util::static_visitor +{ + template + std::string operator() (T const& obj) const + { + return std::string("TYPE_ID=") + typeid(obj).name(); + } +}; + +struct calculator : public util::static_visitor +{ +public: + + int operator()(int value) const + { + return value; + } + + int operator()(std::unique_ptr> const& binary) const + { + return util::apply_visitor(calculator(), binary->left) + + util::apply_visitor(calculator(), binary->right); + } + + int operator()(std::unique_ptr> const& binary) const + { + return util::apply_visitor(calculator(), binary->left) + - util::apply_visitor(calculator(), binary->right); + } +}; + +struct to_string : public util::static_visitor +{ +public: + + std::string operator()(int value) const + { + return std::to_string(value); + } + + std::string operator()(std::unique_ptr> const& binary) const + { + return util::apply_visitor(to_string(), binary->left) + std::string("+") + + util::apply_visitor(to_string(), binary->right); + } + + std::string operator()(std::unique_ptr> const& binary) const + { + return util::apply_visitor(to_string(), binary->left) + std::string("-") + + util::apply_visitor(to_string(), binary->right); + } + +}; + +} // namespace test + +int main (int argc, char** argv) +{ + if (argc != 2) + { + std::cerr << "Usage" << argv[0] << " " << std::endl; + return EXIT_FAILURE; + } + + const std::size_t NUM_ITER = static_cast(std::stol(argv[1])); + + test::expression sum(std::unique_ptr>(new test::binary_op(2, 3))); + test::expression result(std::unique_ptr>(new test::binary_op(std::move(sum), 4))); + std::cerr << "TYPE OF RESULT-> " << util::apply_visitor(test::test(), result) << std::endl; + + { + boost::timer::auto_cpu_timer t; + int total = 0; + for (std::size_t i = 0; i < NUM_ITER; ++i) + { + total += util::apply_visitor(test::calculator(), result); + } + std::cerr << "total=" << total << std::endl; + } + + std::cerr << util::apply_visitor(test::to_string(), result) << "=" << util::apply_visitor(test::calculator(), result) << std::endl; + + return EXIT_SUCCESS; +} diff --git a/test/unit.cpp b/test/unit.cpp new file mode 100644 index 000000000..3998e6a9b --- /dev/null +++ b/test/unit.cpp @@ -0,0 +1,306 @@ +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" + +#include "variant.hpp" +#include "variant_io.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace mapbox; + +template +struct mutating_visitor +{ + mutating_visitor(T & val) + : val_(val) {} + + void operator() (T & val) const + { + val = val_; + } + + template + void operator() (T1& ) const {} // no-op + + T & val_; +}; + + + +TEST_CASE( "variant version", "[variant]" ) { + unsigned int version = VARIANT_VERSION; + REQUIRE(version == 100); + #if VARIANT_VERSION == 100 + REQUIRE(true); + #else + REQUIRE(false); + #endif +} + +TEST_CASE( "variant can be moved into vector", "[variant]" ) { + typedef util::variant variant_type; + variant_type v(std::string("test")); + std::vector vec; + vec.emplace_back(std::move(v)); + REQUIRE(v.get() != std::string("test")); + REQUIRE(vec.at(0).get() == std::string("test")); +} + +TEST_CASE( "variant should support built-in types", "[variant]" ) { + SECTION( "bool" ) { + util::variant v(true); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(v.get() == true); + v.set(false); + REQUIRE(v.get() == false); + v = true; + REQUIRE(v == util::variant(true)); + } + SECTION( "nullptr" ) { + typedef std::nullptr_t value_type; + util::variant v(nullptr); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + // TODO: commented since it breaks on windows: 'operator << is ambiguous' + //REQUIRE(v.get() == nullptr); + // FIXME: does not compile: ./variant.hpp:340:14: error: use of overloaded operator '<<' is ambiguous (with operand types 'std::__1::basic_ostream' and 'const nullptr_t') + // https://github.com/mapbox/variant/issues/14 + //REQUIRE(v == util::variant(nullptr)); + } + SECTION( "unique_ptr" ) { + typedef std::unique_ptr value_type; + util::variant v(value_type(new std::string("hello"))); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(*v.get().get() == *value_type(new std::string("hello")).get()); + } + SECTION( "string" ) { + typedef std::string value_type; + util::variant v(value_type("hello")); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(v.get() == value_type("hello")); + v.set(value_type("there")); + REQUIRE(v.get() == value_type("there")); + v = value_type("variant"); + REQUIRE(v == util::variant(value_type("variant"))); + } + SECTION( "size_t" ) { + typedef std::size_t value_type; + util::variant v(std::numeric_limits::max()); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(v.get() == std::numeric_limits::max()); + v.set(value_type(0)); + REQUIRE(v.get() == value_type(0)); + v = value_type(1); + REQUIRE(v == util::variant(value_type(1))); + } + SECTION( "int8_t" ) { + typedef std::int8_t value_type; + util::variant v(std::numeric_limits::max()); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(v.get() == std::numeric_limits::max()); + v.set(0); + REQUIRE(v.get() == value_type(0)); + v = value_type(1); + REQUIRE(v == util::variant(value_type(1))); + } + SECTION( "int16_t" ) { + typedef std::int16_t value_type; + util::variant v(std::numeric_limits::max()); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(v.get() == std::numeric_limits::max()); + v.set(0); + REQUIRE(v.get() == value_type(0)); + v = value_type(1); + REQUIRE(v == util::variant(value_type(1))); + } + SECTION( "int32_t" ) { + typedef std::int32_t value_type; + util::variant v(std::numeric_limits::max()); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(v.get() == std::numeric_limits::max()); + v.set(0); + REQUIRE(v.get() == value_type(0)); + v = value_type(1); + REQUIRE(v == util::variant(value_type(1))); + } + SECTION( "int64_t" ) { + typedef std::int64_t value_type; + util::variant v(std::numeric_limits::max()); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(v.get() == std::numeric_limits::max()); + v.set(0); + REQUIRE(v.get() == value_type(0)); + v = value_type(1); + REQUIRE(v == util::variant(value_type(1))); + } +} + +struct MissionInteger +{ + typedef uint64_t value_type; + value_type val_; + public: + MissionInteger(uint64_t val) : + val_(val) {} + + bool operator==(MissionInteger const& rhs) const + { + return (val_ == rhs.get()); + } + + uint64_t get() const + { + return val_; + } +}; + +// TODO - remove after https://github.com/mapbox/variant/issues/14 +std::ostream& operator<<(std::ostream& os, MissionInteger const& rhs) +{ + os << rhs.get(); + return os; +} + +TEST_CASE( "variant should support custom types", "[variant]" ) { + // http://www.missionintegers.com/integer/34838300 + util::variant v(MissionInteger(34838300)); + REQUIRE(v.valid()); + REQUIRE(v.is()); + REQUIRE(v.get_type_index() == 0); + REQUIRE(v.get() == MissionInteger(34838300)); + REQUIRE(v.get().get() == MissionInteger::value_type(34838300)); + // TODO: should both of the set usages below compile? + v.set(MissionInteger::value_type(0)); + v.set(MissionInteger(0)); + REQUIRE(v.get().get() == MissionInteger::value_type(0)); + v = MissionInteger(1); + REQUIRE(v == util::variant(MissionInteger(1))); +} + +// Test internal api +TEST_CASE( "variant should correctly index types", "[variant]" ) { + typedef util::variant variant_type; + // Index is in reverse order + REQUIRE(variant_type(true).get_type_index() == 5); + REQUIRE(variant_type(std::string("test")).get_type_index() == 4); + REQUIRE(variant_type(std::uint64_t(0)).get_type_index() == 3); + REQUIRE(variant_type(std::int64_t(0)).get_type_index() == 2); + REQUIRE(variant_type(double(0.0)).get_type_index() == 1); + REQUIRE(variant_type(float(0.0)).get_type_index() == 0); +} + +TEST_CASE( "get with type not in variant type list should throw", "[variant]" ) { + typedef util::variant variant_type; + variant_type var = 5; + REQUIRE(var.get() == 5); + REQUIRE_THROWS(var.get()); // XXX shouldn't this be a compile time error? See https://github.com/mapbox/variant/issues/24 +} + +TEST_CASE( "get with wrong type (here: double) should throw", "[variant]" ) { + typedef util::variant variant_type; + variant_type var = 5; + REQUIRE(var.get() == 5); + REQUIRE_THROWS(var.get()); +} + +TEST_CASE( "get with wrong type (here: int) should throw", "[variant]" ) { + typedef util::variant variant_type; + variant_type var = 5.0; + REQUIRE(var.get() == 5.0); + REQUIRE_THROWS(var.get()); +} + +TEST_CASE( "implicit conversion", "[variant][implicit conversion]" ) { + typedef util::variant variant_type; + variant_type var(5.0); // converted to int + REQUIRE(var.get() == 5); + REQUIRE_THROWS(var.get()); + var = 6.0; // works for operator=, too + REQUIRE(var.get() == 6); +} + +TEST_CASE( "implicit conversion to first type in variant type list", "[variant][implicit conversion]" ) { + typedef util::variant variant_type; + variant_type var = 5.0; // converted to long + REQUIRE(var.get() == 5); + REQUIRE_THROWS(var.get()); + REQUIRE_THROWS(var.get()); +} + +TEST_CASE( "implicit conversion to unsigned char", "[variant][implicit conversion]" ) { + typedef util::variant variant_type; + variant_type var = 100.0; + CHECK(var.get() == static_cast(100.0)); + CHECK(var.get() == static_cast(static_cast(100.0))); +} + +struct dummy {}; + +TEST_CASE( "variant value traits", "[variant::detail]" ) { + // Users should not create variants with duplicated types + // however our type indexing should still work + // Index is in reverse order + REQUIRE((util::detail::value_traits::index == 3)); + REQUIRE((util::detail::value_traits::index == 2)); + REQUIRE((util::detail::value_traits::index == 1)); + REQUIRE((util::detail::value_traits::index == 0)); + REQUIRE((util::detail::value_traits::index == util::detail::invalid_value)); + REQUIRE((util::detail::value_traits, bool, int, double, std::string>::index == util::detail::invalid_value)); +} + +TEST_CASE( "variant default constructor", "[variant][default constructor]" ) { + // By default variant is initialised with (default constructed) first type in template parameters pack + // As a result first type in Types... must be default constructable + // NOTE: index in reverse order -> index = N - 1 + REQUIRE((util::variant().get_type_index() == 2)); + REQUIRE((util::variant(util::no_init()).get_type_index() == util::detail::invalid_value)); +} + +TEST_CASE( "variant visitation", "[visitor][unary visitor]" ) { + util::variant var(123); + REQUIRE(var.get() == 123); + int val = 456; + mutating_visitor visitor(val); + util::apply_visitor(visitor, var); + REQUIRE(var.get() == 456); +} + +TEST_CASE( "variant printer", "[visitor][unary visitor][printer]" ) { + typedef util::variant variant_type; + std::vector var = {2.1, 123, "foo", 456}; + std::stringstream out; + std::copy(var.begin(), var.end(), std::ostream_iterator(out, ",")); + out << var[2]; + REQUIRE(out.str() == "2.1,123,foo,456,foo"); +} + + +int main (int argc, char* const argv[]) +{ + int result = Catch::Session().run(argc, argv); + if (!result) printf("\x1b[1;32m ✓ \x1b[0m\n"); + return result; +} diff --git a/test/variant_hello_world.cpp b/test/variant_hello_world.cpp new file mode 100644 index 000000000..b445fdbab --- /dev/null +++ b/test/variant_hello_world.cpp @@ -0,0 +1,22 @@ +#include "variant.hpp" +#include +#include + +using namespace mapbox; + +struct check : util::static_visitor<> +{ + template + void operator() (T const& val) const + { + if (val != 0) throw std::runtime_error("invalid"); + } +}; + + +int main() { + typedef util::variant variant_type; + variant_type v(0); + util::apply_visitor(check(), v); + return 0; +} diff --git a/variant.gyp b/variant.gyp new file mode 100644 index 000000000..712cafed1 --- /dev/null +++ b/variant.gyp @@ -0,0 +1,21 @@ +{ + "includes": [ + "common.gypi" + ], + "targets": [ + { + "target_name": "tests", + "type": "executable", + "sources": [ + "test/unit.cpp" + ], + "xcode_settings": { + "SDKROOT": "macosx", + "SUPPORTED_PLATFORMS":["macosx"] + }, + "include_dirs": [ + "./" + ] + } + ] +} \ No newline at end of file diff --git a/variant.hpp b/variant.hpp new file mode 100644 index 000000000..880ca1b2a --- /dev/null +++ b/variant.hpp @@ -0,0 +1,755 @@ +#ifndef MAPBOX_UTIL_VARIANT_HPP +#define MAPBOX_UTIL_VARIANT_HPP + +#include +#include +#include +#include // runtime_error +#include // operator new +#include // size_t +#include +#include + +#include "recursive_wrapper.hpp" + +#ifdef _MSC_VER + // http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx + #ifdef NDEBUG + #define VARIANT_INLINE __forceinline + #else + #define VARIANT_INLINE __declspec(noinline) + #endif +#else + #ifdef NDEBUG + #define VARIANT_INLINE inline __attribute__((always_inline)) + #else + #define VARIANT_INLINE __attribute__((noinline)) + #endif +#endif + +#define VARIANT_MAJOR_VERSION 0 +#define VARIANT_MINOR_VERSION 1 +#define VARIANT_PATCH_VERSION 0 + +// translates to 100 +#define VARIANT_VERSION (VARIANT_MAJOR_VERSION*100000) + (VARIANT_MINOR_VERSION*100) + (VARIANT_PATCH_VERSION) + +namespace mapbox { namespace util { + +// static visitor +template +struct static_visitor +{ + using result_type = R; +protected: + static_visitor() {} + ~static_visitor() {} +}; + +namespace detail { + +static constexpr std::size_t invalid_value = std::size_t(-1); + +template +struct direct_type; + +template +struct direct_type +{ + static constexpr std::size_t index = std::is_same::value + ? sizeof...(Types) : direct_type::index; +}; + +template +struct direct_type +{ + static constexpr std::size_t index = invalid_value; +}; + +template +struct convertible_type; + +template +struct convertible_type +{ + static constexpr std::size_t index = std::is_convertible::value + ? sizeof...(Types) : convertible_type::index; +}; + +template +struct convertible_type +{ + static constexpr std::size_t index = invalid_value; +}; + +template +struct value_traits +{ + static constexpr std::size_t direct_index = direct_type::index; + static constexpr std::size_t index = + (direct_index == invalid_value) ? convertible_type::index : direct_index; +}; + +template +struct is_valid_type; + +template +struct is_valid_type +{ + static constexpr bool value = std::is_convertible::value + || is_valid_type::value; +}; + +template +struct is_valid_type : std::false_type {}; + +template +struct select_type +{ + static_assert(N < sizeof...(Types), "index out of bounds"); +}; + +template +struct select_type +{ + using type = typename select_type::type; +}; + +template +struct select_type<0, T, Types...> +{ + using type = T; +}; + + +template +struct enable_if_type { using type = R; }; + +template +struct result_of_unary_visit +{ + using type = typename std::result_of::type; +}; + +template +struct result_of_unary_visit::type > +{ + using type = typename F::result_type; +}; + +template +struct result_of_binary_visit +{ + using type = typename std::result_of::type; +}; + + +template +struct result_of_binary_visit::type > +{ + using type = typename F::result_type; +}; + + +} // namespace detail + + +template +struct static_max; + +template +struct static_max +{ + static const std::size_t value = arg; +}; + +template +struct static_max +{ + static const std::size_t value = arg1 >= arg2 ? static_max::value : + static_max::value; +}; + +template +struct variant_helper; + +template +struct variant_helper +{ + VARIANT_INLINE static void destroy(const std::size_t id, void * data) + { + if (id == sizeof...(Types)) + { + reinterpret_cast(data)->~T(); + } + else + { + variant_helper::destroy(id, data); + } + } + + VARIANT_INLINE static void move(const std::size_t old_id, void * old_value, void * new_value) + { + if (old_id == sizeof...(Types)) + { + new (new_value) T(std::move(*reinterpret_cast(old_value))); + //std::memcpy(new_value, old_value, sizeof(T)); + // ^^ DANGER: this should only be considered for relocatable types e.g built-in types + // Also, I don't see any measurable performance benefit just yet + } + else + { + variant_helper::move(old_id, old_value, new_value); + } + } + + VARIANT_INLINE static void copy(const std::size_t old_id, const void * old_value, void * new_value) + { + if (old_id == sizeof...(Types)) + { + new (new_value) T(*reinterpret_cast(old_value)); + } + else + { + variant_helper::copy(old_id, old_value, new_value); + } + } +}; + +template<> struct variant_helper<> +{ + VARIANT_INLINE static void destroy(const std::size_t, void *) {} + VARIANT_INLINE static void move(const std::size_t, void *, void *) {} + VARIANT_INLINE static void copy(const std::size_t, const void *, void *) {} +}; + +namespace detail { + +template +struct unwrapper +{ + T const& operator() (T const& obj) const + { + return obj; + } + + T& operator() (T & obj) const + { + return obj; + } +}; + + +template +struct unwrapper> +{ + auto operator() (recursive_wrapper const& obj) const + -> typename recursive_wrapper::type const& + { + return obj.get(); + } +}; + + +template +struct dispatcher; + +template +struct dispatcher +{ + using result_type = R; + VARIANT_INLINE static result_type apply_const(V const& v, F f) + { + if (v.get_type_index() == sizeof...(Types)) + { + return f(unwrapper()(v. template get())); + } + else + { + return dispatcher::apply_const(v, f); + } + } + + VARIANT_INLINE static result_type apply(V & v, F f) + { + if (v.get_type_index() == sizeof...(Types)) + { + return f(unwrapper()(v. template get())); + } + else + { + return dispatcher::apply(v, f); + } + } +}; + +template +struct dispatcher +{ + using result_type = R; + VARIANT_INLINE static result_type apply_const(V const&, F) + { + throw std::runtime_error(std::string("unary dispatch: FAIL ") + typeid(V).name()); + } + + VARIANT_INLINE static result_type apply(V &, F) + { + throw std::runtime_error(std::string("unary dispatch: FAIL ") + typeid(V).name()); + } +}; + + +template +struct binary_dispatcher_rhs; + +template +struct binary_dispatcher_rhs +{ + using result_type = R; + VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f) + { + if (rhs.get_type_index() == sizeof...(Types)) // call binary functor + { + return f(unwrapper()(lhs. template get()), + unwrapper()(rhs. template get())); + } + else + { + return binary_dispatcher_rhs::apply_const(lhs, rhs, f); + } + } + + VARIANT_INLINE static result_type apply(V & lhs, V & rhs, F f) + { + if (rhs.get_type_index() == sizeof...(Types)) // call binary functor + { + return f(unwrapper()(lhs. template get()), + unwrapper()(rhs. template get())); + } + else + { + return binary_dispatcher_rhs::apply(lhs, rhs, f); + } + } + +}; + +template +struct binary_dispatcher_rhs +{ + using result_type = R; + VARIANT_INLINE static result_type apply_const(V const&, V const&, F) + { + throw std::runtime_error("binary dispatch: FAIL"); + } + VARIANT_INLINE static result_type apply(V &, V &, F) + { + throw std::runtime_error("binary dispatch: FAIL"); + } +}; + + +template +struct binary_dispatcher_lhs; + +template +struct binary_dispatcher_lhs +{ + using result_type = R; + VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f) + { + if (lhs.get_type_index() == sizeof...(Types)) // call binary functor + { + return f(lhs. template get(), rhs. template get()); + } + else + { + return binary_dispatcher_lhs::apply_const(lhs, rhs, f); + } + } + + VARIANT_INLINE static result_type apply(V & lhs, V & rhs, F f) + { + if (lhs.get_type_index() == sizeof...(Types)) // call binary functor + { + return f(lhs. template get(), rhs. template get()); + } + else + { + return binary_dispatcher_lhs::apply(lhs, rhs, f); + } + } + +}; + +template +struct binary_dispatcher_lhs +{ + using result_type = R; + VARIANT_INLINE static result_type apply_const(V const&, V const&, F) + { + throw std::runtime_error("binary dispatch: FAIL"); + } + + VARIANT_INLINE static result_type apply(V &, V &, F) + { + throw std::runtime_error("binary dispatch: FAIL"); + } +}; + +template +struct binary_dispatcher; + +template +struct binary_dispatcher +{ + using result_type = R; + VARIANT_INLINE static result_type apply_const(V const& v0, V const& v1, F f) + { + if (v0.get_type_index() == sizeof...(Types)) + { + if (v0.get_type_index() == v1.get_type_index()) + { + return f(v0. template get(), v1. template get()); // call binary functor + } + else + { + return binary_dispatcher_rhs::apply_const(v0, v1, f); + } + } + else if (v1.get_type_index() == sizeof...(Types)) + { + return binary_dispatcher_lhs::apply_const(v0, v1, f); + } + return binary_dispatcher::apply_const(v0, v1, f); + } + + VARIANT_INLINE static result_type apply(V & v0, V & v1, F f) + { + if (v0.get_type_index() == sizeof...(Types)) + { + if (v0.get_type_index() == v1.get_type_index()) + { + return f(v0. template get(), v1. template get()); // call binary functor + } + else + { + return binary_dispatcher_rhs::apply(v0, v1, f); + } + } + else if (v1.get_type_index() == sizeof...(Types)) + { + return binary_dispatcher_lhs::apply(v0, v1, f); + } + return binary_dispatcher::apply(v0, v1, f); + } +}; + +template +struct binary_dispatcher +{ + using result_type = R; + VARIANT_INLINE static result_type apply_const(V const&, V const&, F) + { + throw std::runtime_error("binary dispatch: FAIL"); + } + + VARIANT_INLINE static result_type apply(V &, V &, F) + { + throw std::runtime_error("binary dispatch: FAIL"); + } +}; + +// comparator functors +struct equal_comp +{ + template + bool operator()(T const& lhs, T const& rhs) const + { + return lhs == rhs; + } +}; + +struct less_comp +{ + template + bool operator()(T const& lhs, T const& rhs) const + { + return lhs < rhs; + } +}; + +template +class comparer +{ +public: + explicit comparer(Variant const& lhs) noexcept + : lhs_(lhs) {} + comparer& operator=(comparer const&) = delete; + // visitor + template + bool operator()(T const& rhs_content) const + { + T const& lhs_content = lhs_.template get(); + return Comp()(lhs_content, rhs_content); + } +private: + Variant const& lhs_; +}; + + +} // namespace detail + +struct no_init {}; + +template +class variant +{ +private: + + static const std::size_t data_size = static_max::value; + static const std::size_t data_align = static_max::value; + + using data_type = typename std::aligned_storage::type; + using helper_type = variant_helper; + + std::size_t type_index; + data_type data; + +public: + + VARIANT_INLINE variant() + : type_index(sizeof...(Types) - 1) + { + new (&data) typename detail::select_type<0, Types...>::type(); + } + + VARIANT_INLINE variant(no_init) + : type_index(detail::invalid_value) {} + + // http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers + template ::type, Types...>::value>::type> + VARIANT_INLINE variant(T && val) noexcept + : type_index(detail::value_traits::type, Types...>::index) + { + constexpr std::size_t index = sizeof...(Types) - detail::value_traits::type, Types...>::index - 1; + using target_type = typename detail::select_type::type; + new (&data) target_type(std::forward(val)); // nothrow + } + + VARIANT_INLINE variant(variant const& old) + : type_index(old.type_index) + { + helper_type::copy(old.type_index, &old.data, &data); + } + + VARIANT_INLINE variant(variant&& old) noexcept + : type_index(old.type_index) + { + helper_type::move(old.type_index, &old.data, &data); + } + + friend void swap(variant & first, variant & second) + { + using std::swap; //enable ADL + swap(first.type_index, second.type_index); + swap(first.data, second.data); + } + + VARIANT_INLINE variant& operator=(variant other) + { + swap(*this, other); + return *this; + } + + // conversions + // move-assign + template + VARIANT_INLINE variant& operator=(T && rhs) noexcept + { + variant temp(std::forward(rhs)); + swap(*this, temp); + return *this; + } + + // copy-assign + template + VARIANT_INLINE variant& operator=(T const& rhs) + { + variant temp(rhs); + swap(*this, temp); + return *this; + } + + template + VARIANT_INLINE bool is() const + { + return (type_index == detail::direct_type::index); + } + + VARIANT_INLINE bool valid() const + { + return (type_index != detail::invalid_value); + } + + template + VARIANT_INLINE void set(Args&&... args) + { + helper_type::destroy(type_index, &data); + new (&data) T(std::forward(args)...); + type_index = detail::direct_type::index; + } + + template + VARIANT_INLINE T& get() + { + if (type_index == detail::direct_type::index) + { + return *reinterpret_cast(&data); + } + else + { + throw std::runtime_error("in get()"); + } + } + + template + VARIANT_INLINE T const& get() const + { + if (type_index == detail::direct_type::index) + { + return *reinterpret_cast(&data); + } + else + { + throw std::runtime_error("in get()"); + } + } + + VARIANT_INLINE std::size_t get_type_index() const + { + return type_index; + } + + // visitor + // unary + template + auto VARIANT_INLINE + static visit(V const& v, F f) + -> decltype(detail::dispatcher::type>::type, Types...>::apply_const(v, f)) + { + using R = typename detail::result_of_unary_visit::type>::type; + return detail::dispatcher::apply_const(v, f); + } + // non-const + template + auto VARIANT_INLINE + static visit(V & v, F f) + -> decltype(detail::dispatcher::type>::type, Types...>::apply(v, f)) + { + using R = typename detail::result_of_unary_visit::type>::type; + return detail::dispatcher::apply(v, f); + } + + // binary + // const + template + auto VARIANT_INLINE + static binary_visit(V const& v0, V const& v1, F f) + -> decltype(detail::binary_dispatcher::type>::type, Types...>::apply_const(v0, v1, f)) + { + using R = typename detail::result_of_binary_visit::type>::type; + return detail::binary_dispatcher::apply_const(v0, v1, f); + } + // non-const + template + auto VARIANT_INLINE + static binary_visit(V& v0, V& v1, F f) + -> decltype(detail::binary_dispatcher::type>::type, Types...>::apply(v0, v1, f)) + { + using R = typename detail::result_of_binary_visit::type>::type; + return detail::binary_dispatcher::apply(v0, v1, f); + } + + ~variant() noexcept + { + helper_type::destroy(type_index, &data); + } + + // comparison operators + // equality + VARIANT_INLINE bool operator==(variant const& rhs) const + { + if (this->get_type_index() != rhs.get_type_index()) + return false; + detail::comparer visitor(*this); + return visit(rhs, visitor); + } + // less than + VARIANT_INLINE bool operator<(variant const& rhs) const + { + if (this->get_type_index() != rhs.get_type_index()) + { + return this->get_type_index() < rhs.get_type_index(); + // ^^ borrowed from boost::variant + } + detail::comparer visitor(*this); + return visit(rhs, visitor); + } +}; + +// unary visitor interface + +// const +template +auto VARIANT_INLINE static apply_visitor(F f, V const& v) -> decltype(V::visit(v, f)) +{ + return V::visit(v, f); +} +// non-const +template +auto VARIANT_INLINE static apply_visitor(F f, V & v) -> decltype(V::visit(v, f)) +{ + return V::visit(v, f); +} + +// binary visitor interface +// const +template +auto VARIANT_INLINE static apply_visitor(F f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, f)) +{ + return V::binary_visit(v0, v1, f); +} +// non-const +template +auto VARIANT_INLINE static apply_visitor(F f, V & v0, V & v1) -> decltype(V::binary_visit(v0, v1, f)) +{ + return V::binary_visit(v0, v1, f); +} + +// getter interface +template +ResultType & get(T & var) +{ + return var.template get(); +} + +template +ResultType const& get(T const& var) +{ + return var.template get(); +} + + +}} + +#endif // MAPBOX_UTIL_VARIANT_HPP diff --git a/variant_io.hpp b/variant_io.hpp new file mode 100644 index 000000000..8b0c13743 --- /dev/null +++ b/variant_io.hpp @@ -0,0 +1,39 @@ +#ifndef MAPBOX_UTIL_VARIANT_IO_HPP +#define MAPBOX_UTIL_VARIANT_IO_HPP + +namespace mapbox { namespace util { + +namespace detail { +// operator<< helper +template +class printer +{ +public: + explicit printer(Out & out) + : out_(out) {} + printer& operator=(printer const&) = delete; + +// visitor + template + void operator()(T const& operand) const + { + out_ << operand; + } +private: + Out & out_; +}; +} + +// operator<< +template +VARIANT_INLINE std::basic_ostream& +operator<< (std::basic_ostream& out, variant const& rhs) +{ + detail::printer> visitor(out); + apply_visitor(visitor, rhs); + return out; +} + +}} + +#endif //MAPBOX_UTIL_VARIANT_IO_HPP diff --git a/vcbuild.bat b/vcbuild.bat new file mode 100644 index 000000000..21489a134 --- /dev/null +++ b/vcbuild.bat @@ -0,0 +1,8 @@ +SET configuration=Debug +IF NOT EXIST deps\gyp\ git clone --depth 1 https://chromium.googlesource.com/external/gyp.git deps/gyp +IF EXIST %configuration% rd /s /q %configuration% +del variant.sln +del tests.vcxproj +C:\Python27\python.exe deps/gyp/gyp_main.py variant.gyp --depth=. -f msvs -G msvs_version=2013 +msbuild variant.sln /nologo /p:Configuration=%configuration%;Platform=Win32 +.\"%configuration%"\tests.exe \ No newline at end of file From f67eeb66aa16e8e4dfb09523a3da252dd9c56627 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 9 Feb 2015 17:38:40 +0100 Subject: [PATCH 174/360] untangle includes using iwyu --- algorithms/douglas_peucker.cpp | 2 +- algorithms/douglas_peucker.hpp | 10 ++++++---- data_structures/coordinate.cpp | 4 ---- data_structures/coordinate_calculation.cpp | 2 ++ data_structures/coordinate_calculation.hpp | 3 +-- data_structures/external_memory_node.cpp | 1 + data_structures/external_memory_node.hpp | 2 +- data_structures/import_edge.cpp | 3 ++- data_structures/phantom_node.cpp | 7 +++++++ data_structures/phantom_node.hpp | 1 + datastore.cpp | 4 ++++ extract.cpp | 2 ++ extractor/extractor_options.hpp | 4 +++- prepare.cpp | 6 +++++- server/request_parser.cpp | 6 ++++++ util/fingerprint.cpp.in | 2 ++ util/simple_logger.cpp | 14 ++++---------- 17 files changed, 48 insertions(+), 25 deletions(-) diff --git a/algorithms/douglas_peucker.cpp b/algorithms/douglas_peucker.cpp index b3a01f440..e94912482 100644 --- a/algorithms/douglas_peucker.cpp +++ b/algorithms/douglas_peucker.cpp @@ -28,13 +28,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "douglas_peucker.hpp" #include "../data_structures/segment_information.hpp" -#include "../util/integer_range.hpp" #include #include #include #include +#include namespace { diff --git a/algorithms/douglas_peucker.hpp b/algorithms/douglas_peucker.hpp index 417e80a38..7c5f8c1e8 100644 --- a/algorithms/douglas_peucker.hpp +++ b/algorithms/douglas_peucker.hpp @@ -28,9 +28,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef DOUGLAS_PEUCKER_HPP_ #define DOUGLAS_PEUCKER_HPP_ -#include -#include +#include "../data_structures/segment_information.hpp" + #include +#include +#include +#include + /* This class object computes the bitvector of indicating generalized input * points according to the (Ramer-)Douglas-Peucker algorithm. @@ -39,8 +43,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * bit indicating if the points is present in the generalization. * Note: points may also be pre-selected*/ -struct SegmentInformation; - static const std::array DOUGLAS_PEUCKER_THRESHOLDS {{ 512440, // z0 256720, // z1 diff --git a/data_structures/coordinate.cpp b/data_structures/coordinate.cpp index bbe4f18ff..29151cf4c 100644 --- a/data_structures/coordinate.cpp +++ b/data_structures/coordinate.cpp @@ -27,15 +27,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "coordinate_calculation.hpp" -#include "../util/mercator.hpp" #ifndef NDEBUG #include "../util/simple_logger.hpp" #endif -#include #include -#include - #ifndef NDEBUG #include #endif diff --git a/data_structures/coordinate_calculation.cpp b/data_structures/coordinate_calculation.cpp index 05dc08789..58f92ce33 100644 --- a/data_structures/coordinate_calculation.cpp +++ b/data_structures/coordinate_calculation.cpp @@ -32,6 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include + #include #include diff --git a/data_structures/coordinate_calculation.hpp b/data_structures/coordinate_calculation.hpp index 359fdb585..9dbaa646b 100644 --- a/data_structures/coordinate_calculation.hpp +++ b/data_structures/coordinate_calculation.hpp @@ -28,9 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef COORDINATE_CALCULATION #define COORDINATE_CALCULATION -#include +struct FixedPointCoordinate; -#include //for std::ostream #include #include diff --git a/data_structures/external_memory_node.cpp b/data_structures/external_memory_node.cpp index cd6271b1c..3ede2c5a0 100644 --- a/data_structures/external_memory_node.cpp +++ b/data_structures/external_memory_node.cpp @@ -26,6 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "external_memory_node.hpp" +#include "query_node.hpp" #include diff --git a/data_structures/external_memory_node.hpp b/data_structures/external_memory_node.hpp index f88a23e7b..4ac6b9237 100644 --- a/data_structures/external_memory_node.hpp +++ b/data_structures/external_memory_node.hpp @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "query_node.hpp" -#include +#include "../typedefs.h" struct ExternalMemoryNode : QueryNode { diff --git a/data_structures/import_edge.cpp b/data_structures/import_edge.cpp index 55f5f161e..098adb32a 100644 --- a/data_structures/import_edge.cpp +++ b/data_structures/import_edge.cpp @@ -27,7 +27,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "import_edge.hpp" -#include +#include "travel_mode.hpp" +#include "../typedefs.h" bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const { diff --git a/data_structures/phantom_node.cpp b/data_structures/phantom_node.cpp index 413c0d79e..5351a4dfb 100644 --- a/data_structures/phantom_node.cpp +++ b/data_structures/phantom_node.cpp @@ -27,6 +27,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "phantom_node.hpp" +#include "../typedefs.h" +#include "travel_mode.hpp" + +#include + +#include + PhantomNode::PhantomNode(NodeID forward_node_id, NodeID reverse_node_id, unsigned name_id, int forward_weight, int reverse_weight, int forward_offset, int reverse_offset, unsigned packed_geometry_id, unsigned component_id, FixedPointCoordinate &location, diff --git a/data_structures/phantom_node.hpp b/data_structures/phantom_node.hpp index 3cc1f510d..0356e851f 100644 --- a/data_structures/phantom_node.hpp +++ b/data_structures/phantom_node.hpp @@ -34,6 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include struct PhantomNode diff --git a/datastore.cpp b/datastore.cpp index e701b4e89..77d933fda 100644 --- a/datastore.cpp +++ b/datastore.cpp @@ -28,10 +28,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "data_structures/original_edge_data.hpp" #include "data_structures/range_table.hpp" #include "data_structures/query_edge.hpp" +#include "data_structures/query_node.hpp" #include "data_structures/shared_memory_factory.hpp" #include "data_structures/shared_memory_vector_wrapper.hpp" #include "data_structures/static_graph.hpp" #include "data_structures/static_rtree.hpp" +#include "data_structures/travel_mode.hpp" #include "data_structures/turn_instructions.hpp" #include "server/data_structures/datafacade_base.hpp" #include "server/data_structures/shared_datatype.hpp" @@ -44,6 +46,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "typedefs.h" #include +#include using RTreeLeaf = BaseDataFacade::RTreeLeaf; using RTreeNode = StaticRTree::vector, true>::TreeNode; @@ -58,6 +61,7 @@ using QueryGraph = StaticGraph; #include + #include #include diff --git a/extract.cpp b/extract.cpp index b37518444..b1f30a6ad 100644 --- a/extract.cpp +++ b/extract.cpp @@ -29,6 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "extractor/extractor_options.hpp" #include "util/simple_logger.hpp" +#include + int main(int argc, char *argv[]) { try diff --git a/extractor/extractor_options.hpp b/extractor/extractor_options.hpp index 0813896d7..4c5e2b696 100644 --- a/extractor/extractor_options.hpp +++ b/extractor/extractor_options.hpp @@ -28,7 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef EXTRACTOR_OPTIONS_HPP #define EXTRACTOR_OPTIONS_HPP -#include +#include + +#include enum class return_code : unsigned { diff --git a/prepare.cpp b/prepare.cpp index e50f134c3..2fbe6ba70 100644 --- a/prepare.cpp +++ b/prepare.cpp @@ -26,8 +26,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "contractor/processing_chain.hpp" +#include "util/simple_logger.hpp" -#include +#include + +#include +#include int main(int argc, char *argv[]) { diff --git a/server/request_parser.cpp b/server/request_parser.cpp index 0e9ab442f..ff9e0d42d 100644 --- a/server/request_parser.cpp +++ b/server/request_parser.cpp @@ -27,10 +27,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "request_parser.hpp" +#include "http/compression_type.hpp" +#include "http/header.hpp" #include "http/request.hpp" +#include "../data_structures/tribool.hpp" + #include +#include + namespace http { diff --git a/util/fingerprint.cpp.in b/util/fingerprint.cpp.in index 6f9a6658f..e30b5ab1a 100644 --- a/util/fingerprint.cpp.in +++ b/util/fingerprint.cpp.in @@ -31,6 +31,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include + #include #include diff --git a/util/simple_logger.cpp b/util/simple_logger.cpp index 325684af9..238e0b57d 100644 --- a/util/simple_logger.cpp +++ b/util/simple_logger.cpp @@ -26,13 +26,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "simple_logger.hpp" - -#include "osrm_exception.hpp" - -#include - -#include - #ifdef _MSC_VER #include #define isatty _isatty @@ -40,10 +33,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #else #include #endif +#include +#include +#include +#include -#include -#include -#include namespace { From a81542eeee467a3e9aa8af55737cec62de4dba7b Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 10 Feb 2015 10:07:35 +0100 Subject: [PATCH 175/360] add virtual keyword to functions with override final specifiers --- descriptors/json_descriptor.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/descriptors/json_descriptor.hpp b/descriptors/json_descriptor.hpp index d7e824482..a87d598cd 100644 --- a/descriptors/json_descriptor.hpp +++ b/descriptors/json_descriptor.hpp @@ -77,7 +77,7 @@ template class JSONDescriptor final : public BaseDescriptor< { } - void SetConfig(const DescriptorConfig &c) override final { config = c; } + virtual void SetConfig(const DescriptorConfig &c) override final { config = c; } unsigned DescribeLeg(const std::vector route_leg, const PhantomNodes &leg_phantoms, @@ -100,7 +100,7 @@ template class JSONDescriptor final : public BaseDescriptor< return added_element_count; } - void Run(const InternalRouteResult &raw_route, JSON::Object &json_result) override final + virtual void Run(const InternalRouteResult &raw_route, JSON::Object &json_result) override final { if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length) { From e0f8acf733d2bc631f49b3b7f259727391b37ba9 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 10 Feb 2015 11:04:49 +0100 Subject: [PATCH 176/360] make constant a float to avoid implicit cast --- data_structures/coordinate_calculation.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/data_structures/coordinate_calculation.cpp b/data_structures/coordinate_calculation.cpp index 58f92ce33..674912e66 100644 --- a/data_structures/coordinate_calculation.cpp +++ b/data_structures/coordinate_calculation.cpp @@ -40,7 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace { -constexpr static const float RAD = 0.017453292519943295769236907684886; +constexpr static const float RAD = 0.017453292519943295769236907684886f; // earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi) // The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles) constexpr static const float earth_radius = 6372797.560856f; @@ -68,9 +68,9 @@ double coordinate_calculation::great_circle_distance(const int lat1, const double dLong = dlong1 - dlong2; const double dLat = dlat1 - dlat2; - const double aHarv = - pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2); - const double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv)); + const double aHarv = std::pow(std::sin(dLat / 2.0), 2.0) + + std::cos(dlat1) * std::cos(dlat2) * std::pow(std::sin(dLong / 2.), 2); + const double cHarv = 2. * std::atan2(std::sqrt(aHarv), std::sqrt(1.0 - aHarv)); return earth_radius * cHarv; } @@ -251,8 +251,9 @@ float coordinate_calculation::bearing(const FixedPointCoordinate &first_coordina const float lon_delta = deg_to_rad(lon_diff); const float lat1 = deg_to_rad(first_coordinate.lat / COORDINATE_PRECISION); const float lat2 = deg_to_rad(second_coordinate.lat / COORDINATE_PRECISION); - const float y = sin(lon_delta) * cos(lat2); - const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon_delta); + const float y = std::sin(lon_delta) * std::cos(lat2); + const float x = + std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta); float result = rad_to_deg(std::atan2(y, x)); while (result < 0.f) { From 5a1ff4b50deb09e3c51f2b515df88803f9aed9bb Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 10 Feb 2015 11:09:51 +0100 Subject: [PATCH 177/360] fix warning: implicit conversion changes signedness: 'int' to 'unsigned int' --- data_structures/phantom_node.cpp | 105 ++++++++++++------------------- 1 file changed, 40 insertions(+), 65 deletions(-) diff --git a/data_structures/phantom_node.cpp b/data_structures/phantom_node.cpp index 5351a4dfb..9a0988564 100644 --- a/data_structures/phantom_node.cpp +++ b/data_structures/phantom_node.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -34,40 +34,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -PhantomNode::PhantomNode(NodeID forward_node_id, NodeID reverse_node_id, unsigned name_id, - int forward_weight, int reverse_weight, int forward_offset, int reverse_offset, - unsigned packed_geometry_id, unsigned component_id, FixedPointCoordinate &location, - unsigned short fwd_segment_position, - TravelMode forward_travel_mode, TravelMode backward_travel_mode) : - forward_node_id(forward_node_id), - reverse_node_id(reverse_node_id), - name_id(name_id), - forward_weight(forward_weight), - reverse_weight(reverse_weight), - forward_offset(forward_offset), - reverse_offset(reverse_offset), - packed_geometry_id(packed_geometry_id), - component_id(component_id), - location(location), - fwd_segment_position(fwd_segment_position), - forward_travel_mode(forward_travel_mode), - backward_travel_mode(backward_travel_mode) -{ } +PhantomNode::PhantomNode(NodeID forward_node_id, + NodeID reverse_node_id, + unsigned name_id, + int forward_weight, + int reverse_weight, + int forward_offset, + int reverse_offset, + unsigned packed_geometry_id, + unsigned component_id, + FixedPointCoordinate &location, + unsigned short fwd_segment_position, + TravelMode forward_travel_mode, + TravelMode backward_travel_mode) + : forward_node_id(forward_node_id), reverse_node_id(reverse_node_id), name_id(name_id), + forward_weight(forward_weight), reverse_weight(reverse_weight), + forward_offset(forward_offset), reverse_offset(reverse_offset), + packed_geometry_id(packed_geometry_id), component_id(component_id), location(location), + fwd_segment_position(fwd_segment_position), forward_travel_mode(forward_travel_mode), + backward_travel_mode(backward_travel_mode) +{ +} -PhantomNode::PhantomNode() : - forward_node_id(SPECIAL_NODEID), - reverse_node_id(SPECIAL_NODEID), - name_id(std::numeric_limits::max()), - forward_weight(INVALID_EDGE_WEIGHT), - reverse_weight(INVALID_EDGE_WEIGHT), - forward_offset(0), - reverse_offset(0), - packed_geometry_id(SPECIAL_EDGEID), - component_id(-1), - fwd_segment_position(0), - forward_travel_mode(TRAVEL_MODE_INACCESSIBLE), - backward_travel_mode(TRAVEL_MODE_INACCESSIBLE) -{ } +PhantomNode::PhantomNode() + : forward_node_id(SPECIAL_NODEID), reverse_node_id(SPECIAL_NODEID), + name_id(std::numeric_limits::max()), forward_weight(INVALID_EDGE_WEIGHT), + reverse_weight(INVALID_EDGE_WEIGHT), forward_offset(0), reverse_offset(0), + packed_geometry_id(SPECIAL_EDGEID), component_id(std::numeric_limits::max()), + fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE), + backward_travel_mode(TRAVEL_MODE_INACCESSIBLE) +{ +} int PhantomNode::GetForwardWeightPlusOffset() const { @@ -89,43 +86,21 @@ int PhantomNode::GetReverseWeightPlusOffset() const bool PhantomNode::is_bidirected() const { - return (forward_node_id != SPECIAL_NODEID) && - (reverse_node_id != SPECIAL_NODEID); + return (forward_node_id != SPECIAL_NODEID) && (reverse_node_id != SPECIAL_NODEID); } -bool PhantomNode::is_compressed() const -{ - return (forward_offset != 0) || (reverse_offset != 0); -} +bool PhantomNode::is_compressed() const { return (forward_offset != 0) || (reverse_offset != 0); } bool PhantomNode::is_valid(const unsigned number_of_nodes) const -{ - return - location.is_valid() && - ( - (forward_node_id < number_of_nodes) || - (reverse_node_id < number_of_nodes) - ) && - ( - (forward_weight != INVALID_EDGE_WEIGHT) || - (reverse_weight != INVALID_EDGE_WEIGHT) - ) && - (name_id != INVALID_NAMEID - ); -} - -bool PhantomNode::is_in_tiny_component() const -{ - return component_id != 0; -} - -bool PhantomNode::is_valid() const { return location.is_valid() && + ((forward_node_id < number_of_nodes) || (reverse_node_id < number_of_nodes)) && + ((forward_weight != INVALID_EDGE_WEIGHT) || (reverse_weight != INVALID_EDGE_WEIGHT)) && (name_id != INVALID_NAMEID); } -bool PhantomNode::operator==(const PhantomNode & other) const -{ - return location == other.location; -} +bool PhantomNode::is_in_tiny_component() const { return component_id != 0; } + +bool PhantomNode::is_valid() const { return location.is_valid() && (name_id != INVALID_NAMEID); } + +bool PhantomNode::operator==(const PhantomNode &other) const { return location == other.location; } From adb520ec2a808f94175c3d68807a0589821c513b Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 10 Feb 2015 11:31:36 +0100 Subject: [PATCH 178/360] fix old-style casts --- util/graph_loader.hpp | 44 ++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/util/graph_loader.hpp b/util/graph_loader.hpp index 44f628034..b85f89109 100644 --- a/util/graph_loader.hpp +++ b/util/graph_loader.hpp @@ -62,7 +62,7 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, { const FingerPrint fingerprint_orig; FingerPrint fingerprint_loaded; - input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint)); + input_stream.read(reinterpret_cast(&fingerprint_loaded), sizeof(FingerPrint)); if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig)) { @@ -73,13 +73,13 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, std::unordered_map ext_to_int_id_map; NodeID n; - input_stream.read((char *)&n, sizeof(NodeID)); + input_stream.read(reinterpret_cast(&n), sizeof(NodeID)); SimpleLogger().Write() << "Importing n = " << n << " nodes "; ExternalMemoryNode current_node; for (NodeID i = 0; i < n; ++i) { - input_stream.read((char *)¤t_node, sizeof(ExternalMemoryNode)); + input_stream.read(reinterpret_cast(¤t_node), sizeof(ExternalMemoryNode)); int_to_ext_node_id_map->emplace_back(current_node.lat, current_node.lon, current_node.node_id); ext_to_int_id_map.emplace(current_node.node_id, i); @@ -138,23 +138,23 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, TravelMode travel_mode; EdgeID m; - input_stream.read((char *)&m, sizeof(unsigned)); + input_stream.read(reinterpret_cast(&m), sizeof(unsigned)); edge_list.reserve(m); SimpleLogger().Write() << " and " << m << " edges "; for (EdgeID i = 0; i < m; ++i) { - input_stream.read((char *)&source, sizeof(unsigned)); - input_stream.read((char *)&target, sizeof(unsigned)); - input_stream.read((char *)&length, sizeof(int)); - input_stream.read((char *)&dir, sizeof(short)); - input_stream.read((char *)&weight, sizeof(int)); - input_stream.read((char *)&nameID, sizeof(unsigned)); - input_stream.read((char *)&is_roundabout, sizeof(bool)); - input_stream.read((char *)&ignore_in_grid, sizeof(bool)); - input_stream.read((char *)&is_access_restricted, sizeof(bool)); - input_stream.read((char *)&travel_mode, sizeof(TravelMode)); - input_stream.read((char *)&is_split, sizeof(bool)); + input_stream.read(reinterpret_cast(&source), sizeof(unsigned)); + input_stream.read(reinterpret_cast(&target), sizeof(unsigned)); + input_stream.read(reinterpret_cast(&length), sizeof(int)); + input_stream.read(reinterpret_cast(&dir), sizeof(short)); + input_stream.read(reinterpret_cast(&weight), sizeof(int)); + input_stream.read(reinterpret_cast(&nameID), sizeof(unsigned)); + input_stream.read(reinterpret_cast(&is_roundabout), sizeof(bool)); + input_stream.read(reinterpret_cast(&ignore_in_grid), sizeof(bool)); + input_stream.read(reinterpret_cast(&is_access_restricted), sizeof(bool)); + input_stream.read(reinterpret_cast(&travel_mode), sizeof(TravelMode)); + input_stream.read(reinterpret_cast(&is_split), sizeof(bool)); BOOST_ASSERT_MSG(length > 0, "loaded null length edge"); BOOST_ASSERT_MSG(weight > 0, "loaded null weight"); @@ -286,7 +286,7 @@ unsigned readHSGRFromStream(const boost::filesystem::path &hsgr_file, boost::filesystem::ifstream hsgr_input_stream(hsgr_file, std::ios::binary); FingerPrint fingerprint_loaded, fingerprint_orig; - hsgr_input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint)); + hsgr_input_stream.read(reinterpret_cast(&fingerprint_loaded), sizeof(FingerPrint)); if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig)) { SimpleLogger().Write(logWARNING) << ".hsgr was prepared with different build.\n" @@ -295,22 +295,24 @@ unsigned readHSGRFromStream(const boost::filesystem::path &hsgr_file, unsigned number_of_nodes = 0; unsigned number_of_edges = 0; - hsgr_input_stream.read((char *)check_sum, sizeof(unsigned)); - hsgr_input_stream.read((char *)&number_of_nodes, sizeof(unsigned)); + hsgr_input_stream.read(reinterpret_cast(check_sum), sizeof(unsigned)); + hsgr_input_stream.read(reinterpret_cast(&number_of_nodes), sizeof(unsigned)); BOOST_ASSERT_MSG(0 != number_of_nodes, "number of nodes is zero"); - hsgr_input_stream.read((char *)&number_of_edges, sizeof(unsigned)); + hsgr_input_stream.read(reinterpret_cast(&number_of_edges), sizeof(unsigned)); SimpleLogger().Write() << "number_of_nodes: " << number_of_nodes << ", number_of_edges: " << number_of_edges; // BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero"); node_list.resize(number_of_nodes); - hsgr_input_stream.read((char *)&(node_list[0]), number_of_nodes * sizeof(NodeT)); + hsgr_input_stream.read(reinterpret_cast(&node_list[0]), + number_of_nodes * sizeof(NodeT)); edge_list.resize(number_of_edges); if (number_of_edges > 0) { - hsgr_input_stream.read((char *)&(edge_list[0]), number_of_edges * sizeof(EdgeT)); + hsgr_input_stream.read(reinterpret_cast(&edge_list[0]), + number_of_edges * sizeof(EdgeT)); } hsgr_input_stream.close(); From 09bea2ad5b2d2abec9b4cb4e40732605724e8ab1 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 10 Feb 2015 11:32:39 +0100 Subject: [PATCH 179/360] fix warning: implicit float/double cast --- data_structures/coordinate_calculation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/coordinate_calculation.cpp b/data_structures/coordinate_calculation.cpp index 674912e66..69e2ead17 100644 --- a/data_structures/coordinate_calculation.cpp +++ b/data_structures/coordinate_calculation.cpp @@ -103,7 +103,7 @@ float coordinate_calculation::euclidean_distance(const int lat1, const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD; const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD; - const float x_value = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.f); + const float x_value = (float_lon2 - float_lon1) * std::cos((float_lat1 + float_lat2) / 2.f); const float y_value = float_lat2 - float_lat1; return std::hypot(x_value, y_value) * earth_radius; } From 858245db7d9c25a75be2fa3040198d24033ff0e8 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 10 Feb 2015 11:35:58 +0100 Subject: [PATCH 180/360] fix warning: implicit signed/unsigned warning --- algorithms/tiny_components.hpp | 4 ++-- data_structures/binary_heap.hpp | 19 +++++++------------ data_structures/deallocating_vector.hpp | 6 +++++- data_structures/dynamic_graph.hpp | 2 +- data_structures/node_based_graph.hpp | 14 +++++++------- data_structures/xor_fast_hash.hpp | 12 ++++++------ 6 files changed, 28 insertions(+), 29 deletions(-) diff --git a/algorithms/tiny_components.hpp b/algorithms/tiny_components.hpp index 5354fc785..b595ac427 100644 --- a/algorithms/tiny_components.hpp +++ b/algorithms/tiny_components.hpp @@ -102,7 +102,7 @@ template class TarjanSCC std::stack tarjan_stack; std::vector tarjan_node_list(m_node_based_graph->GetNumberOfNodes()); unsigned component_index = 0, size_of_current_component = 0; - int index = 0; + unsigned index = 0; const NodeID last_node = m_node_based_graph->GetNumberOfNodes(); std::vector processing_node_before_recursion(m_node_based_graph->GetNumberOfNodes(), true); @@ -226,7 +226,7 @@ template class TarjanSCC std::size_t get_number_of_components() const { return component_size_vector.size(); } - unsigned get_size_one_count() const { return size_one_counter; } + std::size_t get_size_one_count() const { return size_one_counter; } unsigned get_component_size(const NodeID node) const { diff --git a/data_structures/binary_heap.hpp b/data_structures/binary_heap.hpp index 4522460a2..3a2796d7c 100644 --- a/data_structures/binary_heap.hpp +++ b/data_structures/binary_heap.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -40,18 +40,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. template class ArrayStorage { public: - explicit ArrayStorage(size_t size) : positions(size, 0) - { - } + explicit ArrayStorage(size_t size) : positions(size, 0) {} - ~ArrayStorage() { } + ~ArrayStorage() {} Key &operator[](NodeID node) { return positions[node]; } - Key peek_index(const NodeID node) const - { - return positions[node]; - } + Key peek_index(const NodeID node) const { return positions[node]; } void Clear() {} @@ -77,6 +72,7 @@ template class MapStorage } return std::numeric_limits::max(); } + private: std::map nodes; }; @@ -262,8 +258,7 @@ class BinaryHeap while (nextKey < heap_size) { const Key nextKeyOther = nextKey + 1; - if ((nextKeyOther < heap_size) && - (heap[nextKey].weight > heap[nextKeyOther].weight)) + if ((nextKeyOther < heap_size) && (heap[nextKey].weight > heap[nextKeyOther].weight)) { nextKey = nextKeyOther; } @@ -302,7 +297,7 @@ class BinaryHeap void CheckHeap() { #ifndef NDEBUG - for (Key i = 2; i < (Key)heap.size(); ++i) + for (std::size_t i = 2; i < heap.size(); ++i) { BOOST_ASSERT(heap[i].weight >= heap[i >> 1].weight); } diff --git a/data_structures/deallocating_vector.hpp b/data_structures/deallocating_vector.hpp index 5ea2a81ce..968528f3c 100644 --- a/data_structures/deallocating_vector.hpp +++ b/data_structures/deallocating_vector.hpp @@ -32,12 +32,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include #include #include template struct DeallocatingVectorIteratorState { - DeallocatingVectorIteratorState() : index(-1), bucket_list(nullptr) {} + DeallocatingVectorIteratorState() + : index(std::numeric_limits::max()), bucket_list(nullptr) + { + } explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r) : index(r.index), bucket_list(r.bucket_list) { diff --git a/data_structures/dynamic_graph.hpp b/data_structures/dynamic_graph.hpp index 4a666c136..abaa05717 100644 --- a/data_structures/dynamic_graph.hpp +++ b/data_structures/dynamic_graph.hpp @@ -90,7 +90,7 @@ template class DynamicGraph template DynamicGraph(const NodeIterator nodes, const ContainerT &graph) { number_of_nodes = nodes; - number_of_edges = (EdgeIterator)graph.size(); + number_of_edges = static_cast(graph.size()); node_list.reserve(number_of_nodes + 1); node_list.resize(number_of_nodes + 1); EdgeIterator edge = 0; diff --git a/data_structures/node_based_graph.hpp b/data_structures/node_based_graph.hpp index 49dba2c08..82eb59bd5 100644 --- a/data_structures/node_based_graph.hpp +++ b/data_structures/node_based_graph.hpp @@ -112,7 +112,7 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector(import_edge.weight), 1); BOOST_ASSERT(edge.data.distance > 0); edge.data.shortcut = false; edge.data.roundabout = import_edge.roundabout; @@ -171,7 +171,7 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector::max()) + if (static_cast(forward_edge.data.distance) != std::numeric_limits::max()) { forward_edge.data.backward = true; edges_list[edge_count++] = forward_edge; @@ -179,11 +179,11 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector::max()) + if (static_cast(forward_edge.data.distance) != std::numeric_limits::max()) { edges_list[edge_count++] = forward_edge; } - if ((int)reverse_edge.data.distance != std::numeric_limits::max()) + if (static_cast(reverse_edge.data.distance) != std::numeric_limits::max()) { edges_list[edge_count++] = reverse_edge; } @@ -252,18 +252,18 @@ SimpleNodeBasedDynamicGraphFromEdges(int number_of_nodes, std::vector(forward_edge.data.capacity) != INVALID_EDGE_WEIGHT) { edges_list[edge_count++] = forward_edge; } } else { // insert seperate edges - if (((int)forward_edge.data.capacity) != INVALID_EDGE_WEIGHT) + if (static_cast(forward_edge.data.capacity) != INVALID_EDGE_WEIGHT) { edges_list[edge_count++] = forward_edge; } - if ((int)reverse_edge.data.capacity != INVALID_EDGE_WEIGHT) + if (static_cast(reverse_edge.data.capacity) != INVALID_EDGE_WEIGHT) { edges_list[edge_count++] = reverse_edge; } diff --git a/data_structures/xor_fast_hash.hpp b/data_structures/xor_fast_hash.hpp index 1f6dc29bb..9e952193d 100644 --- a/data_structures/xor_fast_hash.hpp +++ b/data_structures/xor_fast_hash.hpp @@ -61,8 +61,8 @@ class XORFastHash table2.resize(2 << 16); for (unsigned i = 0; i < (2 << 16); ++i) { - table1[i] = i; - table2[i] = i; + table1[i] = static_cast(i); + table2[i] = static_cast(i); } std::random_shuffle(table1.begin(), table1.end()); std::random_shuffle(table2.begin(), table2.end()); @@ -92,10 +92,10 @@ class XORMiniHash table4.resize(1 << 8); for (unsigned i = 0; i < (1 << 8); ++i) { - table1[i] = i; - table2[i] = i; - table3[i] = i; - table4[i] = i; + table1[i] = static_cast(i); + table2[i] = static_cast(i); + table3[i] = static_cast(i); + table4[i] = static_cast(i); } std::random_shuffle(table1.begin(), table1.end()); std::random_shuffle(table2.begin(), table2.end()); From 25fb985af883d1056ded20b309b00cf07bbe16e3 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 10 Feb 2015 12:02:13 +0100 Subject: [PATCH 181/360] fix warning: use of old-style cast --- algorithms/object_encoder.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/algorithms/object_encoder.hpp b/algorithms/object_encoder.hpp index 5a1e75309..c7f6f1fab 100644 --- a/algorithms/object_encoder.hpp +++ b/algorithms/object_encoder.hpp @@ -51,7 +51,7 @@ struct ObjectEncoder template static void EncodeToBase64(const ObjectT &object, std::string &encoded) { - const char *char_ptr_to_object = (const char *)&object; + const char *char_ptr_to_object = reinterpret_cast(&object); std::vector data(sizeof(object)); std::copy(char_ptr_to_object, char_ptr_to_object + sizeof(ObjectT), data.begin()); @@ -80,7 +80,7 @@ struct ObjectEncoder replaceAll(encoded, "_", "/"); std::copy(binary_t(encoded.begin()), binary_t(encoded.begin() + encoded.length() - 1), - (char *)&object); + reinterpret_cast(&object)); } catch (...) { From 1ff8b62bf5c026fb206f20f06553563cd9941ce1 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 10 Feb 2015 12:03:23 +0100 Subject: [PATCH 182/360] fix warning: extra ';' after member function definition --- routing_algorithms/routing_base.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routing_algorithms/routing_base.hpp b/routing_algorithms/routing_base.hpp index 67dd2f5a8..89e152f12 100644 --- a/routing_algorithms/routing_base.hpp +++ b/routing_algorithms/routing_base.hpp @@ -56,7 +56,7 @@ template class BasicRoutingInterface BasicRoutingInterface() = delete; BasicRoutingInterface(const BasicRoutingInterface &) = delete; explicit BasicRoutingInterface(DataFacadeT *facade) : facade(facade) {} - virtual ~BasicRoutingInterface(){}; + virtual ~BasicRoutingInterface() {} inline void RoutingStep(SearchEngineData::QueryHeap &forward_heap, SearchEngineData::QueryHeap &reverse_heap, From 00e8caa0e35e5bff14924f5bc1cc056c1bb4dd1d Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 10 Feb 2015 12:08:17 +0100 Subject: [PATCH 183/360] fix signed/unsigned comparisons and casts --- data_structures/edge_based_node.hpp | 114 ++++++++++++---------------- 1 file changed, 47 insertions(+), 67 deletions(-) diff --git a/data_structures/edge_based_node.hpp b/data_structures/edge_based_node.hpp index 2566efffb..b5bc7b176 100644 --- a/data_structures/edge_based_node.hpp +++ b/data_structures/edge_based_node.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -39,86 +39,66 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct EdgeBasedNode { - EdgeBasedNode() : - forward_edge_based_node_id(SPECIAL_NODEID), - reverse_edge_based_node_id(SPECIAL_NODEID), - u(SPECIAL_NODEID), - v(SPECIAL_NODEID), - name_id(0), - forward_weight(INVALID_EDGE_WEIGHT >> 1), - reverse_weight(INVALID_EDGE_WEIGHT >> 1), - forward_offset(0), - reverse_offset(0), - packed_geometry_id(SPECIAL_EDGEID), - component_id(-1), - fwd_segment_position( std::numeric_limits::max() ), - forward_travel_mode(TRAVEL_MODE_INACCESSIBLE), - backward_travel_mode(TRAVEL_MODE_INACCESSIBLE) - { } + EdgeBasedNode() + : forward_edge_based_node_id(SPECIAL_NODEID), reverse_edge_based_node_id(SPECIAL_NODEID), + u(SPECIAL_NODEID), v(SPECIAL_NODEID), name_id(0), + forward_weight(INVALID_EDGE_WEIGHT >> 1), reverse_weight(INVALID_EDGE_WEIGHT >> 1), + forward_offset(0), reverse_offset(0), packed_geometry_id(SPECIAL_EDGEID), + component_id(-1), fwd_segment_position(std::numeric_limits::max()), + forward_travel_mode(TRAVEL_MODE_INACCESSIBLE), + backward_travel_mode(TRAVEL_MODE_INACCESSIBLE) + { + } - explicit EdgeBasedNode( - NodeID forward_edge_based_node_id, - NodeID reverse_edge_based_node_id, - NodeID u, - NodeID v, - unsigned name_id, - int forward_weight, - int reverse_weight, - int forward_offset, - int reverse_offset, - unsigned packed_geometry_id, - unsigned component_id, - unsigned short fwd_segment_position, - TravelMode forward_travel_mode, - TravelMode backward_travel_mode - ) : - forward_edge_based_node_id(forward_edge_based_node_id), - reverse_edge_based_node_id(reverse_edge_based_node_id), - u(u), - v(v), - name_id(name_id), - forward_weight(forward_weight), - reverse_weight(reverse_weight), - forward_offset(forward_offset), - reverse_offset(reverse_offset), - packed_geometry_id(packed_geometry_id), - component_id(component_id), - fwd_segment_position(fwd_segment_position), - forward_travel_mode(forward_travel_mode), - backward_travel_mode(backward_travel_mode) + explicit EdgeBasedNode(NodeID forward_edge_based_node_id, + NodeID reverse_edge_based_node_id, + NodeID u, + NodeID v, + unsigned name_id, + int forward_weight, + int reverse_weight, + int forward_offset, + int reverse_offset, + unsigned packed_geometry_id, + unsigned component_id, + unsigned short fwd_segment_position, + TravelMode forward_travel_mode, + TravelMode backward_travel_mode) + : forward_edge_based_node_id(forward_edge_based_node_id), + reverse_edge_based_node_id(reverse_edge_based_node_id), u(u), v(v), name_id(name_id), + forward_weight(forward_weight), reverse_weight(reverse_weight), + forward_offset(forward_offset), reverse_offset(reverse_offset), + packed_geometry_id(packed_geometry_id), component_id(component_id), + fwd_segment_position(fwd_segment_position), forward_travel_mode(forward_travel_mode), + backward_travel_mode(backward_travel_mode) { BOOST_ASSERT((forward_edge_based_node_id != SPECIAL_NODEID) || (reverse_edge_based_node_id != SPECIAL_NODEID)); } - static inline FixedPointCoordinate Centroid(const FixedPointCoordinate & a, const FixedPointCoordinate & b) + static inline FixedPointCoordinate Centroid(const FixedPointCoordinate &a, + const FixedPointCoordinate &b) { FixedPointCoordinate centroid; - //The coordinates of the midpoint are given by: - centroid.lat = (a.lat + b.lat)/2; - centroid.lon = (a.lon + b.lon)/2; + // The coordinates of the midpoint are given by: + centroid.lat = (a.lat + b.lat) / 2; + centroid.lon = (a.lon + b.lon) / 2; return centroid; } - bool IsCompressed() const - { - return packed_geometry_id != SPECIAL_EDGEID; - } + bool IsCompressed() const { return packed_geometry_id != SPECIAL_EDGEID; } - bool is_in_tiny_cc() const - { - return 0 != component_id; - } + bool is_in_tiny_cc() const { return 0 != component_id; } NodeID forward_edge_based_node_id; // needed for edge-expanded graph NodeID reverse_edge_based_node_id; // needed for edge-expanded graph - NodeID u; // indices into the coordinates array - NodeID v; // indices into the coordinates array - unsigned name_id; // id of the edge name - int forward_weight; // weight of the edge - int reverse_weight; // weight in the other direction (may be different) - int forward_offset; // prefix sum of the weight up the edge TODO: short must suffice - int reverse_offset; // prefix sum of the weight from the edge TODO: short must suffice + NodeID u; // indices into the coordinates array + NodeID v; // indices into the coordinates array + unsigned name_id; // id of the edge name + int forward_weight; // weight of the edge + int reverse_weight; // weight in the other direction (may be different) + int forward_offset; // prefix sum of the weight up the edge TODO: short must suffice + int reverse_offset; // prefix sum of the weight from the edge TODO: short must suffice unsigned packed_geometry_id; // if set, then the edge represents a packed geometry unsigned component_id; unsigned short fwd_segment_position; // segment id in a compressed geometry @@ -126,4 +106,4 @@ struct EdgeBasedNode TravelMode backward_travel_mode : 4; }; -#endif //EDGE_BASED_NODE_HPP +#endif // EDGE_BASED_NODE_HPP From 539b9be1d34d80fdf99a588f34953eaaecbb6cae Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 10 Feb 2015 12:12:05 +0100 Subject: [PATCH 184/360] fix warning: use of old-style cast --- algorithms/crc32_processor.hpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/algorithms/crc32_processor.hpp b/algorithms/crc32_processor.hpp index a68514dce..de5b8f67f 100644 --- a/algorithms/crc32_processor.hpp +++ b/algorithms/crc32_processor.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -49,7 +49,7 @@ class IteratorbasedCRC32 while (iter != end) { using value_type = typename std::iterator_traits::value_type; - char *data = (char *)(&(*iter)); + char *data = reinterpret_cast(&(*iter)); if (use_hardware_implementation) { @@ -96,7 +96,7 @@ class IteratorbasedCRC32 ++p; } - str = (char *)p; + str = reinterpret_cast(p); while (r--) { __asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;" @@ -131,8 +131,7 @@ class IteratorbasedCRC32 struct RangebasedCRC32 { - template - unsigned operator()(const Iteratable &iterable) + template unsigned operator()(const Iteratable &iterable) { return crc32(std::begin(iterable), std::end(iterable)); } From 2c773750c7e54d13c1dcaac02fb0879f87285488 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 10 Feb 2015 12:26:57 +0100 Subject: [PATCH 185/360] fix const correctness --- algorithms/crc32_processor.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/algorithms/crc32_processor.hpp b/algorithms/crc32_processor.hpp index de5b8f67f..2a9d6ad6b 100644 --- a/algorithms/crc32_processor.hpp +++ b/algorithms/crc32_processor.hpp @@ -49,7 +49,7 @@ class IteratorbasedCRC32 while (iter != end) { using value_type = typename std::iterator_traits::value_type; - char *data = reinterpret_cast(&(*iter)); + const char *data = reinterpret_cast(&(*iter)); if (use_hardware_implementation) { @@ -73,14 +73,14 @@ class IteratorbasedCRC32 return sse42_found; } - unsigned compute_in_software(char *str, unsigned len) + unsigned compute_in_software(const char *str, unsigned len) { crc_processor.process_bytes(str, len); return crc_processor.checksum(); } // adapted from http://byteworm.com/2010/10/13/crc32/ - unsigned compute_in_hardware(char *str, unsigned len) + unsigned compute_in_hardware(const char *str, unsigned len) { #if defined(__x86_64__) unsigned q = len / sizeof(unsigned); From b6314e0c73bd3fd572fd1e3229168f384af5f9d7 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 10 Feb 2015 12:27:27 +0100 Subject: [PATCH 186/360] remove unnecessary casts in debug build --- routing_algorithms/shortest_path.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/routing_algorithms/shortest_path.hpp b/routing_algorithms/shortest_path.hpp index 8282aa25f..6b6f98277 100644 --- a/routing_algorithms/shortest_path.hpp +++ b/routing_algorithms/shortest_path.hpp @@ -236,8 +236,8 @@ class ShortestPathRouting final : public BasicRoutingInterface std::vector temporary_packed_leg1; std::vector temporary_packed_leg2; - BOOST_ASSERT((unsigned)current_leg < packed_legs1.size()); - BOOST_ASSERT((unsigned)current_leg < packed_legs2.size()); + BOOST_ASSERT(current_leg < packed_legs1.size()); + BOOST_ASSERT(current_leg < packed_legs2.size()); if (INVALID_EDGE_WEIGHT != local_upper_bound1) { From b865bea48227f92add430f416af47c90dd9a164c Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 10 Feb 2015 12:29:52 +0100 Subject: [PATCH 187/360] fix floating point comparison, remove superflous inline keywords --- data_structures/rectangle.hpp | 138 ++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 65 deletions(-) diff --git a/data_structures/rectangle.hpp b/data_structures/rectangle.hpp index 110f22794..06c4b08ed 100644 --- a/data_structures/rectangle.hpp +++ b/data_structures/rectangle.hpp @@ -39,15 +39,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // TODO: Make template type, add tests struct RectangleInt2D { - RectangleInt2D() : min_lon(std::numeric_limits::max()), - max_lon(std::numeric_limits::min()), - min_lat(std::numeric_limits::max()), - max_lat(std::numeric_limits::min()) {} + RectangleInt2D() + : min_lon(std::numeric_limits::max()), + max_lon(std::numeric_limits::min()), + min_lat(std::numeric_limits::max()), max_lat(std::numeric_limits::min()) + { + } int32_t min_lon, max_lon; int32_t min_lat, max_lat; - inline void MergeBoundingBoxes(const RectangleInt2D &other) + void MergeBoundingBoxes(const RectangleInt2D &other) { min_lon = std::min(min_lon, other.min_lon); max_lon = std::max(max_lon, other.max_lon); @@ -59,7 +61,7 @@ struct RectangleInt2D BOOST_ASSERT(max_lon != std::numeric_limits::min()); } - inline FixedPointCoordinate Centroid() const + FixedPointCoordinate Centroid() const { FixedPointCoordinate centroid; // The coordinates of the midpoints are given by: @@ -69,7 +71,7 @@ struct RectangleInt2D return centroid; } - inline bool Intersects(const RectangleInt2D &other) const + bool Intersects(const RectangleInt2D &other) const { FixedPointCoordinate upper_left(other.max_lat, other.min_lon); FixedPointCoordinate upper_right(other.max_lat, other.max_lon); @@ -80,7 +82,7 @@ struct RectangleInt2D Contains(lower_left)); } - inline float GetMinDist(const FixedPointCoordinate &location) const + float GetMinDist(const FixedPointCoordinate &location) const { const bool is_contained = Contains(location); if (is_contained) @@ -90,66 +92,74 @@ struct RectangleInt2D enum Direction { - INVALID = 0, - NORTH = 1, - SOUTH = 2, - EAST = 4, + INVALID = 0, + NORTH = 1, + SOUTH = 2, + EAST = 4, NORTH_EAST = 5, SOUTH_EAST = 6, - WEST = 8, + WEST = 8, NORTH_WEST = 9, SOUTH_WEST = 10 }; Direction d = INVALID; if (location.lat > max_lat) - d = (Direction) (d | NORTH); + d = (Direction)(d | NORTH); else if (location.lat < min_lat) - d = (Direction) (d | SOUTH); + d = (Direction)(d | SOUTH); if (location.lon > max_lon) - d = (Direction) (d | EAST); + d = (Direction)(d | EAST); else if (location.lon < min_lon) - d = (Direction) (d | WEST); + d = (Direction)(d | WEST); BOOST_ASSERT(d != INVALID); float min_dist = std::numeric_limits::max(); switch (d) { - case NORTH: - min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(max_lat, location.lon)); - break; - case SOUTH: - min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(min_lat, location.lon)); - break; - case WEST: - min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(location.lat, min_lon)); - break; - case EAST: - min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(location.lat, max_lon)); - break; - case NORTH_EAST: - min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(max_lat, max_lon)); - break; - case NORTH_WEST: - min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(max_lat, min_lon)); - break; - case SOUTH_EAST: - min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(min_lat, max_lon)); - break; - case SOUTH_WEST: - min_dist = coordinate_calculation::euclidean_distance(location, FixedPointCoordinate(min_lat, min_lon)); - break; - default: - break; + case NORTH: + min_dist = coordinate_calculation::euclidean_distance( + location, FixedPointCoordinate(max_lat, location.lon)); + break; + case SOUTH: + min_dist = coordinate_calculation::euclidean_distance( + location, FixedPointCoordinate(min_lat, location.lon)); + break; + case WEST: + min_dist = coordinate_calculation::euclidean_distance( + location, FixedPointCoordinate(location.lat, min_lon)); + break; + case EAST: + min_dist = coordinate_calculation::euclidean_distance( + location, FixedPointCoordinate(location.lat, max_lon)); + break; + case NORTH_EAST: + min_dist = coordinate_calculation::euclidean_distance( + location, FixedPointCoordinate(max_lat, max_lon)); + break; + case NORTH_WEST: + min_dist = coordinate_calculation::euclidean_distance( + location, FixedPointCoordinate(max_lat, min_lon)); + break; + case SOUTH_EAST: + min_dist = coordinate_calculation::euclidean_distance( + location, FixedPointCoordinate(min_lat, max_lon)); + break; + case SOUTH_WEST: + min_dist = coordinate_calculation::euclidean_distance( + location, FixedPointCoordinate(min_lat, min_lon)); + break; + default: + break; } - BOOST_ASSERT(min_dist != std::numeric_limits::max()); + BOOST_ASSERT(min_dist < std::numeric_limits::max()); return min_dist; } - inline float GetMinMaxDist(const FixedPointCoordinate &location) const + float GetMinMaxDist(const FixedPointCoordinate &location) const { float min_max_dist = std::numeric_limits::max(); // Get minmax distance to each of the four sides @@ -158,38 +168,36 @@ struct RectangleInt2D const FixedPointCoordinate lower_right(min_lat, max_lon); const FixedPointCoordinate lower_left(min_lat, min_lon); - min_max_dist = std::min( - min_max_dist, - std::max( - coordinate_calculation::euclidean_distance(location, upper_left), - coordinate_calculation::euclidean_distance(location, upper_right))); + min_max_dist = + std::min(min_max_dist, + std::max(coordinate_calculation::euclidean_distance(location, upper_left), + coordinate_calculation::euclidean_distance(location, upper_right))); - min_max_dist = std::min( - min_max_dist, - std::max( - coordinate_calculation::euclidean_distance(location, upper_right), - coordinate_calculation::euclidean_distance(location, lower_right))); + min_max_dist = + std::min(min_max_dist, + std::max(coordinate_calculation::euclidean_distance(location, upper_right), + coordinate_calculation::euclidean_distance(location, lower_right))); - min_max_dist = std::min( - min_max_dist, - std::max(coordinate_calculation::euclidean_distance(location, lower_right), - coordinate_calculation::euclidean_distance(location, lower_left))); + min_max_dist = + std::min(min_max_dist, + std::max(coordinate_calculation::euclidean_distance(location, lower_right), + coordinate_calculation::euclidean_distance(location, lower_left))); - min_max_dist = std::min( - min_max_dist, - std::max(coordinate_calculation::euclidean_distance(location, lower_left), - coordinate_calculation::euclidean_distance(location, upper_left))); + min_max_dist = + std::min(min_max_dist, + std::max(coordinate_calculation::euclidean_distance(location, lower_left), + coordinate_calculation::euclidean_distance(location, upper_left))); return min_max_dist; } - inline bool Contains(const FixedPointCoordinate &location) const + bool Contains(const FixedPointCoordinate &location) const { const bool lats_contained = (location.lat >= min_lat) && (location.lat <= max_lat); const bool lons_contained = (location.lon >= min_lon) && (location.lon <= max_lon); return lats_contained && lons_contained; } - inline friend std::ostream &operator<<(std::ostream &out, const RectangleInt2D &rect) + friend std::ostream &operator<<(std::ostream &out, const RectangleInt2D &rect) { out << rect.min_lat / COORDINATE_PRECISION << "," << rect.min_lon / COORDINATE_PRECISION << " " << rect.max_lat / COORDINATE_PRECISION << "," From 56b6d928b62fcfdc8a4fd9ff68adefb17577b5e8 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 10 Feb 2015 12:34:13 +0100 Subject: [PATCH 188/360] add include to be self-sufficient --- data_structures/rectangle.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data_structures/rectangle.hpp b/data_structures/rectangle.hpp index 06c4b08ed..c36074dbd 100644 --- a/data_structures/rectangle.hpp +++ b/data_structures/rectangle.hpp @@ -32,6 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include + #include #include #include From 9931155c689575c514edf96def92b97ac22fd7c3 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 10 Feb 2015 18:02:23 +0100 Subject: [PATCH 189/360] port make_unique from libcxx --- util/make_unique.hpp | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/util/make_unique.hpp b/util/make_unique.hpp index b88145d17..e670ffd4d 100644 --- a/util/make_unique.hpp +++ b/util/make_unique.hpp @@ -34,24 +34,40 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace osrm { -// Taken from http://msdn.microsoft.com/en-us/library/dn439780.asp -// Note, that the snippet was broken there and needed minor massaging +// Implement make_unique according to N3656. Taken from libcxx's implementation -// make_unique -template std::unique_ptr make_unique(Types &&... Args) +/// \brief Constructs a `new T()` with the given args and returns a +/// `unique_ptr` which owns the object. +/// +/// Example: +/// +/// auto p = make_unique(); +/// auto p = make_unique>(0, 1); +template +typename std::enable_if::value, std::unique_ptr>::type +make_unique(Args &&... args) { - return (std::unique_ptr(new T(std::forward(Args)...))); + return std::unique_ptr(new T(std::forward(args)...)); } -// make_unique -template std::unique_ptr make_unique(std::size_t Size) +/// \brief Constructs a `new T[n]` with the given args and returns a +/// `unique_ptr` which owns the object. +/// +/// \param n size of the new array. +/// +/// Example: +/// +/// auto p = make_unique(2); // value-initializes the array with 0's. +template +typename std::enable_if::value && std::extent::value == 0, + std::unique_ptr>::type +make_unique(size_t n) { - return (std::unique_ptr(new T[Size]())); + return std::unique_ptr(new typename std::remove_extent::type[n]()); } -// make_unique disallowed -template -typename std::enable_if::value != 0, void>::type make_unique(Types &&...) = delete; +/// This function isn't used and is only here to provide better compile errors. +template +typename std::enable_if::value != 0>::type make_unique(Args &&...) = delete; } - #endif // MAKE_UNIQUE_H_ From 85ab2425a8ef3c7ed4281c89e26ccfc8a17dfb60 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 11 Feb 2015 11:47:25 +0100 Subject: [PATCH 190/360] move travis notifications to slack --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 493cf27e3..cb0ffcc01 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,6 +46,7 @@ env: - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5000 OSRM_TIMEOUT=60 - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5010 OSRM_TIMEOUT=60 notifications: + slack: mapbox:cBzPx49r0dcpxSghmUfG3Wio irc: channels: - irc.oftc.net#osrm From f9e9bb887086cf9ab0c0beb3948fc8409ec76e30 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 11 Feb 2015 13:22:18 +0100 Subject: [PATCH 191/360] update slack channel --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cb0ffcc01..a163e0352 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,7 +46,7 @@ env: - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5000 OSRM_TIMEOUT=60 - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5010 OSRM_TIMEOUT=60 notifications: - slack: mapbox:cBzPx49r0dcpxSghmUfG3Wio + slack: mapbox:4A6euphDwfxAQnhLurXbu6A1 irc: channels: - irc.oftc.net#osrm From 6d9cd504a0c1b3dec325f174bc7ed809edd533d0 Mon Sep 17 00:00:00 2001 From: Neil Buckman Date: Thu, 12 Feb 2015 08:01:46 +0000 Subject: [PATCH 192/360] Made the request parser a member of the Connection Previously, the request parser was created on demand...but this could cause requests to be flagged as bad requests if the string length was large enough to cause the string to be split up into chunks by boost's read_some method. --- server/connection.cpp | 4 +++- server/connection.hpp | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/server/connection.cpp b/server/connection.cpp index 0f16f465f..aee7f4e56 100644 --- a/server/connection.cpp +++ b/server/connection.cpp @@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "connection.hpp" #include "request_handler.hpp" #include "request_parser.hpp" +//#include "../util/simple_logger.hpp" #include #include @@ -68,7 +69,7 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t compression_type compression_type(no_compression); osrm::tribool result; std::tie(result, compression_type) = - RequestParser().parse(current_request, incoming_data_buffer.data(), + request_parser.parse(current_request, incoming_data_buffer.data(), incoming_data_buffer.data() + bytes_transferred); // the request has been parsed @@ -126,6 +127,7 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t else { // we don't have a result yet, so continue reading + //SimpleLogger().Write(logDEBUG) << "Continue reading..."; TCP_socket.async_read_some( boost::asio::buffer(incoming_data_buffer), strand.wrap(boost::bind(&Connection::handle_read, this->shared_from_this(), diff --git a/server/connection.hpp b/server/connection.hpp index d549f6e44..119289080 100644 --- a/server/connection.hpp +++ b/server/connection.hpp @@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "http/compression_type.hpp" #include "http/reply.hpp" #include "http/request.hpp" +#include "request_parser.hpp" #include #include @@ -82,6 +83,7 @@ class Connection : public std::enable_shared_from_this boost::asio::io_service::strand strand; boost::asio::ip::tcp::socket TCP_socket; RequestHandler &request_handler; + RequestParser request_parser; boost::array incoming_data_buffer; request current_request; reply current_reply; From fa638ae3a051ffd7fa479349db09199fdb691103 Mon Sep 17 00:00:00 2001 From: Neil Buckman Date: Thu, 12 Feb 2015 09:55:13 +0000 Subject: [PATCH 193/360] Removed debug logging --- server/connection.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/connection.cpp b/server/connection.cpp index aee7f4e56..9d8b7a76e 100644 --- a/server/connection.cpp +++ b/server/connection.cpp @@ -28,7 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "connection.hpp" #include "request_handler.hpp" #include "request_parser.hpp" -//#include "../util/simple_logger.hpp" #include #include @@ -127,7 +126,6 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t else { // we don't have a result yet, so continue reading - //SimpleLogger().Write(logDEBUG) << "Continue reading..."; TCP_socket.async_read_some( boost::asio::buffer(incoming_data_buffer), strand.wrap(boost::bind(&Connection::handle_read, this->shared_from_this(), From 25c52b74824ebc9c9e1ecd8010a771034498d287 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 12 Feb 2015 15:02:16 +0100 Subject: [PATCH 194/360] rewrite sort/unique function to be more generic --- util/container.hpp | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/util/container.hpp b/util/container.hpp index a35d56a6d..41c8821f8 100644 --- a/util/container.hpp +++ b/util/container.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CONTAINER_HPP_ -#define CONTAINER_HPP_ +#ifndef CONTAINER_HPP +#define CONTAINER_HPP #include #include @@ -34,12 +34,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace osrm { -template void sort_unique_resize(std::vector &vector) +namespace detail { - std::sort(vector.begin(), vector.end()); +// Culled by SFINAE if reserve does not exist or is not accessible +template constexpr auto has_resize_method(T &t) -> decltype(t.resize(0), bool()) +{ + return true; +} + +// Used as fallback when SFINAE culls the template method +constexpr bool has_resize_method(...) { return false; } +} + +template void sort_unique_resize(Container &vector) +{ + std::sort(std::begin(vector), std::end(vector)); const auto number_of_unique_elements = - std::unique(vector.begin(), vector.end()) - vector.begin(); - vector.resize(number_of_unique_elements); + std::unique(std::begin(vector), std::end(vector)) - std::begin(vector); + if (detail::has_resize_method(vector)) + { + vector.resize(number_of_unique_elements); + } } // template inline void sort_unique_resize_shrink_vector(std::vector &vector) @@ -82,4 +97,4 @@ Function for_each_pair(ContainerT &container, Function function) return for_each_pair(std::begin(container), std::end(container), function); } } -#endif /* CONTAINER_HPP_ */ +#endif /* CONTAINER_HPP */ From a1d4798ded40317221162f07ab37026daf4add4a Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 12 Feb 2015 15:03:53 +0100 Subject: [PATCH 195/360] refactor AlternativePathRouting step to have the same interface semantics regardless of search direction --- routing_algorithms/alternative_path.hpp | 65 +++++++++++++------------ 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/routing_algorithms/alternative_path.hpp b/routing_algorithms/alternative_path.hpp index e3a81251b..5bbc1e067 100644 --- a/routing_algorithms/alternative_path.hpp +++ b/routing_algorithms/alternative_path.hpp @@ -156,7 +156,7 @@ class AlternativeRouting final : private BasicRoutingInterface } if (0 < reverse_heap1.Size()) { - AlternativeRoutingStep(reverse_heap1, forward_heap1, &middle_node, + AlternativeRoutingStep(forward_heap1, reverse_heap1, &middle_node, &upper_bound_to_shortest_path_distance, via_node_candidate_list, reverse_search_space, min_edge_offset); @@ -351,13 +351,13 @@ class AlternativeRouting final : private BasicRoutingInterface private: // unpack alternate by exploring search spaces from v - inline void RetrievePackedAlternatePath(const QueryHeap &forward_heap1, - const QueryHeap &reverse_heap1, - const QueryHeap &forward_heap2, - const QueryHeap &reverse_heap2, - const NodeID s_v_middle, - const NodeID v_t_middle, - std::vector &packed_path) const + void RetrievePackedAlternatePath(const QueryHeap &forward_heap1, + const QueryHeap &reverse_heap1, + const QueryHeap &forward_heap2, + const QueryHeap &reverse_heap2, + const NodeID s_v_middle, + const NodeID v_t_middle, + std::vector &packed_path) const { // fetch packed path [s,v) std::vector packed_v_t_path; @@ -375,11 +375,11 @@ class AlternativeRouting final : private BasicRoutingInterface // compute and unpack and by exploring search spaces // from v and intersecting against queues. only half-searches have to be // done at this stage - inline void ComputeLengthAndSharingOfViaPath(const NodeID via_node, - int *real_length_of_via_path, - int *sharing_of_via_path, - const std::vector &packed_shortest_path, - const EdgeWeight min_edge_offset) + void ComputeLengthAndSharingOfViaPath(const NodeID via_node, + int *real_length_of_via_path, + int *sharing_of_via_path, + const std::vector &packed_shortest_path, + const EdgeWeight min_edge_offset) { engine_working_data.InitializeOrClearSecondThreadLocalStorage( super::facade->GetNumberOfNodes()); @@ -522,7 +522,7 @@ class AlternativeRouting final : private BasicRoutingInterface // variable } - // inline int approximateAmountOfSharing( + // int approximateAmountOfSharing( // const NodeID alternate_path_middle_node_id, // QueryHeap & forward_heap, // QueryHeap & reverse_heap, @@ -569,14 +569,17 @@ class AlternativeRouting final : private BasicRoutingInterface // todo: reorder parameters template - inline void AlternativeRoutingStep(QueryHeap &forward_heap, - QueryHeap &reverse_heap, - NodeID *middle_node, - int *upper_bound_to_shortest_path_distance, - std::vector &search_space_intersection, - std::vector &search_space, - const EdgeWeight min_edge_offset) const + void AlternativeRoutingStep(QueryHeap &heap1, + QueryHeap &heap2, + NodeID *middle_node, + int *upper_bound_to_shortest_path_distance, + std::vector &search_space_intersection, + std::vector &search_space, + const EdgeWeight min_edge_offset) const { + QueryHeap &forward_heap = (is_forward_directed ? heap1 : heap2); + QueryHeap &reverse_heap = (is_forward_directed ? heap2 : heap1); + const NodeID node = forward_heap.DeleteMin(); const int distance = forward_heap.GetKey(node); // const NodeID parentnode = forward_heap.GetData(node).parent; @@ -645,16 +648,16 @@ class AlternativeRouting final : private BasicRoutingInterface } // conduct T-Test - inline bool ViaNodeCandidatePassesTTest(QueryHeap &existing_forward_heap, - QueryHeap &existing_reverse_heap, - QueryHeap &new_forward_heap, - QueryHeap &new_reverse_heap, - const RankedCandidateNode &candidate, - const int length_of_shortest_path, - int *length_of_via_path, - NodeID *s_v_middle, - NodeID *v_t_middle, - const EdgeWeight min_edge_offset) const + bool ViaNodeCandidatePassesTTest(QueryHeap &existing_forward_heap, + QueryHeap &existing_reverse_heap, + QueryHeap &new_forward_heap, + QueryHeap &new_reverse_heap, + const RankedCandidateNode &candidate, + const int length_of_shortest_path, + int *length_of_via_path, + NodeID *s_v_middle, + NodeID *v_t_middle, + const EdgeWeight min_edge_offset) const { new_forward_heap.Clear(); new_reverse_heap.Clear(); From 45838b33b7cb74d2be6e690b5d6ddc0c1b30abdb Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 12 Feb 2015 15:40:55 +0100 Subject: [PATCH 196/360] avoid implicit conversion to int --- descriptors/json_descriptor.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/descriptors/json_descriptor.hpp b/descriptors/json_descriptor.hpp index a87d598cd..676e78d85 100644 --- a/descriptors/json_descriptor.hpp +++ b/descriptors/json_descriptor.hpp @@ -352,7 +352,7 @@ template class JSONDescriptor final : public BaseDescriptor< facade->GetEscapedNameForNameID(segment.name_id)); json_instruction_row.values.push_back(std::round(segment.length)); json_instruction_row.values.push_back(necessary_segments_running_index); - json_instruction_row.values.push_back(round(segment.duration / 10)); + json_instruction_row.values.push_back(std::round(segment.duration / 10.)); json_instruction_row.values.push_back( cast::integral_to_string(static_cast(segment.length)) + "m"); const double bearing_value = (segment.bearing / 10.); From 86d3556c6d141d42fb0e2ae1c8e05dbb165b1b88 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 13 Feb 2015 14:24:05 +0100 Subject: [PATCH 197/360] add ctor that converts from rtree segment to phantom node --- data_structures/phantom_node.hpp | 51 ++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/data_structures/phantom_node.hpp b/data_structures/phantom_node.hpp index 0356e851f..d22cb9504 100644 --- a/data_structures/phantom_node.hpp +++ b/data_structures/phantom_node.hpp @@ -55,6 +55,28 @@ struct PhantomNode PhantomNode(); + template PhantomNode(const OtherT &other, const FixedPointCoordinate &foot_point) + { + forward_node_id = other.forward_edge_based_node_id; + reverse_node_id = other.reverse_edge_based_node_id; + name_id = other.name_id; + + forward_weight = other.forward_weight; + reverse_weight = other.reverse_weight; + + forward_offset = other.forward_offset; + reverse_offset = other.reverse_offset; + + packed_geometry_id = other.packed_geometry_id; + component_id = other.component_id; + + location = foot_point; + fwd_segment_position = other.fwd_segment_position; + + forward_travel_mode = other.forward_travel_mode; + backward_travel_mode = other.backward_travel_mode; + } + NodeID forward_node_id; NodeID reverse_node_id; unsigned name_id; @@ -83,14 +105,13 @@ struct PhantomNode bool is_in_tiny_component() const; - bool operator==(const PhantomNode & other) const; + bool operator==(const PhantomNode &other) const; }; using PhantomNodeArray = std::vector>; class phantom_node_pair : public std::pair { - }; struct PhantomNodeLists @@ -105,26 +126,26 @@ struct PhantomNodes PhantomNode target_phantom; }; -inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn) +inline std::ostream &operator<<(std::ostream &out, const PhantomNodes &pn) { out << "source_coord: " << pn.source_phantom.location << "\n"; out << "target_coord: " << pn.target_phantom.location << std::endl; return out; } -inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn) +inline std::ostream &operator<<(std::ostream &out, const PhantomNode &pn) { - out << "node1: " << pn.forward_node_id << ", " << - "node2: " << pn.reverse_node_id << ", " << - "name: " << pn.name_id << ", " << - "fwd-w: " << pn.forward_weight << ", " << - "rev-w: " << pn.reverse_weight << ", " << - "fwd-o: " << pn.forward_offset << ", " << - "rev-o: " << pn.reverse_offset << ", " << - "geom: " << pn.packed_geometry_id << ", " << - "comp: " << pn.component_id << ", " << - "pos: " << pn.fwd_segment_position << ", " << - "loc: " << pn.location; + out << "node1: " << pn.forward_node_id << ", " + << "node2: " << pn.reverse_node_id << ", " + << "name: " << pn.name_id << ", " + << "fwd-w: " << pn.forward_weight << ", " + << "rev-w: " << pn.reverse_weight << ", " + << "fwd-o: " << pn.forward_offset << ", " + << "rev-o: " << pn.reverse_offset << ", " + << "geom: " << pn.packed_geometry_id << ", " + << "comp: " << pn.component_id << ", " + << "pos: " << pn.fwd_segment_position << ", " + << "loc: " << pn.location; return out; } From e5f12347bda53a0e7c41554c2637360d3564270b Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 13 Feb 2015 14:26:19 +0100 Subject: [PATCH 198/360] simplify code by using new phantom node ctor --- data_structures/static_rtree.hpp | 48 ++++++++++++++------------------ 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/data_structures/static_rtree.hpp b/data_structures/static_rtree.hpp index 5eaf64768..87766cbb8 100644 --- a/data_structures/static_rtree.hpp +++ b/data_structures/static_rtree.hpp @@ -656,8 +656,9 @@ class StaticRTree unsigned number_of_elements_from_big_cc = 0; unsigned number_of_elements_from_tiny_cc = 0; +#ifdef NDEBUG unsigned pruned_elements = 0; - +#endif std::pair projected_coordinate = { mercator::lat2y(input_coordinate.lat / COORDINATE_PRECISION), input_coordinate.lon / COORDINATE_PRECISION}; @@ -701,10 +702,12 @@ class StaticRTree pruning_bound.insert(current_perpendicular_distance); traversal_queue.emplace(current_perpendicular_distance, current_edge); } +#ifdef NDEBUG else { ++pruned_elements; } +#endif } } else @@ -749,14 +752,8 @@ class StaticRTree projected_coordinate, foot_point_coordinate_on_segment, current_ratio); // store phantom node in result vector - result_phantom_node_vector.emplace_back( - current_segment.forward_edge_based_node_id, - current_segment.reverse_edge_based_node_id, current_segment.name_id, - current_segment.forward_weight, current_segment.reverse_weight, - current_segment.forward_offset, current_segment.reverse_offset, - current_segment.packed_geometry_id, current_segment.component_id, - foot_point_coordinate_on_segment, current_segment.fwd_segment_position, - current_segment.forward_travel_mode, current_segment.backward_travel_mode); + result_phantom_node_vector.emplace_back(current_segment, + foot_point_coordinate_on_segment); // Hack to fix rounding errors and wandering via nodes. FixUpRoundingIssue(input_coordinate, result_phantom_node_vector.back()); @@ -784,17 +781,18 @@ class StaticRTree traversal_queue = std::priority_queue{}; } } - // SimpleLogger().Write() << "result_phantom_node_vector.size(): " << - // result_phantom_node_vector.size(); - // SimpleLogger().Write() << "max_number_of_phantom_nodes: " << max_number_of_phantom_nodes; - // SimpleLogger().Write() << "number_of_elements_from_big_cc: " << - // number_of_elements_from_big_cc; - // SimpleLogger().Write() << "number_of_elements_from_tiny_cc: " << - // number_of_elements_from_tiny_cc; - // SimpleLogger().Write() << "inspected_elements: " << inspected_elements; - // SimpleLogger().Write() << "max_checked_elements: " << max_checked_elements; - // SimpleLogger().Write() << "pruned_elements: " << pruned_elements; - +#ifdef NDEBUG +// SimpleLogger().Write() << "result_phantom_node_vector.size(): " << +// result_phantom_node_vector.size(); +// SimpleLogger().Write() << "max_number_of_phantom_nodes: " << max_number_of_phantom_nodes; +// SimpleLogger().Write() << "number_of_elements_from_big_cc: " << +// number_of_elements_from_big_cc; +// SimpleLogger().Write() << "number_of_elements_from_tiny_cc: " << +// number_of_elements_from_tiny_cc; +// SimpleLogger().Write() << "inspected_elements: " << inspected_elements; +// SimpleLogger().Write() << "max_checked_elements: " << max_checked_elements; +// SimpleLogger().Write() << "pruned_elements: " << pruned_elements; +#endif return !result_phantom_node_vector.empty(); } @@ -915,13 +913,9 @@ class StaticRTree !osrm::epsilon_compare(current_perpendicular_distance, current_min_dist)) { // store phantom node in result vector - result_phantom_node_vector.emplace_back( - current_segment.forward_edge_based_node_id, - current_segment.reverse_edge_based_node_id, current_segment.name_id, - current_segment.forward_weight, current_segment.reverse_weight, - current_segment.forward_offset, current_segment.reverse_offset, - current_segment.packed_geometry_id, foot_point_coordinate_on_segment, - current_segment.fwd_segment_position, current_perpendicular_distance); + result_phantom_node_vector.emplace_back(current_segment, + foot_point_coordinate_on_segment, + current_perpendicular_distance); // Hack to fix rounding errors and wandering via nodes. FixUpRoundingIssue(input_coordinate, result_phantom_node_vector.back()); From 9e0916859722acd6e083d4f747a0001b0255cbb9 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 16 Feb 2015 14:18:04 +0100 Subject: [PATCH 199/360] un-lint CMakeLists.txt --- CMakeLists.txt | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2beaa31c3..3bf2f9c1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,12 +23,12 @@ else() message(WARNING "Building on a 32 bit system is unsupported") endif() -if (WIN32 AND MSVC_VERSION LESS 1800) +if(WIN32 AND MSVC_VERSION LESS 1800) message(FATAL_ERROR "Building with Microsoft compiler needs Visual Studio 2013 or later (Express version works too)") endif() -OPTION(WITH_TOOLS "Build OSRM tools" OFF) -OPTION(BUILD_TOOLS "Build OSRM tools" OFF) +option(WITH_TOOLS "Build OSRM tools" OFF) +option(BUILD_TOOLS "Build OSRM tools" OFF) include_directories(${CMAKE_SOURCE_DIR}/include/) include_directories(${CMAKE_SOURCE_DIR}/third_party/) @@ -123,10 +123,10 @@ if(CMAKE_BUILD_TYPE MATCHES Release) # Check if LTO is available set(LTO_FLAGS "") check_cxx_compiler_flag("-flto" LTO_AVAILABLE) - if (LTO_AVAILABLE) + if(LTO_AVAILABLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto") set(CHECK_LTO_SRC "int main(){return 0;}") - CHECK_CXX_SOURCE_COMPILES("${CHECK_LTO_SRC}" LTO_WORKS) + check_cxx_source_compiles("${CHECK_LTO_SRC}" LTO_WORKS) if(LTO_WORKS) message(STATUS "LTO working") else() @@ -135,17 +135,17 @@ if(CMAKE_BUILD_TYPE MATCHES Release) endif() # Since gcc 4.9 the LTO format is non-standart ('slim'), so we need to use the build-in tools - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND NOT "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.9.0" AND NOT MINGW) message(STATUS "Using gcc specific binutils for LTO.") set(CMAKE_AR "/usr/bin/gcc-ar") set(CMAKE_RANLIB "/usr/bin/gcc-ranlib") endif() - endif () + endif() endif() -if (NOT WIN32) -add_definitions(-DBOOST_TEST_DYN_LINK) +if(NOT WIN32) + add_definitions(-DBOOST_TEST_DYN_LINK) endif() # Configuring compilers @@ -155,16 +155,16 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -pedantic -fPIC") elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(COLOR_FLAG "-fdiagnostics-color=auto") - CHECK_CXX_COMPILER_FLAG("-fdiagnostics-color=auto" HAS_COLOR_FLAG) + check_cxx_compiler_flag("-fdiagnostics-color=auto" HAS_COLOR_FLAG) if(NOT HAS_COLOR_FLAG) set(COLOR_FLAG "") endif() # using GCC set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -fPIC ${COLOR_FLAG}") - if (WIN32) # using mingw + if(WIN32) # using mingw add_definitions(-D_USE_MATH_DEFINES) # define M_PI, M_1_PI etc. add_definitions(-DWIN32) - SET(OPTIONAL_SOCKET_LIBS ws2_32 wsock32) + set(OPTIONAL_SOCKET_LIBS ws2_32 wsock32) endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") # using Intel C++ @@ -275,8 +275,8 @@ target_link_libraries(osrm-prepare ${STXXL_LIBRARY}) set(OpenMP_FIND_QUIETLY ON) find_package(OpenMP) if(OPENMP_FOUND) - message(STATUS "OpenMP support found. Linking just in case for stxxl") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + message(STATUS "OpenMP support found. Linking just in case for stxxl") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") endif() find_package(OSMPBF REQUIRED) @@ -355,11 +355,11 @@ install(TARGETS OSRM DESTINATION lib) list(GET Boost_LIBRARIES 1 BOOST_LIBRARY_FIRST) get_filename_component(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_FIRST}" PATH) set(BOOST_LIBRARY_LISTING "-L${BOOST_LIBRARY_LISTING}") -foreach (lib ${Boost_LIBRARIES}) +foreach(lib ${Boost_LIBRARIES}) get_filename_component(BOOST_LIBRARY_NAME "${lib}" NAME_WE) string(REPLACE "lib" "" BOOST_LIBRARY_NAME ${BOOST_LIBRARY_NAME}) set(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_LISTING} -l${BOOST_LIBRARY_NAME}") -endforeach () +endforeach() configure_file(${CMAKE_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY) install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION lib/pkgconfig) From 79b9bdf7ce2771e002c1b3073749642ab2683a72 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 18 Feb 2015 10:46:40 +0100 Subject: [PATCH 200/360] rename JSON namespace to osrm::json to avoid namespace clash with V8 --- algorithms/polyline_formatter.cpp | 10 +++--- algorithms/polyline_formatter.hpp | 4 +-- descriptors/description_factory.cpp | 2 +- descriptors/description_factory.hpp | 2 +- descriptors/descriptor_base.hpp | 2 +- descriptors/gpx_descriptor.hpp | 16 ++++----- descriptors/json_descriptor.hpp | 55 +++++++++++++++-------------- extract.cpp | 2 ++ include/osrm/json_container.hpp | 12 ++++--- library/osrm.hpp | 7 ++-- library/osrm_impl.cpp | 4 +-- library/osrm_impl.hpp | 2 +- plugins/distance_table.hpp | 8 ++--- plugins/hello_world.hpp | 10 +++--- plugins/locate.hpp | 4 +-- plugins/nearest.hpp | 10 +++--- plugins/plugin_base.hpp | 17 +++++---- plugins/timestamp.hpp | 2 +- plugins/viaroute.hpp | 2 +- server/request_handler.cpp | 12 +++---- tools/simpleclient.cpp | 4 +-- util/json_renderer.hpp | 10 +++--- util/string_util.hpp | 2 +- util/xml_renderer.hpp | 8 +++-- 24 files changed, 109 insertions(+), 98 deletions(-) diff --git a/algorithms/polyline_formatter.cpp b/algorithms/polyline_formatter.cpp index 22a1df369..b5dad6c78 100644 --- a/algorithms/polyline_formatter.cpp +++ b/algorithms/polyline_formatter.cpp @@ -32,21 +32,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -JSON::String +osrm::json::String PolylineFormatter::printEncodedString(const std::vector &polyline) const { - return JSON::String(PolylineCompressor().get_encoded_string(polyline)); + return osrm::json::String(PolylineCompressor().get_encoded_string(polyline)); } -JSON::Array +osrm::json::Array PolylineFormatter::printUnencodedString(const std::vector &polyline) const { - JSON::Array json_geometry_array; + osrm::json::Array json_geometry_array; for (const auto &segment : polyline) { if (segment.necessary) { - JSON::Array json_coordinate; + osrm::json::Array json_coordinate; json_coordinate.values.push_back(segment.location.lat / COORDINATE_PRECISION); json_coordinate.values.push_back(segment.location.lon / COORDINATE_PRECISION); json_geometry_array.values.push_back(json_coordinate); diff --git a/algorithms/polyline_formatter.hpp b/algorithms/polyline_formatter.hpp index e4018154d..181a0cf15 100644 --- a/algorithms/polyline_formatter.hpp +++ b/algorithms/polyline_formatter.hpp @@ -37,9 +37,9 @@ struct SegmentInformation; struct PolylineFormatter { - JSON::String printEncodedString(const std::vector &polyline) const; + osrm::json::String printEncodedString(const std::vector &polyline) const; - JSON::Array printUnencodedString(const std::vector &polyline) const; + osrm::json::Array printUnencodedString(const std::vector &polyline) const; }; #endif /* POLYLINE_FORMATTER_HPP */ diff --git a/descriptors/description_factory.cpp b/descriptors/description_factory.cpp index 034dc88ae..4d9918759 100644 --- a/descriptors/description_factory.cpp +++ b/descriptors/description_factory.cpp @@ -98,7 +98,7 @@ void DescriptionFactory::AppendSegment(const FixedPointCoordinate &coordinate, turn, path_point.travel_mode); } -JSON::Value DescriptionFactory::AppendGeometryString(const bool return_encoded) +osrm::json::Value DescriptionFactory::AppendGeometryString(const bool return_encoded) { if (return_encoded) { diff --git a/descriptors/description_factory.hpp b/descriptors/description_factory.hpp index 2b377f687..7f975e030 100644 --- a/descriptors/description_factory.hpp +++ b/descriptors/description_factory.hpp @@ -85,7 +85,7 @@ class DescriptionFactory void SetEndSegment(const PhantomNode &start_phantom, const bool traversed_in_reverse, const bool is_via_location = false); - JSON::Value AppendGeometryString(const bool return_encoded); + osrm::json::Value AppendGeometryString(const bool return_encoded); std::vector const &GetViaIndices() const; double get_entire_length() const { return entire_length; } diff --git a/descriptors/descriptor_base.hpp b/descriptors/descriptor_base.hpp index 815b1d5af..0526047fe 100644 --- a/descriptors/descriptor_base.hpp +++ b/descriptors/descriptor_base.hpp @@ -78,7 +78,7 @@ template class BaseDescriptor BaseDescriptor() {} // Maybe someone can explain the pure virtual destructor thing to me (dennis) virtual ~BaseDescriptor() {} - virtual void Run(const InternalRouteResult &raw_route, JSON::Object &json_result) = 0; + virtual void Run(const InternalRouteResult &raw_route, osrm::json::Object &json_result) = 0; virtual void SetConfig(const DescriptorConfig &c) = 0; }; diff --git a/descriptors/gpx_descriptor.hpp b/descriptors/gpx_descriptor.hpp index 384d2c2e9..deda9c52f 100644 --- a/descriptors/gpx_descriptor.hpp +++ b/descriptors/gpx_descriptor.hpp @@ -41,11 +41,11 @@ template class GPXDescriptor final : public BaseDescriptor class GPXDescriptor final : public BaseDescriptor class GPXDescriptor final : public BaseDescriptor class GPXDescriptor final : public BaseDescriptor class JSONDescriptor final : public BaseDescriptor< return added_element_count; } - virtual void Run(const InternalRouteResult &raw_route, JSON::Object &json_result) override final + virtual void Run(const InternalRouteResult &raw_route, + osrm::json::Object &json_result) override final { if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length) { // We do not need to do much, if there is no route ;-) json_result.values["status"] = 207; json_result.values["status_message"] = "Cannot find route between points"; - // JSON::render(reply.content, json_result); + // osrm::json::render(reply.content, json_result); return; } @@ -139,20 +140,20 @@ template class JSONDescriptor final : public BaseDescriptor< if (config.geometry) { - JSON::Value route_geometry = + osrm::json::Value route_geometry = description_factory.AppendGeometryString(config.encode_geometry); json_result.values["route_geometry"] = route_geometry; } if (config.instructions) { - JSON::Array json_route_instructions; + osrm::json::Array json_route_instructions; BuildTextualDescription(description_factory, json_route_instructions, raw_route.shortest_path_length, shortest_path_segments); json_result.values["route_instructions"] = json_route_instructions; } description_factory.BuildRouteSummary(description_factory.get_entire_length(), raw_route.shortest_path_length); - JSON::Object json_route_summary; + osrm::json::Object json_route_summary; json_route_summary.values["total_distance"] = description_factory.summary.distance; json_route_summary.values["total_time"] = description_factory.summary.duration; json_route_summary.values["start_point"] = @@ -163,8 +164,8 @@ template class JSONDescriptor final : public BaseDescriptor< BOOST_ASSERT(!raw_route.segment_end_coordinates.empty()); - JSON::Array json_via_points_array; - JSON::Array json_first_coordinate; + osrm::json::Array json_via_points_array; + osrm::json::Array json_first_coordinate; json_first_coordinate.values.push_back( raw_route.segment_end_coordinates.front().source_phantom.location.lat / COORDINATE_PRECISION); @@ -175,7 +176,7 @@ template class JSONDescriptor final : public BaseDescriptor< for (const PhantomNodes &nodes : raw_route.segment_end_coordinates) { std::string tmp; - JSON::Array json_coordinate; + osrm::json::Array json_coordinate; json_coordinate.values.push_back(nodes.target_phantom.location.lat / COORDINATE_PRECISION); json_coordinate.values.push_back(nodes.target_phantom.location.lon / @@ -184,7 +185,7 @@ template class JSONDescriptor final : public BaseDescriptor< } json_result.values["via_points"] = json_via_points_array; - JSON::Array json_via_indices_array; + osrm::json::Array json_via_indices_array; std::vector const &shortest_leg_end_indices = description_factory.GetViaIndices(); json_via_indices_array.values.insert(json_via_indices_array.values.end(), @@ -195,7 +196,7 @@ template class JSONDescriptor final : public BaseDescriptor< // only one alternative route is computed at this time, so this is hardcoded if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length) { - json_result.values["found_alternative"] = JSON::True(); + json_result.values["found_alternative"] = osrm::json::True(); BOOST_ASSERT(!raw_route.alt_source_traversed_in_reverse.empty()); alternate_description_factory.SetStartSegment( raw_route.segment_end_coordinates.front().source_phantom, @@ -213,15 +214,15 @@ template class JSONDescriptor final : public BaseDescriptor< if (config.geometry) { - JSON::Value alternate_geometry_string = + osrm::json::Value alternate_geometry_string = alternate_description_factory.AppendGeometryString(config.encode_geometry); - JSON::Array json_alternate_geometries_array; + osrm::json::Array json_alternate_geometries_array; json_alternate_geometries_array.values.push_back(alternate_geometry_string); json_result.values["alternative_geometries"] = json_alternate_geometries_array; } // Generate instructions for each alternative (simulated here) - JSON::Array json_alt_instructions; - JSON::Array json_current_alt_instructions; + osrm::json::Array json_alt_instructions; + osrm::json::Array json_current_alt_instructions; if (config.instructions) { BuildTextualDescription( @@ -234,8 +235,8 @@ template class JSONDescriptor final : public BaseDescriptor< alternate_description_factory.get_entire_length(), raw_route.alternative_path_length); - JSON::Object json_alternate_route_summary; - JSON::Array json_alternate_route_summary_array; + osrm::json::Object json_alternate_route_summary; + osrm::json::Array json_alternate_route_summary_array; json_alternate_route_summary.values["total_distance"] = alternate_description_factory.summary.distance; json_alternate_route_summary.values["total_time"] = @@ -249,7 +250,7 @@ template class JSONDescriptor final : public BaseDescriptor< std::vector const &alternate_leg_end_indices = alternate_description_factory.GetViaIndices(); - JSON::Array json_altenative_indices_array; + osrm::json::Array json_altenative_indices_array; json_altenative_indices_array.values.insert(json_altenative_indices_array.values.end(), alternate_leg_end_indices.begin(), alternate_leg_end_indices.end()); @@ -257,30 +258,30 @@ template class JSONDescriptor final : public BaseDescriptor< } else { - json_result.values["found_alternative"] = JSON::False(); + json_result.values["found_alternative"] = osrm::json::False(); } // Get Names for both routes RouteNames route_names = GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade); - JSON::Array json_route_names; + osrm::json::Array json_route_names; json_route_names.values.push_back(route_names.shortest_path_name_1); json_route_names.values.push_back(route_names.shortest_path_name_2); json_result.values["route_name"] = json_route_names; if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length) { - JSON::Array json_alternate_names_array; - JSON::Array json_alternate_names; + osrm::json::Array json_alternate_names_array; + osrm::json::Array json_alternate_names; json_alternate_names.values.push_back(route_names.alternative_path_name_1); json_alternate_names.values.push_back(route_names.alternative_path_name_2); json_alternate_names_array.values.push_back(json_alternate_names); json_result.values["alternative_names"] = json_alternate_names_array; } - JSON::Object json_hint_object; + osrm::json::Object json_hint_object; json_hint_object.values["checksum"] = facade->GetCheckSum(); - JSON::Array json_location_hint_array; + osrm::json::Array json_location_hint_array; std::string hint; for (const auto i : osrm::irange(0, raw_route.segment_end_coordinates.size())) { @@ -296,14 +297,14 @@ template class JSONDescriptor final : public BaseDescriptor< // render the content to the output array // TIMER_START(route_render); - // JSON::render(reply.content, json_result); + // osrm::json::render(reply.content, json_result); // TIMER_STOP(route_render); // SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render); } // TODO: reorder parameters inline void BuildTextualDescription(DescriptionFactory &description_factory, - JSON::Array &json_instruction_array, + osrm::json::Array &json_instruction_array, const int route_length, std::vector &route_segments_list) { @@ -317,7 +318,7 @@ template class JSONDescriptor final : public BaseDescriptor< // Fetch data from Factory and generate a string from it. for (const SegmentInformation &segment : description_factory.path_description) { - JSON::Array json_instruction_row; + osrm::json::Array json_instruction_row; TurnInstruction current_instruction = segment.turn_instruction; entered_restricted_area_count += (current_instruction != segment.turn_instruction); if (TurnInstructionsClass::TurnIsNecessary(current_instruction)) @@ -377,7 +378,7 @@ template class JSONDescriptor final : public BaseDescriptor< } } - JSON::Array json_last_instruction_row; + osrm::json::Array json_last_instruction_row; temp_instruction = cast::integral_to_string( cast::enum_to_underlying(TurnInstruction::ReachedYourDestination)); json_last_instruction_row.values.push_back(temp_instruction); diff --git a/extract.cpp b/extract.cpp index b1f30a6ad..cb953a566 100644 --- a/extract.cpp +++ b/extract.cpp @@ -31,6 +31,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include + int main(int argc, char *argv[]) { try diff --git a/include/osrm/json_container.hpp b/include/osrm/json_container.hpp index 9bbbec433..4ec164965 100644 --- a/include/osrm/json_container.hpp +++ b/include/osrm/json_container.hpp @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // based on // https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp -#ifndef JSON_CONTAINER_H -#define JSON_CONTAINER_H +#ifndef JSON_CONTAINER_HPP +#define JSON_CONTAINER_HPP #include @@ -38,7 +38,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -namespace JSON +namespace osrm +{ +namespace json { struct Object; @@ -90,5 +92,5 @@ struct Array }; } // namespace JSON - -#endif // JSON_CONTAINER_H +} // namespace osrm +#endif // JSON_CONTAINER_HPP diff --git a/library/osrm.hpp b/library/osrm.hpp index 571297d06..dd7ffd749 100644 --- a/library/osrm.hpp +++ b/library/osrm.hpp @@ -35,10 +35,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. class OSRM_impl; struct RouteParameters; -namespace JSON +namespace osrm +{ +namespace json { struct Object; } +} class OSRM { @@ -48,7 +51,7 @@ class OSRM public: explicit OSRM(libosrm_config &lib_config); ~OSRM(); - int RunQuery(RouteParameters &route_parameters, JSON::Object &json_result); + int RunQuery(RouteParameters &route_parameters, osrm::json::Object &json_result); }; #endif // OSRM_HPP diff --git a/library/osrm_impl.cpp b/library/osrm_impl.cpp index aea85a44c..0aec3f15c 100644 --- a/library/osrm_impl.cpp +++ b/library/osrm_impl.cpp @@ -104,7 +104,7 @@ void OSRM_impl::RegisterPlugin(BasePlugin *plugin) plugin_map.emplace(plugin->GetDescriptor(), plugin); } -int OSRM_impl::RunQuery(RouteParameters &route_parameters, JSON::Object &json_result) +int OSRM_impl::RunQuery(RouteParameters &route_parameters, osrm::json::Object &json_result) { const auto &plugin_iterator = plugin_map.find(route_parameters.service); @@ -172,7 +172,7 @@ OSRM::OSRM(libosrm_config &lib_config) : OSRM_pimpl_(osrm::make_uniqueRunQuery(route_parameters, json_result); } diff --git a/library/osrm_impl.hpp b/library/osrm_impl.hpp index 55674c84b..3f235f6ec 100644 --- a/library/osrm_impl.hpp +++ b/library/osrm_impl.hpp @@ -52,7 +52,7 @@ class OSRM_impl OSRM_impl(libosrm_config &lib_config); OSRM_impl(const OSRM_impl &) = delete; virtual ~OSRM_impl(); - int RunQuery(RouteParameters &route_parameters, JSON::Object &json_result); + int RunQuery(RouteParameters &route_parameters, osrm::json::Object &json_result); private: void RegisterPlugin(BasePlugin *plugin); diff --git a/plugins/distance_table.hpp b/plugins/distance_table.hpp index 0a8912640..d4dfdc322 100644 --- a/plugins/distance_table.hpp +++ b/plugins/distance_table.hpp @@ -68,7 +68,7 @@ template class DistanceTablePlugin final : public BasePlugin const std::string GetDescriptor() const override final { return descriptor_string; } int HandleRequest(const RouteParameters &route_parameters, - JSON::Object &json_result) override final + osrm::json::Object &json_result) override final { if (!check_all_coordinates(route_parameters.coordinates)) { @@ -110,18 +110,18 @@ template class DistanceTablePlugin final : public BasePlugin return 400; } - JSON::Array json_array; + osrm::json::Array json_array; const auto number_of_locations = phantom_node_vector.size(); for (const auto row : osrm::irange(0, number_of_locations)) { - JSON::Array json_row; + osrm::json::Array json_row; auto row_begin_iterator = result_table->begin() + (row * number_of_locations); auto row_end_iterator = result_table->begin() + ((row + 1) * number_of_locations); json_row.values.insert(json_row.values.end(), row_begin_iterator, row_end_iterator); json_array.values.push_back(json_row); } json_result.values["distance_table"] = json_array; - // JSON::render(reply.content, json_object); + // osrm::json::render(reply.content, json_object); return 200; } diff --git a/plugins/hello_world.hpp b/plugins/hello_world.hpp index 5b08663db..269441715 100644 --- a/plugins/hello_world.hpp +++ b/plugins/hello_world.hpp @@ -48,7 +48,7 @@ class HelloWorldPlugin final : public BasePlugin const std::string GetDescriptor() const override final { return descriptor_string; } int HandleRequest(const RouteParameters &routeParameters, - JSON::Object &json_result) override final + osrm::json::Object &json_result) override final { std::string temp_string; json_result.values["title"] = "Hello World"; @@ -71,12 +71,12 @@ class HelloWorldPlugin final : public BasePlugin temp_string = cast::integral_to_string(routeParameters.coordinates.size()); json_result.values["location_count"] = temp_string; - JSON::Array json_locations; + osrm::json::Array json_locations; unsigned counter = 0; for (const FixedPointCoordinate &coordinate : routeParameters.coordinates) { - JSON::Object json_location; - JSON::Array json_coordinates; + osrm::json::Object json_location; + osrm::json::Array json_coordinates; json_coordinates.values.push_back( static_cast(coordinate.lat / COORDINATE_PRECISION)); @@ -89,7 +89,7 @@ class HelloWorldPlugin final : public BasePlugin json_result.values["locations"] = json_locations; json_result.values["hint_count"] = routeParameters.hints.size(); - JSON::Array json_hints; + osrm::json::Array json_hints; counter = 0; for (const std::string ¤t_hint : routeParameters.hints) { diff --git a/plugins/locate.hpp b/plugins/locate.hpp index 260361462..397bde649 100644 --- a/plugins/locate.hpp +++ b/plugins/locate.hpp @@ -45,7 +45,7 @@ template class LocatePlugin final : public BasePlugin const std::string GetDescriptor() const override final { return descriptor_string; } int HandleRequest(const RouteParameters &route_parameters, - JSON::Object &json_result) override final + osrm::json::Object &json_result) override final { // check number of parameters if (route_parameters.coordinates.empty() || @@ -63,7 +63,7 @@ template class LocatePlugin final : public BasePlugin else { json_result.values["status"] = 0; - JSON::Array json_coordinate; + osrm::json::Array json_coordinate; json_coordinate.values.push_back(result.lat / COORDINATE_PRECISION); json_coordinate.values.push_back(result.lon / COORDINATE_PRECISION); json_result.values["mapped_coordinate"] = json_coordinate; diff --git a/plugins/nearest.hpp b/plugins/nearest.hpp index 6221fcfb3..fc4e98046 100644 --- a/plugins/nearest.hpp +++ b/plugins/nearest.hpp @@ -50,7 +50,7 @@ template class NearestPlugin final : public BasePlugin const std::string GetDescriptor() const override final { return descriptor_string; } int HandleRequest(const RouteParameters &route_parameters, - JSON::Object &json_result) override final + osrm::json::Object &json_result) override final { // check number of parameters if (route_parameters.coordinates.empty() || @@ -75,14 +75,14 @@ template class NearestPlugin final : public BasePlugin if (number_of_results > 1) { - JSON::Array results; + osrm::json::Array results; auto vector_length = phantom_node_vector.size(); for (const auto i : osrm::irange(0, std::min(number_of_results, vector_length))) { - JSON::Array json_coordinate; - JSON::Object result; + osrm::json::Array json_coordinate; + osrm::json::Object result; json_coordinate.values.push_back(phantom_node_vector.at(i).location.lat / COORDINATE_PRECISION); json_coordinate.values.push_back(phantom_node_vector.at(i).location.lon / @@ -97,7 +97,7 @@ template class NearestPlugin final : public BasePlugin } else { - JSON::Array json_coordinate; + osrm::json::Array json_coordinate; json_coordinate.values.push_back(phantom_node_vector.front().location.lat / COORDINATE_PRECISION); json_coordinate.values.push_back(phantom_node_vector.front().location.lon / diff --git a/plugins/plugin_base.hpp b/plugins/plugin_base.hpp index 37d32b5b2..9b839016c 100644 --- a/plugins/plugin_base.hpp +++ b/plugins/plugin_base.hpp @@ -42,16 +42,15 @@ class BasePlugin // Maybe someone can explain the pure virtual destructor thing to me (dennis) virtual ~BasePlugin() {} virtual const std::string GetDescriptor() const = 0; - virtual int HandleRequest(const RouteParameters &, JSON::Object &) = 0; - virtual bool check_all_coordinates(const std::vector &coordinates) const final + virtual int HandleRequest(const RouteParameters &, osrm::json::Object &) = 0; + virtual bool + check_all_coordinates(const std::vector &coordinates) const final { - if (2 > coordinates.size() || - std::any_of(std::begin(coordinates), - std::end(coordinates), - [](const FixedPointCoordinate &coordinate) - { - return !coordinate.is_valid(); - })) + if (2 > coordinates.size() || std::any_of(std::begin(coordinates), std::end(coordinates), + [](const FixedPointCoordinate &coordinate) + { + return !coordinate.is_valid(); + })) { return false; } diff --git a/plugins/timestamp.hpp b/plugins/timestamp.hpp index db265ec47..59a8f56f9 100644 --- a/plugins/timestamp.hpp +++ b/plugins/timestamp.hpp @@ -45,7 +45,7 @@ template class TimestampPlugin final : public BasePlugin } const std::string GetDescriptor() const override final { return descriptor_string; } int HandleRequest(const RouteParameters &route_parameters, - JSON::Object &json_result) override final + osrm::json::Object &json_result) override final { json_result.values["status"] = 0; const std::string timestamp = facade->GetTimestamp(); diff --git a/plugins/viaroute.hpp b/plugins/viaroute.hpp index 630cba579..dd5edee57 100644 --- a/plugins/viaroute.hpp +++ b/plugins/viaroute.hpp @@ -72,7 +72,7 @@ template class ViaRoutePlugin final : public BasePlugin const std::string GetDescriptor() const override final { return descriptor_string; } int HandleRequest(const RouteParameters &route_parameters, - JSON::Object &json_result) override final + osrm::json::Object &json_result) override final { if (!check_all_coordinates(route_parameters.coordinates)) { diff --git a/server/request_handler.cpp b/server/request_handler.cpp index 464ba5b94..25637c3ad 100644 --- a/server/request_handler.cpp +++ b/server/request_handler.cpp @@ -92,7 +92,7 @@ void RequestHandler::handle_request(const http::request ¤t_request, const bool result = boost::spirit::qi::parse(api_iterator, request_string.end(), api_parser); - JSON::Object json_result; + osrm::json::Object json_result; // check if the was an error with the request if (!result || (api_iterator != request_string.end())) { @@ -104,7 +104,7 @@ void RequestHandler::handle_request(const http::request ¤t_request, std::string message = "Query string malformed close to position "; message += cast::integral_to_string(position); json_result.values["status_message"] = message; - JSON::render(current_reply.content, json_result); + osrm::json::render(current_reply.content, json_result); return; } @@ -124,7 +124,7 @@ void RequestHandler::handle_request(const http::request ¤t_request, json_result.values["status"] = 400; std::string message = "Bad Request"; json_result.values["status_message"] = message; - JSON::render(current_reply.content, json_result); + osrm::json::render(current_reply.content, json_result); return; } // set headers @@ -132,7 +132,7 @@ void RequestHandler::handle_request(const http::request ¤t_request, cast::integral_to_string(current_reply.content.size())); if ("gpx" == route_parameters.output_format) { // gpx file - JSON::gpx_render(current_reply.content, json_result.values["route"]); + osrm::json::gpx_render(current_reply.content, json_result.values["route"]); current_reply.headers.emplace_back("Content-Type", "application/gpx+xml; charset=UTF-8"); current_reply.headers.emplace_back("Content-Disposition", @@ -140,14 +140,14 @@ void RequestHandler::handle_request(const http::request ¤t_request, } else if (route_parameters.jsonp_parameter.empty()) { // json file - JSON::render(current_reply.content, json_result); + osrm::json::render(current_reply.content, json_result); current_reply.headers.emplace_back("Content-Type", "application/json; charset=UTF-8"); current_reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.json\""); } else { // jsonp - JSON::render(current_reply.content, json_result); + osrm::json::render(current_reply.content, json_result); current_reply.headers.emplace_back("Content-Type", "text/javascript; charset=UTF-8"); current_reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.js\""); diff --git a/tools/simpleclient.cpp b/tools/simpleclient.cpp index 2567b9319..0235b6bdb 100644 --- a/tools/simpleclient.cpp +++ b/tools/simpleclient.cpp @@ -81,10 +81,10 @@ int main(int argc, const char *argv[]) // target_coordinate route_parameters.coordinates.emplace_back(52.513191 * COORDINATE_PRECISION, 13.415852 * COORDINATE_PRECISION); - JSON::Object json_result; + osrm::json::Object json_result; const int result_code = routing_machine.RunQuery(route_parameters, json_result); SimpleLogger().Write() << "http code: " << result_code; - JSON::render(SimpleLogger().Write(), json_result); + osrm::json::render(SimpleLogger().Write(), json_result); } catch (std::exception ¤t_exception) { diff --git a/util/json_renderer.hpp b/util/json_renderer.hpp index adb7c544e..143066cb7 100644 --- a/util/json_renderer.hpp +++ b/util/json_renderer.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -35,7 +35,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -namespace JSON +namespace osrm +{ +namespace json { struct Renderer : mapbox::util::static_visitor<> @@ -179,6 +181,6 @@ inline void render(std::vector &out, const Object &object) mapbox::util::apply_visitor(ArrayRenderer(out), value); } -} // namespace JSON - +} // namespace json +} // namespace osrm #endif // JSON_RENDERER_HPP diff --git a/util/string_util.hpp b/util/string_util.hpp index 08af55483..92fac59c7 100644 --- a/util/string_util.hpp +++ b/util/string_util.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM, Dennis Luxen, others All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/xml_renderer.hpp b/util/xml_renderer.hpp index bbf2287e1..5783ab133 100644 --- a/util/xml_renderer.hpp +++ b/util/xml_renderer.hpp @@ -32,7 +32,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -namespace JSON +namespace osrm +{ +namespace json { struct XMLToArrayRenderer : mapbox::util::static_visitor<> @@ -135,6 +137,6 @@ template inline void gpx_render(std::vector &out, const const std::string footer{""}; out.insert(out.end(), footer.begin(), footer.end()); } -} // namespace JSON - +} // namespace json +} // namespace osrm #endif // XML_RENDERER_HPP From 3bd27ae8c5b217eeed5c1fd726435efd9b1875a6 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 19 Feb 2015 09:19:51 +0100 Subject: [PATCH 201/360] change copyright line from personal names to project --- Gemfile | 2 +- LICENCE.TXT | 2 +- algorithms/bfs_components.hpp | 8 +- algorithms/crc32_processor.hpp | 2 +- algorithms/douglas_peucker.cpp | 2 +- algorithms/douglas_peucker.hpp | 5 +- algorithms/object_encoder.hpp | 2 +- algorithms/polyline_compressor.cpp | 2 +- algorithms/polyline_compressor.hpp | 2 +- algorithms/polyline_formatter.cpp | 2 +- algorithms/polyline_formatter.hpp | 2 +- algorithms/route_name_extraction.hpp | 51 ++++++------ algorithms/tiny_components.hpp | 2 +- benchmarks/static_rtree.cpp | 2 +- data_structures/binary_heap.hpp | 2 +- data_structures/concurrent_queue.hpp | 16 ++-- data_structures/coordinate.cpp | 2 +- data_structures/coordinate_calculation.cpp | 2 +- data_structures/coordinate_calculation.hpp | 2 +- data_structures/deallocating_vector.hpp | 2 +- data_structures/dynamic_graph.hpp | 2 +- data_structures/edge_based_node.hpp | 2 +- data_structures/external_memory_node.cpp | 9 +-- data_structures/external_memory_node.hpp | 2 +- data_structures/fixed_point_number.hpp | 2 +- data_structures/hilbert_value.cpp | 2 +- data_structures/hilbert_value.hpp | 2 +- data_structures/import_edge.cpp | 6 +- data_structures/import_edge.hpp | 2 +- data_structures/internal_route_result.hpp | 17 ++-- data_structures/lru_cache.hpp | 2 +- data_structures/node_based_graph.hpp | 2 +- data_structures/node_id.hpp | 2 +- data_structures/original_edge_data.hpp | 7 +- data_structures/percent.hpp | 4 +- data_structures/phantom_node.cpp | 2 +- data_structures/phantom_node.hpp | 2 +- data_structures/query_edge.hpp | 2 +- data_structures/query_node.hpp | 4 +- data_structures/range_table.hpp | 2 +- data_structures/rectangle.hpp | 2 +- data_structures/restriction.hpp | 8 +- data_structures/restriction_map.cpp | 77 +++++++++---------- data_structures/restriction_map.hpp | 2 +- data_structures/route_parameters.cpp | 6 +- data_structures/search_engine.hpp | 5 +- data_structures/search_engine_data.cpp | 2 +- data_structures/search_engine_data.hpp | 2 +- data_structures/segment_information.hpp | 2 +- data_structures/shared_memory_factory.hpp | 2 +- .../shared_memory_vector_wrapper.hpp | 6 +- data_structures/static_graph.hpp | 2 +- data_structures/static_kdtree.hpp | 6 +- data_structures/static_rtree.hpp | 2 +- data_structures/travel_mode.hpp | 5 +- data_structures/tribool.hpp | 2 +- data_structures/turn_instructions.hpp | 29 +++++-- data_structures/upper_bound.hpp | 2 +- data_structures/xor_fast_hash.hpp | 2 +- data_structures/xor_fast_hash_storage.hpp | 2 +- datastore.cpp | 3 +- descriptors/description_factory.cpp | 2 +- descriptors/description_factory.hpp | 2 +- descriptors/descriptor_base.hpp | 2 +- descriptors/gpx_descriptor.hpp | 2 +- descriptors/json_descriptor.hpp | 2 +- extract.cpp | 2 +- extractor/extraction_containers.cpp | 2 +- extractor/extraction_containers.hpp | 2 +- extractor/extraction_helper_functions.hpp | 2 +- extractor/extraction_node.hpp | 2 +- extractor/extraction_way.hpp | 2 +- extractor/extractor.cpp | 2 +- extractor/extractor.hpp | 2 +- extractor/extractor_callbacks.cpp | 2 +- extractor/extractor_callbacks.hpp | 2 +- extractor/extractor_options.cpp | 2 +- extractor/extractor_options.hpp | 2 +- extractor/first_and_last_segment_of_way.hpp | 2 +- extractor/internal_extractor_edge.hpp | 2 +- extractor/restriction_parser.cpp | 2 +- extractor/restriction_parser.hpp | 2 +- extractor/scripting_environment.cpp | 2 +- extractor/scripting_environment.hpp | 2 +- include/osrm/coordinate.hpp | 2 +- include/osrm/json_container.hpp | 2 +- include/osrm/libosrm_config.hpp | 2 +- include/osrm/route_parameters.hpp | 2 +- include/osrm/server_paths.hpp | 2 +- library/osrm.hpp | 2 +- library/osrm_impl.cpp | 2 +- library/osrm_impl.hpp | 2 +- plugins/distance_table.hpp | 2 +- plugins/hello_world.hpp | 2 +- plugins/locate.hpp | 2 +- plugins/nearest.hpp | 2 +- plugins/plugin_base.hpp | 2 +- plugins/timestamp.hpp | 2 +- plugins/viaroute.hpp | 2 +- prepare.cpp | 2 +- routed.cpp | 2 +- routing_algorithms/alternative_path.hpp | 2 +- routing_algorithms/many_to_many.hpp | 20 +++-- routing_algorithms/routing_base.hpp | 2 +- routing_algorithms/shortest_path.hpp | 2 +- server/api_grammar.hpp | 2 +- server/connection.cpp | 4 +- server/connection.hpp | 2 +- server/data_structures/datafacade_base.hpp | 2 +- .../data_structures/internal_datafacade.hpp | 2 +- server/data_structures/shared_barriers.hpp | 2 +- server/data_structures/shared_datafacade.hpp | 2 +- server/data_structures/shared_datatype.hpp | 2 +- server/http/compression_type.hpp | 2 +- server/http/header.hpp | 2 +- server/http/reply.cpp | 2 +- server/http/reply.hpp | 2 +- server/http/request.hpp | 2 +- server/request_handler.cpp | 2 +- server/request_handler.hpp | 2 +- server/request_parser.cpp | 2 +- server/request_parser.hpp | 2 +- server/server.hpp | 2 +- tools/check-hsgr.cpp | 2 +- tools/components.cpp | 2 +- tools/io-benchmark.cpp | 2 +- tools/simpleclient.cpp | 2 +- tools/springclean.cpp | 2 +- tools/unlock_all_mutexes.cpp | 2 +- unit_tests/algorithm_tests.cpp | 3 +- unit_tests/algorithms/douglas_peucker.cpp | 33 ++++---- unit_tests/data_structures/binary_heap.cpp | 2 +- unit_tests/data_structures/coordinate.cpp | 2 +- unit_tests/data_structures/range_table.cpp | 7 +- unit_tests/data_structures/static_graph.cpp | 2 +- unit_tests/data_structures/static_rtree.cpp | 2 +- unit_tests/datastructure_tests.cpp | 2 +- util/bearing.cpp | 2 +- util/bearing.hpp | 2 +- util/boost_filesystem_2_fix.hpp | 2 +- util/cast.hpp | 2 +- util/compute_angle.cpp | 2 +- util/compute_angle.hpp | 2 +- util/container.hpp | 2 +- util/datastore_options.hpp | 2 +- util/fingerprint.hpp | 2 +- util/floating_point.hpp | 2 +- util/git_sha.cpp.in | 2 +- util/git_sha.hpp | 2 +- util/graph_loader.hpp | 2 +- util/ini_file.hpp | 2 +- util/integer_range.hpp | 2 +- util/iterator_range.hpp | 2 +- util/json_renderer.hpp | 2 +- util/lua_util.hpp | 2 +- util/make_unique.hpp | 2 +- util/mercator.cpp | 2 +- util/mercator.hpp | 2 +- util/osrm_exception.cpp | 2 +- util/osrm_exception.hpp | 2 +- util/routed_options.hpp | 2 +- util/simple_logger.cpp | 11 ++- util/simple_logger.hpp | 2 +- util/std_hash.hpp | 2 +- util/string_util.hpp | 2 +- util/timing_util.hpp | 2 +- util/trigonometry_table.hpp | 2 +- util/xml_renderer.hpp | 2 +- 168 files changed, 314 insertions(+), 322 deletions(-) diff --git a/Gemfile b/Gemfile index 114808e49..31d044bd6 100644 --- a/Gemfile +++ b/Gemfile @@ -4,4 +4,4 @@ gem "cucumber" gem "rake" gem "osmlib-base" gem "sys-proctable" -gem "rspec-expectations" \ No newline at end of file +gem "rspec-expectations" diff --git a/LICENCE.TXT b/LICENCE.TXT index 28fe97b35..c77e5cd1b 100644 --- a/LICENCE.TXT +++ b/LICENCE.TXT @@ -1,4 +1,4 @@ -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/algorithms/bfs_components.hpp b/algorithms/bfs_components.hpp index 57be63553..b3f536401 100644 --- a/algorithms/bfs_components.hpp +++ b/algorithms/bfs_components.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -95,8 +95,8 @@ template class BFSComponentExplorer * Explores the current component that starts at node using BFS. */ unsigned ExploreComponent(std::queue> &bfs_queue, - NodeID node, - unsigned current_component) + NodeID node, + unsigned current_component) { /* Graphical representation of variables: @@ -118,7 +118,7 @@ template class BFSComponentExplorer std::pair current_queue_item = bfs_queue.front(); bfs_queue.pop(); - const NodeID v = current_queue_item.first; // current node + const NodeID v = current_queue_item.first; // current node const NodeID u = current_queue_item.second; // parent // increment size counter of current component ++current_component_size; diff --git a/algorithms/crc32_processor.hpp b/algorithms/crc32_processor.hpp index 2a9d6ad6b..b9444e7b6 100644 --- a/algorithms/crc32_processor.hpp +++ b/algorithms/crc32_processor.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/algorithms/douglas_peucker.cpp b/algorithms/douglas_peucker.cpp index e94912482..fa7d7826b 100644 --- a/algorithms/douglas_peucker.cpp +++ b/algorithms/douglas_peucker.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/algorithms/douglas_peucker.hpp b/algorithms/douglas_peucker.hpp index 7c5f8c1e8..da02982f3 100644 --- a/algorithms/douglas_peucker.hpp +++ b/algorithms/douglas_peucker.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -35,7 +35,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include - /* This class object computes the bitvector of indicating generalized input * points according to the (Ramer-)Douglas-Peucker algorithm. * @@ -43,7 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * bit indicating if the points is present in the generalization. * Note: points may also be pre-selected*/ -static const std::array DOUGLAS_PEUCKER_THRESHOLDS {{ +static const std::array DOUGLAS_PEUCKER_THRESHOLDS{{ 512440, // z0 256720, // z1 122560, // z2 diff --git a/algorithms/object_encoder.hpp b/algorithms/object_encoder.hpp index c7f6f1fab..e880496a2 100644 --- a/algorithms/object_encoder.hpp +++ b/algorithms/object_encoder.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/algorithms/polyline_compressor.cpp b/algorithms/polyline_compressor.cpp index 7886de91c..6310a2ec9 100644 --- a/algorithms/polyline_compressor.cpp +++ b/algorithms/polyline_compressor.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/algorithms/polyline_compressor.hpp b/algorithms/polyline_compressor.hpp index 8bff4a040..933ac7afa 100644 --- a/algorithms/polyline_compressor.hpp +++ b/algorithms/polyline_compressor.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/algorithms/polyline_formatter.cpp b/algorithms/polyline_formatter.cpp index b5dad6c78..670a6121f 100644 --- a/algorithms/polyline_formatter.cpp +++ b/algorithms/polyline_formatter.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/algorithms/polyline_formatter.hpp b/algorithms/polyline_formatter.hpp index 181a0cf15..68cc70293 100644 --- a/algorithms/polyline_formatter.hpp +++ b/algorithms/polyline_formatter.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/algorithms/route_name_extraction.hpp b/algorithms/route_name_extraction.hpp index 519452f98..8275de099 100644 --- a/algorithms/route_name_extraction.hpp +++ b/algorithms/route_name_extraction.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -54,7 +54,8 @@ template struct ExtractRouteNames for (const SegmentT &segment : segment_list) { - if (segment.name_id != blocked_name_id && segment.length > result_segment.length && segment.name_id != 0) + if (segment.name_id != blocked_name_id && segment.length > result_segment.length && + segment.name_id != 0) { result_segment = segment; } @@ -73,9 +74,13 @@ template struct ExtractRouteNames SegmentT alternative_segment_1, alternative_segment_2; auto length_comperator = [](const SegmentT &a, const SegmentT &b) - { return a.length > b.length; }; + { + return a.length > b.length; + }; auto name_id_comperator = [](const SegmentT &a, const SegmentT &b) - { return a.name_id < b.name_id; }; + { + return a.name_id < b.name_id; + }; if (shortest_path_segments.empty()) { @@ -87,8 +92,7 @@ template struct ExtractRouteNames shortest_segment_1 = shortest_path_segments[0]; if (!alternative_path_segments.empty()) { - std::sort(alternative_path_segments.begin(), - alternative_path_segments.end(), + std::sort(alternative_path_segments.begin(), alternative_path_segments.end(), length_comperator); // also pick the longest segment for the alternative path @@ -99,16 +103,13 @@ template struct ExtractRouteNames // alternative std::vector shortest_path_set_difference(shortest_path_segments.size()); std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), name_id_comperator); - std::sort(alternative_path_segments.begin(), alternative_path_segments.end(), name_id_comperator); - std::set_difference(shortest_path_segments.begin(), - shortest_path_segments.end(), - alternative_path_segments.begin(), - alternative_path_segments.end(), - shortest_path_set_difference.begin(), - name_id_comperator); + std::sort(alternative_path_segments.begin(), alternative_path_segments.end(), + name_id_comperator); + std::set_difference(shortest_path_segments.begin(), shortest_path_segments.end(), + alternative_path_segments.begin(), alternative_path_segments.end(), + shortest_path_set_difference.begin(), name_id_comperator); - std::sort(shortest_path_set_difference.begin(), - shortest_path_set_difference.end(), + std::sort(shortest_path_set_difference.begin(), shortest_path_set_difference.end(), length_comperator); shortest_segment_2 = PickNextLongestSegment(shortest_path_set_difference, shortest_segment_1.name_id); @@ -116,29 +117,23 @@ template struct ExtractRouteNames // compute the set difference (for alternative path) depending on names between shortest and // alternative // vectors are still sorted, no need to do again - BOOST_ASSERT(std::is_sorted(shortest_path_segments.begin(), - shortest_path_segments.end(), + BOOST_ASSERT(std::is_sorted(shortest_path_segments.begin(), shortest_path_segments.end(), name_id_comperator)); BOOST_ASSERT(std::is_sorted(alternative_path_segments.begin(), - alternative_path_segments.end(), - name_id_comperator)); + alternative_path_segments.end(), name_id_comperator)); std::vector alternative_path_set_difference(alternative_path_segments.size()); - std::set_difference(alternative_path_segments.begin(), - alternative_path_segments.end(), - shortest_path_segments.begin(), - shortest_path_segments.end(), - alternative_path_set_difference.begin(), - name_id_comperator); + std::set_difference(alternative_path_segments.begin(), alternative_path_segments.end(), + shortest_path_segments.begin(), shortest_path_segments.end(), + alternative_path_set_difference.begin(), name_id_comperator); - std::sort(alternative_path_set_difference.begin(), - alternative_path_set_difference.end(), + std::sort(alternative_path_set_difference.begin(), alternative_path_set_difference.end(), length_comperator); if (!alternative_path_segments.empty()) { alternative_segment_2 = PickNextLongestSegment(alternative_path_set_difference, - alternative_segment_1.name_id); + alternative_segment_1.name_id); } // move the segments into the order in which they occur. diff --git a/algorithms/tiny_components.hpp b/algorithms/tiny_components.hpp index b595ac427..f3ca3c412 100644 --- a/algorithms/tiny_components.hpp +++ b/algorithms/tiny_components.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/benchmarks/static_rtree.cpp b/benchmarks/static_rtree.cpp index 7d2ae9f55..9d883311b 100644 --- a/benchmarks/static_rtree.cpp +++ b/benchmarks/static_rtree.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/binary_heap.hpp b/data_structures/binary_heap.hpp index 3a2796d7c..a23a6b0f5 100644 --- a/data_structures/binary_heap.hpp +++ b/data_structures/binary_heap.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/concurrent_queue.hpp b/data_structures/concurrent_queue.hpp index b3d4e1a2a..7341a8cc4 100644 --- a/data_structures/concurrent_queue.hpp +++ b/data_structures/concurrent_queue.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -40,9 +40,10 @@ template class ConcurrentQueue inline void push(const Data &data) { std::unique_lock lock(m_mutex); - m_not_full.wait(lock, - [this] - { return m_internal_queue.size() < m_internal_queue.capacity(); }); + m_not_full.wait(lock, [this] + { + return m_internal_queue.size() < m_internal_queue.capacity(); + }); m_internal_queue.push_back(data); m_not_empty.notify_one(); } @@ -52,9 +53,10 @@ template class ConcurrentQueue inline void wait_and_pop(Data &popped_value) { std::unique_lock lock(m_mutex); - m_not_empty.wait(lock, - [this] - { return !m_internal_queue.empty(); }); + m_not_empty.wait(lock, [this] + { + return !m_internal_queue.empty(); + }); popped_value = m_internal_queue.front(); m_internal_queue.pop_front(); m_not_full.notify_one(); diff --git a/data_structures/coordinate.cpp b/data_structures/coordinate.cpp index 29151cf4c..df3abe44a 100644 --- a/data_structures/coordinate.cpp +++ b/data_structures/coordinate.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/coordinate_calculation.cpp b/data_structures/coordinate_calculation.cpp index 69e2ead17..0c44989b4 100644 --- a/data_structures/coordinate_calculation.cpp +++ b/data_structures/coordinate_calculation.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/coordinate_calculation.hpp b/data_structures/coordinate_calculation.hpp index 9dbaa646b..73183dfa4 100644 --- a/data_structures/coordinate_calculation.hpp +++ b/data_structures/coordinate_calculation.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/deallocating_vector.hpp b/data_structures/deallocating_vector.hpp index 968528f3c..de5a24d85 100644 --- a/data_structures/deallocating_vector.hpp +++ b/data_structures/deallocating_vector.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/dynamic_graph.hpp b/data_structures/dynamic_graph.hpp index abaa05717..498f94a7c 100644 --- a/data_structures/dynamic_graph.hpp +++ b/data_structures/dynamic_graph.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/edge_based_node.hpp b/data_structures/edge_based_node.hpp index b5bc7b176..72a585a13 100644 --- a/data_structures/edge_based_node.hpp +++ b/data_structures/edge_based_node.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/external_memory_node.cpp b/data_structures/external_memory_node.cpp index 3ede2c5a0..72b8198f9 100644 --- a/data_structures/external_memory_node.cpp +++ b/data_structures/external_memory_node.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -45,11 +45,8 @@ ExternalMemoryNode ExternalMemoryNode::min_value() ExternalMemoryNode ExternalMemoryNode::max_value() { - return ExternalMemoryNode(std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::max(), - false, - false); + return ExternalMemoryNode(std::numeric_limits::max(), std::numeric_limits::max(), + std::numeric_limits::max(), false, false); } bool ExternalMemoryNodeSTXXLCompare::operator()(const ExternalMemoryNode &left, diff --git a/data_structures/external_memory_node.hpp b/data_structures/external_memory_node.hpp index 4ac6b9237..83b88e759 100644 --- a/data_structures/external_memory_node.hpp +++ b/data_structures/external_memory_node.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/fixed_point_number.hpp b/data_structures/fixed_point_number.hpp index eab685026..c7ed257e5 100644 --- a/data_structures/fixed_point_number.hpp +++ b/data_structures/fixed_point_number.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/hilbert_value.cpp b/data_structures/hilbert_value.cpp index 8487fac11..c09773118 100644 --- a/data_structures/hilbert_value.cpp +++ b/data_structures/hilbert_value.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/hilbert_value.hpp b/data_structures/hilbert_value.hpp index e1940296e..7b8bffa93 100644 --- a/data_structures/hilbert_value.hpp +++ b/data_structures/hilbert_value.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/import_edge.cpp b/data_structures/import_edge.cpp index 098adb32a..f41b066b1 100644 --- a/data_structures/import_edge.cpp +++ b/data_structures/import_edge.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -58,8 +58,8 @@ NodeBasedEdge::NodeBasedEdge(NodeID source, bool access_restricted, TravelMode travel_mode, bool is_split) - : source(source), target(target), name_id(name_id), weight(weight), - forward(forward), backward(backward), roundabout(roundabout), in_tiny_cc(in_tiny_cc), + : source(source), target(target), name_id(name_id), weight(weight), forward(forward), + backward(backward), roundabout(roundabout), in_tiny_cc(in_tiny_cc), access_restricted(access_restricted), is_split(is_split), travel_mode(travel_mode) { } diff --git a/data_structures/import_edge.hpp b/data_structures/import_edge.hpp index f9004d45a..f422de116 100644 --- a/data_structures/import_edge.hpp +++ b/data_structures/import_edge.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/internal_route_result.hpp b/data_structures/internal_route_result.hpp index 629e50d8a..068b63a80 100644 --- a/data_structures/internal_route_result.hpp +++ b/data_structures/internal_route_result.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -40,10 +40,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct PathData { PathData() - : node(SPECIAL_NODEID), name_id(INVALID_EDGE_WEIGHT), - segment_duration(INVALID_EDGE_WEIGHT), - turn_instruction(TurnInstruction::NoTurn), - travel_mode(TRAVEL_MODE_INACCESSIBLE) + : node(SPECIAL_NODEID), name_id(INVALID_EDGE_WEIGHT), segment_duration(INVALID_EDGE_WEIGHT), + turn_instruction(TurnInstruction::NoTurn), travel_mode(TRAVEL_MODE_INACCESSIBLE) { } @@ -52,8 +50,8 @@ struct PathData TurnInstruction turn_instruction, EdgeWeight segment_duration, TravelMode travel_mode) - : node(node), name_id(name_id), segment_duration(segment_duration), turn_instruction(turn_instruction), - travel_mode(travel_mode) + : node(node), name_id(name_id), segment_duration(segment_duration), + turn_instruction(turn_instruction), travel_mode(travel_mode) { } NodeID node; @@ -80,9 +78,8 @@ struct InternalRouteResult return (leg != unpacked_path_segments.size() - 1); } - InternalRouteResult() : - shortest_path_length(INVALID_EDGE_WEIGHT), - alternative_path_length(INVALID_EDGE_WEIGHT) + InternalRouteResult() + : shortest_path_length(INVALID_EDGE_WEIGHT), alternative_path_length(INVALID_EDGE_WEIGHT) { } }; diff --git a/data_structures/lru_cache.hpp b/data_structures/lru_cache.hpp index b7296eeb6..155ab1ef4 100644 --- a/data_structures/lru_cache.hpp +++ b/data_structures/lru_cache.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/node_based_graph.hpp b/data_structures/node_based_graph.hpp index 82eb59bd5..54e07a7ec 100644 --- a/data_structures/node_based_graph.hpp +++ b/data_structures/node_based_graph.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/node_id.hpp b/data_structures/node_id.hpp index 4f0780965..4d6fff0b2 100644 --- a/data_structures/node_id.hpp +++ b/data_structures/node_id.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/original_edge_data.hpp b/data_structures/original_edge_data.hpp index b4fdfd97f..cbbc1b276 100644 --- a/data_structures/original_edge_data.hpp +++ b/data_structures/original_edge_data.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -48,9 +48,8 @@ struct OriginalEdgeData OriginalEdgeData() : via_node(std::numeric_limits::max()), - name_id(std::numeric_limits::max()), - turn_instruction(TurnInstruction::NoTurn), compressed_geometry(false), - travel_mode(TRAVEL_MODE_INACCESSIBLE) + name_id(std::numeric_limits::max()), turn_instruction(TurnInstruction::NoTurn), + compressed_geometry(false), travel_mode(TRAVEL_MODE_INACCESSIBLE) { } diff --git a/data_structures/percent.hpp b/data_structures/percent.hpp index 0c4e15246..392417e76 100644 --- a/data_structures/percent.hpp +++ b/data_structures/percent.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -36,7 +36,7 @@ class Percent public: explicit Percent(unsigned max_value, unsigned step = 5) { reinit(max_value, step); } - // Reinitializes + // Reinitializes void reinit(unsigned max_value, unsigned step = 5) { m_max_value = max_value; diff --git a/data_structures/phantom_node.cpp b/data_structures/phantom_node.cpp index 9a0988564..eba6492cd 100644 --- a/data_structures/phantom_node.cpp +++ b/data_structures/phantom_node.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/phantom_node.hpp b/data_structures/phantom_node.hpp index d22cb9504..b048eb7f2 100644 --- a/data_structures/phantom_node.hpp +++ b/data_structures/phantom_node.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/query_edge.hpp b/data_structures/query_edge.hpp index 84a7f1591..0d51aac3f 100644 --- a/data_structures/query_edge.hpp +++ b/data_structures/query_edge.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/query_node.hpp b/data_structures/query_node.hpp index 18808fd95..f3e990476 100644 --- a/data_structures/query_node.hpp +++ b/data_structures/query_node.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct QueryNode { using key_type = NodeID; // type of NodeID - using value_type = int; // type of lat,lons + using value_type = int; // type of lat,lons explicit QueryNode(int lat, int lon, NodeID node_id) : lat(lat), lon(lon), node_id(node_id) {} QueryNode() diff --git a/data_structures/range_table.hpp b/data_structures/range_table.hpp index ec0167231..4662f06c0 100644 --- a/data_structures/range_table.hpp +++ b/data_structures/range_table.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/rectangle.hpp b/data_structures/rectangle.hpp index c36074dbd..55720a37d 100644 --- a/data_structures/rectangle.hpp +++ b/data_structures/rectangle.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/restriction.hpp b/data_structures/restriction.hpp index ed38dc639..f278bd8d2 100644 --- a/data_structures/restriction.hpp +++ b/data_structures/restriction.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -108,8 +108,7 @@ struct InputRestrictionContainer struct CmpRestrictionContainerByFrom { typedef InputRestrictionContainer value_type; - bool operator()(const InputRestrictionContainer &a, - const InputRestrictionContainer &b) const + bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b) const { return a.restriction.from.way < b.restriction.from.way; } @@ -120,8 +119,7 @@ struct CmpRestrictionContainerByFrom struct CmpRestrictionContainerByTo { typedef InputRestrictionContainer value_type; - bool operator()(const InputRestrictionContainer &a, - const InputRestrictionContainer &b) const + bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b) const { return a.restriction.to.way < b.restriction.to.way; } diff --git a/data_structures/restriction_map.cpp b/data_structures/restriction_map.cpp index 0f230f819..017ee3251 100644 --- a/data_structures/restriction_map.cpp +++ b/data_structures/restriction_map.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -27,54 +27,51 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "restriction_map.hpp" -RestrictionMap::RestrictionMap(const std::vector &restriction_list) - : m_count(0) +RestrictionMap::RestrictionMap(const std::vector &restriction_list) : m_count(0) +{ + // decompose restriction consisting of a start, via and end node into a + // a pair of starting edge and a list of all end nodes + for (auto &restriction : restriction_list) { - // decompose restriction consisting of a start, via and end node into a - // a pair of starting edge and a list of all end nodes - for (auto &restriction : restriction_list) + m_restriction_start_nodes.insert(restriction.from.node); + m_no_turn_via_node_set.insert(restriction.via.node); + + RestrictionSource restriction_source = {restriction.from.node, restriction.via.node}; + + std::size_t index; + auto restriction_iter = m_restriction_map.find(restriction_source); + if (restriction_iter == m_restriction_map.end()) { - m_restriction_start_nodes.insert(restriction.from.node); - m_no_turn_via_node_set.insert(restriction.via.node); - - RestrictionSource restriction_source = {restriction.from.node, restriction.via.node}; - - std::size_t index; - auto restriction_iter = m_restriction_map.find(restriction_source); - if (restriction_iter == m_restriction_map.end()) - { - index = m_restriction_bucket_list.size(); - m_restriction_bucket_list.resize(index + 1); - m_restriction_map.emplace(restriction_source, index); - } - else - { - index = restriction_iter->second; - // Map already contains an is_only_*-restriction - if (m_restriction_bucket_list.at(index).begin()->is_only) - { - continue; - } - else if (restriction.flags.is_only) - { - // We are going to insert an is_only_*-restriction. There can be only one. - m_count -= m_restriction_bucket_list.at(index).size(); - m_restriction_bucket_list.at(index).clear(); - } - } - ++m_count; - m_restriction_bucket_list.at(index) - .emplace_back(restriction.to.node, restriction.flags.is_only); + index = m_restriction_bucket_list.size(); + m_restriction_bucket_list.resize(index + 1); + m_restriction_map.emplace(restriction_source, index); } + else + { + index = restriction_iter->second; + // Map already contains an is_only_*-restriction + if (m_restriction_bucket_list.at(index).begin()->is_only) + { + continue; + } + else if (restriction.flags.is_only) + { + // We are going to insert an is_only_*-restriction. There can be only one. + m_count -= m_restriction_bucket_list.at(index).size(); + m_restriction_bucket_list.at(index).clear(); + } + } + ++m_count; + m_restriction_bucket_list.at(index) + .emplace_back(restriction.to.node, restriction.flags.is_only); } - +} bool RestrictionMap::IsViaNode(const NodeID node) const { return m_no_turn_via_node_set.find(node) != m_no_turn_via_node_set.end(); } - // Replaces start edge (v, w) with (u, w). Only start node changes. void RestrictionMap::FixupStartingTurnRestriction(const NodeID node_u, const NodeID node_v, @@ -156,7 +153,7 @@ bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID node_u, for (const RestrictionTarget &restriction_target : bucket) { if (node_w == restriction_target.target_node && // target found - !restriction_target.is_only) // and not an only_-restr. + !restriction_target.is_only) // and not an only_-restr. { return true; } diff --git a/data_structures/restriction_map.hpp b/data_structures/restriction_map.hpp index a11b987f2..27a6698db 100644 --- a/data_structures/restriction_map.hpp +++ b/data_structures/restriction_map.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/route_parameters.cpp b/data_structures/route_parameters.cpp index fa54ad6b2..5f6d37f90 100644 --- a/data_structures/route_parameters.cpp +++ b/data_structures/route_parameters.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -108,8 +108,8 @@ void RouteParameters::setGeometryFlag(const bool flag) { geometry = flag; } void RouteParameters::setCompressionFlag(const bool flag) { compression = flag; } -void -RouteParameters::addCoordinate(const boost::fusion::vector &transmitted_coordinates) +void RouteParameters::addCoordinate( + const boost::fusion::vector &transmitted_coordinates) { coordinates.emplace_back( static_cast(COORDINATE_PRECISION * boost::fusion::at_c<0>(transmitted_coordinates)), diff --git a/data_structures/search_engine.hpp b/data_structures/search_engine.hpp index 0b2b888dc..24e550767 100644 --- a/data_structures/search_engine.hpp +++ b/data_structures/search_engine.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -51,7 +51,8 @@ template class SearchEngine alternative_path(facade, engine_working_data), distance_table(facade, engine_working_data) { static_assert(!std::is_pointer::value, "don't instantiate with ptr type"); - static_assert(std::is_object::value, "don't instantiate with void, function, or reference"); + static_assert(std::is_object::value, + "don't instantiate with void, function, or reference"); } ~SearchEngine() {} diff --git a/data_structures/search_engine_data.cpp b/data_structures/search_engine_data.cpp index 810762acd..fbdbc06ce 100644 --- a/data_structures/search_engine_data.cpp +++ b/data_structures/search_engine_data.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/search_engine_data.hpp b/data_structures/search_engine_data.hpp index 6c2efb1d6..82ee706c7 100644 --- a/data_structures/search_engine_data.hpp +++ b/data_structures/search_engine_data.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/segment_information.hpp b/data_structures/segment_information.hpp index 5729380cc..7118a320e 100644 --- a/data_structures/segment_information.hpp +++ b/data_structures/segment_information.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/shared_memory_factory.hpp b/data_structures/shared_memory_factory.hpp index 56e458ff1..58fed9bb3 100644 --- a/data_structures/shared_memory_factory.hpp +++ b/data_structures/shared_memory_factory.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/shared_memory_vector_wrapper.hpp b/data_structures/shared_memory_vector_wrapper.hpp index d508e5f56..dc51cff0d 100644 --- a/data_structures/shared_memory_vector_wrapper.hpp +++ b/data_structures/shared_memory_vector_wrapper.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -147,8 +147,8 @@ template <> class SharedMemoryWrapper template struct ShM { using vector = typename std::conditional, - std::vector>::type; + SharedMemoryWrapper, + std::vector>::type; }; #endif // SHARED_MEMORY_VECTOR_WRAPPER_HPP diff --git a/data_structures/static_graph.hpp b/data_structures/static_graph.hpp index 1358027f7..2a5f6481e 100644 --- a/data_structures/static_graph.hpp +++ b/data_structures/static_graph.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/static_kdtree.hpp b/data_structures/static_kdtree.hpp index b173d3a02..1e65dc844 100644 --- a/data_structures/static_kdtree.hpp +++ b/data_structures/static_kdtree.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -138,8 +138,8 @@ class StaticKDTree continue; Iterator middle = tree.left + (tree.right - tree.left) / 2; - std::nth_element( - kdtree + tree.left, kdtree + middle, kdtree + tree.right, Less(tree.dimension)); + std::nth_element(kdtree + tree.left, kdtree + middle, kdtree + tree.right, + Less(tree.dimension)); s.push(Tree(tree.left, middle, (tree.dimension + 1) % k)); s.push(Tree(middle + 1, tree.right, (tree.dimension + 1) % k)); } diff --git a/data_structures/static_rtree.hpp b/data_structures/static_rtree.hpp index 87766cbb8..a0ce38a1e 100644 --- a/data_structures/static_rtree.hpp +++ b/data_structures/static_rtree.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/travel_mode.hpp b/data_structures/travel_mode.hpp index 345ec90e3..2bbe46317 100644 --- a/data_structures/travel_mode.hpp +++ b/data_structures/travel_mode.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -28,7 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef TRAVEL_MODE_HPP #define TRAVEL_MODE_HPP -namespace { +namespace +{ using TravelMode = unsigned char; static const TravelMode TRAVEL_MODE_INACCESSIBLE = 0; static const TravelMode TRAVEL_MODE_DEFAULT = 1; diff --git a/data_structures/tribool.hpp b/data_structures/tribool.hpp index 446bf31ea..2d4b6108d 100644 --- a/data_structures/tribool.hpp +++ b/data_structures/tribool.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/turn_instructions.hpp b/data_structures/turn_instructions.hpp index 4b36658b3..1ca065f68 100644 --- a/data_structures/turn_instructions.hpp +++ b/data_structures/turn_instructions.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -30,10 +30,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. enum class TurnInstruction : unsigned char { - NoTurn = 0, GoStraight, TurnSlightRight, TurnRight, TurnSharpRight, UTurn, - TurnSharpLeft, TurnLeft, TurnSlightLeft, ReachViaLocation, HeadOn, EnterRoundAbout, - LeaveRoundAbout, StayOnRoundAbout, StartAtEndOfStreet, ReachedYourDestination, - EnterAgainstAllowedDirection, LeaveAgainstAllowedDirection, + NoTurn = 0, + GoStraight, + TurnSlightRight, + TurnRight, + TurnSharpRight, + UTurn, + TurnSharpLeft, + TurnLeft, + TurnSlightLeft, + ReachViaLocation, + HeadOn, + EnterRoundAbout, + LeaveRoundAbout, + StayOnRoundAbout, + StartAtEndOfStreet, + ReachedYourDestination, + EnterAgainstAllowedDirection, + LeaveAgainstAllowedDirection, InverseAccessRestrictionFlag = 127, AccessRestrictionFlag = 128, AccessRestrictionPenalty = 129 @@ -42,7 +56,7 @@ enum class TurnInstruction : unsigned char struct TurnInstructionsClass { TurnInstructionsClass() = delete; - TurnInstructionsClass(const TurnInstructionsClass&) = delete; + TurnInstructionsClass(const TurnInstructionsClass &) = delete; static inline TurnInstruction GetTurnDirectionOfInstruction(const double angle) { @@ -79,7 +93,8 @@ struct TurnInstructionsClass static inline bool TurnIsNecessary(const TurnInstruction turn_instruction) { - if (TurnInstruction::NoTurn == turn_instruction || TurnInstruction::StayOnRoundAbout == turn_instruction) + if (TurnInstruction::NoTurn == turn_instruction || + TurnInstruction::StayOnRoundAbout == turn_instruction) { return false; } diff --git a/data_structures/upper_bound.hpp b/data_structures/upper_bound.hpp index 1fc77de38..80695f2c5 100644 --- a/data_structures/upper_bound.hpp +++ b/data_structures/upper_bound.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/xor_fast_hash.hpp b/data_structures/xor_fast_hash.hpp index 9e952193d..3af5ab1db 100644 --- a/data_structures/xor_fast_hash.hpp +++ b/data_structures/xor_fast_hash.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/data_structures/xor_fast_hash_storage.hpp b/data_structures/xor_fast_hash_storage.hpp index 3da95e7c2..ff65717a3 100644 --- a/data_structures/xor_fast_hash_storage.hpp +++ b/data_structures/xor_fast_hash_storage.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/datastore.cpp b/datastore.cpp index 77d933fda..3c032a2a9 100644 --- a/datastore.cpp +++ b/datastore.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -61,7 +61,6 @@ using QueryGraph = StaticGraph; #include - #include #include diff --git a/descriptors/description_factory.cpp b/descriptors/description_factory.cpp index 4d9918759..e4665622f 100644 --- a/descriptors/description_factory.cpp +++ b/descriptors/description_factory.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/descriptors/description_factory.hpp b/descriptors/description_factory.hpp index 7f975e030..985f9c1c5 100644 --- a/descriptors/description_factory.hpp +++ b/descriptors/description_factory.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/descriptors/descriptor_base.hpp b/descriptors/descriptor_base.hpp index 0526047fe..70d8f1c04 100644 --- a/descriptors/descriptor_base.hpp +++ b/descriptors/descriptor_base.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/descriptors/gpx_descriptor.hpp b/descriptors/gpx_descriptor.hpp index deda9c52f..fb4c5b9de 100644 --- a/descriptors/gpx_descriptor.hpp +++ b/descriptors/gpx_descriptor.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/descriptors/json_descriptor.hpp b/descriptors/json_descriptor.hpp index 7e731691e..35dd9c91e 100644 --- a/descriptors/json_descriptor.hpp +++ b/descriptors/json_descriptor.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extract.cpp b/extract.cpp index cb953a566..a14762983 100644 --- a/extract.cpp +++ b/extract.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extractor/extraction_containers.cpp b/extractor/extraction_containers.cpp index e40959d62..8c484eb81 100644 --- a/extractor/extraction_containers.cpp +++ b/extractor/extraction_containers.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extractor/extraction_containers.hpp b/extractor/extraction_containers.hpp index ec5b620ea..12d88a26c 100644 --- a/extractor/extraction_containers.hpp +++ b/extractor/extraction_containers.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extractor/extraction_helper_functions.hpp b/extractor/extraction_helper_functions.hpp index ef840212b..c56c3b7e5 100644 --- a/extractor/extraction_helper_functions.hpp +++ b/extractor/extraction_helper_functions.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extractor/extraction_node.hpp b/extractor/extraction_node.hpp index 7fd7d7ca9..e821d6ffa 100644 --- a/extractor/extraction_node.hpp +++ b/extractor/extraction_node.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extractor/extraction_way.hpp b/extractor/extraction_way.hpp index 97133b3af..d47de20b0 100644 --- a/extractor/extraction_way.hpp +++ b/extractor/extraction_way.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extractor/extractor.cpp b/extractor/extractor.cpp index b7d84156c..0581e4e5c 100644 --- a/extractor/extractor.cpp +++ b/extractor/extractor.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extractor/extractor.hpp b/extractor/extractor.hpp index c06968c55..8ea56c3cb 100644 --- a/extractor/extractor.hpp +++ b/extractor/extractor.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extractor/extractor_callbacks.cpp b/extractor/extractor_callbacks.cpp index 2770cd918..224468b06 100644 --- a/extractor/extractor_callbacks.cpp +++ b/extractor/extractor_callbacks.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extractor/extractor_callbacks.hpp b/extractor/extractor_callbacks.hpp index 0bb30104b..8eab0182b 100644 --- a/extractor/extractor_callbacks.hpp +++ b/extractor/extractor_callbacks.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extractor/extractor_options.cpp b/extractor/extractor_options.cpp index 12ac458fc..9ae5cd4c1 100644 --- a/extractor/extractor_options.cpp +++ b/extractor/extractor_options.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extractor/extractor_options.hpp b/extractor/extractor_options.hpp index 4c5e2b696..5712ea01a 100644 --- a/extractor/extractor_options.hpp +++ b/extractor/extractor_options.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extractor/first_and_last_segment_of_way.hpp b/extractor/first_and_last_segment_of_way.hpp index 8e8ad7276..3a26be7ce 100644 --- a/extractor/first_and_last_segment_of_way.hpp +++ b/extractor/first_and_last_segment_of_way.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extractor/internal_extractor_edge.hpp b/extractor/internal_extractor_edge.hpp index 2760f7256..27e1af146 100644 --- a/extractor/internal_extractor_edge.hpp +++ b/extractor/internal_extractor_edge.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extractor/restriction_parser.cpp b/extractor/restriction_parser.cpp index de73dda5f..ea9cad27a 100644 --- a/extractor/restriction_parser.cpp +++ b/extractor/restriction_parser.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extractor/restriction_parser.hpp b/extractor/restriction_parser.hpp index 8347de306..0a632d83e 100644 --- a/extractor/restriction_parser.hpp +++ b/extractor/restriction_parser.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extractor/scripting_environment.cpp b/extractor/scripting_environment.cpp index 0cc073a39..2b34b8047 100644 --- a/extractor/scripting_environment.cpp +++ b/extractor/scripting_environment.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/extractor/scripting_environment.hpp b/extractor/scripting_environment.hpp index 8cc862a6a..be05103c8 100644 --- a/extractor/scripting_environment.hpp +++ b/extractor/scripting_environment.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/include/osrm/coordinate.hpp b/include/osrm/coordinate.hpp index 546515d49..6318465e1 100644 --- a/include/osrm/coordinate.hpp +++ b/include/osrm/coordinate.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/include/osrm/json_container.hpp b/include/osrm/json_container.hpp index 4ec164965..40f39b825 100644 --- a/include/osrm/json_container.hpp +++ b/include/osrm/json_container.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/include/osrm/libosrm_config.hpp b/include/osrm/libosrm_config.hpp index 2f0edaf35..777a0ccb9 100644 --- a/include/osrm/libosrm_config.hpp +++ b/include/osrm/libosrm_config.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/include/osrm/route_parameters.hpp b/include/osrm/route_parameters.hpp index 0a450d571..ca3c4bdcb 100644 --- a/include/osrm/route_parameters.hpp +++ b/include/osrm/route_parameters.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/include/osrm/server_paths.hpp b/include/osrm/server_paths.hpp index 52b60c7c4..60553a632 100644 --- a/include/osrm/server_paths.hpp +++ b/include/osrm/server_paths.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/library/osrm.hpp b/library/osrm.hpp index dd7ffd749..27acb4039 100644 --- a/library/osrm.hpp +++ b/library/osrm.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/library/osrm_impl.cpp b/library/osrm_impl.cpp index 0aec3f15c..71ea1fb1d 100644 --- a/library/osrm_impl.cpp +++ b/library/osrm_impl.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/library/osrm_impl.hpp b/library/osrm_impl.hpp index 3f235f6ec..a736c042f 100644 --- a/library/osrm_impl.hpp +++ b/library/osrm_impl.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/plugins/distance_table.hpp b/plugins/distance_table.hpp index d4dfdc322..d7a980419 100644 --- a/plugins/distance_table.hpp +++ b/plugins/distance_table.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/plugins/hello_world.hpp b/plugins/hello_world.hpp index 269441715..faf5b1048 100644 --- a/plugins/hello_world.hpp +++ b/plugins/hello_world.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/plugins/locate.hpp b/plugins/locate.hpp index 397bde649..144765ad8 100644 --- a/plugins/locate.hpp +++ b/plugins/locate.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/plugins/nearest.hpp b/plugins/nearest.hpp index fc4e98046..81aa01e9c 100644 --- a/plugins/nearest.hpp +++ b/plugins/nearest.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/plugins/plugin_base.hpp b/plugins/plugin_base.hpp index 9b839016c..b20525643 100644 --- a/plugins/plugin_base.hpp +++ b/plugins/plugin_base.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/plugins/timestamp.hpp b/plugins/timestamp.hpp index 59a8f56f9..8a5d208b7 100644 --- a/plugins/timestamp.hpp +++ b/plugins/timestamp.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/plugins/viaroute.hpp b/plugins/viaroute.hpp index dd5edee57..335bda1af 100644 --- a/plugins/viaroute.hpp +++ b/plugins/viaroute.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/prepare.cpp b/prepare.cpp index 2fbe6ba70..af10df035 100644 --- a/prepare.cpp +++ b/prepare.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/routed.cpp b/routed.cpp index a5ba4906d..ce5691715 100644 --- a/routed.cpp +++ b/routed.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/routing_algorithms/alternative_path.hpp b/routing_algorithms/alternative_path.hpp index 5bbc1e067..7dd15b533 100644 --- a/routing_algorithms/alternative_path.hpp +++ b/routing_algorithms/alternative_path.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/routing_algorithms/many_to_many.hpp b/routing_algorithms/many_to_many.hpp index f1e996096..48bea0250 100644 --- a/routing_algorithms/many_to_many.hpp +++ b/routing_algorithms/many_to_many.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -39,7 +39,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -template class ManyToManyRouting final : public BasicRoutingInterface +template +class ManyToManyRouting final : public BasicRoutingInterface { using super = BasicRoutingInterface; using QueryHeap = SearchEngineData::QueryHeap; @@ -64,8 +65,8 @@ template class ManyToManyRouting final : public BasicRouting ~ManyToManyRouting() {} - std::shared_ptr> operator()(const PhantomNodeArray &phantom_nodes_array) - const + std::shared_ptr> + operator()(const PhantomNodeArray &phantom_nodes_array) const { const auto number_of_locations = phantom_nodes_array.size(); std::shared_ptr> result_table = @@ -134,11 +135,8 @@ template class ManyToManyRouting final : public BasicRouting // explore search space while (!query_heap.Empty()) { - ForwardRoutingStep(source_id, - number_of_locations, - query_heap, - search_space_with_buckets, - result_table); + ForwardRoutingStep(source_id, number_of_locations, query_heap, + search_space_with_buckets, result_table); } ++source_id; @@ -237,8 +235,8 @@ template class ManyToManyRouting final : public BasicRouting // Stalling template - inline bool StallAtNode(const NodeID node, const EdgeWeight distance, QueryHeap &query_heap) - const + inline bool + StallAtNode(const NodeID node, const EdgeWeight distance, QueryHeap &query_heap) const { for (auto edge : super::facade->GetAdjacentEdgeRange(node)) { diff --git a/routing_algorithms/routing_base.hpp b/routing_algorithms/routing_base.hpp index 89e152f12..714d903cd 100644 --- a/routing_algorithms/routing_base.hpp +++ b/routing_algorithms/routing_base.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/routing_algorithms/shortest_path.hpp b/routing_algorithms/shortest_path.hpp index 6b6f98277..bd2084008 100644 --- a/routing_algorithms/shortest_path.hpp +++ b/routing_algorithms/shortest_path.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/server/api_grammar.hpp b/server/api_grammar.hpp index 0697e21c8..fecbb92cc 100644 --- a/server/api_grammar.hpp +++ b/server/api_grammar.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/server/connection.cpp b/server/connection.cpp index 9d8b7a76e..41b653e82 100644 --- a/server/connection.cpp +++ b/server/connection.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -69,7 +69,7 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t osrm::tribool result; std::tie(result, compression_type) = request_parser.parse(current_request, incoming_data_buffer.data(), - incoming_data_buffer.data() + bytes_transferred); + incoming_data_buffer.data() + bytes_transferred); // the request has been parsed if (result == osrm::tribool::yes) diff --git a/server/connection.hpp b/server/connection.hpp index 119289080..9228a18a0 100644 --- a/server/connection.hpp +++ b/server/connection.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/server/data_structures/datafacade_base.hpp b/server/data_structures/datafacade_base.hpp index deff7c6ab..977f818a4 100644 --- a/server/data_structures/datafacade_base.hpp +++ b/server/data_structures/datafacade_base.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/server/data_structures/internal_datafacade.hpp b/server/data_structures/internal_datafacade.hpp index 93b261e83..3c8a57c68 100644 --- a/server/data_structures/internal_datafacade.hpp +++ b/server/data_structures/internal_datafacade.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/server/data_structures/shared_barriers.hpp b/server/data_structures/shared_barriers.hpp index 2d7de7e74..e6f1234ca 100644 --- a/server/data_structures/shared_barriers.hpp +++ b/server/data_structures/shared_barriers.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/server/data_structures/shared_datafacade.hpp b/server/data_structures/shared_datafacade.hpp index 4944d320f..468db30e2 100644 --- a/server/data_structures/shared_datafacade.hpp +++ b/server/data_structures/shared_datafacade.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/server/data_structures/shared_datatype.hpp b/server/data_structures/shared_datatype.hpp index f4cc6ca1c..326157389 100644 --- a/server/data_structures/shared_datatype.hpp +++ b/server/data_structures/shared_datatype.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/server/http/compression_type.hpp b/server/http/compression_type.hpp index 49163adab..f0dc692fa 100644 --- a/server/http/compression_type.hpp +++ b/server/http/compression_type.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/server/http/header.hpp b/server/http/header.hpp index 7996be439..08d2476b1 100644 --- a/server/http/header.hpp +++ b/server/http/header.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/server/http/reply.cpp b/server/http/reply.cpp index 2642e2be2..036d1ae05 100644 --- a/server/http/reply.cpp +++ b/server/http/reply.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/server/http/reply.hpp b/server/http/reply.hpp index a4b6cb69b..733818c2c 100644 --- a/server/http/reply.hpp +++ b/server/http/reply.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/server/http/request.hpp b/server/http/request.hpp index 0ad622580..c487fba65 100644 --- a/server/http/request.hpp +++ b/server/http/request.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/server/request_handler.cpp b/server/request_handler.cpp index 25637c3ad..7e99d025f 100644 --- a/server/request_handler.cpp +++ b/server/request_handler.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/server/request_handler.hpp b/server/request_handler.hpp index 1965a79c0..b4019db7d 100644 --- a/server/request_handler.hpp +++ b/server/request_handler.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/server/request_parser.cpp b/server/request_parser.cpp index ff9e0d42d..584dcbeeb 100644 --- a/server/request_parser.cpp +++ b/server/request_parser.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/server/request_parser.hpp b/server/request_parser.hpp index 045db8d17..2b6bf6944 100644 --- a/server/request_parser.hpp +++ b/server/request_parser.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/server/server.hpp b/server/server.hpp index 46a87d23a..0ec316379 100644 --- a/server/server.hpp +++ b/server/server.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/tools/check-hsgr.cpp b/tools/check-hsgr.cpp index be2f973c7..2418a473f 100644 --- a/tools/check-hsgr.cpp +++ b/tools/check-hsgr.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/tools/components.cpp b/tools/components.cpp index 41e7a59ca..85cfd88bd 100644 --- a/tools/components.cpp +++ b/tools/components.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/tools/io-benchmark.cpp b/tools/io-benchmark.cpp index 277bd2ad1..ae76327e2 100644 --- a/tools/io-benchmark.cpp +++ b/tools/io-benchmark.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/tools/simpleclient.cpp b/tools/simpleclient.cpp index 0235b6bdb..40407ced2 100644 --- a/tools/simpleclient.cpp +++ b/tools/simpleclient.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/tools/springclean.cpp b/tools/springclean.cpp index cb4559c1c..2d8910621 100644 --- a/tools/springclean.cpp +++ b/tools/springclean.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/tools/unlock_all_mutexes.cpp b/tools/unlock_all_mutexes.cpp index 9a279ee1e..299aa61f5 100644 --- a/tools/unlock_all_mutexes.cpp +++ b/tools/unlock_all_mutexes.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/unit_tests/algorithm_tests.cpp b/unit_tests/algorithm_tests.cpp index 216a713e4..0a9f3fdff 100644 --- a/unit_tests/algorithm_tests.cpp +++ b/unit_tests/algorithm_tests.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -32,4 +32,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* * This file will contain an automatically generated main function. */ - diff --git a/unit_tests/algorithms/douglas_peucker.cpp b/unit_tests/algorithms/douglas_peucker.cpp index 93e2aee8e..9654e4da3 100644 --- a/unit_tests/algorithms/douglas_peucker.cpp +++ b/unit_tests/algorithms/douglas_peucker.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -40,8 +40,8 @@ BOOST_AUTO_TEST_SUITE(douglas_peucker) SegmentInformation getTestInfo(int lat, int lon, bool necessary) { - return SegmentInformation(FixedPointCoordinate(lat, lon), - 0, 0, 0, TurnInstruction::HeadOn, necessary, false, 0); + return SegmentInformation(FixedPointCoordinate(lat, lon), 0, 0, 0, TurnInstruction::HeadOn, + necessary, false, 0); } BOOST_AUTO_TEST_CASE(all_necessary_test) @@ -53,17 +53,15 @@ BOOST_AUTO_TEST_CASE(all_necessary_test) * / \ * x x */ - std::vector info = { - getTestInfo(5, 5, true), - getTestInfo(6, 6, true), - getTestInfo(10, 10, true), - getTestInfo(5, 15, true) - }; + std::vector info = {getTestInfo(5, 5, true), + getTestInfo(6, 6, true), + getTestInfo(10, 10, true), + getTestInfo(5, 15, true)}; DouglasPeucker dp; for (unsigned z = 0; z < DOUGLAS_PEUCKER_THRESHOLDS.size(); z++) { dp.Run(info, z); - for (const auto& i : info) + for (const auto &i : info) { BOOST_CHECK_EQUAL(i.necessary, true); } @@ -83,17 +81,14 @@ BOOST_AUTO_TEST_CASE(remove_second_node_test) * x */ std::vector info = { - getTestInfo(5 * COORDINATE_PRECISION, - 5 * COORDINATE_PRECISION, true), - getTestInfo(5 * COORDINATE_PRECISION, - 5 * COORDINATE_PRECISION + DOUGLAS_PEUCKER_THRESHOLDS[z], false), - getTestInfo(10 * COORDINATE_PRECISION, - 10 * COORDINATE_PRECISION, false), + getTestInfo(5 * COORDINATE_PRECISION, 5 * COORDINATE_PRECISION, true), + getTestInfo(5 * COORDINATE_PRECISION, + 5 * COORDINATE_PRECISION + DOUGLAS_PEUCKER_THRESHOLDS[z], false), + getTestInfo(10 * COORDINATE_PRECISION, 10 * COORDINATE_PRECISION, false), getTestInfo(10 * COORDINATE_PRECISION, 10 + COORDINATE_PRECISION + DOUGLAS_PEUCKER_THRESHOLDS[z] * 2, false), - getTestInfo(5 * COORDINATE_PRECISION, - 15 * COORDINATE_PRECISION, false), - getTestInfo(5 * COORDINATE_PRECISION + DOUGLAS_PEUCKER_THRESHOLDS[z], + getTestInfo(5 * COORDINATE_PRECISION, 15 * COORDINATE_PRECISION, false), + getTestInfo(5 * COORDINATE_PRECISION + DOUGLAS_PEUCKER_THRESHOLDS[z], 15 * COORDINATE_PRECISION, true), }; BOOST_TEST_MESSAGE("Threshold (" << z << "): " << DOUGLAS_PEUCKER_THRESHOLDS[z]); diff --git a/unit_tests/data_structures/binary_heap.cpp b/unit_tests/data_structures/binary_heap.cpp index 9cfdae260..d039710c0 100644 --- a/unit_tests/data_structures/binary_heap.cpp +++ b/unit_tests/data_structures/binary_heap.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/unit_tests/data_structures/coordinate.cpp b/unit_tests/data_structures/coordinate.cpp index b371368be..6e891563a 100644 --- a/unit_tests/data_structures/coordinate.cpp +++ b/unit_tests/data_structures/coordinate.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/unit_tests/data_structures/range_table.cpp b/unit_tests/data_structures/range_table.cpp index 9c925328a..ec3b724ad 100644 --- a/unit_tests/data_structures/range_table.cpp +++ b/unit_tests/data_structures/range_table.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -52,8 +52,9 @@ void ConstructionTest(std::vector lengths, std::vector offse } } -void -ComputeLengthsOffsets(std::vector &lengths, std::vector &offsets, unsigned num) +void ComputeLengthsOffsets(std::vector &lengths, + std::vector &offsets, + unsigned num) { lengths.resize(num); offsets.resize(num + 1); diff --git a/unit_tests/data_structures/static_graph.cpp b/unit_tests/data_structures/static_graph.cpp index 4f82f8e7b..4b68b254d 100644 --- a/unit_tests/data_structures/static_graph.cpp +++ b/unit_tests/data_structures/static_graph.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/unit_tests/data_structures/static_rtree.cpp b/unit_tests/data_structures/static_rtree.cpp index 44912a6f6..42bc71898 100644 --- a/unit_tests/data_structures/static_rtree.cpp +++ b/unit_tests/data_structures/static_rtree.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/unit_tests/datastructure_tests.cpp b/unit_tests/datastructure_tests.cpp index ab39d8df2..850d61910 100644 --- a/unit_tests/datastructure_tests.cpp +++ b/unit_tests/datastructure_tests.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/bearing.cpp b/util/bearing.cpp index 92c47e6b8..df238277a 100644 --- a/util/bearing.cpp +++ b/util/bearing.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/bearing.hpp b/util/bearing.hpp index 0066e9e02..b8a79ee97 100644 --- a/util/bearing.hpp +++ b/util/bearing.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/boost_filesystem_2_fix.hpp b/util/boost_filesystem_2_fix.hpp index aeab380b2..2e41abd6a 100644 --- a/util/boost_filesystem_2_fix.hpp +++ b/util/boost_filesystem_2_fix.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/cast.hpp b/util/cast.hpp index e28b9ff84..c031e22b6 100644 --- a/util/cast.hpp +++ b/util/cast.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/compute_angle.cpp b/util/compute_angle.cpp index e83b67b75..86be5634b 100644 --- a/util/compute_angle.cpp +++ b/util/compute_angle.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/compute_angle.hpp b/util/compute_angle.hpp index 73682bceb..477e43689 100644 --- a/util/compute_angle.hpp +++ b/util/compute_angle.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/container.hpp b/util/container.hpp index 41c8821f8..c1f3bc77b 100644 --- a/util/container.hpp +++ b/util/container.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/datastore_options.hpp b/util/datastore_options.hpp index 1992860b5..76edc7827 100644 --- a/util/datastore_options.hpp +++ b/util/datastore_options.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/fingerprint.hpp b/util/fingerprint.hpp index 494a877ab..82eb1364a 100644 --- a/util/fingerprint.hpp +++ b/util/fingerprint.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/floating_point.hpp b/util/floating_point.hpp index 5c4810279..13f2d3bc4 100644 --- a/util/floating_point.hpp +++ b/util/floating_point.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/git_sha.cpp.in b/util/git_sha.cpp.in index 5b19337e9..e3686da19 100644 --- a/util/git_sha.cpp.in +++ b/util/git_sha.cpp.in @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/git_sha.hpp b/util/git_sha.hpp index 9e55deff3..b0a9a7ca3 100644 --- a/util/git_sha.hpp +++ b/util/git_sha.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/graph_loader.hpp b/util/graph_loader.hpp index b85f89109..0dfd72aef 100644 --- a/util/graph_loader.hpp +++ b/util/graph_loader.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/ini_file.hpp b/util/ini_file.hpp index 20616257a..b42f9aef8 100644 --- a/util/ini_file.hpp +++ b/util/ini_file.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/integer_range.hpp b/util/integer_range.hpp index 030b2fa63..ea98b1312 100644 --- a/util/integer_range.hpp +++ b/util/integer_range.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013,2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2013,2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/iterator_range.hpp b/util/iterator_range.hpp index a057d7c92..d5224c983 100644 --- a/util/iterator_range.hpp +++ b/util/iterator_range.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/json_renderer.hpp b/util/json_renderer.hpp index 143066cb7..00212a8b7 100644 --- a/util/json_renderer.hpp +++ b/util/json_renderer.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/lua_util.hpp b/util/lua_util.hpp index f367949da..af6277c59 100644 --- a/util/lua_util.hpp +++ b/util/lua_util.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/make_unique.hpp b/util/make_unique.hpp index e670ffd4d..83e230194 100644 --- a/util/make_unique.hpp +++ b/util/make_unique.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM, Dennis Luxen, others +Copyright (c) 2013, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/mercator.cpp b/util/mercator.cpp index ddd80685d..298257630 100644 --- a/util/mercator.cpp +++ b/util/mercator.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/mercator.hpp b/util/mercator.hpp index 2929db2f9..462c73e23 100644 --- a/util/mercator.hpp +++ b/util/mercator.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/osrm_exception.cpp b/util/osrm_exception.cpp index e6b7986e3..9738b8e36 100644 --- a/util/osrm_exception.cpp +++ b/util/osrm_exception.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/osrm_exception.hpp b/util/osrm_exception.hpp index ac5044a79..e9a01381e 100644 --- a/util/osrm_exception.hpp +++ b/util/osrm_exception.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/routed_options.hpp b/util/routed_options.hpp index 74e79b070..322737d6d 100644 --- a/util/routed_options.hpp +++ b/util/routed_options.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/simple_logger.cpp b/util/simple_logger.cpp index 238e0b57d..e3f4f8ed0 100644 --- a/util/simple_logger.cpp +++ b/util/simple_logger.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -33,11 +33,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #else #include #endif -#include -#include -#include -#include - +#include +#include +#include +#include namespace { diff --git a/util/simple_logger.hpp b/util/simple_logger.hpp index f4dfc0b02..df61a9deb 100644 --- a/util/simple_logger.hpp +++ b/util/simple_logger.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/std_hash.hpp b/util/std_hash.hpp index 8b4af3dd8..9e78fcce4 100644 --- a/util/std_hash.hpp +++ b/util/std_hash.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/string_util.hpp b/util/string_util.hpp index 92fac59c7..46b6a5a64 100644 --- a/util/string_util.hpp +++ b/util/string_util.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/timing_util.hpp b/util/timing_util.hpp index 2279bd083..c0c59c8a6 100644 --- a/util/timing_util.hpp +++ b/util/timing_util.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/trigonometry_table.hpp b/util/trigonometry_table.hpp index ebcf7ba4d..234a94e56 100644 --- a/util/trigonometry_table.hpp +++ b/util/trigonometry_table.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/util/xml_renderer.hpp b/util/xml_renderer.hpp index 5783ab133..4ef1e5dc0 100644 --- a/util/xml_renderer.hpp +++ b/util/xml_renderer.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM, Dennis Luxen, others +Copyright (c) 2014, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, From b0f9a0feb4e4d1642c351436d873af8a5be5bd74 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 19 Feb 2015 10:11:49 +0100 Subject: [PATCH 202/360] rename variable name to be a little more telling --- data_structures/route_parameters.cpp | 8 ++++---- include/osrm/route_parameters.hpp | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/data_structures/route_parameters.cpp b/data_structures/route_parameters.cpp index 5f6d37f90..9416a6d69 100644 --- a/data_structures/route_parameters.cpp +++ b/data_structures/route_parameters.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM contributors +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -109,9 +109,9 @@ void RouteParameters::setGeometryFlag(const bool flag) { geometry = flag; } void RouteParameters::setCompressionFlag(const bool flag) { compression = flag; } void RouteParameters::addCoordinate( - const boost::fusion::vector &transmitted_coordinates) + const boost::fusion::vector &received_coordinates) { coordinates.emplace_back( - static_cast(COORDINATE_PRECISION * boost::fusion::at_c<0>(transmitted_coordinates)), - static_cast(COORDINATE_PRECISION * boost::fusion::at_c<1>(transmitted_coordinates))); + static_cast(COORDINATE_PRECISION * boost::fusion::at_c<0>(received_coordinates)), + static_cast(COORDINATE_PRECISION * boost::fusion::at_c<1>(received_coordinates))); } diff --git a/include/osrm/route_parameters.hpp b/include/osrm/route_parameters.hpp index ca3c4bdcb..04538986e 100644 --- a/include/osrm/route_parameters.hpp +++ b/include/osrm/route_parameters.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM contributors +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ROUTE_PARAMETERS_H -#define ROUTE_PARAMETERS_H +#ifndef ROUTE_PARAMETERS_HPP +#define ROUTE_PARAMETERS_HPP #include @@ -69,7 +69,7 @@ struct RouteParameters void setCompressionFlag(const bool flag); - void addCoordinate(const boost::fusion::vector &coordinates); + void addCoordinate(const boost::fusion::vector &received_coordinates); short zoom_level; bool print_instructions; @@ -89,4 +89,4 @@ struct RouteParameters std::vector coordinates; }; -#endif // ROUTE_PARAMETERS_H +#endif // ROUTE_PARAMETERS_HPP From 9b1f108051aa055c546dacea34935fe6d53d0a66 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Thu, 19 Feb 2015 10:40:16 +0100 Subject: [PATCH 203/360] Allow CORS requests in osrm-routed. --- server/request_handler.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/request_handler.cpp b/server/request_handler.cpp index 7e99d025f..d6645f4d8 100644 --- a/server/request_handler.cpp +++ b/server/request_handler.cpp @@ -127,6 +127,11 @@ void RequestHandler::handle_request(const http::request ¤t_request, osrm::json::render(current_reply.content, json_result); return; } + + current_reply.headers.emplace_back("Access-Control-Allow-Origin", "*"); + current_reply.headers.emplace_back("Access-Control-Allow-Methods", "GET"); + current_reply.headers.emplace_back("Access-Control-Allow-Headers", "X-Requested-With"); + // set headers current_reply.headers.emplace_back("Content-Length", cast::integral_to_string(current_reply.content.size())); From dc08c516bf0af3a080305bb311f8ebb4c7030108 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 19 Feb 2015 19:15:16 +0100 Subject: [PATCH 204/360] use std::tie() to simplify lexicographic comparisons --- data_structures/dynamic_graph.hpp | 8 ++------ data_structures/query_edge.hpp | 18 ++++++++---------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/data_structures/dynamic_graph.hpp b/data_structures/dynamic_graph.hpp index 498f94a7c..3a8f520c6 100644 --- a/data_structures/dynamic_graph.hpp +++ b/data_structures/dynamic_graph.hpp @@ -67,13 +67,9 @@ template class DynamicGraph { } - bool operator<(const InputEdge &right) const + bool operator<(const InputEdge &rhs) const { - if (source != right.source) - { - return source < right.source; - } - return target < right.target; + return std::tie(source, target) < std::tie(rhs.source, rhs.target); } }; diff --git a/data_structures/query_edge.hpp b/data_structures/query_edge.hpp index 0d51aac3f..417bb4a13 100644 --- a/data_structures/query_edge.hpp +++ b/data_structures/query_edge.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM contributors +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,11 +25,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef QUERYEDGE_HPP_ -#define QUERYEDGE_HPP_ +#ifndef QUERYEDGE_HPP +#define QUERYEDGE_HPP #include "../typedefs.h" +#include + struct QueryEdge { NodeID source; @@ -60,13 +62,9 @@ struct QueryEdge { } - bool operator<(const QueryEdge &right) const + bool operator<(const QueryEdge &rhs) const { - if (source != right.source) - { - return source < right.source; - } - return target < right.target; + return std::tie(source, target) < std::tie(rhs.source, rhs.target); } bool operator==(const QueryEdge &right) const @@ -78,4 +76,4 @@ struct QueryEdge } }; -#endif /* QUERYEDGE_HPP_ */ +#endif // QUERYEDGE_HPP From e9e12b88f84ac0b772b4aaa47397af41bf2016b0 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 20 Feb 2015 00:34:21 +0100 Subject: [PATCH 205/360] Add CORS Content-Type HTTP header flag Firefox needs this for JSON. --- server/request_handler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/request_handler.cpp b/server/request_handler.cpp index d6645f4d8..a7e9d79b7 100644 --- a/server/request_handler.cpp +++ b/server/request_handler.cpp @@ -130,7 +130,7 @@ void RequestHandler::handle_request(const http::request ¤t_request, current_reply.headers.emplace_back("Access-Control-Allow-Origin", "*"); current_reply.headers.emplace_back("Access-Control-Allow-Methods", "GET"); - current_reply.headers.emplace_back("Access-Control-Allow-Headers", "X-Requested-With"); + current_reply.headers.emplace_back("Access-Control-Allow-Headers", "X-Requested-With, Content-Type"); // set headers current_reply.headers.emplace_back("Content-Length", From 4c4c126361dc23bca68863e9d731de970e50f77e Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 19 Feb 2015 15:17:04 +0100 Subject: [PATCH 206/360] implements a penalty for very narrow road: - implements discussion of #1388 - implements basic test cases --- features/car/maxspeed.feature | 20 ++++++++++++++++++++ profiles/car.lua | 15 +++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index 8f85d3a67..3bc1ad03f 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -73,3 +73,23 @@ OSRM will use 4/5 of the projected free-flow speed. | runway | | | 100 | | | | | runway | | | | 100 | | | | runway | | | | | 100 | | + + Scenario: Car - Too narrow streets should be ignored or incur a penalty + Then routability should be + + | highway | maxspeed | width | maxspeed:forward | maxspeed:backward | forw | backw | + | primary | | | | | 63 km/h | 63 km/h | + | primary | | 3 | | | 31 km/h | 31 km/h | + | primary | 60 | | | | 59 km/h | 59 km/h | + | primary | 60 | 3 | | | 29 km/h | 29 km/h | + | primary | | | 60 | | 59 km/h | 63 km/h | + | primary | | 3 | 60 | | 29 km/h | 31 km/h | + | primary | | | | 60 | 63 km/h | 59 km/h | + | primary | | 3 | | 60 | 31 km/h | 29 km/h | + | primary | 15 | | 60 | | 59 km/h | 23 km/h | + | primary | 15 | 3 | 60 | | 29 km/h | 11 km/h | + | primary | 15 | | | 60 | 23 km/h | 59 km/h | + | primary | 15 | 3 | | 60 | 11 km/h | 29 km/h | + | primary | 15 | | 30 | 60 | 34 km/h | 59 km/h | + | primary | 15 | 3 | 30 | 60 | 17 km/h | 29 km/h | + diff --git a/profiles/car.lua b/profiles/car.lua index 27d0d2343..8e4d09e18 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -248,6 +248,13 @@ function way_function (way, result) return end + local width = math.huge + local width_string = way:get_value_by_key("width") + if width_string and tonumber(width_string:match("%d*")) then + width = tonumber(width_string:match("%d*")) + io.write("width: "..width.."\n") + end + -- Check if we are allowed to access the way local access = find_access_tag(way, access_tags_hierachy) if access_tag_blacklist[access] then @@ -385,12 +392,20 @@ function way_function (way, result) result.ignore_in_grid = true end + -- scale speeds to get better avg driving times if result.forward_speed > 0 then result.forward_speed = result.forward_speed*speed_reduction + 11; + if width <= 3 then + result.forward_speed = result.forward_speed / 2; + end end + if result.backward_speed > 0 then result.backward_speed = result.backward_speed*speed_reduction + 11; + if width <= 3 then + result.backward_speed = result.backward_speed / 2; + end end end From a85fe2cb08cfa2d7f875d4d8d9cec45418930d79 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 19 Feb 2015 16:22:46 +0100 Subject: [PATCH 207/360] remove debug output, thx @emiltin --- profiles/car.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/profiles/car.lua b/profiles/car.lua index 8e4d09e18..24fdc2925 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -252,7 +252,6 @@ function way_function (way, result) local width_string = way:get_value_by_key("width") if width_string and tonumber(width_string:match("%d*")) then width = tonumber(width_string:match("%d*")) - io.write("width: "..width.."\n") end -- Check if we are allowed to access the way From b89c7580e63c3a77455ea80bf0feec244a8e47e8 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 20 Feb 2015 10:28:49 +0100 Subject: [PATCH 208/360] implement scaling for narrow roads as an alternative expected speed and take the minimum. Follows @emiltin's idea. --- features/car/maxspeed.feature | 14 +++++++------- profiles/car.lua | 12 ++++++++---- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index 3bc1ad03f..781f4c617 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -79,17 +79,17 @@ OSRM will use 4/5 of the projected free-flow speed. | highway | maxspeed | width | maxspeed:forward | maxspeed:backward | forw | backw | | primary | | | | | 63 km/h | 63 km/h | - | primary | | 3 | | | 31 km/h | 31 km/h | + | primary | | 3 | | | 32 km/h | 32 km/h | | primary | 60 | | | | 59 km/h | 59 km/h | - | primary | 60 | 3 | | | 29 km/h | 29 km/h | + | primary | 60 | 3 | | | 30 km/h | 30 km/h | | primary | | | 60 | | 59 km/h | 63 km/h | - | primary | | 3 | 60 | | 29 km/h | 31 km/h | + | primary | | 3 | 60 | | 30 km/h | 32 km/h | | primary | | | | 60 | 63 km/h | 59 km/h | - | primary | | 3 | | 60 | 31 km/h | 29 km/h | + | primary | | 3 | | 60 | 32 km/h | 30 km/h | | primary | 15 | | 60 | | 59 km/h | 23 km/h | - | primary | 15 | 3 | 60 | | 29 km/h | 11 km/h | + | primary | 15 | 3 | 60 | | 30 km/h | 7 km/h | | primary | 15 | | | 60 | 23 km/h | 59 km/h | - | primary | 15 | 3 | | 60 | 11 km/h | 29 km/h | + | primary | 15 | 3 | | 60 | 7 km/h | 30 km/h | | primary | 15 | | 30 | 60 | 34 km/h | 59 km/h | - | primary | 15 | 3 | 30 | 60 | 17 km/h | 29 km/h | + | primary | 15 | 3 | 30 | 60 | 15 km/h | 30 km/h | diff --git a/profiles/car.lua b/profiles/car.lua index 24fdc2925..a2b76388d 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -394,17 +394,21 @@ function way_function (way, result) -- scale speeds to get better avg driving times if result.forward_speed > 0 then - result.forward_speed = result.forward_speed*speed_reduction + 11; + local scaled_speed = result.forward_speed*speed_reduction + 11; + local penalized_speed = math.huge if width <= 3 then - result.forward_speed = result.forward_speed / 2; + penalized_speed = result.forward_speed / 2; end + result.forward_speed = math.min(penalized_speed, scaled_speed) end if result.backward_speed > 0 then - result.backward_speed = result.backward_speed*speed_reduction + 11; + local scaled_speed = result.backward_speed*speed_reduction + 11; + local penalized_speed = math.huge if width <= 3 then - result.backward_speed = result.backward_speed / 2; + penalized_speed = result.backward_speed / 2; end + result.backward_speed = math.min(penalized_speed, scaled_speed) end end From 8adab959730131b0205194a091c4e7581f9b8071 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 20 Feb 2015 11:59:03 +0100 Subject: [PATCH 209/360] refactor iterator range utility class --- util/iterator_range.hpp | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/util/iterator_range.hpp b/util/iterator_range.hpp index d5224c983..900426863 100644 --- a/util/iterator_range.hpp +++ b/util/iterator_range.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM contributors +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -25,17 +25,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef RANGE_HPP_ -#define RANGE_HPP_ +#ifndef ITERATOR_RANGE_HPP +#define ITERATOR_RANGE_HPP namespace osrm { -namespace util -{ -template class Range +template class iter_range { public: - Range(Iterator begin, Iterator end) : begin_(begin), end_(end) {} + iter_range(Iterator begin, Iterator end) : begin_(begin), end_(end) {} Iterator begin() const { return begin_; } Iterator end() const { return end_; } @@ -48,25 +46,25 @@ template class Range // Convenience functions for template parameter inference, // akin to std::make_pair. -template Range range(Iterator begin, Iterator end) +template iter_range integer_range(Iterator begin, Iterator end) { - return Range(begin, end); + return iter_range(begin, end); } template -Range reverse(Reversable *reversable) +iter_range reverse(Reversable *reversable) { - return Range(reversable->rbegin(), reversable->rend()); + return iter_range(reversable->rbegin(), + reversable->rend()); } template -Range +iter_range const_reverse(const ConstReversable *const_reversable) { - return Range(const_reversable->crbegin(), - const_reversable->crend()); -} + return iter_range(const_reversable->crbegin(), + const_reversable->crend()); } } -#endif // RANGE_HPP_ +#endif // ITERATOR_RANGE_HPP From 0296c767bf741869a36e4f135e9af8becb36db07 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 24 Feb 2015 09:08:59 +0100 Subject: [PATCH 210/360] fix code-format regression --- server/request_handler.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/request_handler.cpp b/server/request_handler.cpp index a7e9d79b7..d1c6e6265 100644 --- a/server/request_handler.cpp +++ b/server/request_handler.cpp @@ -130,7 +130,8 @@ void RequestHandler::handle_request(const http::request ¤t_request, current_reply.headers.emplace_back("Access-Control-Allow-Origin", "*"); current_reply.headers.emplace_back("Access-Control-Allow-Methods", "GET"); - current_reply.headers.emplace_back("Access-Control-Allow-Headers", "X-Requested-With, Content-Type"); + current_reply.headers.emplace_back("Access-Control-Allow-Headers", + "X-Requested-With, Content-Type"); // set headers current_reply.headers.emplace_back("Content-Length", From 3da1e8598bbab477a235661051db911394fece12 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 24 Feb 2015 14:36:38 +0100 Subject: [PATCH 211/360] fix copyright year --- util/integer_range.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/integer_range.hpp b/util/integer_range.hpp index ea98b1312..df9d43cd4 100644 --- a/util/integer_range.hpp +++ b/util/integer_range.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013,2014, Project OSRM contributors +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, From fdf2e5934d40be6ce46ebea7dc0771e461758842 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Tue, 24 Feb 2015 20:29:14 +0100 Subject: [PATCH 212/360] Add algorithm include for any_of --- plugins/plugin_base.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/plugin_base.hpp b/plugins/plugin_base.hpp index b20525643..7ec00f1ef 100644 --- a/plugins/plugin_base.hpp +++ b/plugins/plugin_base.hpp @@ -34,6 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include class BasePlugin { From bad2576397ab8db06bcc2cb5a122fd3c23774cfd Mon Sep 17 00:00:00 2001 From: RockLobster Date: Wed, 25 Feb 2015 18:25:03 +0100 Subject: [PATCH 213/360] Replaced CMAKE_SOURCE_DIR in osrm root dir's cmake file with CMAKE_CURRENT_SOURCE_DIR => Allows osrm to be used as a subproject aswell --- CMakeLists.txt | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bf2f9c1e..b957d5dce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 2.8.8) -if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE) +if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR AND NOT MSVC_IDE) message(FATAL_ERROR "In-source builds are not allowed. Please create a directory and run cmake from there, passing the path to this source directory as the last argument. This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. Please delete them.") @@ -11,7 +11,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) include(CheckCXXCompilerFlag) include(FindPackageHandleStandardArgs) -list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include(GetGitRevisionDescription) git_describe(GIT_DESCRIPTION) @@ -30,27 +30,27 @@ endif() option(WITH_TOOLS "Build OSRM tools" OFF) option(BUILD_TOOLS "Build OSRM tools" OFF) -include_directories(${CMAKE_SOURCE_DIR}/include/) -include_directories(${CMAKE_SOURCE_DIR}/third_party/) -include_directories(${CMAKE_SOURCE_DIR}/third_party/libosmium/include/) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/third_party/) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/include/) -add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/util/fingerprint.cpp fingerprint.cpp.alwaysbuild - COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR} +add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/util/fingerprint.cpp fingerprint.cpp.alwaysbuild + COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FingerPrint-Config.cmake DEPENDS - ${CMAKE_SOURCE_DIR}/util/fingerprint.cpp.in + ${CMAKE_CURRENT_SOURCE_DIR}/util/fingerprint.cpp.in COMMENT "Configuring fingerprint.cpp" VERBATIM) -add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_SOURCE_DIR}/util/fingerprint.cpp) +add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/util/fingerprint.cpp) add_custom_target(tests DEPENDS datastructure-tests algorithm-tests) add_custom_target(benchmarks DEPENDS rtree-bench) set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread unit_test_framework) configure_file( - ${CMAKE_SOURCE_DIR}/util/git_sha.cpp.in - ${CMAKE_SOURCE_DIR}/util/git_sha.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/util/git_sha.cpp.in + ${CMAKE_CURRENT_SOURCE_DIR}/util/git_sha.cpp ) file(GLOB ExtractorGlob extractor/*.cpp) file(GLOB ImporterGlob data_structures/import_edge.cpp data_structures/external_memory_node.cpp) @@ -361,7 +361,7 @@ foreach(lib ${Boost_LIBRARIES}) set(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_LISTING} -l${BOOST_LIBRARY_NAME}") endforeach() -configure_file(${CMAKE_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY) install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION lib/pkgconfig) if(BUILD_DEBIAN_PACKAGE) From 440eda3807de0e5c31ab5e3cefdcfea014a98e55 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Wed, 25 Feb 2015 21:10:09 +0100 Subject: [PATCH 214/360] Escape string in json renderer --- algorithms/polyline_compressor.cpp | 8 ------ util/json_renderer.hpp | 44 ++++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/algorithms/polyline_compressor.cpp b/algorithms/polyline_compressor.cpp index 6310a2ec9..d5fd5828b 100644 --- a/algorithms/polyline_compressor.cpp +++ b/algorithms/polyline_compressor.cpp @@ -56,19 +56,11 @@ std::string PolylineCompressor::encode_number(int number_to_encode) const { const int next_value = (0x20 | (number_to_encode & 0x1f)) + 63; output += static_cast(next_value); - if (92 == next_value) - { - output += static_cast(next_value); - } number_to_encode >>= 5; } number_to_encode += 63; output += static_cast(number_to_encode); - if (92 == number_to_encode) - { - output += static_cast(number_to_encode); - } return output; } diff --git a/util/json_renderer.hpp b/util/json_renderer.hpp index 00212a8b7..5a49d3c98 100644 --- a/util/json_renderer.hpp +++ b/util/json_renderer.hpp @@ -40,11 +40,33 @@ namespace osrm namespace json { + struct Renderer : mapbox::util::static_visitor<> { explicit Renderer(std::ostream &_out) : out(_out) {} - void operator()(const String &string) const { out << "\"" << string.value << "\""; } + void operator()(const String &string) const { + out << "\""; + + // check if we need escaping + std::size_t pos = string.value.find_first_of('\\'); + if (pos != std::string::npos) + { + std::string escapedString(string.value); + do + { + escapedString.insert(pos, 1, '\\'); + pos = escapedString.find_first_of('\\', pos); + } while (pos != std::string::npos); + } + // no need to escape + else + { + out << string.value; + } + + out << "\""; + } void operator()(const Number &number) const { @@ -101,7 +123,25 @@ struct ArrayRenderer : mapbox::util::static_visitor<> void operator()(const String &string) const { out.push_back('\"'); - out.insert(out.end(), string.value.begin(), string.value.end()); + + // check if we need escaping + std::size_t pos = string.value.find_first_of('\\'); + if (pos != std::string::npos) + { + std::string escapedString(string.value); + do + { + escapedString.insert(pos, 1, '\\'); + pos = escapedString.find_first_of('\\', pos+2); + } while (pos != std::string::npos); + out.insert(out.end(), escapedString.begin(), escapedString.end()); + } + // no need to escape + else + { + out.insert(out.end(), string.value.begin(), string.value.end()); + } + out.push_back('\"'); } From 37fb89c691c28799e71a08d1c2dcd890b54bd50b Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 26 Feb 2015 10:10:19 +0100 Subject: [PATCH 215/360] add size() call to integer range --- util/integer_range.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/util/integer_range.hpp b/util/integer_range.hpp index df9d43cd4..811bbbe9f 100644 --- a/util/integer_range.hpp +++ b/util/integer_range.hpp @@ -50,6 +50,7 @@ template class range const range &end() const { return *this; } Integer front() const { return iter; } Integer back() const { return last - 1; } + Integer size() const { return last - iter; } // Iterator functions bool operator!=(const range &) const { return iter < last; } From 51e42ded446998dd6e6846de2ccea59342fff6d2 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 26 Feb 2015 10:11:33 +0100 Subject: [PATCH 216/360] - output only get escaped when actually output. Better seperation of functionality - refactor facade::GetEscapeName() into get_name_for_id() call that is implemented in subclasses - remove dead code - fix failing tests where names got double-escaped - fixes https://github.com/Project-OSRM/node-osrm/issues/83 --- algorithms/route_name_extraction.hpp | 12 +++-- descriptors/descriptor_base.hpp | 2 + descriptors/json_descriptor.hpp | 18 +++----- plugins/nearest.hpp | 10 ++--- server/data_structures/datafacade_base.hpp | 9 +--- .../data_structures/internal_datafacade.hpp | 15 ++++--- server/data_structures/shared_datafacade.hpp | 12 ++--- util/json_renderer.hpp | 45 +++---------------- util/string_util.hpp | 11 ++++- 9 files changed, 50 insertions(+), 84 deletions(-) diff --git a/algorithms/route_name_extraction.hpp b/algorithms/route_name_extraction.hpp index 8275de099..00dae89c4 100644 --- a/algorithms/route_name_extraction.hpp +++ b/algorithms/route_name_extraction.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM contributors +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -147,15 +147,13 @@ template struct ExtractRouteNames } // fetching names for the selected segments - route_names.shortest_path_name_1 = - facade->GetEscapedNameForNameID(shortest_segment_1.name_id); - route_names.shortest_path_name_2 = - facade->GetEscapedNameForNameID(shortest_segment_2.name_id); + route_names.shortest_path_name_1 = facade->get_name_for_id(shortest_segment_1.name_id); + route_names.shortest_path_name_2 = facade->get_name_for_id(shortest_segment_2.name_id); route_names.alternative_path_name_1 = - facade->GetEscapedNameForNameID(alternative_segment_1.name_id); + facade->get_name_for_id(alternative_segment_1.name_id); route_names.alternative_path_name_2 = - facade->GetEscapedNameForNameID(alternative_segment_2.name_id); + facade->get_name_for_id(alternative_segment_2.name_id); return route_names; } diff --git a/descriptors/descriptor_base.hpp b/descriptors/descriptor_base.hpp index 70d8f1c04..497c2161d 100644 --- a/descriptors/descriptor_base.hpp +++ b/descriptors/descriptor_base.hpp @@ -33,6 +33,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/phantom_node.hpp" #include "../typedefs.h" +#include + #include #include diff --git a/descriptors/json_descriptor.hpp b/descriptors/json_descriptor.hpp index 35dd9c91e..352b55a94 100644 --- a/descriptors/json_descriptor.hpp +++ b/descriptors/json_descriptor.hpp @@ -113,9 +113,6 @@ template class JSONDescriptor final : public BaseDescriptor< } // check if first segment is non-zero - std::string road_name = facade->GetEscapedNameForNameID( - raw_route.segment_end_coordinates.front().source_phantom.name_id); - BOOST_ASSERT(raw_route.unpacked_path_segments.size() == raw_route.segment_end_coordinates.size()); @@ -157,9 +154,9 @@ template class JSONDescriptor final : public BaseDescriptor< json_route_summary.values["total_distance"] = description_factory.summary.distance; json_route_summary.values["total_time"] = description_factory.summary.duration; json_route_summary.values["start_point"] = - facade->GetEscapedNameForNameID(description_factory.summary.source_name_id); + facade->get_name_for_id(description_factory.summary.source_name_id); json_route_summary.values["end_point"] = - facade->GetEscapedNameForNameID(description_factory.summary.target_name_id); + facade->get_name_for_id(description_factory.summary.target_name_id); json_result.values["route_summary"] = json_route_summary; BOOST_ASSERT(!raw_route.segment_end_coordinates.empty()); @@ -241,10 +238,10 @@ template class JSONDescriptor final : public BaseDescriptor< alternate_description_factory.summary.distance; json_alternate_route_summary.values["total_time"] = alternate_description_factory.summary.duration; - json_alternate_route_summary.values["start_point"] = facade->GetEscapedNameForNameID( - alternate_description_factory.summary.source_name_id); - json_alternate_route_summary.values["end_point"] = facade->GetEscapedNameForNameID( - alternate_description_factory.summary.target_name_id); + json_alternate_route_summary.values["start_point"] = + facade->get_name_for_id(alternate_description_factory.summary.source_name_id); + json_alternate_route_summary.values["end_point"] = + facade->get_name_for_id(alternate_description_factory.summary.target_name_id); json_alternate_route_summary_array.values.push_back(json_alternate_route_summary); json_result.values["alternative_summaries"] = json_alternate_route_summary_array; @@ -349,8 +346,7 @@ template class JSONDescriptor final : public BaseDescriptor< } json_instruction_row.values.push_back(current_turn_instruction); - json_instruction_row.values.push_back( - facade->GetEscapedNameForNameID(segment.name_id)); + json_instruction_row.values.push_back(facade->get_name_for_id(segment.name_id)); json_instruction_row.values.push_back(std::round(segment.length)); json_instruction_row.values.push_back(necessary_segments_running_index); json_instruction_row.values.push_back(std::round(segment.duration / 10.)); diff --git a/plugins/nearest.hpp b/plugins/nearest.hpp index 81aa01e9c..bf4cff3a1 100644 --- a/plugins/nearest.hpp +++ b/plugins/nearest.hpp @@ -88,9 +88,8 @@ template class NearestPlugin final : public BasePlugin json_coordinate.values.push_back(phantom_node_vector.at(i).location.lon / COORDINATE_PRECISION); result.values["mapped coordinate"] = json_coordinate; - std::string temp_string; - facade->GetName(phantom_node_vector.at(i).name_id, temp_string); - result.values["name"] = temp_string; + result.values["name"] = + facade->get_name_for_id(phantom_node_vector.at(i).name_id); results.values.push_back(result); } json_result.values["results"] = results; @@ -103,9 +102,8 @@ template class NearestPlugin final : public BasePlugin json_coordinate.values.push_back(phantom_node_vector.front().location.lon / COORDINATE_PRECISION); json_result.values["mapped_coordinate"] = json_coordinate; - std::string temp_string; - facade->GetName(phantom_node_vector.front().name_id, temp_string); - json_result.values["name"] = temp_string; + json_result.values["name"] = + facade->get_name_for_id(phantom_node_vector.front().name_id); } } return 200; diff --git a/server/data_structures/datafacade_base.hpp b/server/data_structures/datafacade_base.hpp index 977f818a4..0a2d22025 100644 --- a/server/data_structures/datafacade_base.hpp +++ b/server/data_structures/datafacade_base.hpp @@ -109,14 +109,7 @@ template class BaseDataFacade virtual unsigned GetNameIndexFromEdgeID(const unsigned id) const = 0; - virtual void GetName(const unsigned name_id, std::string &result) const = 0; - - std::string GetEscapedNameForNameID(const unsigned name_id) const - { - std::string temporary_string; - GetName(name_id, temporary_string); - return EscapeJSONString(temporary_string); - } + virtual std::string get_name_for_id(const unsigned name_id) const = 0; virtual std::string GetTimestamp() const = 0; }; diff --git a/server/data_structures/internal_datafacade.hpp b/server/data_structures/internal_datafacade.hpp index 3c8a57c68..746402418 100644 --- a/server/data_structures/internal_datafacade.hpp +++ b/server/data_structures/internal_datafacade.hpp @@ -46,6 +46,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include + template class InternalDataFacade final : public BaseDataFacade { @@ -418,24 +420,25 @@ template class InternalDataFacade final : public BaseDataFacad unsigned GetNameIndexFromEdgeID(const unsigned id) const override final { return m_name_ID_list.at(id); - }; + } - void GetName(const unsigned name_id, std::string &result) const override final + std::string get_name_for_id(const unsigned name_id) const override final { - if (UINT_MAX == name_id) + if (std::numeric_limits::max() == name_id) { - result = ""; - return; + return ""; } auto range = m_name_table.GetRange(name_id); - result.clear(); + std::string result; + result.reserve(range.size()); if (range.begin() != range.end()) { result.resize(range.back() - range.front() + 1); std::copy(m_names_char_list.begin() + range.front(), m_names_char_list.begin() + range.back() + 1, result.begin()); } + return result; } virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const override final diff --git a/server/data_structures/shared_datafacade.hpp b/server/data_structures/shared_datafacade.hpp index 468db30e2..fcec478b2 100644 --- a/server/data_structures/shared_datafacade.hpp +++ b/server/data_structures/shared_datafacade.hpp @@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../util/simple_logger.hpp" #include +#include #include template class SharedDataFacade final : public BaseDataFacade @@ -409,22 +410,23 @@ template class SharedDataFacade final : public BaseDataFacade< return m_name_ID_list.at(id); }; - void GetName(const unsigned name_id, std::string &result) const override final + std::string get_name_for_id(const unsigned name_id) const override final { - if (UINT_MAX == name_id) + if (std::numeric_limits::max() == name_id) { - result = ""; - return; + return ""; } auto range = m_name_table->GetRange(name_id); - result.clear(); + std::string result; + result.reserve(range.size()); if (range.begin() != range.end()) { result.resize(range.back() - range.front() + 1); std::copy(m_names_char_list.begin() + range.front(), m_names_char_list.begin() + range.back() + 1, result.begin()); } + return result; } std::string GetTimestamp() const override final { return m_timestamp; } diff --git a/util/json_renderer.hpp b/util/json_renderer.hpp index 5a49d3c98..e5bbf6f92 100644 --- a/util/json_renderer.hpp +++ b/util/json_renderer.hpp @@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define JSON_RENDERER_HPP #include "cast.hpp" +#include "string_util.hpp" #include @@ -40,31 +41,14 @@ namespace osrm namespace json { - struct Renderer : mapbox::util::static_visitor<> { explicit Renderer(std::ostream &_out) : out(_out) {} - void operator()(const String &string) const { + void operator()(const String &string) const + { out << "\""; - - // check if we need escaping - std::size_t pos = string.value.find_first_of('\\'); - if (pos != std::string::npos) - { - std::string escapedString(string.value); - do - { - escapedString.insert(pos, 1, '\\'); - pos = escapedString.find_first_of('\\', pos); - } while (pos != std::string::npos); - } - // no need to escape - else - { - out << string.value; - } - + out << escape_JSON(string.value); out << "\""; } @@ -123,25 +107,8 @@ struct ArrayRenderer : mapbox::util::static_visitor<> void operator()(const String &string) const { out.push_back('\"'); - - // check if we need escaping - std::size_t pos = string.value.find_first_of('\\'); - if (pos != std::string::npos) - { - std::string escapedString(string.value); - do - { - escapedString.insert(pos, 1, '\\'); - pos = escapedString.find_first_of('\\', pos+2); - } while (pos != std::string::npos); - out.insert(out.end(), escapedString.begin(), escapedString.end()); - } - // no need to escape - else - { - out.insert(out.end(), string.value.begin(), string.value.end()); - } - + const auto string_to_insert = escape_JSON(string.value); + out.insert(std::end(out), std::begin(string_to_insert), std::end(string_to_insert)); out.push_back('\"'); } diff --git a/util/string_util.hpp b/util/string_util.hpp index 46b6a5a64..31be0444b 100644 --- a/util/string_util.hpp +++ b/util/string_util.hpp @@ -77,10 +77,17 @@ inline void replaceAll(std::string &s, const std::string &sub, const std::string boost::replace_all(s, sub, other); } -inline std::string EscapeJSONString(const std::string &input) +inline std::string escape_JSON(const std::string &input) { + // return the input if no backslash can be found -> no allocations + if (input.find_first_of('\\') == std::string::npos) + { + return input; + } + + // escape and skip reallocations if possible std::string output; - output.reserve(input.size()); + output.reserve(input.size() + 4); // +4 assumes two backslashes on avg for (auto iter = input.begin(); iter != input.end(); ++iter) { switch (iter[0]) From 645e3ccbb30c64aff14eb2239e5f460e6de56511 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 26 Feb 2015 14:56:01 +0100 Subject: [PATCH 217/360] add movable bridge support to the car profile. Implements #1399 --- features/car/bridge.feature | 47 +++++++++++++++++++++++++++++++++++++ profiles/car.lua | 25 +++++++++++++++++--- 2 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 features/car/bridge.feature diff --git a/features/car/bridge.feature b/features/car/bridge.feature new file mode 100644 index 000000000..41dc10bdb --- /dev/null +++ b/features/car/bridge.feature @@ -0,0 +1,47 @@ +@routing @car @bridge +Feature: Car - Handle movable bridge + + Background: + Given the profile "car" + + Scenario: Car - Use a ferry route + Given the node map + | a | b | c | | | + | | | d | | | + | | | e | f | g | + + And the ways + | nodes | highway | bridge | bicycle | + | abc | primary | | | + | cde | | movable | yes | + | efg | primary | | | + + When I route I should get + | from | to | route | modes | + | a | g | abc,cde,efg | 1,3,1 | + | b | f | abc,cde,efg | 1,3,1 | + | e | c | cde | 3 | + | e | b | cde,abc | 3,1 | + | e | a | cde,abc | 3,1 | + | c | e | cde | 3 | + | c | f | cde,efg | 3,1 | + | c | g | cde,efg | 3,1 | + + Scenario: Car - Properly handle durations + Given the node map + | a | b | c | | | + | | | d | | | + | | | e | f | g | + + And the ways + | nodes | highway | bridge | duration | + | abc | primary | | | + | cde | | movable | 00:05:00 | + | efg | primary | | | + + When I route I should get + | from | to | route | modes | speed | + | a | g | abc,cde,efg | 1,3,1 | 6 km/h | + | b | f | abc,cde,efg | 1,3,1 | 4 km/h | + | c | e | cde | 3 | 2 km/h | + | e | c | cde | 3 | 2 km/h | diff --git a/profiles/car.lua b/profiles/car.lua index a2b76388d..175a98945 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -28,6 +28,7 @@ speed_profile = { ["service"] = 15, -- ["track"] = 5, ["ferry"] = 5, + ["movable"] = 5, ["shuttle_train"] = 10, ["default"] = 10 } @@ -144,6 +145,7 @@ local speed_reduction = 0.8 --modes local mode_normal = 1 local mode_ferry = 2 +local mode_movable_bridge = 3 local function find_access_tag(source, access_tags_hierachy) for i,v in ipairs(access_tags_hierachy) do @@ -221,8 +223,9 @@ end function way_function (way, result) local highway = way:get_value_by_key("highway") local route = way:get_value_by_key("route") + local bridge = way:get_value_by_key("bridge") - if not ((highway and highway ~= "") or (route and route ~= "")) then + if not ((highway and highway ~= "") or (route and route ~= "") or (bridge and bridge ~= "")) then return end @@ -260,9 +263,9 @@ function way_function (way, result) return end - -- Handling ferries and piers + -- handling ferries and piers local route_speed = speed_profile[route] - if(route_speed and route_speed > 0) then + if (route_speed and route_speed > 0) then highway = route; local duration = way:get_value_by_key("duration") if duration and durationIsValid(duration) then @@ -274,6 +277,22 @@ function way_function (way, result) result.backward_speed = route_speed end + -- handling movable bridges + local bridge_speed = speed_profile[bridge] + if (bridge_speed and bridge_speed > 0) then + io.write("-bridge: "..bridge.."\n") + highway = bridge; + io.write("-highway: "..highway.."\n") + local duration = way:get_value_by_key("duration") + if duration and durationIsValid(duration) then + result.duration = max( parseDuration(duration), 1 ); + end + result.forward_mode = mode_movable_bridge + result.backward_mode = mode_movable_bridge + result.forward_speed = bridge_speed + result.backward_speed = bridge_speed + end + -- leave early of this way is not accessible if "" == highway then return From 7cf363eb067bb6789c498de4c155dd7a7790fb8a Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 26 Feb 2015 16:09:48 +0100 Subject: [PATCH 218/360] reorder includes, fixes style regression from commit fdf2e59. --- plugins/plugin_base.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/plugin_base.hpp b/plugins/plugin_base.hpp index 7ec00f1ef..acc820432 100644 --- a/plugins/plugin_base.hpp +++ b/plugins/plugin_base.hpp @@ -32,9 +32,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include #include -#include class BasePlugin { From 845020b0e2fe37da30fdef1316ab78410983174a Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 26 Feb 2015 16:17:42 +0100 Subject: [PATCH 219/360] remove debug output --- profiles/car.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/profiles/car.lua b/profiles/car.lua index 175a98945..cb10a5e9f 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -280,9 +280,7 @@ function way_function (way, result) -- handling movable bridges local bridge_speed = speed_profile[bridge] if (bridge_speed and bridge_speed > 0) then - io.write("-bridge: "..bridge.."\n") highway = bridge; - io.write("-highway: "..highway.."\n") local duration = way:get_value_by_key("duration") if duration and durationIsValid(duration) then result.duration = max( parseDuration(duration), 1 ); From dd5f9260776a56854ab15554ca54ee0ce59d3a2d Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 26 Feb 2015 16:22:18 +0100 Subject: [PATCH 220/360] respect capacity:car for movable bridges in car profile --- profiles/car.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/profiles/car.lua b/profiles/car.lua index cb10a5e9f..ac008a1b8 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -279,7 +279,8 @@ function way_function (way, result) -- handling movable bridges local bridge_speed = speed_profile[bridge] - if (bridge_speed and bridge_speed > 0) then + local capacity_car = way:get_value_by_key("capacity:car") + if (bridge_speed and bridge_speed > 0) and (capacity_car ~= 0) then highway = bridge; local duration = way:get_value_by_key("duration") if duration and durationIsValid(duration) then From 6b88856c16c0629f84a8f83f32678e6e041aae9b Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 26 Feb 2015 16:28:04 +0100 Subject: [PATCH 221/360] add support for movable bridges in the biking profile, cf #1399 --- features/bicycle/bridge.feature | 47 +++++++++++++++++++++++++++++++++ profiles/bicycle.lua | 13 ++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 features/bicycle/bridge.feature diff --git a/features/bicycle/bridge.feature b/features/bicycle/bridge.feature new file mode 100644 index 000000000..a90afea3b --- /dev/null +++ b/features/bicycle/bridge.feature @@ -0,0 +1,47 @@ +@routing @bicycle @bridge +Feature: Bicycle - Handle movable bridge + + Background: + Given the profile "bicycle" + + Scenario: Car - Use a ferry route + Given the node map + | a | b | c | | | + | | | d | | | + | | | e | f | g | + + And the ways + | nodes | highway | bridge | bicycle | + | abc | primary | | | + | cde | | movable | yes | + | efg | primary | | | + + When I route I should get + | from | to | route | modes | + | a | g | abc,cde,efg | 1,3,1 | + | b | f | abc,cde,efg | 1,3,1 | + | e | c | cde | 3 | + | e | b | cde,abc | 3,1 | + | e | a | cde,abc | 3,1 | + | c | e | cde | 3 | + | c | f | cde,efg | 3,1 | + | c | g | cde,efg | 3,1 | + + Scenario: Car - Properly handle durations + Given the node map + | a | b | c | | | + | | | d | | | + | | | e | f | g | + + And the ways + | nodes | highway | bridge | duration | + | abc | primary | | | + | cde | | movable | 00:05:00 | + | efg | primary | | | + + When I route I should get + | from | to | route | modes | speed | + | a | g | abc,cde,efg | 1,3,1 | 6 km/h | + | b | f | abc,cde,efg | 1,3,1 | 4 km/h | + | c | e | cde | 3 | 2 km/h | + | e | c | cde | 3 | 2 km/h | diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 713c6b737..a496d3536 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -219,7 +219,18 @@ function way_function (way, result) end -- speed - if route_speeds[route] then + local bridge_speed = speed_profile[bridge] + if (bridge_speed and bridge_speed > 0) then + highway = bridge; + local duration = way:get_value_by_key("duration") + if duration and durationIsValid(duration) then + result.duration = max( parseDuration(duration), 1 ); + end + result.forward_mode = mode_movable_bridge + result.backward_mode = mode_movable_bridge + result.forward_speed = bridge_speed + result.backward_speed = bridge_speed + elseif route_speeds[route] then -- ferries (doesn't cover routes tagged using relations) result.forward_mode = mode_ferry result.backward_mode = mode_ferry From 023dd3e8803539a40b0dd305f010786dc1b828a8 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 26 Feb 2015 16:44:26 +0100 Subject: [PATCH 222/360] fix regression in bike profile --- profiles/bicycle.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index a496d3536..4ecbbab13 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -219,7 +219,7 @@ function way_function (way, result) end -- speed - local bridge_speed = speed_profile[bridge] + local bridge_speed = bicycle_speeds[bridge] if (bridge_speed and bridge_speed > 0) then highway = bridge; local duration = way:get_value_by_key("duration") From 878c49e4e18696ef1dafb138634ba12e49661084 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 26 Feb 2015 17:17:43 +0100 Subject: [PATCH 223/360] fix incomplete implementation of movable bridges in bike profiles, plenty of regressions --- features/bicycle/bridge.feature | 24 ++++++++++++------------ profiles/bicycle.lua | 15 ++++++++++----- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/features/bicycle/bridge.feature b/features/bicycle/bridge.feature index a90afea3b..232581647 100644 --- a/features/bicycle/bridge.feature +++ b/features/bicycle/bridge.feature @@ -18,14 +18,14 @@ Feature: Bicycle - Handle movable bridge When I route I should get | from | to | route | modes | - | a | g | abc,cde,efg | 1,3,1 | - | b | f | abc,cde,efg | 1,3,1 | - | e | c | cde | 3 | - | e | b | cde,abc | 3,1 | - | e | a | cde,abc | 3,1 | - | c | e | cde | 3 | - | c | f | cde,efg | 3,1 | - | c | g | cde,efg | 3,1 | + | a | g | abc,cde,efg | 1,5,1 | + | b | f | abc,cde,efg | 1,5,1 | + | e | c | cde | 5 | + | e | b | cde,abc | 5,1 | + | e | a | cde,abc | 5,1 | + | c | e | cde | 5 | + | c | f | cde,efg | 5,1 | + | c | g | cde,efg | 5,1 | Scenario: Car - Properly handle durations Given the node map @@ -41,7 +41,7 @@ Feature: Bicycle - Handle movable bridge When I route I should get | from | to | route | modes | speed | - | a | g | abc,cde,efg | 1,3,1 | 6 km/h | - | b | f | abc,cde,efg | 1,3,1 | 4 km/h | - | c | e | cde | 3 | 2 km/h | - | e | c | cde | 3 | 2 km/h | + | a | g | abc,cde,efg | 1,5,1 | 5 km/h | + | b | f | abc,cde,efg | 1,5,1 | 3 km/h | + | c | e | cde | 5 | 2 km/h | + | e | c | cde | 5 | 2 km/h | diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 4ecbbab13..497321ccf 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -66,6 +66,10 @@ route_speeds = { ["ferry"] = 5 } +bridge_speeds = { + ["movable"] = 5 +} + surface_speeds = { ["asphalt"] = default_speed, ["cobblestone:flattened"] = 10, @@ -102,7 +106,7 @@ mode_normal = 1 mode_pushing = 2 mode_ferry = 3 mode_train = 4 - +mode_movable_bridge = 5 local function parse_maxspeed(source) if not source then @@ -159,12 +163,14 @@ function way_function (way, result) local railway = way:get_value_by_key("railway") local amenity = way:get_value_by_key("amenity") local public_transport = way:get_value_by_key("public_transport") + local bridge = way:get_value_by_key("bridge") if (not highway or highway == '') and (not route or route == '') and (not railway or railway=='') and (not amenity or amenity=='') and (not man_made or man_made=='') and - (not public_transport or public_transport=='') + (not public_transport or public_transport=='') and + (not bridge or bridge=='') then return end @@ -219,12 +225,11 @@ function way_function (way, result) end -- speed - local bridge_speed = bicycle_speeds[bridge] + local bridge_speed = bridge_speeds[bridge] if (bridge_speed and bridge_speed > 0) then highway = bridge; - local duration = way:get_value_by_key("duration") if duration and durationIsValid(duration) then - result.duration = max( parseDuration(duration), 1 ); + result.duration = math.max( parseDuration(duration), 1 ); end result.forward_mode = mode_movable_bridge result.backward_mode = mode_movable_bridge From 773ff182ee96bb7b99f1382ae9e15b8442353c18 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 26 Feb 2015 18:54:13 +0100 Subject: [PATCH 224/360] fix license header --- util/range_algorithms.hpp | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/util/range_algorithms.hpp b/util/range_algorithms.hpp index 5aafd8e17..4d01d29c8 100644 --- a/util/range_algorithms.hpp +++ b/util/range_algorithms.hpp @@ -1,22 +1,29 @@ /* - open source routing machine - Copyright (C) Dennis Luxen, others 2010 -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU AFFERO General Public License as published by -the Free Software Foundation; either version 3 of the License, or -any later version. +Copyright (c) 2015, Project OSRM contributors +All rights reserved. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: -You should have received a copy of the GNU Affero General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -or see http://www.gnu.org/licenses/agpl.txt. - */ +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ #ifndef RANGE_ALGORITHMS_HPP #define RANGE_ALGORITHMS_HPP From c2098938f59dd1e6a1dd5e5b4309d88a7b1fdd77 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 27 Feb 2015 13:52:58 +0100 Subject: [PATCH 225/360] add convenience variadic template function to append elements to a container --- util/container.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/util/container.hpp b/util/container.hpp index c1f3bc77b..49329a58b 100644 --- a/util/container.hpp +++ b/util/container.hpp @@ -96,5 +96,15 @@ Function for_each_pair(ContainerT &container, Function function) { return for_each_pair(std::begin(container), std::end(container), function); } + +template void append_to_container(Container &&a) {} + +template +void append_to_container(Container &&container, T value, Args &&... args) +{ + container.emplace_back(value); + append_to_container(std::forward(container), std::forward(args)...); } + +} // namespace osrm #endif /* CONTAINER_HPP */ From 73a2a938b41606d8b13ab3e0441575bb639dc24f Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 2 Mar 2015 11:55:55 +0100 Subject: [PATCH 226/360] use CRTP instead of virtual functions in routing plugins --- data_structures/search_engine_data.cpp | 36 ++++++++--------- data_structures/search_engine_data.hpp | 14 +++---- routing_algorithms/alternative_path.hpp | 25 ++++++------ routing_algorithms/many_to_many.hpp | 7 ++-- routing_algorithms/routing_base.hpp | 52 ++++++++++++------------- routing_algorithms/shortest_path.hpp | 13 ++++--- 6 files changed, 75 insertions(+), 72 deletions(-) diff --git a/data_structures/search_engine_data.cpp b/data_structures/search_engine_data.cpp index fbdbc06ce..3282a0ccb 100644 --- a/data_structures/search_engine_data.cpp +++ b/data_structures/search_engine_data.cpp @@ -31,63 +31,63 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes) { - if (forwardHeap.get()) + if (forward_heap_1.get()) { - forwardHeap->Clear(); + forward_heap_1->Clear(); } else { - forwardHeap.reset(new QueryHeap(number_of_nodes)); + forward_heap_1.reset(new QueryHeap(number_of_nodes)); } - if (backwardHeap.get()) + if (reverse_heap_1.get()) { - backwardHeap->Clear(); + reverse_heap_1->Clear(); } else { - backwardHeap.reset(new QueryHeap(number_of_nodes)); + reverse_heap_1.reset(new QueryHeap(number_of_nodes)); } } void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes) { - if (forwardHeap2.get()) + if (forward_heap_2.get()) { - forwardHeap2->Clear(); + forward_heap_2->Clear(); } else { - forwardHeap2.reset(new QueryHeap(number_of_nodes)); + forward_heap_2.reset(new QueryHeap(number_of_nodes)); } - if (backwardHeap2.get()) + if (reverse_heap_2.get()) { - backwardHeap2->Clear(); + reverse_heap_2->Clear(); } else { - backwardHeap2.reset(new QueryHeap(number_of_nodes)); + reverse_heap_2.reset(new QueryHeap(number_of_nodes)); } } void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes) { - if (forwardHeap3.get()) + if (forward_heap_3.get()) { - forwardHeap3->Clear(); + forward_heap_3->Clear(); } else { - forwardHeap3.reset(new QueryHeap(number_of_nodes)); + forward_heap_3.reset(new QueryHeap(number_of_nodes)); } - if (backwardHeap3.get()) + if (reverse_heap_3.get()) { - backwardHeap3->Clear(); + reverse_heap_3->Clear(); } else { - backwardHeap3.reset(new QueryHeap(number_of_nodes)); + reverse_heap_3.reset(new QueryHeap(number_of_nodes)); } } diff --git a/data_structures/search_engine_data.hpp b/data_structures/search_engine_data.hpp index 82ee706c7..8c1c1619e 100644 --- a/data_structures/search_engine_data.hpp +++ b/data_structures/search_engine_data.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, Project OSRM contributors +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -44,12 +44,12 @@ struct SearchEngineData using QueryHeap = BinaryHeap>; using SearchEngineHeapPtr = boost::thread_specific_ptr; - static SearchEngineHeapPtr forwardHeap; - static SearchEngineHeapPtr backwardHeap; - static SearchEngineHeapPtr forwardHeap2; - static SearchEngineHeapPtr backwardHeap2; - static SearchEngineHeapPtr forwardHeap3; - static SearchEngineHeapPtr backwardHeap3; + static SearchEngineHeapPtr forward_heap_1; + static SearchEngineHeapPtr reverse_heap_1; + static SearchEngineHeapPtr forward_heap_2; + static SearchEngineHeapPtr reverse_heap_2; + static SearchEngineHeapPtr forward_heap_3; + static SearchEngineHeapPtr reverse_heap_3; void InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes); diff --git a/routing_algorithms/alternative_path.hpp b/routing_algorithms/alternative_path.hpp index 7dd15b533..3b509573a 100644 --- a/routing_algorithms/alternative_path.hpp +++ b/routing_algorithms/alternative_path.hpp @@ -45,9 +45,10 @@ const double VIAPATH_EPSILON = 0.15; // alternative at most 15% longer const double VIAPATH_GAMMA = 0.75; // alternative shares at most 75% with the shortest. template -class AlternativeRouting final : private BasicRoutingInterface +class AlternativeRouting final + : private BasicRoutingInterface> { - using super = BasicRoutingInterface; + using super = BasicRoutingInterface>; using EdgeData = typename DataFacadeT::EdgeData; using QueryHeap = SearchEngineData::QueryHeap; using SearchSpaceEdge = std::pair; @@ -94,10 +95,10 @@ class AlternativeRouting final : private BasicRoutingInterface engine_working_data.InitializeOrClearThirdThreadLocalStorage( super::facade->GetNumberOfNodes()); - QueryHeap &forward_heap1 = *(engine_working_data.forwardHeap); - QueryHeap &reverse_heap1 = *(engine_working_data.backwardHeap); - QueryHeap &forward_heap2 = *(engine_working_data.forwardHeap2); - QueryHeap &reverse_heap2 = *(engine_working_data.backwardHeap2); + QueryHeap &forward_heap1 = *(engine_working_data.forward_heap_1); + QueryHeap &reverse_heap1 = *(engine_working_data.reverse_heap_1); + QueryHeap &forward_heap2 = *(engine_working_data.forward_heap_2); + QueryHeap &reverse_heap2 = *(engine_working_data.reverse_heap_2); int upper_bound_to_shortest_path_distance = INVALID_EDGE_WEIGHT; NodeID middle_node = SPECIAL_NODEID; @@ -384,10 +385,10 @@ class AlternativeRouting final : private BasicRoutingInterface engine_working_data.InitializeOrClearSecondThreadLocalStorage( super::facade->GetNumberOfNodes()); - QueryHeap &existing_forward_heap = *engine_working_data.forwardHeap; - QueryHeap &existing_reverse_heap = *engine_working_data.backwardHeap; - QueryHeap &new_forward_heap = *engine_working_data.forwardHeap2; - QueryHeap &new_reverse_heap = *engine_working_data.backwardHeap2; + QueryHeap &existing_forward_heap = *engine_working_data.forward_heap_1; + QueryHeap &existing_reverse_heap = *engine_working_data.reverse_heap_1; + QueryHeap &new_forward_heap = *engine_working_data.forward_heap_2; + QueryHeap &new_reverse_heap = *engine_working_data.reverse_heap_2; std::vector packed_s_v_path; std::vector packed_v_t_path; @@ -841,8 +842,8 @@ class AlternativeRouting final : private BasicRoutingInterface engine_working_data.InitializeOrClearThirdThreadLocalStorage( super::facade->GetNumberOfNodes()); - QueryHeap &forward_heap3 = *engine_working_data.forwardHeap3; - QueryHeap &reverse_heap3 = *engine_working_data.backwardHeap3; + QueryHeap &forward_heap3 = *engine_working_data.forward_heap_3; + QueryHeap &reverse_heap3 = *engine_working_data.reverse_heap_3; int upper_bound = INVALID_EDGE_WEIGHT; NodeID middle = SPECIAL_NODEID; diff --git a/routing_algorithms/many_to_many.hpp b/routing_algorithms/many_to_many.hpp index 48bea0250..238880471 100644 --- a/routing_algorithms/many_to_many.hpp +++ b/routing_algorithms/many_to_many.hpp @@ -40,9 +40,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include template -class ManyToManyRouting final : public BasicRoutingInterface +class ManyToManyRouting final + : public BasicRoutingInterface> { - using super = BasicRoutingInterface; + using super = BasicRoutingInterface>; using QueryHeap = SearchEngineData::QueryHeap; SearchEngineData &engine_working_data; @@ -76,7 +77,7 @@ class ManyToManyRouting final : public BasicRoutingInterface engine_working_data.InitializeOrClearFirstThreadLocalStorage( super::facade->GetNumberOfNodes()); - QueryHeap &query_heap = *(engine_working_data.forwardHeap); + QueryHeap &query_heap = *(engine_working_data.forward_heap_1); SearchSpaceWithBuckets search_space_with_buckets; diff --git a/routing_algorithms/routing_base.hpp b/routing_algorithms/routing_base.hpp index 714d903cd..e10c86a59 100644 --- a/routing_algorithms/routing_base.hpp +++ b/routing_algorithms/routing_base.hpp @@ -37,17 +37,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap; -SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap; -SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap2; -SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap2; -SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap3; -SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap3; +SearchEngineData::SearchEngineHeapPtr SearchEngineData::forward_heap_1; +SearchEngineData::SearchEngineHeapPtr SearchEngineData::reverse_heap_1; +SearchEngineData::SearchEngineHeapPtr SearchEngineData::forward_heap_2; +SearchEngineData::SearchEngineHeapPtr SearchEngineData::reverse_heap_2; +SearchEngineData::SearchEngineHeapPtr SearchEngineData::forward_heap_3; +SearchEngineData::SearchEngineHeapPtr SearchEngineData::reverse_heap_3; -template class BasicRoutingInterface +template class BasicRoutingInterface { private: - typedef typename DataFacadeT::EdgeData EdgeData; + using EdgeData = typename DataFacadeT::EdgeData; protected: DataFacadeT *facade; @@ -56,14 +56,14 @@ template class BasicRoutingInterface BasicRoutingInterface() = delete; BasicRoutingInterface(const BasicRoutingInterface &) = delete; explicit BasicRoutingInterface(DataFacadeT *facade) : facade(facade) {} - virtual ~BasicRoutingInterface() {} + ~BasicRoutingInterface() {} - inline void RoutingStep(SearchEngineData::QueryHeap &forward_heap, - SearchEngineData::QueryHeap &reverse_heap, - NodeID *middle_node_id, - int *upper_bound, - const int min_edge_offset, - const bool forward_direction) const + void RoutingStep(SearchEngineData::QueryHeap &forward_heap, + SearchEngineData::QueryHeap &reverse_heap, + NodeID *middle_node_id, + int *upper_bound, + const int min_edge_offset, + const bool forward_direction) const { const NodeID node = forward_heap.DeleteMin(); const int distance = forward_heap.GetKey(node); @@ -148,9 +148,9 @@ template class BasicRoutingInterface } } - inline void UnpackPath(const std::vector &packed_path, - const PhantomNodes &phantom_node_pair, - std::vector &unpacked_path) const + void UnpackPath(const std::vector &packed_path, + const PhantomNodes &phantom_node_pair, + std::vector &unpacked_path) const { const bool start_traversed_in_reverse = (packed_path.front() != phantom_node_pair.source_phantom.forward_node_id); @@ -331,7 +331,7 @@ template class BasicRoutingInterface } } - inline void UnpackEdge(const NodeID s, const NodeID t, std::vector &unpacked_path) const + void UnpackEdge(const NodeID s, const NodeID t, std::vector &unpacked_path) const { std::stack> recursion_stack; recursion_stack.emplace(s, t); @@ -388,10 +388,10 @@ template class BasicRoutingInterface unpacked_path.emplace_back(t); } - inline void RetrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap, - const SearchEngineData::QueryHeap &reverse_heap, - const NodeID middle_node_id, - std::vector &packed_path) const + void RetrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap, + const SearchEngineData::QueryHeap &reverse_heap, + const NodeID middle_node_id, + std::vector &packed_path) const { RetrievePackedPathFromSingleHeap(forward_heap, middle_node_id, packed_path); std::reverse(packed_path.begin(), packed_path.end()); @@ -399,9 +399,9 @@ template class BasicRoutingInterface RetrievePackedPathFromSingleHeap(reverse_heap, middle_node_id, packed_path); } - inline void RetrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap, - const NodeID middle_node_id, - std::vector &packed_path) const + void RetrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap, + const NodeID middle_node_id, + std::vector &packed_path) const { NodeID current_node_id = middle_node_id; while (current_node_id != search_heap.GetData(current_node_id).parent) diff --git a/routing_algorithms/shortest_path.hpp b/routing_algorithms/shortest_path.hpp index bd2084008..4b3cc49a4 100644 --- a/routing_algorithms/shortest_path.hpp +++ b/routing_algorithms/shortest_path.hpp @@ -36,9 +36,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../typedefs.h" template -class ShortestPathRouting final : public BasicRoutingInterface +class ShortestPathRouting final + : public BasicRoutingInterface> { - using super = BasicRoutingInterface; + using super = BasicRoutingInterface>; using QueryHeap = SearchEngineData::QueryHeap; SearchEngineData &engine_working_data; @@ -70,10 +71,10 @@ class ShortestPathRouting final : public BasicRoutingInterface engine_working_data.InitializeOrClearThirdThreadLocalStorage( super::facade->GetNumberOfNodes()); - QueryHeap &forward_heap1 = *(engine_working_data.forwardHeap); - QueryHeap &reverse_heap1 = *(engine_working_data.backwardHeap); - QueryHeap &forward_heap2 = *(engine_working_data.forwardHeap2); - QueryHeap &reverse_heap2 = *(engine_working_data.backwardHeap2); + QueryHeap &forward_heap1 = *(engine_working_data.forward_heap_1); + QueryHeap &reverse_heap1 = *(engine_working_data.reverse_heap_1); + QueryHeap &forward_heap2 = *(engine_working_data.forward_heap_2); + QueryHeap &reverse_heap2 = *(engine_working_data.reverse_heap_2); std::size_t current_leg = 0; // Get distance to next pair of target nodes. From 7e00a86bb47dce69913bf27588b73d9a96dce254 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 2 Mar 2015 16:41:03 +0100 Subject: [PATCH 227/360] implement ISO 8601 durations parsing, cf. #1399 --- extractor/extraction_helper_functions.hpp | 99 +++++++++++++------- features/car/ferry.feature | 21 ++++- unit_tests/algorithms/duration_parsing.cpp | 64 +++++++++++++ util/iso_8601_duration_parser.hpp | 102 +++++++++++++++++++++ 4 files changed, 250 insertions(+), 36 deletions(-) create mode 100644 unit_tests/algorithms/duration_parsing.cpp create mode 100644 util/iso_8601_duration_parser.hpp diff --git a/extractor/extraction_helper_functions.hpp b/extractor/extraction_helper_functions.hpp index c56c3b7e5..d10200abb 100644 --- a/extractor/extraction_helper_functions.hpp +++ b/extractor/extraction_helper_functions.hpp @@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define EXTRACTION_HELPER_FUNCTIONS_HPP #include "../util/cast.hpp" +#include "../util/iso_8601_duration_parser.hpp" #include #include @@ -37,53 +38,81 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -namespace qi = boost::spirit::qi; - -// TODO: Move into LUA - -bool durationIsValid(const std::string &s) +bool simple_duration_is_valid(const std::string &s) { - boost::regex e( + boost::regex simple_format( "((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)", boost::regex_constants::icase | boost::regex_constants::perl); - std::vector result; - boost::algorithm::split_regex(result, s, boost::regex(":")); - const bool matched = regex_match(s, e); - return matched; + const bool simple_matched = regex_match(s, simple_format); + + if (simple_matched) + { + return true; + } + return false; +} + +bool iso_8601_duration_is_valid(const std::string &s) +{ + iso_8601_grammar iso_parser; + const bool result = qi::parse(s.begin(), s.end(), iso_parser); + + // check if the was an error with the request + if (result && (0 != iso_parser.get_duration())) + { + return true; + } + return false; +} + +bool durationIsValid(const std::string &s) +{ + return simple_duration_is_valid(s) || iso_8601_duration_is_valid(s); } unsigned parseDuration(const std::string &s) { - unsigned hours = 0; - unsigned minutes = 0; - unsigned seconds = 0; - boost::regex e( - "((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)", - boost::regex_constants::icase | boost::regex_constants::perl); - - std::vector result; - boost::algorithm::split_regex(result, s, boost::regex(":")); - const bool matched = regex_match(s, e); - if (matched) + if (simple_duration_is_valid(s)) { - if (1 == result.size()) + unsigned hours = 0; + unsigned minutes = 0; + unsigned seconds = 0; + boost::regex e( + "((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)", + boost::regex_constants::icase | boost::regex_constants::perl); + + std::vector result; + boost::algorithm::split_regex(result, s, boost::regex(":")); + const bool matched = regex_match(s, e); + if (matched) { - minutes = cast::string_to_int(result[0]); + if (1 == result.size()) + { + minutes = cast::string_to_int(result[0]); + } + if (2 == result.size()) + { + minutes = cast::string_to_int(result[1]); + hours = cast::string_to_int(result[0]); + } + if (3 == result.size()) + { + seconds = cast::string_to_int(result[2]); + minutes = cast::string_to_int(result[1]); + hours = cast::string_to_int(result[0]); + } + return 10 * (3600 * hours + 60 * minutes + seconds); } - if (2 == result.size()) - { - minutes = cast::string_to_int(result[1]); - hours = cast::string_to_int(result[0]); - } - if (3 == result.size()) - { - seconds = cast::string_to_int(result[2]); - minutes = cast::string_to_int(result[1]); - hours = cast::string_to_int(result[0]); - } - return 10 * (3600 * hours + 60 * minutes + seconds); } + else if (iso_8601_duration_is_valid(s)) + { + iso_8601_grammar iso_parser; + qi::parse(s.begin(), s.end(), iso_parser); + + return iso_parser.get_duration(); + } + return std::numeric_limits::max(); } diff --git a/features/car/ferry.feature b/features/car/ferry.feature index abbe5ed49..eb245598a 100644 --- a/features/car/ferry.feature +++ b/features/car/ferry.feature @@ -27,7 +27,7 @@ Feature: Car - Handle ferry routes | c | f | cde,efg | 2,1 | | c | g | cde,efg | 2,1 | - Scenario: Car - Properly handle durations + Scenario: Car - Properly handle simple durations Given the node map | a | b | c | | | | | | d | | | @@ -45,3 +45,22 @@ Feature: Car - Handle ferry routes | b | f | abc,cde,efg | 1,2,1 | 20 km/h | | c | e | cde | 2 | 12 km/h | | e | c | cde | 2 | 12 km/h | + + Scenario: Car - Properly handle ISO 8601 durations + Given the node map + | a | b | c | | | + | | | d | | | + | | | e | f | g | + + And the ways + | nodes | highway | route | duration | + | abc | primary | | | + | cde | | ferry | PT1M | + | efg | primary | | | + + When I route I should get + | from | to | route | modes | speed | + | a | g | abc,cde,efg | 1,2,1 | 26 km/h | + | b | f | abc,cde,efg | 1,2,1 | 20 km/h | + | c | e | cde | 2 | 12 km/h | + | e | c | cde | 2 | 12 km/h | diff --git a/unit_tests/algorithms/duration_parsing.cpp b/unit_tests/algorithms/duration_parsing.cpp new file mode 100644 index 000000000..ec3b8191a --- /dev/null +++ b/unit_tests/algorithms/duration_parsing.cpp @@ -0,0 +1,64 @@ +/* + +Copyright (c) 2015, Project OSRM contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "../../extractor/extraction_helper_functions.hpp" + +#include +#include + +BOOST_AUTO_TEST_SUITE(durations_are_valid) + +BOOST_AUTO_TEST_CASE(all_necessary_test) +{ + BOOST_CHECK_EQUAL(durationIsValid("00:01"), true); + BOOST_CHECK_EQUAL(durationIsValid("00:01:01"), true); + BOOST_CHECK_EQUAL(durationIsValid("PT15M"), true); +} + +BOOST_AUTO_TEST_CASE(common_durations_get_translated) +{ + BOOST_CHECK_EQUAL(parseDuration("00:01"), 600); + BOOST_CHECK_EQUAL(parseDuration("00:01:01"), 610); + BOOST_CHECK_EQUAL(parseDuration("01:01"), 36600); + + // check all combinations of iso duration tokens + BOOST_CHECK_EQUAL(parseDuration("PT1M1S"), 610); + BOOST_CHECK_EQUAL(parseDuration("PT1H1S"), 36010); + BOOST_CHECK_EQUAL(parseDuration("PT15M"), 9000); + BOOST_CHECK_EQUAL(parseDuration("PT15S"), 150); + BOOST_CHECK_EQUAL(parseDuration("PT15H"), 540000); + BOOST_CHECK_EQUAL(parseDuration("PT1H15M"), 45000); + BOOST_CHECK_EQUAL(parseDuration("PT1H15M1S"), 45010); +} + +BOOST_AUTO_TEST_CASE(iso_8601_durations_case_insensitive) +{ + BOOST_CHECK_EQUAL(parseDuration("PT15m"), 9000); + BOOST_CHECK_EQUAL(parseDuration("PT1h15m"), 45000); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/util/iso_8601_duration_parser.hpp b/util/iso_8601_duration_parser.hpp new file mode 100644 index 000000000..1981c8982 --- /dev/null +++ b/util/iso_8601_duration_parser.hpp @@ -0,0 +1,102 @@ +/* + +Copyright (c) 2015, Project OSRM contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef ISO_8601_DURATION_PARSER_HPP +#define ISO_8601_DURATION_PARSER_HPP + +#include +#include +#include + +namespace qi = boost::spirit::qi; + +template struct iso_8601_grammar : qi::grammar +{ + iso_8601_grammar() + : iso_8601_grammar::base_type(iso_period), temp(0), hours(0), minutes(0), seconds(0) + { + iso_period = qi::lit('P') >> qi::lit('T') >> + ((value >> hour >> value >> minute >> value >> second) | + (value >> hour >> value >> minute) | (value >> hour >> value >> second) | + (value >> hour) | (value >> minute >> value >> second) | (value >> minute) | + (value >> second)); + + value = qi::uint_[boost::bind(&iso_8601_grammar::set_temp, this, ::_1)]; + second = (qi::lit('s') | + qi::lit('S'))[boost::bind(&iso_8601_grammar::set_seconds, this)]; + minute = (qi::lit('m') | + qi::lit('M'))[boost::bind(&iso_8601_grammar::set_minutes, this)]; + hour = (qi::lit('h') | + qi::lit('H'))[boost::bind(&iso_8601_grammar::set_hours, this)]; + } + + qi::rule iso_period; + qi::rule value, hour, minute, second; + + unsigned temp; + unsigned hours; + unsigned minutes; + unsigned seconds; + + void set_temp(unsigned number) { temp = number; } + + void set_hours() + { + if (temp < 24) + { + hours = temp; + } + } + + void set_minutes() + { + if (temp < 60) + { + minutes = temp; + } + } + + void set_seconds() + { + if (temp < 60) + { + seconds = temp; + } + } + + unsigned get_duration() const + { + unsigned temp = 10 * (3600 * hours + 60 * minutes + seconds); + if (temp == 0) + { + temp = std::numeric_limits::max(); + } + return temp; + } +}; + +#endif // ISO_8601_DURATION_PARSER_HPP From 2259bce05f03758136afa0276f37858372398b1b Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 23 Sep 2014 18:46:14 +0200 Subject: [PATCH 228/360] Add skeleton code for matching --- data_structures/search_engine.hpp | 9 +- data_structures/static_rtree.hpp | 172 +++++----- library/osrm_impl.cpp | 2 + plugins/map_matching.hpp | 107 ++++++ routing_algorithms/map_matching.hpp | 317 ++++++++++++++++++ server/data_structures/datafacade_base.hpp | 5 + .../data_structures/internal_datafacade.hpp | 15 + server/data_structures/shared_datafacade.hpp | 15 + 8 files changed, 552 insertions(+), 90 deletions(-) create mode 100644 plugins/map_matching.hpp create mode 100644 routing_algorithms/map_matching.hpp diff --git a/data_structures/search_engine.hpp b/data_structures/search_engine.hpp index 24e550767..7e47b1f5d 100644 --- a/data_structures/search_engine.hpp +++ b/data_structures/search_engine.hpp @@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "search_engine_data.hpp" #include "../routing_algorithms/alternative_path.hpp" #include "../routing_algorithms/many_to_many.hpp" +#include "../routing_algorithms/map_matching.hpp" #include "../routing_algorithms/shortest_path.hpp" #include @@ -45,10 +46,14 @@ template class SearchEngine ShortestPathRouting shortest_path; AlternativeRouting alternative_path; ManyToManyRouting distance_table; + MapMatching map_matching; explicit SearchEngine(DataFacadeT *facade) - : facade(facade), shortest_path(facade, engine_working_data), - alternative_path(facade, engine_working_data), distance_table(facade, engine_working_data) + : facade(facade), + shortest_path(facade, engine_working_data), + alternative_path(facade, engine_working_data), + distance_table(facade, engine_working_data), + map_matching(facade, engine_working_data) { static_assert(!std::is_pointer::value, "don't instantiate with ptr type"); static_assert(std::is_object::value, diff --git a/data_structures/static_rtree.hpp b/data_structures/static_rtree.hpp index a0ce38a1e..45109df73 100644 --- a/data_structures/static_rtree.hpp +++ b/data_structures/static_rtree.hpp @@ -745,6 +745,7 @@ class StaticRTree // check if it is smaller than what we had before float current_ratio = 0.f; FixedPointCoordinate foot_point_coordinate_on_segment; + // const float current_perpendicular_distance = coordinate_calculation::perpendicular_distance_from_projected_coordinate( m_coordinate_list->at(current_segment.u), @@ -796,20 +797,24 @@ class StaticRTree return !result_phantom_node_vector.empty(); } - // implementation of the Hjaltason/Samet query [3], a BFS traversal of the tree bool IncrementalFindPhantomNodeForCoordinateWithDistance( const FixedPointCoordinate &input_coordinate, std::vector> &result_phantom_node_vector, - const unsigned number_of_results, - const unsigned max_checked_segments = 4 * LEAF_NODE_SIZE) + const unsigned max_number_of_phantom_nodes, + const unsigned max_checked_elements = 4 * LEAF_NODE_SIZE) { - std::vector min_found_distances(number_of_results, - std::numeric_limits::max()); + unsigned inspected_elements = 0; + unsigned number_of_elements_from_big_cc = 0; + unsigned number_of_elements_from_tiny_cc = 0; - unsigned number_of_results_found_in_big_cc = 0; - unsigned number_of_results_found_in_tiny_cc = 0; + unsigned pruned_elements = 0; - unsigned inspected_segments = 0; + std::pair projected_coordinate = { + mercator::lat2y(input_coordinate.lat / COORDINATE_PRECISION), + input_coordinate.lon / COORDINATE_PRECISION}; + + // upper bound pruning technique + upper_bound pruning_bound(max_number_of_phantom_nodes); // initialize queue with root element std::priority_queue traversal_queue; @@ -820,42 +825,43 @@ class StaticRTree const IncrementalQueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop(); - const float current_min_dist = min_found_distances[number_of_results - 1]; - - if (current_query_node.min_dist > current_min_dist) - { - continue; - } - - if (current_query_node.RepresentsTreeNode()) - { + if (current_query_node.node.template is()) + { // current object is a tree node const TreeNode ¤t_tree_node = current_query_node.node.template get(); if (current_tree_node.child_is_on_disk) { LeafNode current_leaf_node; LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node); - // Add all objects from leaf into queue - for (uint32_t i = 0; i < current_leaf_node.object_count; ++i) + + // current object represents a block on disk + for (const auto i : osrm::irange(0u, current_leaf_node.object_count)) { const auto ¤t_edge = current_leaf_node.objects[i]; - const float current_perpendicular_distance = - coordinate_calculation::perpendicular_distance( + const float current_perpendicular_distance = coordinate_calculation:: + perpendicular_distance_from_projected_coordinate( m_coordinate_list->at(current_edge.u), - m_coordinate_list->at(current_edge.v), input_coordinate); + m_coordinate_list->at(current_edge.v), input_coordinate, + projected_coordinate); // distance must be non-negative - BOOST_ASSERT(0. <= current_perpendicular_distance); + BOOST_ASSERT(0.f <= current_perpendicular_distance); - if (current_perpendicular_distance < current_min_dist) + if (pruning_bound.get() >= current_perpendicular_distance || + current_edge.is_in_tiny_cc()) { + pruning_bound.insert(current_perpendicular_distance); traversal_queue.emplace(current_perpendicular_distance, current_edge); } + else + { + ++pruned_elements; + } } } else { - // for each child mbr - for (uint32_t i = 0; i < current_tree_node.child_count; ++i) + // for each child mbr get a lower bound and enqueue it + for (const auto i : osrm::irange(0u, current_tree_node.child_count)) { const int32_t child_id = current_tree_node.children[i]; const TreeNode &child_tree_node = m_search_tree[child_id]; @@ -863,99 +869,89 @@ class StaticRTree child_tree_node.minimum_bounding_rectangle; const float lower_bound_to_element = child_rectangle.GetMinDist(input_coordinate); + BOOST_ASSERT(0.f <= lower_bound_to_element); - // TODO - enough elements found, i.e. nearest distance > maximum distance? - // ie. some measure of 'confidence of accuracy' - - // check if it needs to be explored by mindist - if (lower_bound_to_element < current_min_dist) - { - traversal_queue.emplace(lower_bound_to_element, child_tree_node); - } + traversal_queue.emplace(lower_bound_to_element, child_tree_node); } - // SimpleLogger().Write(logDEBUG) << "added " << current_tree_node.child_count - // << " mbrs into queue of " << traversal_queue.size(); } } else - { - ++inspected_segments; + { // current object is a leaf node + ++inspected_elements; // inspecting an actual road segment const EdgeDataT ¤t_segment = current_query_node.node.template get(); - // don't collect too many results from small components - if (number_of_results_found_in_big_cc == number_of_results && - !current_segment.is_in_tiny_cc) - { - continue; - } - - // don't collect too many results from big components - if (number_of_results_found_in_tiny_cc == number_of_results && - current_segment.is_in_tiny_cc) + // continue searching for the first segment from a big component + if (number_of_elements_from_big_cc == 0 && + number_of_elements_from_tiny_cc >= max_number_of_phantom_nodes && + current_segment.is_in_tiny_cc()) { continue; } // check if it is smaller than what we had before - float current_ratio = 0.; + float current_ratio = 0.f; FixedPointCoordinate foot_point_coordinate_on_segment; + const float current_perpendicular_distance = - coordinate_calculation::perpendicular_distance( - m_coordinate_list->at(current_segment.u), - m_coordinate_list->at(current_segment.v), input_coordinate, - foot_point_coordinate_on_segment, current_ratio); + coordinate_calculation::perpendicular_distance_from_projected_coordinate( + m_coordinate_list->at(current_segment.u), + m_coordinate_list->at(current_segment.v), input_coordinate, + projected_coordinate, foot_point_coordinate_on_segment, current_ratio); - BOOST_ASSERT(0. <= current_perpendicular_distance); + // store phantom node in result vector + result_phantom_node_vector.emplace_back( + PhantomNode( current_segment.forward_edge_based_node_id, + current_segment.reverse_edge_based_node_id, current_segment.name_id, + current_segment.forward_weight, current_segment.reverse_weight, + current_segment.forward_offset, current_segment.reverse_offset, + current_segment.packed_geometry_id, current_segment.component_id, + foot_point_coordinate_on_segment, current_segment.fwd_segment_position, + current_segment.forward_travel_mode, current_segment.backward_travel_mode), + current_perpendicular_distance); - if ((current_perpendicular_distance < current_min_dist) && - !osrm::epsilon_compare(current_perpendicular_distance, current_min_dist)) - { - // store phantom node in result vector - result_phantom_node_vector.emplace_back(current_segment, - foot_point_coordinate_on_segment, - current_perpendicular_distance); + // Hack to fix rounding errors and wandering via nodes. + FixUpRoundingIssue(input_coordinate, result_phantom_node_vector.back().first); - // Hack to fix rounding errors and wandering via nodes. - FixUpRoundingIssue(input_coordinate, result_phantom_node_vector.back()); + // set forward and reverse weights on the phantom node + SetForwardAndReverseWeightsOnPhantomNode(current_segment, + result_phantom_node_vector.back().first); - // set forward and reverse weights on the phantom node - SetForwardAndReverseWeightsOnPhantomNode(current_segment, - result_phantom_node_vector.back()); - - // do we have results only in a small scc - if (current_segment.is_in_tiny_cc) - { - ++number_of_results_found_in_tiny_cc; - } - else - { - // found an element in a large component - min_found_distances[number_of_results_found_in_big_cc] = - current_perpendicular_distance; - ++number_of_results_found_in_big_cc; - // SimpleLogger().Write(logDEBUG) << std::setprecision(8) << - // foot_point_coordinate_on_segment << " at " << - // current_perpendicular_distance; - } + // update counts on what we found from which result class + if (current_segment.is_in_tiny_cc()) + { // found an element in tiny component + ++number_of_elements_from_tiny_cc; + } + else + { // found an element in a big component + ++number_of_elements_from_big_cc; } } - // TODO add indicator to prune if maxdist > threshold - if (number_of_results == number_of_results_found_in_big_cc || - inspected_segments >= max_checked_segments) + // stop the search by flushing the queue + if ((result_phantom_node_vector.size() >= max_number_of_phantom_nodes && + number_of_elements_from_big_cc > 0) || + inspected_elements >= max_checked_elements) { - // SimpleLogger().Write(logDEBUG) << "flushing queue of " << traversal_queue.size() - // << " elements"; - // work-around for traversal_queue.clear(); traversal_queue = std::priority_queue{}; } } + // SimpleLogger().Write() << "result_phantom_node_vector.size(): " << + // result_phantom_node_vector.size(); + // SimpleLogger().Write() << "max_number_of_phantom_nodes: " << max_number_of_phantom_nodes; + // SimpleLogger().Write() << "number_of_elements_from_big_cc: " << + // number_of_elements_from_big_cc; + // SimpleLogger().Write() << "number_of_elements_from_tiny_cc: " << + // number_of_elements_from_tiny_cc; + // SimpleLogger().Write() << "inspected_elements: " << inspected_elements; + // SimpleLogger().Write() << "max_checked_elements: " << max_checked_elements; + // SimpleLogger().Write() << "pruned_elements: " << pruned_elements; return !result_phantom_node_vector.empty(); } + bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, PhantomNode &result_phantom_node, const unsigned zoom_level) diff --git a/library/osrm_impl.cpp b/library/osrm_impl.cpp index 71ea1fb1d..9ea009912 100644 --- a/library/osrm_impl.cpp +++ b/library/osrm_impl.cpp @@ -42,6 +42,7 @@ class named_mutex; #include "../plugins/nearest.hpp" #include "../plugins/timestamp.hpp" #include "../plugins/viaroute.hpp" +#include "../plugins/map_matching.hpp" #include "../server/data_structures/datafacade_base.hpp" #include "../server/data_structures/internal_datafacade.hpp" #include "../server/data_structures/shared_barriers.hpp" @@ -81,6 +82,7 @@ OSRM_impl::OSRM_impl(libosrm_config &lib_config) RegisterPlugin(new HelloWorldPlugin()); RegisterPlugin(new LocatePlugin>(query_data_facade)); RegisterPlugin(new NearestPlugin>(query_data_facade)); + RegisterPlugin(new MapMatchingPlugin>(query_data_facade)); RegisterPlugin(new TimestampPlugin>(query_data_facade)); RegisterPlugin(new ViaRoutePlugin>(query_data_facade)); } diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp new file mode 100644 index 000000000..8b997d881 --- /dev/null +++ b/plugins/map_matching.hpp @@ -0,0 +1,107 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, others 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. + */ + +#ifndef MAP_MATCHING_PLUGIN_H +#define MAP_MATCHING_PLUGIN_H + +#include "plugin_base.hpp" + +#include "../algorithms/object_encoder.hpp" +#include "../util/integer_range.hpp" +#include "../data_structures/search_engine.hpp" +#include "../routing_algorithms/map_matching.hpp" +#include "../util/simple_logger.hpp" +#include "../util/string_util.hpp" + +#include + +#include +#include +#include +#include + +template class MapMatchingPlugin : public BasePlugin +{ + private: + std::shared_ptr> search_engine_ptr; + + public: + MapMatchingPlugin(DataFacadeT *facade) : descriptor_string("match"), facade(facade) + { + search_engine_ptr = std::make_shared>(facade); + } + + virtual ~MapMatchingPlugin() { search_engine_ptr.reset(); } + + const std::string GetDescriptor() const final { return descriptor_string; } + + int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final + { + // check number of parameters + + SimpleLogger().Write() << "1"; + if (!check_all_coordinates(route_parameters.coordinates)) + { + return 400; + } + + SimpleLogger().Write() << "2"; + + InternalRouteResult raw_route; + Matching::CandidateLists candidate_lists; + candidate_lists.resize(route_parameters.coordinates.size()); + + SimpleLogger().Write() << "3"; + // fetch 10 candidates for each given coordinate + for (const auto current_coordinate : osrm::irange(0, candidate_lists.size())) + { + if (!facade->IncrementalFindPhantomNodeForCoordinateWithDistance( + route_parameters.coordinates[current_coordinate], + candidate_lists[current_coordinate], + 10)) + { + return 400; + } + + while (candidate_lists[current_coordinate].size() < 10) + { + // TODO: add dummy candidates, if any are missing + // TODO: add factory method to get an invalid PhantomNode/Distance pair + } + } + SimpleLogger().Write() << "4"; + + // call the actual map matching + search_engine_ptr->map_matching(10, candidate_lists, route_parameters.coordinates, raw_route); + + if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length) + { + SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found"; + } + + return 200; + } + + private: + std::string descriptor_string; + DataFacadeT *facade; +}; + +#endif /* MAP_MATCHING_PLUGIN_H */ diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp new file mode 100644 index 000000000..80152f1ef --- /dev/null +++ b/routing_algorithms/map_matching.hpp @@ -0,0 +1,317 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, others 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. + */ + +#ifndef MAP_MATCHING_H +#define MAP_MATCHING_H + +#include "routing_base.hpp" + +#include "../data_structures/coordinate_calculation.hpp" +#include "../util/simple_logger.hpp" +#include "../util/container.hpp" + +#include +#include +#include + +namespace Matching +{ +typedef std::vector> CandidateList; +typedef std::vector CandidateLists; +typedef std::pair PhantomNodesWithProbability; +} + +// implements a hidden markov model map matching algorithm +template class MapMatching final + : public BasicRoutingInterface> +{ + using super = BasicRoutingInterface>; + using QueryHeap = SearchEngineData::QueryHeap; + SearchEngineData &engine_working_data; + + constexpr static const double sigma_z = 4.07; + + constexpr double emission_probability(const double distance) const + { + return (1. / (std::sqrt(2. * M_PI) * sigma_z)) * + std::exp(-0.5 * std::pow((distance / sigma_z), 2.)); + } + + constexpr double log_probability(const double probability) const + { + return std::log2(probability); + } + + // TODO: needs to be estimated from the input locations + //constexpr static const double beta = 1.; + // samples/min and beta + // 1 0.49037673 + // 2 0.82918373 + // 3 1.24364564 + // 4 1.67079581 + // 5 2.00719298 + // 6 2.42513007 + // 7 2.81248831 + // 8 3.15745473 + // 9 3.52645392 + // 10 4.09511775 + // 11 4.67319795 + // 21 12.55107715 + // 12 5.41088180 + // 13 6.47666590 + // 14 6.29010734 + // 15 7.80752112 + // 16 8.09074504 + // 17 8.08550528 + // 18 9.09405065 + // 19 11.09090603 + // 20 11.87752824 + // 21 12.55107715 + // 22 15.82820829 + // 23 17.69496773 + // 24 18.07655652 + // 25 19.63438911 + // 26 25.40832185 + // 27 23.76001877 + // 28 28.43289797 + // 29 32.21683062 + // 30 34.56991141 + + constexpr double transition_probability(const float d_t, const float beta) const + { + return (1. / beta) * std::exp(-d_t / beta); + } + + // deprecated + // translates a distance into how likely it is an input + // double DistanceToProbability(const double distance) const + // { + // if (0. > distance) + // { + // return 0.; + // } + // return 1. - 1. / (1. + exp((-distance + 35.) / 6.)); + // } + + double get_beta(const unsigned state_size, + const Matching::CandidateLists ×tamp_list, + const std::vector coordinate_list) const + { + std::vector d_t_list, median_select_d_t_list; + for (auto t = 1; t < timestamp_list.size(); ++t) + { + for (auto s = 0; s < state_size; ++s) + { + d_t_list.push_back(get_distance_difference(coordinate_list[t - 1], + coordinate_list[t], + timestamp_list[t - 1][s].first, + timestamp_list[t][s].first)); + median_select_d_t_list.push_back(d_t_list.back()); + } + } + + std::nth_element(median_select_d_t_list.begin(), + median_select_d_t_list.begin() + median_select_d_t_list.size() / 2, + median_select_d_t_list.end()); + const auto median_d_t = median_select_d_t_list[median_select_d_t_list.size() / 2]; + + return (1. / std::log(2)) * median_d_t; + } + + + double get_distance_difference(const FixedPointCoordinate &location1, + const FixedPointCoordinate &location2, + const PhantomNode &source_phantom, + const PhantomNode &target_phantom) const + { + // great circle distance of two locations - median/avg dist table(candidate list1/2) + const EdgeWeight network_distance = get_network_distance(source_phantom, target_phantom); + const auto great_circle_distance = + coordinate_calculation::great_circle_distance(location1, location2); + + if (great_circle_distance > network_distance) + { + return great_circle_distance - network_distance; + } + return network_distance - great_circle_distance; + } + + EdgeWeight get_network_distance(const PhantomNode &source_phantom, + const PhantomNode &target_phantom) const + { + EdgeWeight upper_bound = INVALID_EDGE_WEIGHT; + NodeID middle_node = SPECIAL_NODEID; + EdgeWeight edge_offset = std::min(0, -source_phantom.GetForwardWeightPlusOffset()); + edge_offset = std::min(edge_offset, -source_phantom.GetReverseWeightPlusOffset()); + + engine_working_data.InitializeOrClearFirstThreadLocalStorage( + super::facade->GetNumberOfNodes()); + engine_working_data.InitializeOrClearSecondThreadLocalStorage( + super::facade->GetNumberOfNodes()); + + QueryHeap &forward_heap = *(engine_working_data.forward_heap_1); + QueryHeap &reverse_heap = *(engine_working_data.reverse_heap_1); + + if (source_phantom.forward_node_id != SPECIAL_NODEID) + { + forward_heap.Insert(source_phantom.forward_node_id, + -source_phantom.GetForwardWeightPlusOffset(), + source_phantom.forward_node_id); + } + if (source_phantom.reverse_node_id != SPECIAL_NODEID) + { + forward_heap.Insert(source_phantom.reverse_node_id, + -source_phantom.GetReverseWeightPlusOffset(), + source_phantom.reverse_node_id); + } + + if (target_phantom.forward_node_id != SPECIAL_NODEID) + { + reverse_heap.Insert(target_phantom.forward_node_id, + target_phantom.GetForwardWeightPlusOffset(), + target_phantom.forward_node_id); + } + if (target_phantom.reverse_node_id != SPECIAL_NODEID) + { + reverse_heap.Insert(target_phantom.reverse_node_id, + target_phantom.GetReverseWeightPlusOffset(), + target_phantom.reverse_node_id); + } + + // search from s and t till new_min/(1+epsilon) > length_of_shortest_path + while (0 < (forward_heap.Size() + reverse_heap.Size())) + { + if (0 < forward_heap.Size()) + { + super::RoutingStep( + forward_heap, reverse_heap, &middle_node, &upper_bound, edge_offset, true); + } + if (0 < reverse_heap.Size()) + { + super::RoutingStep( + reverse_heap, forward_heap, &middle_node, &upper_bound, edge_offset, false); + } + } + return upper_bound; + } + + public: + MapMatching(DataFacadeT *facade, SearchEngineData &engine_working_data) + : super(facade), engine_working_data(engine_working_data) + { + } + + void operator()(const unsigned state_size, + const Matching::CandidateLists ×tamp_list, + const std::vector coordinate_list, + InternalRouteResult &raw_route_data) const + { + BOOST_ASSERT(state_size != std::numeric_limits::max()); + BOOST_ASSERT(state_size != 0); + SimpleLogger().Write() << "matching starts with " << timestamp_list.size() << " locations"; + + SimpleLogger().Write() << "state_size: " << state_size; + + std::vector> viterbi(state_size, + std::vector(timestamp_list.size() + 1, 0)); + std::vector> parent( + state_size, std::vector(timestamp_list.size() + 1, 0)); + + SimpleLogger().Write() << "a"; + + for (auto s = 0; s < state_size; ++s) + { + SimpleLogger().Write() << "initializing s: " << s << "/" << state_size; + SimpleLogger().Write() + << " distance: " << timestamp_list[0][s].second << " at " + << timestamp_list[0][s].first.location << " prob " << std::setprecision(10) + << emission_probability(timestamp_list[0][s].second) << " logprob " + << log_probability(emission_probability(timestamp_list[0][s].second)); + // TODO: implement + const double emission_pr = 0.; + viterbi[s][0] = emission_pr; + parent[s][0] = s; + } + SimpleLogger().Write() << "b"; + + // attention, this call is relatively expensive + const auto beta = get_beta(state_size, timestamp_list, coordinate_list); + + for (auto t = 1; t < timestamp_list.size(); ++t) + { + // compute d_t for this timestamp and the next one + for (auto s = 0; s < state_size; ++s) + { + for (auto s_prime = 0; s_prime < state_size; ++s_prime) + { + // how likely is candidate s_prime at time t to be emitted? + const double emission_pr = emission_probability(timestamp_list[t][s_prime].second); + + // get distance diff between loc1/2 and locs/s_prime + const auto d_t = get_distance_difference(coordinate_list[t-1], + coordinate_list[t], + timestamp_list[t-1][s].first, + timestamp_list[t][s_prime].first); + + // plug probabilities together. TODO: change to addition for logprobs + const double transition_pr = transition_probability(beta, d_t); + const double new_value = viterbi[s][t] * emission_pr * transition_pr; + if (new_value > viterbi[s_prime][t]) + { + viterbi[s_prime][t] = new_value; + parent[s_prime][t] = s; + } + } + } + } + SimpleLogger().Write() << "c"; + SimpleLogger().Write() << "timestamps: " << timestamp_list.size(); + const auto number_of_timestamps = timestamp_list.size(); + const auto max_element_iter = std::max_element(viterbi[number_of_timestamps].begin(), + viterbi[number_of_timestamps].end()); + auto parent_index = std::distance(max_element_iter, viterbi[number_of_timestamps].begin()); + std::deque reconstructed_indices; + + SimpleLogger().Write() << "d"; + + for (auto i = number_of_timestamps - 1; i > 0; --i) + { + SimpleLogger().Write() << "[" << i << "] parent: " << parent_index ; + reconstructed_indices.push_front(parent_index); + parent_index = parent[parent_index][i]; + } + SimpleLogger().Write() << "[0] parent: " << parent_index; + reconstructed_indices.push_front(parent_index); + + SimpleLogger().Write() << "e"; + + for (auto i = 0; i < reconstructed_indices.size(); ++i) + { + auto location_index = reconstructed_indices[i]; + SimpleLogger().Write() << std::setprecision(8) << "location " << coordinate_list[i] << " to " << timestamp_list[i][location_index].first.location; + } + + SimpleLogger().Write() << "f, done"; + } +}; + +//[1] "Hidden Markov Map Matching Through Noise and Sparseness"; P. Newson and J. Krumm; 2009; ACM GIS + +#endif /* MAP_MATCHING_H */ diff --git a/server/data_structures/datafacade_base.hpp b/server/data_structures/datafacade_base.hpp index 0a2d22025..0c9edb2eb 100644 --- a/server/data_structures/datafacade_base.hpp +++ b/server/data_structures/datafacade_base.hpp @@ -105,6 +105,11 @@ template class BaseDataFacade IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, PhantomNode &resulting_phantom_node) = 0; + virtual bool + IncrementalFindPhantomNodeForCoordinateWithDistance(const FixedPointCoordinate &input_coordinate, + std::vector> &resulting_phantom_node_vector, + const unsigned number_of_results) = 0; + virtual unsigned GetCheckSum() const = 0; virtual unsigned GetNameIndexFromEdgeID(const unsigned id) const = 0; diff --git a/server/data_structures/internal_datafacade.hpp b/server/data_structures/internal_datafacade.hpp index 746402418..5ab769bb0 100644 --- a/server/data_structures/internal_datafacade.hpp +++ b/server/data_structures/internal_datafacade.hpp @@ -398,6 +398,7 @@ template class InternalDataFacade final : public BaseDataFacad BOOST_ASSERT(!resulting_phantom_node_vector.empty()); resulting_phantom_node = resulting_phantom_node_vector.front(); } + return result; } @@ -415,6 +416,20 @@ template class InternalDataFacade final : public BaseDataFacad input_coordinate, resulting_phantom_node_vector, number_of_results); } + bool + IncrementalFindPhantomNodeForCoordinateWithDistance(const FixedPointCoordinate &input_coordinate, + std::vector> &resulting_phantom_node_vector, + const unsigned number_of_results) final + { + if (!m_static_rtree.get()) + { + LoadRTree(); + } + + return m_static_rtree->IncrementalFindPhantomNodeForCoordinateWithDistance( + input_coordinate, resulting_phantom_node_vector, number_of_results); + } + unsigned GetCheckSum() const override final { return m_check_sum; } unsigned GetNameIndexFromEdgeID(const unsigned id) const override final diff --git a/server/data_structures/shared_datafacade.hpp b/server/data_structures/shared_datafacade.hpp index fcec478b2..eaf9386f7 100644 --- a/server/data_structures/shared_datafacade.hpp +++ b/server/data_structures/shared_datafacade.hpp @@ -386,6 +386,7 @@ template class SharedDataFacade final : public BaseDataFacade< BOOST_ASSERT(!resulting_phantom_node_vector.empty()); resulting_phantom_node = resulting_phantom_node_vector.front(); } + return result; } @@ -403,6 +404,20 @@ template class SharedDataFacade final : public BaseDataFacade< input_coordinate, resulting_phantom_node_vector, number_of_results); } + bool + IncrementalFindPhantomNodeForCoordinateWithDistance(const FixedPointCoordinate &input_coordinate, + std::vector> &resulting_phantom_node_vector, + const unsigned number_of_results) final + { + if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first) + { + LoadRTree(); + } + + return m_static_rtree->second->IncrementalFindPhantomNodeForCoordinateWithDistance( + input_coordinate, resulting_phantom_node_vector, number_of_results); + } + unsigned GetCheckSum() const override final { return m_check_sum; } unsigned GetNameIndexFromEdgeID(const unsigned id) const override final From 3a5e41ed91beecd7fbfda0dfe1c37de338b709e8 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Mon, 8 Dec 2014 14:46:31 -0800 Subject: [PATCH 229/360] Implement missing matching pieces --- data_structures/static_rtree.hpp | 23 +- plugins/map_matching.hpp | 103 +++++-- routing_algorithms/map_matching.hpp | 287 +++++++++++++----- server/data_structures/datafacade_base.hpp | 4 +- .../data_structures/internal_datafacade.hpp | 6 +- server/data_structures/shared_datafacade.hpp | 6 +- 6 files changed, 317 insertions(+), 112 deletions(-) diff --git a/data_structures/static_rtree.hpp b/data_structures/static_rtree.hpp index 45109df73..e2a93c8e3 100644 --- a/data_structures/static_rtree.hpp +++ b/data_structures/static_rtree.hpp @@ -642,10 +642,6 @@ class StaticRTree return result_coordinate.is_valid(); } - // implementation of the Hjaltason/Samet query [3], a BFS traversal of the tree - // - searches for k elements nearest elements - // - continues to find the k+1st element from a big component if k elements - // come from tiny components bool IncrementalFindPhantomNodeForCoordinate( const FixedPointCoordinate &input_coordinate, std::vector &result_phantom_node_vector, @@ -797,9 +793,17 @@ class StaticRTree return !result_phantom_node_vector.empty(); } + /** + * Returns elements within max_distance. + * If the minium of elements could not be found in the search radius, widen + * it until the minimum can be satisfied. + * At the number of returned nodes is capped at the given maximum. + */ bool IncrementalFindPhantomNodeForCoordinateWithDistance( const FixedPointCoordinate &input_coordinate, std::vector> &result_phantom_node_vector, + const double max_distance, + const unsigned min_number_of_phantom_nodes, const unsigned max_number_of_phantom_nodes, const unsigned max_checked_elements = 4 * LEAF_NODE_SIZE) { @@ -884,7 +888,7 @@ class StaticRTree // continue searching for the first segment from a big component if (number_of_elements_from_big_cc == 0 && - number_of_elements_from_tiny_cc >= max_number_of_phantom_nodes && + number_of_elements_from_tiny_cc >= max_number_of_phantom_nodes-1 && current_segment.is_in_tiny_cc()) { continue; @@ -900,6 +904,14 @@ class StaticRTree m_coordinate_list->at(current_segment.v), input_coordinate, projected_coordinate, foot_point_coordinate_on_segment, current_ratio); + if (number_of_elements_from_big_cc > 0 + && (number_of_elements_from_tiny_cc + number_of_elements_from_tiny_cc >= max_number_of_phantom_nodes + || current_perpendicular_distance >= max_distance)) + { + traversal_queue = std::priority_queue{}; + continue; + } + // store phantom node in result vector result_phantom_node_vector.emplace_back( PhantomNode( current_segment.forward_edge_based_node_id, @@ -951,7 +963,6 @@ class StaticRTree return !result_phantom_node_vector.empty(); } - bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, PhantomNode &result_phantom_node, const unsigned zoom_level) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 8b997d881..7be46ed49 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -1,5 +1,5 @@ -/* - open source routing machine + /* + open source routing machine Copyright (C) Dennis Luxen, others 2010 This program is free software; you can redistribute it and/or modify @@ -29,6 +29,9 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "../routing_algorithms/map_matching.hpp" #include "../util/simple_logger.hpp" #include "../util/string_util.hpp" +#include "../descriptors/descriptor_base.hpp" +#include "../descriptors/gpx_descriptor.hpp" +#include "../descriptors/json_descriptor.hpp" #include @@ -40,11 +43,16 @@ or see http://www.gnu.org/licenses/agpl.txt. template class MapMatchingPlugin : public BasePlugin { private: + std::unordered_map descriptor_table; std::shared_ptr> search_engine_ptr; public: MapMatchingPlugin(DataFacadeT *facade) : descriptor_string("match"), facade(facade) { + descriptor_table.emplace("json", 0); + descriptor_table.emplace("gpx", 1); + // descriptor_table.emplace("geojson", 2); + // search_engine_ptr = std::make_shared>(facade); } @@ -55,47 +63,98 @@ template class MapMatchingPlugin : public BasePlugin int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final { // check number of parameters - - SimpleLogger().Write() << "1"; if (!check_all_coordinates(route_parameters.coordinates)) { return 400; } - SimpleLogger().Write() << "2"; - InternalRouteResult raw_route; Matching::CandidateLists candidate_lists; - candidate_lists.resize(route_parameters.coordinates.size()); - SimpleLogger().Write() << "3"; - // fetch 10 candidates for each given coordinate - for (const auto current_coordinate : osrm::irange(0, candidate_lists.size())) + double last_distance = coordinate_calculation::great_circle_distance( + route_parameters.coordinates[0], + route_parameters.coordinates[1]); + for (const auto current_coordinate : osrm::irange(0, route_parameters.coordinates.size())) { + if (0 < current_coordinate) + last_distance = coordinate_calculation::great_circle_distance( + route_parameters.coordinates[current_coordinate - 1], + route_parameters.coordinates[current_coordinate]); + + std::cout << "Searching: " << current_coordinate << std::endl; + std::vector> candidates; if (!facade->IncrementalFindPhantomNodeForCoordinateWithDistance( route_parameters.coordinates[current_coordinate], - candidate_lists[current_coordinate], - 10)) + candidates, + last_distance, + 5, + 20)) { - return 400; + std::cout << "Nothing found for " << current_coordinate << std::endl; + continue; } - while (candidate_lists[current_coordinate].size() < 10) - { - // TODO: add dummy candidates, if any are missing - // TODO: add factory method to get an invalid PhantomNode/Distance pair - } + candidate_lists.push_back(candidates); + + std::cout << current_coordinate << " (" << (last_distance / 2.0) << ") : " + << candidates.size() << std::endl; + + BOOST_ASSERT(candidate_lists[current_coordinate].size() == 10); + } + + if (2 > candidate_lists.size()) + { + return 400; } - SimpleLogger().Write() << "4"; // call the actual map matching - search_engine_ptr->map_matching(10, candidate_lists, route_parameters.coordinates, raw_route); + std::vector matched_nodes; + JSON::Object debug_info; + search_engine_ptr->map_matching(candidate_lists, route_parameters.coordinates, matched_nodes, debug_info); - if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length) + PhantomNodes current_phantom_node_pair; + for (unsigned i = 0; i < matched_nodes.size() - 1; ++i) { - SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found"; + current_phantom_node_pair.source_phantom = matched_nodes[i]; + current_phantom_node_pair.target_phantom = matched_nodes[i + 1]; + raw_route.segment_end_coordinates.emplace_back(current_phantom_node_pair); } + search_engine_ptr->shortest_path( + raw_route.segment_end_coordinates, route_parameters.uturns, raw_route); + + DescriptorConfig descriptor_config; + + auto iter = descriptor_table.find(route_parameters.output_format); + unsigned descriptor_type = (iter != descriptor_table.end() ? iter->second : 0); + + descriptor_config.zoom_level = route_parameters.zoom_level; + descriptor_config.instructions = route_parameters.print_instructions; + descriptor_config.geometry = route_parameters.geometry; + descriptor_config.encode_geometry = route_parameters.compression; + + std::shared_ptr> descriptor; + switch (descriptor_type) + { + // case 0: + // descriptor = std::make_shared>(); + // break; + case 1: + descriptor = std::make_shared>(facade); + break; + // case 2: + // descriptor = std::make_shared>(); + // break; + default: + descriptor = std::make_shared>(facade); + break; + } + + descriptor->SetConfig(descriptor_config); + descriptor->Run(raw_route, json_result); + + json_result.values["debug"] = debug_info; + return 200; } diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 80152f1ef..1b28f8a30 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -31,6 +31,38 @@ or see http://www.gnu.org/licenses/agpl.txt. #include #include +#include + +template +T makeJSONSave(T d) +{ + if (std::isnan(d) || std::numeric_limits::infinity() == d) { + return std::numeric_limits::max(); + } + if (-std::numeric_limits::infinity() == d) { + return -std::numeric_limits::max(); + } + + return d; +} + +void appendToJSONArray(JSON::Array& a) { } + +template +void appendToJSONArray(JSON::Array& a, T value, Args... args) +{ + a.values.emplace_back(value); + appendToJSONArray(a, args...); +} + +template +JSON::Array makeJSONArray(Args... args) +{ + JSON::Array a; + appendToJSONArray(a, args...); + return a; +} + namespace Matching { typedef std::vector> CandidateList; @@ -115,9 +147,9 @@ template class MapMatching final const std::vector coordinate_list) const { std::vector d_t_list, median_select_d_t_list; - for (auto t = 1; t < timestamp_list.size(); ++t) + for (auto t = 1u; t < timestamp_list.size(); ++t) { - for (auto s = 0; s < state_size; ++s) + for (auto s = 0u; s < state_size; ++s) { d_t_list.push_back(get_distance_difference(coordinate_list[t - 1], coordinate_list[t], @@ -142,7 +174,7 @@ template class MapMatching final const PhantomNode &target_phantom) const { // great circle distance of two locations - median/avg dist table(candidate list1/2) - const EdgeWeight network_distance = get_network_distance(source_phantom, target_phantom); + const auto network_distance = get_network_distance(source_phantom, target_phantom); const auto great_circle_distance = coordinate_calculation::great_circle_distance(location1, location2); @@ -153,7 +185,7 @@ template class MapMatching final return network_distance - great_circle_distance; } - EdgeWeight get_network_distance(const PhantomNode &source_phantom, + double get_network_distance(const PhantomNode &source_phantom, const PhantomNode &target_phantom) const { EdgeWeight upper_bound = INVALID_EDGE_WEIGHT; @@ -209,7 +241,31 @@ template class MapMatching final reverse_heap, forward_heap, &middle_node, &upper_bound, edge_offset, false); } } - return upper_bound; + + double distance = std::numeric_limits::max(); + if (upper_bound != INVALID_EDGE_WEIGHT) + { + std::vector packed_leg; + super::RetrievePackedPathFromHeap(forward_heap, reverse_heap, middle_node, packed_leg); + std::vector unpacked_path; + PhantomNodes nodes; + nodes.source_phantom = source_phantom; + nodes.target_phantom = target_phantom; + super::UnpackPath(packed_leg, nodes, unpacked_path); + + FixedPointCoordinate previous_coordinate = source_phantom.location; + FixedPointCoordinate current_coordinate; + distance = 0; + for (const auto& p : unpacked_path) + { + current_coordinate = super::facade->GetCoordinateOfNode(p.node); + distance += coordinate_calculation::great_circle_distance(previous_coordinate, current_coordinate); + previous_coordinate = current_coordinate; + } + distance += coordinate_calculation::great_circle_distance(previous_coordinate, target_phantom.location); + } + + return distance; } public: @@ -218,97 +274,170 @@ template class MapMatching final { } - void operator()(const unsigned state_size, - const Matching::CandidateLists ×tamp_list, - const std::vector coordinate_list, - InternalRouteResult &raw_route_data) const + // TODO optimize: a lot of copying that could probably be avoided + void expandCandidates(const Matching::CandidateLists &candidates_lists, + Matching::CandidateLists &expanded_lists) const { - BOOST_ASSERT(state_size != std::numeric_limits::max()); - BOOST_ASSERT(state_size != 0); - SimpleLogger().Write() << "matching starts with " << timestamp_list.size() << " locations"; - - SimpleLogger().Write() << "state_size: " << state_size; - - std::vector> viterbi(state_size, - std::vector(timestamp_list.size() + 1, 0)); - std::vector> parent( - state_size, std::vector(timestamp_list.size() + 1, 0)); - - SimpleLogger().Write() << "a"; - - for (auto s = 0; s < state_size; ++s) + // expand list of PhantomNodes to be single-directional + expanded_lists.resize(candidates_lists.size()); + for (const auto i : osrm::irange(0lu, candidates_lists.size())) { - SimpleLogger().Write() << "initializing s: " << s << "/" << state_size; - SimpleLogger().Write() - << " distance: " << timestamp_list[0][s].second << " at " - << timestamp_list[0][s].first.location << " prob " << std::setprecision(10) - << emission_probability(timestamp_list[0][s].second) << " logprob " - << log_probability(emission_probability(timestamp_list[0][s].second)); - // TODO: implement - const double emission_pr = 0.; - viterbi[s][0] = emission_pr; - parent[s][0] = s; - } - SimpleLogger().Write() << "b"; - - // attention, this call is relatively expensive - const auto beta = get_beta(state_size, timestamp_list, coordinate_list); - - for (auto t = 1; t < timestamp_list.size(); ++t) - { - // compute d_t for this timestamp and the next one - for (auto s = 0; s < state_size; ++s) + for (const auto& candidate : candidates_lists[i]) { - for (auto s_prime = 0; s_prime < state_size; ++s_prime) + // bi-directional edge, split phantom node + if (candidate.first.forward_node_id != SPECIAL_NODEID && candidate.first.reverse_node_id != SPECIAL_NODEID) { - // how likely is candidate s_prime at time t to be emitted? - const double emission_pr = emission_probability(timestamp_list[t][s_prime].second); - - // get distance diff between loc1/2 and locs/s_prime - const auto d_t = get_distance_difference(coordinate_list[t-1], - coordinate_list[t], - timestamp_list[t-1][s].first, - timestamp_list[t][s_prime].first); - - // plug probabilities together. TODO: change to addition for logprobs - const double transition_pr = transition_probability(beta, d_t); - const double new_value = viterbi[s][t] * emission_pr * transition_pr; - if (new_value > viterbi[s_prime][t]) - { - viterbi[s_prime][t] = new_value; - parent[s_prime][t] = s; - } + PhantomNode forward_node(candidate.first); + PhantomNode reverse_node(candidate.first); + forward_node.reverse_node_id = SPECIAL_NODEID; + reverse_node.forward_node_id = SPECIAL_NODEID; + expanded_lists[i].emplace_back(forward_node, candidate.second); + expanded_lists[i].emplace_back(reverse_node, candidate.second); + } + else + { + expanded_lists[i].push_back(candidate); } } } - SimpleLogger().Write() << "c"; - SimpleLogger().Write() << "timestamps: " << timestamp_list.size(); - const auto number_of_timestamps = timestamp_list.size(); - const auto max_element_iter = std::max_element(viterbi[number_of_timestamps].begin(), - viterbi[number_of_timestamps].end()); - auto parent_index = std::distance(max_element_iter, viterbi[number_of_timestamps].begin()); + } + + void operator()(const Matching::CandidateLists &candidates_lists, + const std::vector coordinate_list, + std::vector& matched_nodes, + JSON::Object& _debug_info) const + { + BOOST_ASSERT(candidates_lists.size() == coordinate_list.size()); + + Matching::CandidateLists timestamp_list; + expandCandidates(candidates_lists, timestamp_list); + + BOOST_ASSERT(timestamp_list.size() > 0); + + // TODO for the viterbi values we actually only need the current and last row + std::vector> viterbi; + std::vector> parents; + for (const auto& l : timestamp_list) + { + viterbi.emplace_back(l.size(), -std::numeric_limits::infinity()); + parents.emplace_back(l.size(), 0); + } + + JSON::Array _debug_viterbi; + JSON::Array _debug_initial_viterbi; + for (auto s = 0u; s < viterbi[0].size(); ++s) + { + // this might need to be squared as pi_s is also defined as the emission + // probability in the paper. + viterbi[0][s] = log_probability(emission_probability(timestamp_list[0][s].second)); + parents[0][s] = s; + + _debug_initial_viterbi.values.push_back(makeJSONSave(viterbi[0][s])); + } + _debug_viterbi.values.push_back(_debug_initial_viterbi); + + // attention, this call is relatively expensive + //const auto beta = get_beta(state_size, timestamp_list, coordinate_list); + const auto beta = 10.0; + + JSON::Array _debug_timestamps; + for (auto t = 1u; t < timestamp_list.size(); ++t) + { + const auto& prev_viterbi = viterbi[t-1]; + const auto& prev_timestamps_list = timestamp_list[t-1]; + const auto& prev_coordinate = coordinate_list[t-1]; + + auto& current_viterbi = viterbi[t]; + auto& current_parents = parents[t]; + const auto& current_timestamps_list = timestamp_list[t]; + const auto& current_coordinate = coordinate_list[t]; + + JSON::Array _debug_transition_rows; + // compute d_t for this timestamp and the next one + for (auto s = 0u; s < prev_viterbi.size(); ++s) + { + + JSON::Array _debug_row; + for (auto s_prime = 0u; s_prime < current_viterbi.size(); ++s_prime) + { + + // how likely is candidate s_prime at time t to be emitted? + const double emission_pr = log_probability(emission_probability(timestamp_list[t][s_prime].second)); + + // get distance diff between loc1/2 and locs/s_prime + const auto d_t = get_distance_difference(prev_coordinate, + current_coordinate, + prev_timestamps_list[s].first, + current_timestamps_list[s_prime].first); + + // plug probabilities together + const double transition_pr = log_probability(transition_probability(d_t, beta)); + const double new_value = prev_viterbi[s] + emission_pr + transition_pr; + + JSON::Array _debug_element = makeJSONArray( + makeJSONSave(prev_viterbi[s]), + makeJSONSave(emission_pr), + makeJSONSave(transition_pr), + get_network_distance(prev_timestamps_list[s].first, current_timestamps_list[s_prime].first), + coordinate_calculation::great_circle_distance(prev_coordinate, current_coordinate) + ); + + _debug_row.values.push_back(_debug_element); + + if (new_value > current_viterbi[s_prime]) + { + current_viterbi[s_prime] = new_value; + current_parents[s_prime] = s; + } + } + _debug_transition_rows.values.push_back(_debug_row); + } + _debug_timestamps.values.push_back(_debug_transition_rows); + + JSON::Array _debug_viterbi_col; + for (auto s_prime = 0u; s_prime < current_timestamps_list.size(); ++s_prime) + { + _debug_viterbi_col.values.push_back(makeJSONSave(current_viterbi[s_prime])); + } + _debug_viterbi.values.push_back(_debug_viterbi_col); + } + + _debug_info.values["transitions"] = _debug_timestamps; + _debug_info.values["viterbi"] = _debug_viterbi; + _debug_info.values["beta"] = beta; + + // loop through the columns, and only compare the last entry + auto max_element_iter = std::max_element(viterbi.back().begin(), viterbi.back().end()); + auto parent_index = std::distance(viterbi.back().begin(), max_element_iter); std::deque reconstructed_indices; - SimpleLogger().Write() << "d"; - - for (auto i = number_of_timestamps - 1; i > 0; --i) + for (auto i = timestamp_list.size() - 1u; i > 0u; --i) { - SimpleLogger().Write() << "[" << i << "] parent: " << parent_index ; reconstructed_indices.push_front(parent_index); - parent_index = parent[parent_index][i]; + parent_index = parents[i][parent_index]; } - SimpleLogger().Write() << "[0] parent: " << parent_index; reconstructed_indices.push_front(parent_index); - SimpleLogger().Write() << "e"; - - for (auto i = 0; i < reconstructed_indices.size(); ++i) + JSON::Array _debug_chosen_candidates; + matched_nodes.resize(reconstructed_indices.size()); + for (auto i = 0u; i < reconstructed_indices.size(); ++i) { auto location_index = reconstructed_indices[i]; - SimpleLogger().Write() << std::setprecision(8) << "location " << coordinate_list[i] << " to " << timestamp_list[i][location_index].first.location; + matched_nodes[i] = timestamp_list[i][location_index].first; + _debug_chosen_candidates.values.push_back(location_index); } - - SimpleLogger().Write() << "f, done"; + _debug_info.values["chosen_candidates"] = _debug_chosen_candidates; + JSON::Array _debug_expanded_candidates; + for (const auto& l : timestamp_list) { + JSON::Array _debug_expanded_candidates_col; + for (const auto& pair : l) { + const auto& coord = pair.first.location; + _debug_expanded_candidates_col.values.push_back(makeJSONArray(coord.lat / COORDINATE_PRECISION, + coord.lon / COORDINATE_PRECISION)); + } + _debug_expanded_candidates.values.push_back(_debug_expanded_candidates_col); + } + _debug_info.values["expanded_candidates"] = _debug_expanded_candidates; } }; diff --git a/server/data_structures/datafacade_base.hpp b/server/data_structures/datafacade_base.hpp index 0c9edb2eb..9ec01e16e 100644 --- a/server/data_structures/datafacade_base.hpp +++ b/server/data_structures/datafacade_base.hpp @@ -108,7 +108,9 @@ template class BaseDataFacade virtual bool IncrementalFindPhantomNodeForCoordinateWithDistance(const FixedPointCoordinate &input_coordinate, std::vector> &resulting_phantom_node_vector, - const unsigned number_of_results) = 0; + const double max_distance, + const unsigned min_number_of_phantom_nodes, + const unsigned max_number_of_phantom_nodes) = 0; virtual unsigned GetCheckSum() const = 0; diff --git a/server/data_structures/internal_datafacade.hpp b/server/data_structures/internal_datafacade.hpp index 5ab769bb0..da974886b 100644 --- a/server/data_structures/internal_datafacade.hpp +++ b/server/data_structures/internal_datafacade.hpp @@ -419,7 +419,9 @@ template class InternalDataFacade final : public BaseDataFacad bool IncrementalFindPhantomNodeForCoordinateWithDistance(const FixedPointCoordinate &input_coordinate, std::vector> &resulting_phantom_node_vector, - const unsigned number_of_results) final + const double max_distance, + const unsigned min_number_of_phantom_nodes, + const unsigned max_number_of_phantom_nodes) final { if (!m_static_rtree.get()) { @@ -427,7 +429,7 @@ template class InternalDataFacade final : public BaseDataFacad } return m_static_rtree->IncrementalFindPhantomNodeForCoordinateWithDistance( - input_coordinate, resulting_phantom_node_vector, number_of_results); + input_coordinate, resulting_phantom_node_vector, max_distance, min_number_of_phantom_nodes, max_number_of_phantom_nodes); } unsigned GetCheckSum() const override final { return m_check_sum; } diff --git a/server/data_structures/shared_datafacade.hpp b/server/data_structures/shared_datafacade.hpp index eaf9386f7..8451775bb 100644 --- a/server/data_structures/shared_datafacade.hpp +++ b/server/data_structures/shared_datafacade.hpp @@ -407,7 +407,9 @@ template class SharedDataFacade final : public BaseDataFacade< bool IncrementalFindPhantomNodeForCoordinateWithDistance(const FixedPointCoordinate &input_coordinate, std::vector> &resulting_phantom_node_vector, - const unsigned number_of_results) final + const double max_distance, + const unsigned min_number_of_phantom_nodes, + const unsigned max_number_of_phantom_nodes) final { if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first) { @@ -415,7 +417,7 @@ template class SharedDataFacade final : public BaseDataFacade< } return m_static_rtree->second->IncrementalFindPhantomNodeForCoordinateWithDistance( - input_coordinate, resulting_phantom_node_vector, number_of_results); + input_coordinate, resulting_phantom_node_vector, max_distance, min_number_of_phantom_nodes, max_number_of_phantom_nodes); } unsigned GetCheckSum() const override final { return m_check_sum; } From 59727a69676ca931f01f5df0cd827e4e138d5296 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 16 Jan 2015 00:17:40 +0100 Subject: [PATCH 230/360] Get all nodes in dense areas but make sure we don't underflow in sparse ones --- plugins/map_matching.hpp | 18 +++--------------- server/data_structures/datafacade_base.hpp | 3 +-- server/data_structures/internal_datafacade.hpp | 2 +- server/data_structures/shared_datafacade.hpp | 2 +- 4 files changed, 6 insertions(+), 19 deletions(-) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 7be46ed49..3a589ed25 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -81,30 +81,18 @@ template class MapMatchingPlugin : public BasePlugin route_parameters.coordinates[current_coordinate - 1], route_parameters.coordinates[current_coordinate]); - std::cout << "Searching: " << current_coordinate << std::endl; std::vector> candidates; - if (!facade->IncrementalFindPhantomNodeForCoordinateWithDistance( + if (!facade->IncrementalFindPhantomNodeForCoordinateWithMaxDistance( route_parameters.coordinates[current_coordinate], candidates, - last_distance, + last_distance/2.0, 5, 20)) { - std::cout << "Nothing found for " << current_coordinate << std::endl; - continue; + return 400; } candidate_lists.push_back(candidates); - - std::cout << current_coordinate << " (" << (last_distance / 2.0) << ") : " - << candidates.size() << std::endl; - - BOOST_ASSERT(candidate_lists[current_coordinate].size() == 10); - } - - if (2 > candidate_lists.size()) - { - return 400; } // call the actual map matching diff --git a/server/data_structures/datafacade_base.hpp b/server/data_structures/datafacade_base.hpp index 9ec01e16e..04486532d 100644 --- a/server/data_structures/datafacade_base.hpp +++ b/server/data_structures/datafacade_base.hpp @@ -104,9 +104,8 @@ template class BaseDataFacade virtual bool IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, PhantomNode &resulting_phantom_node) = 0; - virtual bool - IncrementalFindPhantomNodeForCoordinateWithDistance(const FixedPointCoordinate &input_coordinate, + IncrementalFindPhantomNodeForCoordinateWithMaxDistance(const FixedPointCoordinate &input_coordinate, std::vector> &resulting_phantom_node_vector, const double max_distance, const unsigned min_number_of_phantom_nodes, diff --git a/server/data_structures/internal_datafacade.hpp b/server/data_structures/internal_datafacade.hpp index da974886b..a85a78e30 100644 --- a/server/data_structures/internal_datafacade.hpp +++ b/server/data_structures/internal_datafacade.hpp @@ -417,7 +417,7 @@ template class InternalDataFacade final : public BaseDataFacad } bool - IncrementalFindPhantomNodeForCoordinateWithDistance(const FixedPointCoordinate &input_coordinate, + IncrementalFindPhantomNodeForCoordinateWithMaxDistance(const FixedPointCoordinate &input_coordinate, std::vector> &resulting_phantom_node_vector, const double max_distance, const unsigned min_number_of_phantom_nodes, diff --git a/server/data_structures/shared_datafacade.hpp b/server/data_structures/shared_datafacade.hpp index 8451775bb..87af81929 100644 --- a/server/data_structures/shared_datafacade.hpp +++ b/server/data_structures/shared_datafacade.hpp @@ -405,7 +405,7 @@ template class SharedDataFacade final : public BaseDataFacade< } bool - IncrementalFindPhantomNodeForCoordinateWithDistance(const FixedPointCoordinate &input_coordinate, + IncrementalFindPhantomNodeForCoordinateWithMaxDistance(const FixedPointCoordinate &input_coordinate, std::vector> &resulting_phantom_node_vector, const double max_distance, const unsigned min_number_of_phantom_nodes, From 496338d84d13c415cfa6a3d56eaa61ff1f51f937 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sat, 17 Jan 2015 01:26:43 +0100 Subject: [PATCH 231/360] Implemented pruning and breakage detection --- routing_algorithms/map_matching.hpp | 138 ++++++++++++++++++++++------ 1 file changed, 109 insertions(+), 29 deletions(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 1b28f8a30..baa225fb6 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -312,42 +312,82 @@ template class MapMatching final Matching::CandidateLists timestamp_list; expandCandidates(candidates_lists, timestamp_list); + std::vector breakage(timestamp_list.size(), true); + BOOST_ASSERT(timestamp_list.size() > 0); // TODO for the viterbi values we actually only need the current and last row std::vector> viterbi; std::vector> parents; + std::vector> pruned; for (const auto& l : timestamp_list) { viterbi.emplace_back(l.size(), -std::numeric_limits::infinity()); parents.emplace_back(l.size(), 0); + pruned.emplace_back(l.size(), true); } + JSON::Array _debug_timestamps; JSON::Array _debug_viterbi; - JSON::Array _debug_initial_viterbi; - for (auto s = 0u; s < viterbi[0].size(); ++s) - { - // this might need to be squared as pi_s is also defined as the emission - // probability in the paper. - viterbi[0][s] = log_probability(emission_probability(timestamp_list[0][s].second)); - parents[0][s] = s; + JSON::Array _debug_pruned; - _debug_initial_viterbi.values.push_back(makeJSONSave(viterbi[0][s])); - } - _debug_viterbi.values.push_back(_debug_initial_viterbi); + unsigned initial_timestamp = 0; + do + { + JSON::Array _debug_initial_viterbi; + JSON::Array _debug_initial_pruned; + + for (auto s = 0u; s < viterbi[initial_timestamp].size(); ++s) + { + // this might need to be squared as pi_s is also defined as the emission + // probability in the paper. + viterbi[initial_timestamp][s] = log_probability(emission_probability(timestamp_list[initial_timestamp][s].second)); + parents[initial_timestamp][s] = s; + pruned[initial_timestamp][s] = viterbi[initial_timestamp][s] < -std::numeric_limits::max(); + + breakage[initial_timestamp] = breakage[initial_timestamp] && pruned[initial_timestamp][s]; + } + + for (auto s = 0u; s < viterbi[initial_timestamp].size(); ++s) + { + _debug_initial_viterbi.values.push_back(makeJSONSave(viterbi[initial_timestamp][s])); + _debug_initial_pruned.values.push_back(static_cast(pruned[initial_timestamp][s])); + } + + _debug_viterbi.values.push_back(_debug_initial_viterbi); + _debug_pruned.values.push_back(_debug_initial_pruned); + + + if (initial_timestamp > 0) { + JSON::Array _debug_transition_rows; + for (auto s = 0u; s < viterbi[initial_timestamp-1].size(); ++s) { + _debug_transition_rows.values.push_back(JSON::Array()); + } + _debug_timestamps.values.push_back(_debug_transition_rows); + } + + ++initial_timestamp; + } while (breakage[initial_timestamp - 1]); + + BOOST_ASSERT(initial_timestamp > 0 && initial_timestamp < viterbi.size()); + --initial_timestamp; + + BOOST_ASSERT(breakage[initial_timestamp] == false); // attention, this call is relatively expensive //const auto beta = get_beta(state_size, timestamp_list, coordinate_list); const auto beta = 10.0; - JSON::Array _debug_timestamps; - for (auto t = 1u; t < timestamp_list.size(); ++t) + unsigned prev_unbroken_timestamp = initial_timestamp; + for (auto t = initial_timestamp + 1; t < timestamp_list.size(); ++t) { - const auto& prev_viterbi = viterbi[t-1]; - const auto& prev_timestamps_list = timestamp_list[t-1]; - const auto& prev_coordinate = coordinate_list[t-1]; + const auto& prev_viterbi = viterbi[prev_unbroken_timestamp]; + const auto& prev_pruned = pruned[prev_unbroken_timestamp]; + const auto& prev_unbroken_timestamps_list = timestamp_list[prev_unbroken_timestamp]; + const auto& prev_coordinate = coordinate_list[prev_unbroken_timestamp]; auto& current_viterbi = viterbi[t]; + auto& current_pruned = pruned[t]; auto& current_parents = parents[t]; const auto& current_timestamps_list = timestamp_list[t]; const auto& current_coordinate = coordinate_list[t]; @@ -356,8 +396,13 @@ template class MapMatching final // compute d_t for this timestamp and the next one for (auto s = 0u; s < prev_viterbi.size(); ++s) { - JSON::Array _debug_row; + if (prev_pruned[s]) + { + _debug_transition_rows.values.push_back(_debug_row); + continue; + } + for (auto s_prime = 0u; s_prime < current_viterbi.size(); ++s_prime) { @@ -367,7 +412,7 @@ template class MapMatching final // get distance diff between loc1/2 and locs/s_prime const auto d_t = get_distance_difference(prev_coordinate, current_coordinate, - prev_timestamps_list[s].first, + prev_unbroken_timestamps_list[s].first, current_timestamps_list[s_prime].first); // plug probabilities together @@ -378,7 +423,7 @@ template class MapMatching final makeJSONSave(prev_viterbi[s]), makeJSONSave(emission_pr), makeJSONSave(transition_pr), - get_network_distance(prev_timestamps_list[s].first, current_timestamps_list[s_prime].first), + get_network_distance(prev_unbroken_timestamps_list[s].first, current_timestamps_list[s_prime].first), coordinate_calculation::great_circle_distance(prev_coordinate, current_coordinate) ); @@ -388,6 +433,8 @@ template class MapMatching final { current_viterbi[s_prime] = new_value; current_parents[s_prime] = s; + current_pruned[s_prime] = false; + breakage[t] = false; } } _debug_transition_rows.values.push_back(_debug_row); @@ -395,38 +442,71 @@ template class MapMatching final _debug_timestamps.values.push_back(_debug_transition_rows); JSON::Array _debug_viterbi_col; - for (auto s_prime = 0u; s_prime < current_timestamps_list.size(); ++s_prime) + JSON::Array _debug_pruned_col; + for (auto s_prime = 0u; s_prime < current_viterbi.size(); ++s_prime) { _debug_viterbi_col.values.push_back(makeJSONSave(current_viterbi[s_prime])); + _debug_pruned_col.values.push_back(static_cast(current_pruned[s_prime])); } _debug_viterbi.values.push_back(_debug_viterbi_col); + _debug_pruned.values.push_back(_debug_pruned_col); + + if (!breakage[t]) + { + prev_unbroken_timestamp = t; + } } _debug_info.values["transitions"] = _debug_timestamps; _debug_info.values["viterbi"] = _debug_viterbi; + _debug_info.values["pruned"] = _debug_pruned; _debug_info.values["beta"] = beta; // loop through the columns, and only compare the last entry - auto max_element_iter = std::max_element(viterbi.back().begin(), viterbi.back().end()); - auto parent_index = std::distance(viterbi.back().begin(), max_element_iter); - std::deque reconstructed_indices; + auto max_element_iter = std::max_element(viterbi[prev_unbroken_timestamp].begin(), viterbi[prev_unbroken_timestamp].end()); + auto parent_index = std::distance(viterbi[prev_unbroken_timestamp].begin(), max_element_iter); + std::deque> reconstructed_indices; - for (auto i = timestamp_list.size() - 1u; i > 0u; --i) + for (auto i = prev_unbroken_timestamp; i > initial_timestamp; --i) { - reconstructed_indices.push_front(parent_index); + if (breakage[i]) + continue; + reconstructed_indices.emplace_front(i, parent_index); parent_index = parents[i][parent_index]; } - reconstructed_indices.push_front(parent_index); + reconstructed_indices.emplace_front(initial_timestamp, parent_index); - JSON::Array _debug_chosen_candidates; matched_nodes.resize(reconstructed_indices.size()); for (auto i = 0u; i < reconstructed_indices.size(); ++i) { - auto location_index = reconstructed_indices[i]; - matched_nodes[i] = timestamp_list[i][location_index].first; - _debug_chosen_candidates.values.push_back(location_index); + auto timestamp_index = reconstructed_indices[i].first; + auto location_index = reconstructed_indices[i].second; + + matched_nodes[i] = timestamp_list[timestamp_index][location_index].first; + } + + JSON::Array _debug_chosen_candidates; + auto _debug_candidate_iter = reconstructed_indices.begin(); + for (auto i = 0u; i < timestamp_list.size(); ++i) + { + if (_debug_candidate_iter != reconstructed_indices.end() && _debug_candidate_iter->first == i) + { + _debug_chosen_candidates.values.push_back(_debug_candidate_iter->second); + _debug_candidate_iter = std::next(_debug_candidate_iter); + } + else + { + _debug_chosen_candidates.values.push_back(JSON::Null()); + } } _debug_info.values["chosen_candidates"] = _debug_chosen_candidates; + + JSON::Array _debug_breakage; + for (auto b : breakage) { + _debug_breakage.values.push_back(static_cast(b)); + } + _debug_info.values["breakage"] = _debug_breakage; + JSON::Array _debug_expanded_candidates; for (const auto& l : timestamp_list) { JSON::Array _debug_expanded_candidates_col; From 173fad2362a4b2fe50353470a25a4606a288fb78 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Mon, 19 Jan 2015 23:02:07 +0100 Subject: [PATCH 232/360] Return error when less than 2 points left. --- plugins/map_matching.hpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 3a589ed25..641d198ca 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -108,8 +108,16 @@ template class MapMatchingPlugin : public BasePlugin raw_route.segment_end_coordinates.emplace_back(current_phantom_node_pair); } + if (2 > matched_nodes.size()) + { + reply = http::Reply::StockReply(http::Reply::badRequest); + return; + } + search_engine_ptr->shortest_path( - raw_route.segment_end_coordinates, route_parameters.uturns, raw_route); + raw_route.segment_end_coordinates, + std::vector(raw_route.segment_end_coordinates.size(), true), + raw_route); DescriptorConfig descriptor_config; From a5db3ea25ba9f744867d21838d70e79b2f4d40dc Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Mon, 19 Jan 2015 23:03:26 +0100 Subject: [PATCH 233/360] Print warning when more than 10 points are removed --- routing_algorithms/map_matching.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index baa225fb6..8432c548c 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -485,6 +485,10 @@ template class MapMatching final matched_nodes[i] = timestamp_list[timestamp_index][location_index].first; } + unsigned removed = candidates_lists.size() - matched_nodes.size(); + if (removed > 10) + SimpleLogger().Write(logWARNING) << "Warning: removed " << removed << " candiates."; + JSON::Array _debug_chosen_candidates; auto _debug_candidate_iter = reconstructed_indices.begin(); for (auto i = 0u; i < timestamp_list.size(); ++i) From b5228dcda01359ead1c84f1980a03110b566029e Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Thu, 22 Jan 2015 23:53:35 +0100 Subject: [PATCH 234/360] Detect possible uturns in the data. To make them work, we have to disable PhantomNode splitting for this coordinates. --- CMakeLists.txt | 2 +- plugins/map_matching.hpp | 39 +++++++++++++++++++++-------- routing_algorithms/map_matching.hpp | 11 +++++--- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b957d5dce..e3dac8ba9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,7 +69,7 @@ file(GLOB PrepareGlob contractor/*.cpp data_structures/hilbert_value.cpp util/co set(PrepareSources prepare.cpp ${PrepareGlob}) add_executable(osrm-prepare ${PrepareSources} $ $ $ $ $ $ $ $) -file(GLOB ServerGlob server/*.cpp) +file(GLOB ServerGlob server/*.cpp util/compute_angle.cpp) file(GLOB DescriptorGlob descriptors/*.cpp) file(GLOB DatastructureGlob data_structures/search_engine_data.cpp data_structures/route_parameters.cpp util/bearing.cpp) list(REMOVE_ITEM DatastructureGlob data_structures/Coordinate.cpp) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 641d198ca..3fad436be 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -27,6 +27,7 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "../util/integer_range.hpp" #include "../data_structures/search_engine.hpp" #include "../routing_algorithms/map_matching.hpp" +#include "../util/compute_angle.hpp" #include "../util/simple_logger.hpp" #include "../util/string_util.hpp" #include "../descriptors/descriptor_base.hpp" @@ -68,22 +69,39 @@ template class MapMatchingPlugin : public BasePlugin return 400; } - InternalRouteResult raw_route; + const auto& input_coords = route_parameters.coordinates; Matching::CandidateLists candidate_lists; + std::vector uturn_indicators(false, input_coords.size()); double last_distance = coordinate_calculation::great_circle_distance( - route_parameters.coordinates[0], - route_parameters.coordinates[1]); - for (const auto current_coordinate : osrm::irange(0, route_parameters.coordinates.size())) + input_coords[0], + input_coords[1]); + for (const auto current_coordinate : osrm::irange(0, input_coords.size())) { if (0 < current_coordinate) + { last_distance = coordinate_calculation::great_circle_distance( - route_parameters.coordinates[current_coordinate - 1], - route_parameters.coordinates[current_coordinate]); + input_coords[current_coordinate - 1], + input_coords[current_coordinate]); + } + + if (input_coords.size()-1 > current_coordinate && 0 < current_coordinate) + { + double turn_angle = ComputeAngle::OfThreeFixedPointCoordinates( + input_coords[current_coordinate-1], + input_coords[current_coordinate], + input_coords[current_coordinate+1]); + + // sharp turns indicate a possible uturn + if (turn_angle < 100.0 || turn_angle > 260.0) + { + uturn_indicators[current_coordinate] = true; + } + } std::vector> candidates; if (!facade->IncrementalFindPhantomNodeForCoordinateWithMaxDistance( - route_parameters.coordinates[current_coordinate], + input_coords[current_coordinate], candidates, last_distance/2.0, 5, @@ -98,8 +116,10 @@ template class MapMatchingPlugin : public BasePlugin // call the actual map matching std::vector matched_nodes; JSON::Object debug_info; - search_engine_ptr->map_matching(candidate_lists, route_parameters.coordinates, matched_nodes, debug_info); + search_engine_ptr->map_matching(candidate_lists, input_coords, uturn_indicators, matched_nodes, debug_info); + + InternalRouteResult raw_route; PhantomNodes current_phantom_node_pair; for (unsigned i = 0; i < matched_nodes.size() - 1; ++i) { @@ -110,8 +130,7 @@ template class MapMatchingPlugin : public BasePlugin if (2 > matched_nodes.size()) { - reply = http::Reply::StockReply(http::Reply::badRequest); - return; + return 400; } search_engine_ptr->shortest_path( diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 8432c548c..8ebd8778b 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -276,7 +276,8 @@ template class MapMatching final // TODO optimize: a lot of copying that could probably be avoided void expandCandidates(const Matching::CandidateLists &candidates_lists, - Matching::CandidateLists &expanded_lists) const + Matching::CandidateLists &expanded_lists, + const std::vector& uturn_indicators) const { // expand list of PhantomNodes to be single-directional expanded_lists.resize(candidates_lists.size()); @@ -284,8 +285,8 @@ template class MapMatching final { for (const auto& candidate : candidates_lists[i]) { - // bi-directional edge, split phantom node - if (candidate.first.forward_node_id != SPECIAL_NODEID && candidate.first.reverse_node_id != SPECIAL_NODEID) + // bi-directional edge, split phantom node if we don't expect a uturn + if (!uturn_indicators[i] && candidate.first.forward_node_id != SPECIAL_NODEID && candidate.first.reverse_node_id != SPECIAL_NODEID) { PhantomNode forward_node(candidate.first); PhantomNode reverse_node(candidate.first); @@ -304,13 +305,15 @@ template class MapMatching final void operator()(const Matching::CandidateLists &candidates_lists, const std::vector coordinate_list, + const std::vector& uturn_indicators, std::vector& matched_nodes, JSON::Object& _debug_info) const { BOOST_ASSERT(candidates_lists.size() == coordinate_list.size()); + BOOST_ASSERT(candidates_lists.size() == uturn_indicators.size()); Matching::CandidateLists timestamp_list; - expandCandidates(candidates_lists, timestamp_list); + expandCandidates(candidates_lists, timestamp_list, uturn_indicators); std::vector breakage(timestamp_list.size(), true); From f092fc3fc668fe0b1a58bfee5f60675db8d9d716 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Thu, 29 Jan 2015 23:02:48 +0100 Subject: [PATCH 235/360] Fix minimum number of candidates --- data_structures/static_rtree.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_structures/static_rtree.hpp b/data_structures/static_rtree.hpp index e2a93c8e3..f9cfbfca0 100644 --- a/data_structures/static_rtree.hpp +++ b/data_structures/static_rtree.hpp @@ -905,8 +905,8 @@ class StaticRTree projected_coordinate, foot_point_coordinate_on_segment, current_ratio); if (number_of_elements_from_big_cc > 0 - && (number_of_elements_from_tiny_cc + number_of_elements_from_tiny_cc >= max_number_of_phantom_nodes - || current_perpendicular_distance >= max_distance)) + && result_phantom_node_vector.size() >= min_number_of_phantom_nodes + && current_perpendicular_distance >= max_distance) { traversal_queue = std::priority_queue{}; continue; From fe07f9208cdf39e43ce3779ede9d64d2ca1ee4d3 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 6 Feb 2015 02:15:51 +0100 Subject: [PATCH 236/360] Add bayes classifier --- algorithms/bayes_classifier.hpp | 113 ++++++++++++++++++++++++++++++++ plugins/map_matching.hpp | 12 +++- 2 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 algorithms/bayes_classifier.hpp diff --git a/algorithms/bayes_classifier.hpp b/algorithms/bayes_classifier.hpp new file mode 100644 index 000000000..1fc53937a --- /dev/null +++ b/algorithms/bayes_classifier.hpp @@ -0,0 +1,113 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef BAYES_CLASSIFIER_HPP +#define BAYES_CLASSIFIER_HPP + +#include +#include + +struct NormalDistribution +{ + NormalDistribution(const double mean, const double standard_deviation) + : mean(mean) + , standard_deviation(standard_deviation) + { + } + + // FIXME implement log-probability version since its faster + double probabilityDensityFunction(const double val) + { + const double x = val - mean; + return 1.0 / (std::sqrt(2*M_PI) * standard_deviation) * std::exp(-x*x / (standard_deviation * standard_deviation)); + } + + double mean; + double standard_deviation; +}; + + +struct LaplaceDistribution +{ + LaplaceDistribution(const double location, const double scale) + : location(location) + , scale(scale) + { + } + + // FIXME implement log-probability version since its faster + double probabilityDensityFunction(const double val) + { + const double x = std::abs(val - location); + return 1.0 / (2*scale) * std::exp(-x / scale); + } + + double location; + double scale; +}; + +template +class BayesClassifier +{ +public: + enum class ClassLabel : unsigned {NEGATIVE = 0, POSITIVE}; + + BayesClassifier(const PositiveDistributionT& positive_distribution, + const NegativeDistributionT& negative_distribution, + const double positive_apriori_probability) + : positive_distribution(positive_distribution) + , negative_distribution(negative_distribution) + , positive_apriori_probability(positive_apriori_probability) + , negative_apriori_probability(1 - positive_apriori_probability) + { + } + + /* + * Returns label and the probability of the label. + */ + std::pair classify(const ValueT& v) + { + const double positive_postpriori = positive_apriori_probability * positive_distribution.probabilityDensityFunction(v); + const double negative_postpriori = negative_apriori_probability * negative_distribution.probabilityDensityFunction(v); + const double norm = positive_postpriori + negative_postpriori; + + if (positive_postpriori > negative_postpriori) + { + return std::make_pair(ClassLabel::POSITIVE, positive_postpriori / norm); + } + + return std::make_pair(ClassLabel::NEGATIVE, negative_postpriori / norm); + } + +private: + PositiveDistributionT positive_distribution; + NegativeDistributionT negative_distribution; + double positive_apriori_probability; + double negative_apriori_probability; +}; + +#endif /* BAYES_CLASSIFIER_HPP */ diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 3fad436be..1838ab0b3 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -23,6 +23,7 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "plugin_base.hpp" +#include "../algorithms/bayes_classifier.hpp" #include "../algorithms/object_encoder.hpp" #include "../util/integer_range.hpp" #include "../data_structures/search_engine.hpp" @@ -48,7 +49,14 @@ template class MapMatchingPlugin : public BasePlugin std::shared_ptr> search_engine_ptr; public: - MapMatchingPlugin(DataFacadeT *facade) : descriptor_string("match"), facade(facade) + MapMatchingPlugin(DataFacadeT *facade) + : descriptor_string("match") + , facade(facade) + // the values where derived from fitting a laplace distribution + // to the values of manually classified traces + , classifier(LaplaceDistribution(0.0057154021891018675, 0.020294704891166186), + LaplaceDistribution(0.11467696742821254, 0.49918444000368756), + 0.7977883096366508) // valid apriori probability { descriptor_table.emplace("json", 0); descriptor_table.emplace("gpx", 1); @@ -118,7 +126,6 @@ template class MapMatchingPlugin : public BasePlugin JSON::Object debug_info; search_engine_ptr->map_matching(candidate_lists, input_coords, uturn_indicators, matched_nodes, debug_info); - InternalRouteResult raw_route; PhantomNodes current_phantom_node_pair; for (unsigned i = 0; i < matched_nodes.size() - 1; ++i) @@ -176,6 +183,7 @@ template class MapMatchingPlugin : public BasePlugin private: std::string descriptor_string; DataFacadeT *facade; + BayesClassifier classifier; }; #endif /* MAP_MATCHING_PLUGIN_H */ From 1b16dd126bcbbde1b949712ba65164df529f3c50 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sat, 7 Feb 2015 15:39:07 +0100 Subject: [PATCH 237/360] Actually compute and transmit confidence in the response --- algorithms/bayes_classifier.hpp | 5 +++-- plugins/map_matching.hpp | 40 ++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/algorithms/bayes_classifier.hpp b/algorithms/bayes_classifier.hpp index 1fc53937a..042259111 100644 --- a/algorithms/bayes_classifier.hpp +++ b/algorithms/bayes_classifier.hpp @@ -60,7 +60,7 @@ struct LaplaceDistribution } // FIXME implement log-probability version since its faster - double probabilityDensityFunction(const double val) + double probabilityDensityFunction(const double val) const { const double x = std::abs(val - location); return 1.0 / (2*scale) * std::exp(-x / scale); @@ -75,6 +75,7 @@ class BayesClassifier { public: enum class ClassLabel : unsigned {NEGATIVE = 0, POSITIVE}; + using ClassificationT = std::pair; BayesClassifier(const PositiveDistributionT& positive_distribution, const NegativeDistributionT& negative_distribution, @@ -89,7 +90,7 @@ public: /* * Returns label and the probability of the label. */ - std::pair classify(const ValueT& v) + ClassificationT classify(const ValueT& v) const { const double positive_postpriori = positive_apriori_probability * positive_distribution.probabilityDensityFunction(v); const double negative_postpriori = negative_apriori_probability * negative_distribution.probabilityDensityFunction(v); diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 1838ab0b3..8c3c64a12 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -48,6 +48,9 @@ template class MapMatchingPlugin : public BasePlugin std::unordered_map descriptor_table; std::shared_ptr> search_engine_ptr; + using ClassifierT = BayesClassifier; + using TraceClassification = ClassifierT::ClassificationT; + public: MapMatchingPlugin(DataFacadeT *facade) : descriptor_string("match") @@ -69,6 +72,29 @@ template class MapMatchingPlugin : public BasePlugin const std::string GetDescriptor() const final { return descriptor_string; } + TraceClassification classify(double trace_length, const std::vector& matched_nodes, int removed_points) const + { + double matching_length = 0; + for (const auto current_node : osrm::irange(0, matched_nodes.size()-1)) + { + matching_length += coordinate_calculation::great_circle_distance( + matched_nodes[current_node].location, + matched_nodes[current_node + 1].location); + } + double distance_feature = -std::log(trace_length / matching_length); + + auto label_with_confidence = classifier.classify(distance_feature); + + // "second stage classifier": if we need to remove points there is something fishy + if (removed_points > 0) + { + label_with_confidence.first = ClassifierT::ClassLabel::NEGATIVE; + label_with_confidence.second = 1.0; + } + + return label_with_confidence; + } + int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final { // check number of parameters @@ -84,6 +110,7 @@ template class MapMatchingPlugin : public BasePlugin double last_distance = coordinate_calculation::great_circle_distance( input_coords[0], input_coords[1]); + double trace_length = 0; for (const auto current_coordinate : osrm::irange(0, input_coords.size())) { if (0 < current_coordinate) @@ -91,6 +118,7 @@ template class MapMatchingPlugin : public BasePlugin last_distance = coordinate_calculation::great_circle_distance( input_coords[current_coordinate - 1], input_coords[current_coordinate]); + trace_length += last_distance; } if (input_coords.size()-1 > current_coordinate && 0 < current_coordinate) @@ -126,6 +154,16 @@ template class MapMatchingPlugin : public BasePlugin JSON::Object debug_info; search_engine_ptr->map_matching(candidate_lists, input_coords, uturn_indicators, matched_nodes, debug_info); + TraceClassification classification = classify(trace_length, matched_nodes, input_coords.size() - matched_nodes.size()); + if (classification.first == ClassifierT::ClassLabel::POSITIVE) + { + json_result.values["confidence"] = classification.second; + } + else + { + json_result.values["confidence"] = 1-classification.second; + } + InternalRouteResult raw_route; PhantomNodes current_phantom_node_pair; for (unsigned i = 0; i < matched_nodes.size() - 1; ++i) @@ -183,7 +221,7 @@ template class MapMatchingPlugin : public BasePlugin private: std::string descriptor_string; DataFacadeT *facade; - BayesClassifier classifier; + ClassifierT classifier; }; #endif /* MAP_MATCHING_PLUGIN_H */ From 0fce20c5033f976e026f2bd90d1a649affc961f3 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sat, 7 Feb 2015 17:26:38 +0100 Subject: [PATCH 238/360] Directly compute log probabilities --- routing_algorithms/map_matching.hpp | 75 +++++++++-------------------- 1 file changed, 22 insertions(+), 53 deletions(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 8ebd8778b..7ffe80fd7 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -25,7 +25,6 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "../data_structures/coordinate_calculation.hpp" #include "../util/simple_logger.hpp" -#include "../util/container.hpp" #include #include @@ -78,20 +77,36 @@ template class MapMatching final using QueryHeap = SearchEngineData::QueryHeap; SearchEngineData &engine_working_data; + // FIXME this value should be a table based on samples/meter (or samples/min) + constexpr static const double beta = 10.0; constexpr static const double sigma_z = 4.07; + constexpr static const double log_sigma_z = std::log(sigma_z); + constexpr static const double log_2_pi = std::log(2 * M_PI); + // TODO: move to a probability util header and implement as normal distribution constexpr double emission_probability(const double distance) const { return (1. / (std::sqrt(2. * M_PI) * sigma_z)) * std::exp(-0.5 * std::pow((distance / sigma_z), 2.)); } - constexpr double log_probability(const double probability) const + constexpr double transition_probability(const float d_t, const float beta) const { - return std::log2(probability); + return (1. / beta) * std::exp(-d_t / beta); + } + + inline double log_emission_probability(const double distance) const { + const double normed_distance = distance / sigma_z; + return -0.5 * (log_2_pi + normed_distance * normed_distance) - log_sigma_z; + } + + inline double log_transition_probability(const float d_t, const float beta) const + { + return -std::log(beta) - d_t / beta; } // TODO: needs to be estimated from the input locations + // FIXME These values seem wrong. Higher beta for more samples/minute? Should be inverse proportional. //constexpr static const double beta = 1.; // samples/min and beta // 1 0.49037673 @@ -126,48 +141,6 @@ template class MapMatching final // 29 32.21683062 // 30 34.56991141 - constexpr double transition_probability(const float d_t, const float beta) const - { - return (1. / beta) * std::exp(-d_t / beta); - } - - // deprecated - // translates a distance into how likely it is an input - // double DistanceToProbability(const double distance) const - // { - // if (0. > distance) - // { - // return 0.; - // } - // return 1. - 1. / (1. + exp((-distance + 35.) / 6.)); - // } - - double get_beta(const unsigned state_size, - const Matching::CandidateLists ×tamp_list, - const std::vector coordinate_list) const - { - std::vector d_t_list, median_select_d_t_list; - for (auto t = 1u; t < timestamp_list.size(); ++t) - { - for (auto s = 0u; s < state_size; ++s) - { - d_t_list.push_back(get_distance_difference(coordinate_list[t - 1], - coordinate_list[t], - timestamp_list[t - 1][s].first, - timestamp_list[t][s].first)); - median_select_d_t_list.push_back(d_t_list.back()); - } - } - - std::nth_element(median_select_d_t_list.begin(), - median_select_d_t_list.begin() + median_select_d_t_list.size() / 2, - median_select_d_t_list.end()); - const auto median_d_t = median_select_d_t_list[median_select_d_t_list.size() / 2]; - - return (1. / std::log(2)) * median_d_t; - } - - double get_distance_difference(const FixedPointCoordinate &location1, const FixedPointCoordinate &location2, const PhantomNode &source_phantom, @@ -186,7 +159,7 @@ template class MapMatching final } double get_network_distance(const PhantomNode &source_phantom, - const PhantomNode &target_phantom) const + const PhantomNode &target_phantom) const { EdgeWeight upper_bound = INVALID_EDGE_WEIGHT; NodeID middle_node = SPECIAL_NODEID; @@ -344,7 +317,7 @@ template class MapMatching final { // this might need to be squared as pi_s is also defined as the emission // probability in the paper. - viterbi[initial_timestamp][s] = log_probability(emission_probability(timestamp_list[initial_timestamp][s].second)); + viterbi[initial_timestamp][s] = log_emission_probability(timestamp_list[initial_timestamp][s].second); parents[initial_timestamp][s] = s; pruned[initial_timestamp][s] = viterbi[initial_timestamp][s] < -std::numeric_limits::max(); @@ -377,10 +350,6 @@ template class MapMatching final BOOST_ASSERT(breakage[initial_timestamp] == false); - // attention, this call is relatively expensive - //const auto beta = get_beta(state_size, timestamp_list, coordinate_list); - const auto beta = 10.0; - unsigned prev_unbroken_timestamp = initial_timestamp; for (auto t = initial_timestamp + 1; t < timestamp_list.size(); ++t) { @@ -410,7 +379,7 @@ template class MapMatching final { // how likely is candidate s_prime at time t to be emitted? - const double emission_pr = log_probability(emission_probability(timestamp_list[t][s_prime].second)); + const double emission_pr = log_emission_probability(timestamp_list[t][s_prime].second); // get distance diff between loc1/2 and locs/s_prime const auto d_t = get_distance_difference(prev_coordinate, @@ -419,7 +388,7 @@ template class MapMatching final current_timestamps_list[s_prime].first); // plug probabilities together - const double transition_pr = log_probability(transition_probability(d_t, beta)); + const double transition_pr = log_transition_probability(d_t, beta); const double new_value = prev_viterbi[s] + emission_pr + transition_pr; JSON::Array _debug_element = makeJSONArray( From dc1405ffa822c72a958512a928902a7ce14583d9 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sat, 7 Feb 2015 17:29:09 +0100 Subject: [PATCH 239/360] Fix typo in debugging code --- routing_algorithms/map_matching.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 7ffe80fd7..e52fd225a 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -33,7 +33,7 @@ or see http://www.gnu.org/licenses/agpl.txt. #include template -T makeJSONSave(T d) +T makeJSONSafe(T d) { if (std::isnan(d) || std::numeric_limits::infinity() == d) { return std::numeric_limits::max(); @@ -326,7 +326,7 @@ template class MapMatching final for (auto s = 0u; s < viterbi[initial_timestamp].size(); ++s) { - _debug_initial_viterbi.values.push_back(makeJSONSave(viterbi[initial_timestamp][s])); + _debug_initial_viterbi.values.push_back(makeJSONSafe(viterbi[initial_timestamp][s])); _debug_initial_pruned.values.push_back(static_cast(pruned[initial_timestamp][s])); } @@ -392,9 +392,9 @@ template class MapMatching final const double new_value = prev_viterbi[s] + emission_pr + transition_pr; JSON::Array _debug_element = makeJSONArray( - makeJSONSave(prev_viterbi[s]), - makeJSONSave(emission_pr), - makeJSONSave(transition_pr), + makeJSONSafe(prev_viterbi[s]), + makeJSONSafe(emission_pr), + makeJSONSafe(transition_pr), get_network_distance(prev_unbroken_timestamps_list[s].first, current_timestamps_list[s_prime].first), coordinate_calculation::great_circle_distance(prev_coordinate, current_coordinate) ); @@ -417,7 +417,7 @@ template class MapMatching final JSON::Array _debug_pruned_col; for (auto s_prime = 0u; s_prime < current_viterbi.size(); ++s_prime) { - _debug_viterbi_col.values.push_back(makeJSONSave(current_viterbi[s_prime])); + _debug_viterbi_col.values.push_back(makeJSONSafe(current_viterbi[s_prime])); _debug_pruned_col.values.push_back(static_cast(current_pruned[s_prime])); } _debug_viterbi.values.push_back(_debug_viterbi_col); From 0637215b85a16ef431f7d90ad11ace0c5150b702 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Mon, 9 Feb 2015 00:19:42 +0100 Subject: [PATCH 240/360] Skip computing viterbi if viterbi of previous state is lower than lower bound This causes a speedup of 300%. --- routing_algorithms/map_matching.hpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index e52fd225a..a512e307a 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -377,9 +377,15 @@ template class MapMatching final for (auto s_prime = 0u; s_prime < current_viterbi.size(); ++s_prime) { + double new_value = prev_viterbi[s]; + if (current_viterbi[s_prime] > new_value) + continue; // how likely is candidate s_prime at time t to be emitted? const double emission_pr = log_emission_probability(timestamp_list[t][s_prime].second); + new_value += emission_pr; + if (current_viterbi[s_prime] > new_value) + continue; // get distance diff between loc1/2 and locs/s_prime const auto d_t = get_distance_difference(prev_coordinate, @@ -387,9 +393,8 @@ template class MapMatching final prev_unbroken_timestamps_list[s].first, current_timestamps_list[s_prime].first); - // plug probabilities together const double transition_pr = log_transition_probability(d_t, beta); - const double new_value = prev_viterbi[s] + emission_pr + transition_pr; + new_value += transition_pr; JSON::Array _debug_element = makeJSONArray( makeJSONSafe(prev_viterbi[s]), From 66d7a073d34e7a4d837203a03ba73ff95b891835 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Mon, 9 Feb 2015 00:55:12 +0100 Subject: [PATCH 241/360] Move splitting candidates to plugin --- plugins/map_matching.hpp | 69 ++++++++++++++++++++++------- routing_algorithms/map_matching.hpp | 42 +----------------- 2 files changed, 53 insertions(+), 58 deletions(-) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 8c3c64a12..ae81e5b48 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -95,24 +95,15 @@ template class MapMatchingPlugin : public BasePlugin return label_with_confidence; } - int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final + bool get_candiates(const std::vector& input_coords, double& trace_length, Matching::CandidateLists& candidates_lists) { - // check number of parameters - if (!check_all_coordinates(route_parameters.coordinates)) - { - return 400; - } - - const auto& input_coords = route_parameters.coordinates; - Matching::CandidateLists candidate_lists; - std::vector uturn_indicators(false, input_coords.size()); - double last_distance = coordinate_calculation::great_circle_distance( input_coords[0], input_coords[1]); - double trace_length = 0; + trace_length = 0; for (const auto current_coordinate : osrm::irange(0, input_coords.size())) { + bool allow_uturn = false; if (0 < current_coordinate) { last_distance = coordinate_calculation::great_circle_distance( @@ -131,7 +122,7 @@ template class MapMatchingPlugin : public BasePlugin // sharp turns indicate a possible uturn if (turn_angle < 100.0 || turn_angle > 260.0) { - uturn_indicators[current_coordinate] = true; + allow_uturn = true; } } @@ -143,17 +134,60 @@ template class MapMatchingPlugin : public BasePlugin 5, 20)) { - return 400; + return false; } - candidate_lists.push_back(candidates); + if (allow_uturn) + { + candidates_lists.push_back(candidates); + } + else + { + unsigned compact_size = candidates.size(); + for (const auto i : osrm::irange(0u, compact_size)) + { + // Split edge if it is bidirectional and append reverse direction to end of list + if (candidates[i].first.forward_node_id != SPECIAL_NODEID + && candidates[i].first.reverse_node_id != SPECIAL_NODEID) + { + PhantomNode reverse_node(candidates[i].first); + reverse_node.forward_node_id = SPECIAL_NODEID; + candidates.push_back(std::make_pair(reverse_node, candidates[i].second)); + + candidates[i].first.reverse_node_id = SPECIAL_NODEID; + } + } + candidates_lists.push_back(candidates); + } + + } + + return true; + } + + int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final + { + // check number of parameters + if (!check_all_coordinates(route_parameters.coordinates)) + { + return 400; + } + + double trace_length; + Matching::CandidateLists candidates_lists; + const auto& input_coords = route_parameters.coordinates; + bool found_candidates = get_candiates(input_coords, trace_length, candidates_lists); + if (!found_candidates) + { + return 400; } // call the actual map matching - std::vector matched_nodes; JSON::Object debug_info; - search_engine_ptr->map_matching(candidate_lists, input_coords, uturn_indicators, matched_nodes, debug_info); + std::vector matched_nodes; + search_engine_ptr->map_matching(candidates_lists, input_coords, matched_nodes, debug_info); + // classify result TraceClassification classification = classify(trace_length, matched_nodes, input_coords.size() - matched_nodes.size()); if (classification.first == ClassifierT::ClassLabel::POSITIVE) { @@ -164,6 +198,7 @@ template class MapMatchingPlugin : public BasePlugin json_result.values["confidence"] = 1-classification.second; } + // run shortest path routing to obtain geometry InternalRouteResult raw_route; PhantomNodes current_phantom_node_pair; for (unsigned i = 0; i < matched_nodes.size() - 1; ++i) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index a512e307a..049017e80 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -247,47 +247,11 @@ template class MapMatching final { } - // TODO optimize: a lot of copying that could probably be avoided - void expandCandidates(const Matching::CandidateLists &candidates_lists, - Matching::CandidateLists &expanded_lists, - const std::vector& uturn_indicators) const - { - // expand list of PhantomNodes to be single-directional - expanded_lists.resize(candidates_lists.size()); - for (const auto i : osrm::irange(0lu, candidates_lists.size())) - { - for (const auto& candidate : candidates_lists[i]) - { - // bi-directional edge, split phantom node if we don't expect a uturn - if (!uturn_indicators[i] && candidate.first.forward_node_id != SPECIAL_NODEID && candidate.first.reverse_node_id != SPECIAL_NODEID) - { - PhantomNode forward_node(candidate.first); - PhantomNode reverse_node(candidate.first); - forward_node.reverse_node_id = SPECIAL_NODEID; - reverse_node.forward_node_id = SPECIAL_NODEID; - expanded_lists[i].emplace_back(forward_node, candidate.second); - expanded_lists[i].emplace_back(reverse_node, candidate.second); - } - else - { - expanded_lists[i].push_back(candidate); - } - } - } - } - - void operator()(const Matching::CandidateLists &candidates_lists, + void operator()(const Matching::CandidateLists ×tamp_list, const std::vector coordinate_list, - const std::vector& uturn_indicators, std::vector& matched_nodes, JSON::Object& _debug_info) const { - BOOST_ASSERT(candidates_lists.size() == coordinate_list.size()); - BOOST_ASSERT(candidates_lists.size() == uturn_indicators.size()); - - Matching::CandidateLists timestamp_list; - expandCandidates(candidates_lists, timestamp_list, uturn_indicators); - std::vector breakage(timestamp_list.size(), true); BOOST_ASSERT(timestamp_list.size() > 0); @@ -462,10 +426,6 @@ template class MapMatching final matched_nodes[i] = timestamp_list[timestamp_index][location_index].first; } - unsigned removed = candidates_lists.size() - matched_nodes.size(); - if (removed > 10) - SimpleLogger().Write(logWARNING) << "Warning: removed " << removed << " candiates."; - JSON::Array _debug_chosen_candidates; auto _debug_candidate_iter = reconstructed_indices.begin(); for (auto i = 0u; i < timestamp_list.size(); ++i) From e381566494d91395d32e9333a68c07f92d2b8d08 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Mon, 9 Feb 2015 10:14:26 +0100 Subject: [PATCH 242/360] Eliminate branch --- routing_algorithms/map_matching.hpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 049017e80..ffade6fd8 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -341,13 +341,9 @@ template class MapMatching final for (auto s_prime = 0u; s_prime < current_viterbi.size(); ++s_prime) { - double new_value = prev_viterbi[s]; - if (current_viterbi[s_prime] > new_value) - continue; - // how likely is candidate s_prime at time t to be emitted? const double emission_pr = log_emission_probability(timestamp_list[t][s_prime].second); - new_value += emission_pr; + double new_value = prev_viterbi[s] + emission_pr; if (current_viterbi[s_prime] > new_value) continue; From 1bcf41d382aa5cd4a8a275e06c7bd9479c41e714 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Mon, 9 Feb 2015 11:06:58 +0100 Subject: [PATCH 243/360] Prune low probability transitions --- routing_algorithms/map_matching.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index ffade6fd8..55376d224 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -352,6 +352,9 @@ template class MapMatching final current_coordinate, prev_unbroken_timestamps_list[s].first, current_timestamps_list[s_prime].first); + // very low probability transition -> prune + if (d_t > 2000) + continue; const double transition_pr = log_transition_probability(d_t, beta); new_value += transition_pr; From 4838ffb82dd42abda98263792af59b3b89c4663a Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Mon, 9 Feb 2015 12:41:30 +0100 Subject: [PATCH 244/360] Fix nan values if matched to single point --- plugins/map_matching.hpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index ae81e5b48..f4dec3676 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -81,15 +81,20 @@ template class MapMatchingPlugin : public BasePlugin matched_nodes[current_node].location, matched_nodes[current_node + 1].location); } - double distance_feature = -std::log(trace_length / matching_length); + double distance_feature = -std::log(trace_length) + std::log(matching_length); + + // matched to the same point + if (!std::isfinite(distance_feature)) + { + return std::make_pair(ClassifierT::ClassLabel::NEGATIVE, 1.0); + } auto label_with_confidence = classifier.classify(distance_feature); // "second stage classifier": if we need to remove points there is something fishy if (removed_points > 0) { - label_with_confidence.first = ClassifierT::ClassLabel::NEGATIVE; - label_with_confidence.second = 1.0; + return std::make_pair(ClassifierT::ClassLabel::NEGATIVE, 1.0); } return label_with_confidence; From 6e54f8cfa6c51ad37a5f937c00c9c4c0ff7f2d46 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Tue, 10 Feb 2015 10:54:47 +0100 Subject: [PATCH 245/360] Tighter threshold on low probability transistions --- routing_algorithms/map_matching.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 55376d224..8d22ae81e 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -345,7 +345,10 @@ template class MapMatching final const double emission_pr = log_emission_probability(timestamp_list[t][s_prime].second); double new_value = prev_viterbi[s] + emission_pr; if (current_viterbi[s_prime] > new_value) + { + _debug_row.values.push_back(JSON::Array()); continue; + } // get distance diff between loc1/2 and locs/s_prime const auto d_t = get_distance_difference(prev_coordinate, @@ -353,8 +356,11 @@ template class MapMatching final prev_unbroken_timestamps_list[s].first, current_timestamps_list[s_prime].first); // very low probability transition -> prune - if (d_t > 2000) + if (d_t > 500) + { + _debug_row.values.push_back(JSON::Array()); continue; + } const double transition_pr = log_transition_probability(d_t, beta); new_value += transition_pr; From 1a8c83203937d2d91c47c46d7267f57ac89452bd Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Tue, 10 Feb 2015 13:00:00 +0100 Subject: [PATCH 246/360] Update format of debug json ouput --- routing_algorithms/map_matching.hpp | 116 ++++++++++------------------ 1 file changed, 40 insertions(+), 76 deletions(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 8d22ae81e..9ea4fd763 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -32,6 +32,9 @@ or see http://www.gnu.org/licenses/agpl.txt. #include +using JSONVariantArray = mapbox::util::recursive_wrapper; +using JSONVariantObject = mapbox::util::recursive_wrapper; + template T makeJSONSafe(T d) { @@ -265,18 +268,25 @@ template class MapMatching final viterbi.emplace_back(l.size(), -std::numeric_limits::infinity()); parents.emplace_back(l.size(), 0); pruned.emplace_back(l.size(), true); + } - JSON::Array _debug_timestamps; - JSON::Array _debug_viterbi; - JSON::Array _debug_pruned; + JSON::Array _debug_states; + for (const auto& l : timestamp_list) + { + JSON::Array _debug_timestamps; + for (unsigned i = 0; i < l.size(); i++) + { + JSON::Object _debug_state; + _debug_state.values["transitions"] = JSON::Array(); + _debug_timestamps.values.push_back(_debug_state); + } + _debug_states.values.push_back(_debug_timestamps); + } unsigned initial_timestamp = 0; do { - JSON::Array _debug_initial_viterbi; - JSON::Array _debug_initial_pruned; - for (auto s = 0u; s < viterbi[initial_timestamp].size(); ++s) { // this might need to be squared as pi_s is also defined as the emission @@ -286,24 +296,13 @@ template class MapMatching final pruned[initial_timestamp][s] = viterbi[initial_timestamp][s] < -std::numeric_limits::max(); breakage[initial_timestamp] = breakage[initial_timestamp] && pruned[initial_timestamp][s]; - } - for (auto s = 0u; s < viterbi[initial_timestamp].size(); ++s) - { - _debug_initial_viterbi.values.push_back(makeJSONSafe(viterbi[initial_timestamp][s])); - _debug_initial_pruned.values.push_back(static_cast(pruned[initial_timestamp][s])); - } - - _debug_viterbi.values.push_back(_debug_initial_viterbi); - _debug_pruned.values.push_back(_debug_initial_pruned); - - - if (initial_timestamp > 0) { - JSON::Array _debug_transition_rows; - for (auto s = 0u; s < viterbi[initial_timestamp-1].size(); ++s) { - _debug_transition_rows.values.push_back(JSON::Array()); - } - _debug_timestamps.values.push_back(_debug_transition_rows); + _debug_states.values[initial_timestamp] + .get().get().values[s] + .get().get().values["viterbi"] = makeJSONSafe(viterbi[initial_timestamp][s]); + _debug_states.values[initial_timestamp] + .get().get().values[s] + .get().get().values["pruned"] = static_cast(pruned[initial_timestamp][s]); } ++initial_timestamp; @@ -328,16 +327,11 @@ template class MapMatching final const auto& current_timestamps_list = timestamp_list[t]; const auto& current_coordinate = coordinate_list[t]; - JSON::Array _debug_transition_rows; // compute d_t for this timestamp and the next one for (auto s = 0u; s < prev_viterbi.size(); ++s) { - JSON::Array _debug_row; if (prev_pruned[s]) - { - _debug_transition_rows.values.push_back(_debug_row); continue; - } for (auto s_prime = 0u; s_prime < current_viterbi.size(); ++s_prime) { @@ -345,10 +339,7 @@ template class MapMatching final const double emission_pr = log_emission_probability(timestamp_list[t][s_prime].second); double new_value = prev_viterbi[s] + emission_pr; if (current_viterbi[s_prime] > new_value) - { - _debug_row.values.push_back(JSON::Array()); continue; - } // get distance diff between loc1/2 and locs/s_prime const auto d_t = get_distance_difference(prev_coordinate, @@ -357,23 +348,25 @@ template class MapMatching final current_timestamps_list[s_prime].first); // very low probability transition -> prune if (d_t > 500) - { - _debug_row.values.push_back(JSON::Array()); continue; - } const double transition_pr = log_transition_probability(d_t, beta); new_value += transition_pr; - JSON::Array _debug_element = makeJSONArray( + JSON::Object _debug_transistion; + _debug_transistion.values["to"] = makeJSONArray(t, s_prime); + _debug_transistion.values["properties"] = makeJSONArray( makeJSONSafe(prev_viterbi[s]), makeJSONSafe(emission_pr), makeJSONSafe(transition_pr), get_network_distance(prev_unbroken_timestamps_list[s].first, current_timestamps_list[s_prime].first), coordinate_calculation::great_circle_distance(prev_coordinate, current_coordinate) ); + _debug_states.values[prev_unbroken_timestamp] + .get().get().values[s] + .get().get().values["transitions"] + .get().get().values.push_back(_debug_transistion); - _debug_row.values.push_back(_debug_element); if (new_value > current_viterbi[s_prime]) { @@ -383,19 +376,17 @@ template class MapMatching final breakage[t] = false; } } - _debug_transition_rows.values.push_back(_debug_row); } - _debug_timestamps.values.push_back(_debug_transition_rows); - JSON::Array _debug_viterbi_col; - JSON::Array _debug_pruned_col; for (auto s_prime = 0u; s_prime < current_viterbi.size(); ++s_prime) { - _debug_viterbi_col.values.push_back(makeJSONSafe(current_viterbi[s_prime])); - _debug_pruned_col.values.push_back(static_cast(current_pruned[s_prime])); + _debug_states.values[t] + .get().get().values[s_prime] + .get().get().values["viterbi"] = makeJSONSafe(current_viterbi[s_prime]); + _debug_states.values[t] + .get().get().values[s_prime] + .get().get().values["pruned"] = static_cast(current_pruned[s_prime]); } - _debug_viterbi.values.push_back(_debug_viterbi_col); - _debug_pruned.values.push_back(_debug_pruned_col); if (!breakage[t]) { @@ -403,11 +394,6 @@ template class MapMatching final } } - _debug_info.values["transitions"] = _debug_timestamps; - _debug_info.values["viterbi"] = _debug_viterbi; - _debug_info.values["pruned"] = _debug_pruned; - _debug_info.values["beta"] = beta; - // loop through the columns, and only compare the last entry auto max_element_iter = std::max_element(viterbi[prev_unbroken_timestamp].begin(), viterbi[prev_unbroken_timestamp].end()); auto parent_index = std::distance(viterbi[prev_unbroken_timestamp].begin(), max_element_iter); @@ -429,41 +415,19 @@ template class MapMatching final auto location_index = reconstructed_indices[i].second; matched_nodes[i] = timestamp_list[timestamp_index][location_index].first; - } - JSON::Array _debug_chosen_candidates; - auto _debug_candidate_iter = reconstructed_indices.begin(); - for (auto i = 0u; i < timestamp_list.size(); ++i) - { - if (_debug_candidate_iter != reconstructed_indices.end() && _debug_candidate_iter->first == i) - { - _debug_chosen_candidates.values.push_back(_debug_candidate_iter->second); - _debug_candidate_iter = std::next(_debug_candidate_iter); - } - else - { - _debug_chosen_candidates.values.push_back(JSON::Null()); - } + _debug_states.values[timestamp_index] + .get().get().values[location_index] + .get().get().values["chosen"] = true; } - _debug_info.values["chosen_candidates"] = _debug_chosen_candidates; JSON::Array _debug_breakage; for (auto b : breakage) { _debug_breakage.values.push_back(static_cast(b)); } - _debug_info.values["breakage"] = _debug_breakage; - JSON::Array _debug_expanded_candidates; - for (const auto& l : timestamp_list) { - JSON::Array _debug_expanded_candidates_col; - for (const auto& pair : l) { - const auto& coord = pair.first.location; - _debug_expanded_candidates_col.values.push_back(makeJSONArray(coord.lat / COORDINATE_PRECISION, - coord.lon / COORDINATE_PRECISION)); - } - _debug_expanded_candidates.values.push_back(_debug_expanded_candidates_col); - } - _debug_info.values["expanded_candidates"] = _debug_expanded_candidates; + _debug_info.values["breakage"] = _debug_breakage; + _debug_info.values["states"] = _debug_states; } }; From 38d7db49c88f5dd447bdd3b0a6269e88eae9dc5b Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Tue, 10 Feb 2015 23:24:27 +0100 Subject: [PATCH 247/360] Add state position to debug output --- routing_algorithms/map_matching.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 9ea4fd763..0f2cc0c0c 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -279,6 +279,8 @@ template class MapMatching final { JSON::Object _debug_state; _debug_state.values["transitions"] = JSON::Array(); + _debug_state.values["coordinate"] = makeJSONArray(l[i].first.location.lat / COORDINATE_PRECISION, + l[i].first.location.lon / COORDINATE_PRECISION); _debug_timestamps.values.push_back(_debug_state); } _debug_states.values.push_back(_debug_timestamps); From b3fa03043d604ca443bbf7a10f3500da0ba8f11e Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Thu, 12 Feb 2015 11:44:52 +0100 Subject: [PATCH 248/360] Calculate the real route length for classification --- plugins/map_matching.hpp | 16 ++++-------- routing_algorithms/map_matching.hpp | 40 ++++++++++++----------------- 2 files changed, 22 insertions(+), 34 deletions(-) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index f4dec3676..0f9a94c80 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -72,16 +72,9 @@ template class MapMatchingPlugin : public BasePlugin const std::string GetDescriptor() const final { return descriptor_string; } - TraceClassification classify(double trace_length, const std::vector& matched_nodes, int removed_points) const + TraceClassification classify(float trace_length, float matched_length, int removed_points) const { - double matching_length = 0; - for (const auto current_node : osrm::irange(0, matched_nodes.size()-1)) - { - matching_length += coordinate_calculation::great_circle_distance( - matched_nodes[current_node].location, - matched_nodes[current_node + 1].location); - } - double distance_feature = -std::log(trace_length) + std::log(matching_length); + double distance_feature = -std::log(trace_length) + std::log(matched_length); // matched to the same point if (!std::isfinite(distance_feature)) @@ -189,11 +182,12 @@ template class MapMatchingPlugin : public BasePlugin // call the actual map matching JSON::Object debug_info; + float matched_length; std::vector matched_nodes; - search_engine_ptr->map_matching(candidates_lists, input_coords, matched_nodes, debug_info); + search_engine_ptr->map_matching(candidates_lists, input_coords, matched_nodes, matched_length, debug_info); // classify result - TraceClassification classification = classify(trace_length, matched_nodes, input_coords.size() - matched_nodes.size()); + TraceClassification classification = classify(trace_length, matched_length, input_coords.size() - matched_nodes.size()); if (classification.first == ClassifierT::ClassLabel::POSITIVE) { json_result.values["confidence"] = classification.second; diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 0f2cc0c0c..a87a739eb 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -144,23 +144,6 @@ template class MapMatching final // 29 32.21683062 // 30 34.56991141 - double get_distance_difference(const FixedPointCoordinate &location1, - const FixedPointCoordinate &location2, - const PhantomNode &source_phantom, - const PhantomNode &target_phantom) const - { - // great circle distance of two locations - median/avg dist table(candidate list1/2) - const auto network_distance = get_network_distance(source_phantom, target_phantom); - const auto great_circle_distance = - coordinate_calculation::great_circle_distance(location1, location2); - - if (great_circle_distance > network_distance) - { - return great_circle_distance - network_distance; - } - return network_distance - great_circle_distance; - } - double get_network_distance(const PhantomNode &source_phantom, const PhantomNode &target_phantom) const { @@ -253,6 +236,7 @@ template class MapMatching final void operator()(const Matching::CandidateLists ×tamp_list, const std::vector coordinate_list, std::vector& matched_nodes, + float& matched_length, JSON::Object& _debug_info) const { std::vector breakage(timestamp_list.size(), true); @@ -262,11 +246,13 @@ template class MapMatching final // TODO for the viterbi values we actually only need the current and last row std::vector> viterbi; std::vector> parents; + std::vector> segment_lengths; std::vector> pruned; for (const auto& l : timestamp_list) { viterbi.emplace_back(l.size(), -std::numeric_limits::infinity()); parents.emplace_back(l.size(), 0); + segment_lengths.emplace_back(l.size(), 0); pruned.emplace_back(l.size(), true); } @@ -326,6 +312,7 @@ template class MapMatching final auto& current_viterbi = viterbi[t]; auto& current_pruned = pruned[t]; auto& current_parents = parents[t]; + auto& current_lengths = segment_lengths[t]; const auto& current_timestamps_list = timestamp_list[t]; const auto& current_coordinate = coordinate_list[t]; @@ -344,10 +331,14 @@ template class MapMatching final continue; // get distance diff between loc1/2 and locs/s_prime - const auto d_t = get_distance_difference(prev_coordinate, - current_coordinate, - prev_unbroken_timestamps_list[s].first, - current_timestamps_list[s_prime].first); + const auto network_distance = get_network_distance(prev_unbroken_timestamps_list[s].first, + current_timestamps_list[s_prime].first); + const auto great_circle_distance = + coordinate_calculation::great_circle_distance(prev_coordinate, + current_coordinate); + + const auto d_t = std::abs(network_distance - great_circle_distance); + // very low probability transition -> prune if (d_t > 500) continue; @@ -361,8 +352,8 @@ template class MapMatching final makeJSONSafe(prev_viterbi[s]), makeJSONSafe(emission_pr), makeJSONSafe(transition_pr), - get_network_distance(prev_unbroken_timestamps_list[s].first, current_timestamps_list[s_prime].first), - coordinate_calculation::great_circle_distance(prev_coordinate, current_coordinate) + network_distance, + great_circle_distance ); _debug_states.values[prev_unbroken_timestamp] .get().get().values[s] @@ -374,6 +365,7 @@ template class MapMatching final { current_viterbi[s_prime] = new_value; current_parents[s_prime] = s; + current_lengths[s_prime] = network_distance; current_pruned[s_prime] = false; breakage[t] = false; } @@ -410,6 +402,7 @@ template class MapMatching final } reconstructed_indices.emplace_front(initial_timestamp, parent_index); + matched_length = 0.0f; matched_nodes.resize(reconstructed_indices.size()); for (auto i = 0u; i < reconstructed_indices.size(); ++i) { @@ -417,6 +410,7 @@ template class MapMatching final auto location_index = reconstructed_indices[i].second; matched_nodes[i] = timestamp_list[timestamp_index][location_index].first; + matched_length += segment_lengths[timestamp_index][location_index]; _debug_states.values[timestamp_index] .get().get().values[location_index] From 0c3102721c07e04f492a32e2e34e9c56738c3acf Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 13 Feb 2015 11:01:03 +0100 Subject: [PATCH 249/360] Make number of candidates a parameter --- plugins/map_matching.hpp | 2 +- routing_algorithms/map_matching.hpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 0f9a94c80..8a9988277 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -130,7 +130,7 @@ template class MapMatchingPlugin : public BasePlugin candidates, last_distance/2.0, 5, - 20)) + Matching::max_number_of_candidates)) { return false; } diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index a87a739eb..7bbac2afd 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -70,6 +70,7 @@ namespace Matching typedef std::vector> CandidateList; typedef std::vector CandidateLists; typedef std::pair PhantomNodesWithProbability; +constexpr static const unsigned max_number_of_candidates = 20; } // implements a hidden markov model map matching algorithm From d620da365e8419f56db87b240095bcbae478eeb9 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 13 Feb 2015 14:34:44 +0100 Subject: [PATCH 250/360] Implement more general pruning --- routing_algorithms/map_matching.hpp | 214 ++++++++++++++++++---------- 1 file changed, 142 insertions(+), 72 deletions(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 7bbac2afd..9cb19402b 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -26,6 +26,9 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "../data_structures/coordinate_calculation.hpp" #include "../util/simple_logger.hpp" +#include +#include + #include #include #include @@ -87,24 +90,23 @@ template class MapMatching final constexpr static const double log_sigma_z = std::log(sigma_z); constexpr static const double log_2_pi = std::log(2 * M_PI); - // TODO: move to a probability util header and implement as normal distribution - constexpr double emission_probability(const double distance) const + constexpr static double emission_probability(const double distance) { return (1. / (std::sqrt(2. * M_PI) * sigma_z)) * std::exp(-0.5 * std::pow((distance / sigma_z), 2.)); } - constexpr double transition_probability(const float d_t, const float beta) const + constexpr static double transition_probability(const float d_t, const float beta) { return (1. / beta) * std::exp(-d_t / beta); } - inline double log_emission_probability(const double distance) const { - const double normed_distance = distance / sigma_z; - return -0.5 * (log_2_pi + normed_distance * normed_distance) - log_sigma_z; + constexpr static double log_emission_probability(const double distance) + { + return -0.5 * (log_2_pi + (distance / sigma_z) * (distance / sigma_z)) - log_sigma_z; } - inline double log_transition_probability(const float d_t, const float beta) const + constexpr static double log_transition_probability(const float d_t, const float beta) { return -std::log(beta) - d_t / beta; } @@ -228,92 +230,139 @@ template class MapMatching final return distance; } + struct HiddenMarkovModel + { + std::vector> viterbi; + std::vector> parents; + std::vector> path_lengths; + std::vector> pruned; + std::vector breakage; + + const Matching::CandidateLists& timestamp_list; + + constexpr static double IMPOSSIBLE_LOG_PROB = -std::numeric_limits::infinity(); + constexpr static double MINIMAL_LOG_PROB = -std::numeric_limits::max(); + + HiddenMarkovModel(const Matching::CandidateLists& timestamp_list) + : breakage(timestamp_list.size()) + , timestamp_list(timestamp_list) + { + for (const auto& l : timestamp_list) + { + viterbi.emplace_back(l.size()); + parents.emplace_back(l.size()); + path_lengths.emplace_back(l.size()); + pruned.emplace_back(l.size()); + } + + clear(0); + } + + void clear(unsigned initial_timestamp) + { + BOOST_ASSERT(viterbi.size() == parents.size() + && parents.size() == path_lengths.size() + && path_lengths.size() == pruned.size() + && pruned.size() == breakage.size()); + + for (unsigned t = initial_timestamp; t < viterbi.size(); t++) + { + std::fill(viterbi[t].begin(), viterbi[t].end(), IMPOSSIBLE_LOG_PROB); + std::fill(parents[t].begin(), parents[t].end(), 0); + std::fill(path_lengths[t].begin(), path_lengths[t].end(), 0); + std::fill(pruned[t].begin(), pruned[t].end(), true); + } + std::fill(breakage.begin()+initial_timestamp, breakage.end(), true); + } + + unsigned initialize(unsigned initial_timestamp) + { + BOOST_ASSERT(initial_timestamp < timestamp_list.size()); + + do + { + for (auto s = 0u; s < viterbi[initial_timestamp].size(); ++s) + { + viterbi[initial_timestamp][s] = log_emission_probability(timestamp_list[initial_timestamp][s].second); + parents[initial_timestamp][s] = s; + pruned[initial_timestamp][s] = viterbi[initial_timestamp][s] < MINIMAL_LOG_PROB; + + breakage[initial_timestamp] = breakage[initial_timestamp] && pruned[initial_timestamp][s]; + + } + + ++initial_timestamp; + } while (breakage[initial_timestamp - 1]); + + BOOST_ASSERT(initial_timestamp > 0 && initial_timestamp < viterbi.size()); + --initial_timestamp; + + BOOST_ASSERT(breakage[initial_timestamp] == false); + + return initial_timestamp; + } + + }; + public: MapMatching(DataFacadeT *facade, SearchEngineData &engine_working_data) : super(facade), engine_working_data(engine_working_data) { } + void operator()(const Matching::CandidateLists ×tamp_list, const std::vector coordinate_list, std::vector& matched_nodes, float& matched_length, JSON::Object& _debug_info) const { - std::vector breakage(timestamp_list.size(), true); - BOOST_ASSERT(timestamp_list.size() > 0); - // TODO for the viterbi values we actually only need the current and last row - std::vector> viterbi; - std::vector> parents; - std::vector> segment_lengths; - std::vector> pruned; - for (const auto& l : timestamp_list) - { - viterbi.emplace_back(l.size(), -std::numeric_limits::infinity()); - parents.emplace_back(l.size(), 0); - segment_lengths.emplace_back(l.size(), 0); - pruned.emplace_back(l.size(), true); + HiddenMarkovModel model(timestamp_list); - } + unsigned initial_timestamp = model.initialize(0); JSON::Array _debug_states; - for (const auto& l : timestamp_list) + for (unsigned t = 0; t < timestamp_list.size(); t++) { JSON::Array _debug_timestamps; - for (unsigned i = 0; i < l.size(); i++) + for (unsigned s = 0; s < timestamp_list[t].size(); s++) { JSON::Object _debug_state; _debug_state.values["transitions"] = JSON::Array(); - _debug_state.values["coordinate"] = makeJSONArray(l[i].first.location.lat / COORDINATE_PRECISION, - l[i].first.location.lon / COORDINATE_PRECISION); + _debug_state.values["coordinate"] = makeJSONArray(timestamp_list[t][s].first.location.lat / COORDINATE_PRECISION, + timestamp_list[t][s].first.location.lon / COORDINATE_PRECISION); + if (t < initial_timestamp) + { + _debug_state.values["viterbi"] = makeJSONSafe(HiddenMarkovModel::IMPOSSIBLE_LOG_PROB); + _debug_state.values["pruned"] = 0u; + } + else if (t == initial_timestamp) + { + _debug_state.values["viterbi"] = makeJSONSafe(model.viterbi[t][s]); + _debug_state.values["pruned"] = static_cast(model.pruned[t][s]); + } _debug_timestamps.values.push_back(_debug_state); } _debug_states.values.push_back(_debug_timestamps); } - unsigned initial_timestamp = 0; - do - { - for (auto s = 0u; s < viterbi[initial_timestamp].size(); ++s) - { - // this might need to be squared as pi_s is also defined as the emission - // probability in the paper. - viterbi[initial_timestamp][s] = log_emission_probability(timestamp_list[initial_timestamp][s].second); - parents[initial_timestamp][s] = s; - pruned[initial_timestamp][s] = viterbi[initial_timestamp][s] < -std::numeric_limits::max(); - - breakage[initial_timestamp] = breakage[initial_timestamp] && pruned[initial_timestamp][s]; - - _debug_states.values[initial_timestamp] - .get().get().values[s] - .get().get().values["viterbi"] = makeJSONSafe(viterbi[initial_timestamp][s]); - _debug_states.values[initial_timestamp] - .get().get().values[s] - .get().get().values["pruned"] = static_cast(pruned[initial_timestamp][s]); - } - - ++initial_timestamp; - } while (breakage[initial_timestamp - 1]); - - BOOST_ASSERT(initial_timestamp > 0 && initial_timestamp < viterbi.size()); - --initial_timestamp; - - BOOST_ASSERT(breakage[initial_timestamp] == false); - - unsigned prev_unbroken_timestamp = initial_timestamp; + std::vector prev_unbroken_timestamps; + prev_unbroken_timestamps.reserve(timestamp_list.size()); + prev_unbroken_timestamps.push_back(initial_timestamp); for (auto t = initial_timestamp + 1; t < timestamp_list.size(); ++t) { - const auto& prev_viterbi = viterbi[prev_unbroken_timestamp]; - const auto& prev_pruned = pruned[prev_unbroken_timestamp]; + unsigned prev_unbroken_timestamp = prev_unbroken_timestamps.back(); + const auto& prev_viterbi = model.viterbi[prev_unbroken_timestamp]; + const auto& prev_pruned = model.pruned[prev_unbroken_timestamp]; const auto& prev_unbroken_timestamps_list = timestamp_list[prev_unbroken_timestamp]; const auto& prev_coordinate = coordinate_list[prev_unbroken_timestamp]; - auto& current_viterbi = viterbi[t]; - auto& current_pruned = pruned[t]; - auto& current_parents = parents[t]; - auto& current_lengths = segment_lengths[t]; + auto& current_viterbi = model.viterbi[t]; + auto& current_pruned = model.pruned[t]; + auto& current_parents = model.parents[t]; + auto& current_lengths = model.path_lengths[t]; const auto& current_timestamps_list = timestamp_list[t]; const auto& current_coordinate = coordinate_list[t]; @@ -361,14 +410,13 @@ template class MapMatching final .get().get().values["transitions"] .get().get().values.push_back(_debug_transistion); - if (new_value > current_viterbi[s_prime]) { current_viterbi[s_prime] = new_value; current_parents[s_prime] = s; current_lengths[s_prime] = network_distance; current_pruned[s_prime] = false; - breakage[t] = false; + model.breakage[t] = false; } } } @@ -383,23 +431,45 @@ template class MapMatching final .get().get().values["pruned"] = static_cast(current_pruned[s_prime]); } - if (!breakage[t]) + if (model.breakage[t]) { - prev_unbroken_timestamp = t; + if (prev_unbroken_timestamps.size() > 1) + { + // remove both ends of the breakge + prev_unbroken_timestamps.pop_back(); + } + // we reached the beginning of the trace, discard the whole beginning + else + { + model.clear(t); + model.initialize(t); + } + } + else + { + prev_unbroken_timestamps.push_back(t); } } + if (prev_unbroken_timestamps.size() < 1) + { + return; + } + + unsigned last_unbroken_timestamp = prev_unbroken_timestamps.back(); + // loop through the columns, and only compare the last entry - auto max_element_iter = std::max_element(viterbi[prev_unbroken_timestamp].begin(), viterbi[prev_unbroken_timestamp].end()); - auto parent_index = std::distance(viterbi[prev_unbroken_timestamp].begin(), max_element_iter); + auto max_element_iter = std::max_element(model.viterbi[last_unbroken_timestamp].begin(), + model.viterbi[last_unbroken_timestamp].end()); + auto parent_index = std::distance(model.viterbi[last_unbroken_timestamp].begin(), max_element_iter); std::deque> reconstructed_indices; - for (auto i = prev_unbroken_timestamp; i > initial_timestamp; --i) + for (auto i = last_unbroken_timestamp; i > initial_timestamp; --i) { - if (breakage[i]) + if (model.breakage[i]) continue; reconstructed_indices.emplace_front(i, parent_index); - parent_index = parents[i][parent_index]; + parent_index = model.parents[i][parent_index]; } reconstructed_indices.emplace_front(initial_timestamp, parent_index); @@ -411,7 +481,7 @@ template class MapMatching final auto location_index = reconstructed_indices[i].second; matched_nodes[i] = timestamp_list[timestamp_index][location_index].first; - matched_length += segment_lengths[timestamp_index][location_index]; + matched_length += model.path_lengths[timestamp_index][location_index]; _debug_states.values[timestamp_index] .get().get().values[location_index] @@ -419,7 +489,7 @@ template class MapMatching final } JSON::Array _debug_breakage; - for (auto b : breakage) { + for (auto b : model.breakage) { _debug_breakage.values.push_back(static_cast(b)); } From cb4a81008c60cbbd1be010bb963e090d12f88af1 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Tue, 17 Feb 2015 12:22:11 +0100 Subject: [PATCH 251/360] Split traces into subtraces --- plugins/map_matching.hpp | 147 ++++++++++++++++------------ routing_algorithms/map_matching.hpp | 106 +++++++++++++------- 2 files changed, 155 insertions(+), 98 deletions(-) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 8a9988277..2dd9545b5 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -62,9 +62,6 @@ template class MapMatchingPlugin : public BasePlugin 0.7977883096366508) // valid apriori probability { descriptor_table.emplace("json", 0); - descriptor_table.emplace("gpx", 1); - // descriptor_table.emplace("geojson", 2); - // search_engine_ptr = std::make_shared>(facade); } @@ -93,12 +90,13 @@ template class MapMatchingPlugin : public BasePlugin return label_with_confidence; } - bool get_candiates(const std::vector& input_coords, double& trace_length, Matching::CandidateLists& candidates_lists) + bool get_candiates(const std::vector& input_coords, std::vector& sub_trace_lengths, Matching::CandidateLists& candidates_lists) { double last_distance = coordinate_calculation::great_circle_distance( input_coords[0], input_coords[1]); - trace_length = 0; + sub_trace_lengths.resize(input_coords.size()); + sub_trace_lengths[0] = 0; for (const auto current_coordinate : osrm::irange(0, input_coords.size())) { bool allow_uturn = false; @@ -107,7 +105,7 @@ template class MapMatchingPlugin : public BasePlugin last_distance = coordinate_calculation::great_circle_distance( input_coords[current_coordinate - 1], input_coords[current_coordinate]); - trace_length += last_distance; + sub_trace_lengths[current_coordinate] += sub_trace_lengths[current_coordinate-1] + last_distance; } if (input_coords.size()-1 > current_coordinate && 0 < current_coordinate) @@ -171,10 +169,10 @@ template class MapMatchingPlugin : public BasePlugin return 400; } - double trace_length; + std::vector sub_trace_lengths; Matching::CandidateLists candidates_lists; const auto& input_coords = route_parameters.coordinates; - bool found_candidates = get_candiates(input_coords, trace_length, candidates_lists); + bool found_candidates = get_candiates(input_coords, sub_trace_lengths, candidates_lists); if (!found_candidates) { return 400; @@ -182,72 +180,91 @@ template class MapMatchingPlugin : public BasePlugin // call the actual map matching JSON::Object debug_info; - float matched_length; - std::vector matched_nodes; - search_engine_ptr->map_matching(candidates_lists, input_coords, matched_nodes, matched_length, debug_info); + Matching::SubMatchingList sub_matchings; + search_engine_ptr->map_matching(candidates_lists, input_coords, sub_matchings, debug_info); - // classify result - TraceClassification classification = classify(trace_length, matched_length, input_coords.size() - matched_nodes.size()); - if (classification.first == ClassifierT::ClassLabel::POSITIVE) - { - json_result.values["confidence"] = classification.second; - } - else - { - json_result.values["confidence"] = 1-classification.second; - } - - // run shortest path routing to obtain geometry - InternalRouteResult raw_route; - PhantomNodes current_phantom_node_pair; - for (unsigned i = 0; i < matched_nodes.size() - 1; ++i) - { - current_phantom_node_pair.source_phantom = matched_nodes[i]; - current_phantom_node_pair.target_phantom = matched_nodes[i + 1]; - raw_route.segment_end_coordinates.emplace_back(current_phantom_node_pair); - } - - if (2 > matched_nodes.size()) + if (1 > sub_matchings.size()) { return 400; } - search_engine_ptr->shortest_path( - raw_route.segment_end_coordinates, - std::vector(raw_route.segment_end_coordinates.size(), true), - raw_route); - - DescriptorConfig descriptor_config; - - auto iter = descriptor_table.find(route_parameters.output_format); - unsigned descriptor_type = (iter != descriptor_table.end() ? iter->second : 0); - - descriptor_config.zoom_level = route_parameters.zoom_level; - descriptor_config.instructions = route_parameters.print_instructions; - descriptor_config.geometry = route_parameters.geometry; - descriptor_config.encode_geometry = route_parameters.compression; - - std::shared_ptr> descriptor; - switch (descriptor_type) + JSON::Array traces; + for (auto& sub : sub_matchings) { - // case 0: - // descriptor = std::make_shared>(); - // break; - case 1: - descriptor = std::make_shared>(facade); - break; - // case 2: - // descriptor = std::make_shared>(); - // break; - default: - descriptor = std::make_shared>(facade); - break; + // classify result + double trace_length = sub_trace_lengths[sub.end_idx-1] - sub_trace_lengths[sub.begin_idx]; + TraceClassification classification = classify(trace_length, + sub.length, + (sub.end_idx - sub.begin_idx) - sub.nodes.size()); + if (classification.first == ClassifierT::ClassLabel::POSITIVE) + { + sub.confidence = classification.second; + } + else + { + sub.confidence = 1-classification.second; + } + + // FIXME this is a pretty bad hack. Geometries should obtained directly + // from map_matching. + // run shortest path routing to obtain geometry + InternalRouteResult raw_route; + PhantomNodes current_phantom_node_pair; + for (unsigned i = 0; i < sub.nodes.size() - 1; ++i) + { + current_phantom_node_pair.source_phantom = sub.nodes[i]; + current_phantom_node_pair.target_phantom = sub.nodes[i + 1]; + raw_route.segment_end_coordinates.emplace_back(current_phantom_node_pair); + } + search_engine_ptr->shortest_path( + raw_route.segment_end_coordinates, + std::vector(raw_route.segment_end_coordinates.size(), true), + raw_route); + + + DescriptorConfig descriptor_config; + + auto iter = descriptor_table.find(route_parameters.output_format); + unsigned descriptor_type = (iter != descriptor_table.end() ? iter->second : 0); + + descriptor_config.zoom_level = route_parameters.zoom_level; + descriptor_config.instructions = false; + descriptor_config.geometry = route_parameters.geometry; + descriptor_config.encode_geometry = route_parameters.compression; + + std::shared_ptr> descriptor; + switch (descriptor_type) + { + // case 0: + // descriptor = std::make_shared>(); + // break; + case 1: + descriptor = std::make_shared>(facade); + break; + // case 2: + // descriptor = std::make_shared>(); + // break; + default: + descriptor = std::make_shared>(facade); + break; + } + + JSON::Object temp_result; + descriptor->SetConfig(descriptor_config); + descriptor->Run(raw_route, temp_result); + + JSON::Object subtrace; + // via_route compability + subtrace.values["route_geometry"] = temp_result.values["route_geometry"]; + subtrace.values["confidence"] = sub.confidence; + subtrace.values["via_indicies"] = temp_result.values["via_indicies"]; + subtrace.values["via_points"] = temp_result.values["via_points"]; + + traces.values.push_back(subtrace); } - descriptor->SetConfig(descriptor_config); - descriptor->Run(raw_route, json_result); - json_result.values["debug"] = debug_info; + json_result.values["traces"] = traces; return 200; } diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 9cb19402b..92c05bc67 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -70,9 +70,19 @@ JSON::Array makeJSONArray(Args... args) namespace Matching { -typedef std::vector> CandidateList; -typedef std::vector CandidateLists; -typedef std::pair PhantomNodesWithProbability; + +struct SubMatching +{ + std::vector nodes; + unsigned begin_idx; + unsigned end_idx; + double length; + double confidence; +}; + +using CandidateList = std::vector>; +using CandidateLists = std::vector; +using SubMatchingList = std::vector; constexpr static const unsigned max_number_of_candidates = 20; } @@ -313,8 +323,7 @@ template class MapMatching final void operator()(const Matching::CandidateLists ×tamp_list, const std::vector coordinate_list, - std::vector& matched_nodes, - float& matched_length, + Matching::SubMatchingList& sub_matchings, JSON::Object& _debug_info) const { BOOST_ASSERT(timestamp_list.size() > 0); @@ -348,6 +357,7 @@ template class MapMatching final _debug_states.values.push_back(_debug_timestamps); } + std::vector split_points; std::vector prev_unbroken_timestamps; prev_unbroken_timestamps.reserve(timestamp_list.size()); prev_unbroken_timestamps.push_back(initial_timestamp); @@ -366,6 +376,8 @@ template class MapMatching final const auto& current_timestamps_list = timestamp_list[t]; const auto& current_coordinate = coordinate_list[t]; + std::cout << " # " << prev_unbroken_timestamp << " -> " << t << std::endl; + // compute d_t for this timestamp and the next one for (auto s = 0u; s < prev_viterbi.size(); ++s) { @@ -433,16 +445,24 @@ template class MapMatching final if (model.breakage[t]) { + std::cout << "Broken!" << std::endl; + // TODO we actually don't need to go to the beginning. + // with temporal information we can split after _n_ + // skipped states if (prev_unbroken_timestamps.size() > 1) { // remove both ends of the breakge prev_unbroken_timestamps.pop_back(); } - // we reached the beginning of the trace, discard the whole beginning + // we reached the beginning of the trace and it is still broken + // -> split the trace here else { + split_points.push_back(t); + // note this preserves everything before t model.clear(t); model.initialize(t); + prev_unbroken_timestamps.push_back(t); } } else @@ -451,41 +471,61 @@ template class MapMatching final } } - if (prev_unbroken_timestamps.size() < 1) + if (prev_unbroken_timestamps.size() > 1) { - return; + split_points.push_back(prev_unbroken_timestamps.back()+1); } - unsigned last_unbroken_timestamp = prev_unbroken_timestamps.back(); - - // loop through the columns, and only compare the last entry - auto max_element_iter = std::max_element(model.viterbi[last_unbroken_timestamp].begin(), - model.viterbi[last_unbroken_timestamp].end()); - auto parent_index = std::distance(model.viterbi[last_unbroken_timestamp].begin(), max_element_iter); - std::deque> reconstructed_indices; - - for (auto i = last_unbroken_timestamp; i > initial_timestamp; --i) + unsigned sub_matching_begin = initial_timestamp; + for (const unsigned sub_matching_end : split_points) { - if (model.breakage[i]) + Matching::SubMatching matching; + + // matchings that only consist of one candidate are invalid + if (sub_matching_end - sub_matching_begin < 2) + { + sub_matching_begin = sub_matching_end; continue; - reconstructed_indices.emplace_front(i, parent_index); - parent_index = model.parents[i][parent_index]; - } - reconstructed_indices.emplace_front(initial_timestamp, parent_index); + } - matched_length = 0.0f; - matched_nodes.resize(reconstructed_indices.size()); - for (auto i = 0u; i < reconstructed_indices.size(); ++i) - { - auto timestamp_index = reconstructed_indices[i].first; - auto location_index = reconstructed_indices[i].second; + std::cout << sub_matching_begin << " -> " << sub_matching_end << std::endl; - matched_nodes[i] = timestamp_list[timestamp_index][location_index].first; - matched_length += model.path_lengths[timestamp_index][location_index]; + matching.begin_idx = sub_matching_begin; + matching.end_idx = sub_matching_end; - _debug_states.values[timestamp_index] - .get().get().values[location_index] - .get().get().values["chosen"] = true; + // loop through the columns, and only compare the last entry + auto max_element_iter = std::max_element(model.viterbi[sub_matching_end-1].begin(), + model.viterbi[sub_matching_end-1].end()); + + auto parent_index = std::distance(model.viterbi[sub_matching_end-1].begin(), max_element_iter); + std::deque> reconstructed_indices; + for (auto i = sub_matching_end-1; i > sub_matching_begin; --i) + { + if (model.breakage[i]) + continue; + reconstructed_indices.emplace_front(i, parent_index); + parent_index = model.parents[i][parent_index]; + } + reconstructed_indices.emplace_front(initial_timestamp, parent_index); + + matching.length = 0.0f; + matching.nodes.resize(reconstructed_indices.size()); + for (auto i = 0u; i < reconstructed_indices.size(); ++i) + { + auto timestamp_index = reconstructed_indices[i].first; + auto location_index = reconstructed_indices[i].second; + + matching.nodes[i] = timestamp_list[timestamp_index][location_index].first; + matching.length += model.path_lengths[timestamp_index][location_index]; + + _debug_states.values[timestamp_index] + .get().get().values[location_index] + .get().get().values["chosen"] = true; + } + + sub_matchings.push_back(matching); + + sub_matching_begin = sub_matching_end; } JSON::Array _debug_breakage; From fb0ce48f2f14c6eebff6a7f0911f44ce65a96e74 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Thu, 19 Feb 2015 01:05:24 +0100 Subject: [PATCH 252/360] Simplify matching response --- plugins/map_matching.hpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 2dd9545b5..a1947fe91 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -253,12 +253,19 @@ template class MapMatchingPlugin : public BasePlugin descriptor->SetConfig(descriptor_config); descriptor->Run(raw_route, temp_result); + JSON::Array input_points; + for(const auto& n: sub.nodes) { + JSON::Array coord; + coord.values.emplace_back(n.location.lat / COORDINATE_PRECISION); + coord.values.emplace_back(n.location.lon / COORDINATE_PRECISION); + input_points.values.push_back(coord); + } + JSON::Object subtrace; - // via_route compability - subtrace.values["route_geometry"] = temp_result.values["route_geometry"]; + subtrace.values["geometry"] = temp_result.values["route_geometry"]; subtrace.values["confidence"] = sub.confidence; - subtrace.values["via_indicies"] = temp_result.values["via_indicies"]; - subtrace.values["via_points"] = temp_result.values["via_points"]; + subtrace.values["input_points"] = input_points; + subtrace.values["matched_points"] = temp_result.values["via_points"]; traces.values.push_back(subtrace); } From f46b259384477b810204a241d3e74c697a3af1a8 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 20 Feb 2015 00:35:51 +0100 Subject: [PATCH 253/360] Fix splitting traces --- plugins/map_matching.hpp | 2 + routing_algorithms/map_matching.hpp | 102 +++++++++++++++++----------- 2 files changed, 65 insertions(+), 39 deletions(-) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index a1947fe91..a58b95836 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -205,6 +205,8 @@ template class MapMatchingPlugin : public BasePlugin sub.confidence = 1-classification.second; } + BOOST_ASSERT(sub.nodes.size() > 1); + // FIXME this is a pretty bad hack. Geometries should obtained directly // from map_matching. // run shortest path routing to obtain geometry diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 92c05bc67..3eb375efd 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -83,7 +83,12 @@ struct SubMatching using CandidateList = std::vector>; using CandidateLists = std::vector; using SubMatchingList = std::vector; -constexpr static const unsigned max_number_of_candidates = 20; +constexpr static const unsigned max_number_of_candidates = 10; +constexpr static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits::infinity(); +constexpr static const double MINIMAL_LOG_PROB = -std::numeric_limits::max(); +constexpr static const unsigned INVALID_STATE = std::numeric_limits::max(); +// FIXME that should be a time threshold. +constexpr static const unsigned MAX_BROKEN_STATES = 6; } // implements a hidden markov model map matching algorithm @@ -243,15 +248,13 @@ template class MapMatching final struct HiddenMarkovModel { std::vector> viterbi; - std::vector> parents; + std::vector>> parents; std::vector> path_lengths; std::vector> pruned; std::vector breakage; const Matching::CandidateLists& timestamp_list; - constexpr static double IMPOSSIBLE_LOG_PROB = -std::numeric_limits::infinity(); - constexpr static double MINIMAL_LOG_PROB = -std::numeric_limits::max(); HiddenMarkovModel(const Matching::CandidateLists& timestamp_list) : breakage(timestamp_list.size()) @@ -277,8 +280,8 @@ template class MapMatching final for (unsigned t = initial_timestamp; t < viterbi.size(); t++) { - std::fill(viterbi[t].begin(), viterbi[t].end(), IMPOSSIBLE_LOG_PROB); - std::fill(parents[t].begin(), parents[t].end(), 0); + std::fill(viterbi[t].begin(), viterbi[t].end(), Matching::IMPOSSIBLE_LOG_PROB); + std::fill(parents[t].begin(), parents[t].end(), std::make_pair(0u, 0u)); std::fill(path_lengths[t].begin(), path_lengths[t].end(), 0); std::fill(pruned[t].begin(), pruned[t].end(), true); } @@ -294,8 +297,8 @@ template class MapMatching final for (auto s = 0u; s < viterbi[initial_timestamp].size(); ++s) { viterbi[initial_timestamp][s] = log_emission_probability(timestamp_list[initial_timestamp][s].second); - parents[initial_timestamp][s] = s; - pruned[initial_timestamp][s] = viterbi[initial_timestamp][s] < MINIMAL_LOG_PROB; + parents[initial_timestamp][s] = std::make_pair(initial_timestamp, s); + pruned[initial_timestamp][s] = viterbi[initial_timestamp][s] < Matching::MINIMAL_LOG_PROB; breakage[initial_timestamp] = breakage[initial_timestamp] && pruned[initial_timestamp][s]; @@ -304,7 +307,12 @@ template class MapMatching final ++initial_timestamp; } while (breakage[initial_timestamp - 1]); - BOOST_ASSERT(initial_timestamp > 0 && initial_timestamp < viterbi.size()); + if (initial_timestamp >= viterbi.size()) + { + return Matching::INVALID_STATE; + } + + BOOST_ASSERT(initial_timestamp > 0); --initial_timestamp; BOOST_ASSERT(breakage[initial_timestamp] == false); @@ -331,6 +339,10 @@ template class MapMatching final HiddenMarkovModel model(timestamp_list); unsigned initial_timestamp = model.initialize(0); + if (initial_timestamp == Matching::INVALID_STATE) + { + return; + } JSON::Array _debug_states; for (unsigned t = 0; t < timestamp_list.size(); t++) @@ -344,7 +356,7 @@ template class MapMatching final timestamp_list[t][s].first.location.lon / COORDINATE_PRECISION); if (t < initial_timestamp) { - _debug_state.values["viterbi"] = makeJSONSafe(HiddenMarkovModel::IMPOSSIBLE_LOG_PROB); + _debug_state.values["viterbi"] = makeJSONSafe(Matching::IMPOSSIBLE_LOG_PROB); _debug_state.values["pruned"] = 0u; } else if (t == initial_timestamp) @@ -376,8 +388,6 @@ template class MapMatching final const auto& current_timestamps_list = timestamp_list[t]; const auto& current_coordinate = coordinate_list[t]; - std::cout << " # " << prev_unbroken_timestamp << " -> " << t << std::endl; - // compute d_t for this timestamp and the next one for (auto s = 0u; s < prev_viterbi.size(); ++s) { @@ -425,7 +435,7 @@ template class MapMatching final if (new_value > current_viterbi[s_prime]) { current_viterbi[s_prime] = new_value; - current_parents[s_prime] = s; + current_parents[s_prime] = std::make_pair(prev_unbroken_timestamp, s); current_lengths[s_prime] = network_distance; current_pruned[s_prime] = false; model.breakage[t] = false; @@ -445,24 +455,25 @@ template class MapMatching final if (model.breakage[t]) { - std::cout << "Broken!" << std::endl; - // TODO we actually don't need to go to the beginning. - // with temporal information we can split after _n_ - // skipped states - if (prev_unbroken_timestamps.size() > 1) - { - // remove both ends of the breakge - prev_unbroken_timestamps.pop_back(); - } + BOOST_ASSERT(prev_unbroken_timestamps.size() > 0); + + // remove both ends of the breakage + prev_unbroken_timestamps.pop_back(); + // we reached the beginning of the trace and it is still broken // -> split the trace here - else + if (prev_unbroken_timestamps.size() < 1 || t - prev_unbroken_timestamps.back() > Matching::MAX_BROKEN_STATES) { split_points.push_back(t); // note this preserves everything before t model.clear(t); - model.initialize(t); - prev_unbroken_timestamps.push_back(t); + unsigned new_start = model.initialize(t); + // no new start was found -> stop viterbi calculation + if (new_start == Matching::INVALID_STATE) + { + break; + } + prev_unbroken_timestamps.push_back(new_start); } } else @@ -471,7 +482,7 @@ template class MapMatching final } } - if (prev_unbroken_timestamps.size() > 1) + if (prev_unbroken_timestamps.size() > 0) { split_points.push_back(prev_unbroken_timestamps.back()+1); } @@ -481,32 +492,45 @@ template class MapMatching final { Matching::SubMatching matching; + // find real end of trace + // not sure if this is really needed + unsigned parent_timestamp_index = sub_matching_end-1; + while (parent_timestamp_index >= sub_matching_begin && model.breakage[parent_timestamp_index]) + { + parent_timestamp_index--; + } + // matchings that only consist of one candidate are invalid - if (sub_matching_end - sub_matching_begin < 2) + if (parent_timestamp_index - sub_matching_begin < 2) { sub_matching_begin = sub_matching_end; continue; } - std::cout << sub_matching_begin << " -> " << sub_matching_end << std::endl; - matching.begin_idx = sub_matching_begin; - matching.end_idx = sub_matching_end; + matching.end_idx = parent_timestamp_index; // loop through the columns, and only compare the last entry - auto max_element_iter = std::max_element(model.viterbi[sub_matching_end-1].begin(), - model.viterbi[sub_matching_end-1].end()); + auto max_element_iter = std::max_element(model.viterbi[parent_timestamp_index].begin(), + model.viterbi[parent_timestamp_index].end()); - auto parent_index = std::distance(model.viterbi[sub_matching_end-1].begin(), max_element_iter); - std::deque> reconstructed_indices; - for (auto i = sub_matching_end-1; i > sub_matching_begin; --i) + unsigned parent_candidate_index = std::distance(model.viterbi[parent_timestamp_index].begin(), max_element_iter); + std::deque> reconstructed_indices; + while (parent_timestamp_index > sub_matching_begin) { - if (model.breakage[i]) + if (model.breakage[parent_timestamp_index]) + { continue; - reconstructed_indices.emplace_front(i, parent_index); - parent_index = model.parents[i][parent_index]; + } + reconstructed_indices.emplace_front(parent_timestamp_index, parent_candidate_index); + parent_timestamp_index = model.parents[parent_timestamp_index][parent_candidate_index].first; + parent_candidate_index = model.parents[parent_timestamp_index][parent_candidate_index].second; + } + reconstructed_indices.emplace_front(parent_timestamp_index, parent_candidate_index); + if (reconstructed_indices.size() < 2) + { + continue; } - reconstructed_indices.emplace_front(initial_timestamp, parent_index); matching.length = 0.0f; matching.nodes.resize(reconstructed_indices.size()); From 89460dd39c64ca6e43625505e0e6021debf6b76a Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 20 Feb 2015 01:13:44 +0100 Subject: [PATCH 254/360] Return indices instead of points --- plugins/map_matching.hpp | 16 +++++++--------- routing_algorithms/map_matching.hpp | 8 +++----- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index a58b95836..57717581c 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -192,10 +192,10 @@ template class MapMatchingPlugin : public BasePlugin for (auto& sub : sub_matchings) { // classify result - double trace_length = sub_trace_lengths[sub.end_idx-1] - sub_trace_lengths[sub.begin_idx]; + double trace_length = sub_trace_lengths[sub.indices.back()] - sub_trace_lengths[sub.indices.front()]; TraceClassification classification = classify(trace_length, sub.length, - (sub.end_idx - sub.begin_idx) - sub.nodes.size()); + (sub.indices.back() - sub.indices.front() + 1) - sub.nodes.size()); if (classification.first == ClassifierT::ClassLabel::POSITIVE) { sub.confidence = classification.second; @@ -255,18 +255,16 @@ template class MapMatchingPlugin : public BasePlugin descriptor->SetConfig(descriptor_config); descriptor->Run(raw_route, temp_result); - JSON::Array input_points; - for(const auto& n: sub.nodes) { - JSON::Array coord; - coord.values.emplace_back(n.location.lat / COORDINATE_PRECISION); - coord.values.emplace_back(n.location.lon / COORDINATE_PRECISION); - input_points.values.push_back(coord); + JSON::Array indices; + for (const auto& i : sub.indices) + { + indices.values.emplace_back(i); } JSON::Object subtrace; subtrace.values["geometry"] = temp_result.values["route_geometry"]; subtrace.values["confidence"] = sub.confidence; - subtrace.values["input_points"] = input_points; + subtrace.values["indices"] = indices; subtrace.values["matched_points"] = temp_result.values["via_points"]; traces.values.push_back(subtrace); diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 3eb375efd..6f766aefb 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -74,8 +74,7 @@ namespace Matching struct SubMatching { std::vector nodes; - unsigned begin_idx; - unsigned end_idx; + std::vector indices; double length; double confidence; }; @@ -507,9 +506,6 @@ template class MapMatching final continue; } - matching.begin_idx = sub_matching_begin; - matching.end_idx = parent_timestamp_index; - // loop through the columns, and only compare the last entry auto max_element_iter = std::max_element(model.viterbi[parent_timestamp_index].begin(), model.viterbi[parent_timestamp_index].end()); @@ -534,11 +530,13 @@ template class MapMatching final matching.length = 0.0f; matching.nodes.resize(reconstructed_indices.size()); + matching.indices.resize(reconstructed_indices.size()); for (auto i = 0u; i < reconstructed_indices.size(); ++i) { auto timestamp_index = reconstructed_indices[i].first; auto location_index = reconstructed_indices[i].second; + matching.indices[i] = timestamp_index; matching.nodes[i] = timestamp_list[timestamp_index][location_index].first; matching.length += model.path_lengths[timestamp_index][location_index]; From d429485f0c3e5ff53e6878492898aa4be3882c65 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 20 Feb 2015 02:31:48 +0100 Subject: [PATCH 255/360] Fix stupid error in backtracking --- routing_algorithms/map_matching.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 6f766aefb..ceca02214 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -511,6 +511,7 @@ template class MapMatching final model.viterbi[parent_timestamp_index].end()); unsigned parent_candidate_index = std::distance(model.viterbi[parent_timestamp_index].begin(), max_element_iter); + std::deque> reconstructed_indices; while (parent_timestamp_index > sub_matching_begin) { @@ -518,9 +519,11 @@ template class MapMatching final { continue; } + reconstructed_indices.emplace_front(parent_timestamp_index, parent_candidate_index); - parent_timestamp_index = model.parents[parent_timestamp_index][parent_candidate_index].first; - parent_candidate_index = model.parents[parent_timestamp_index][parent_candidate_index].second; + const auto& next = model.parents[parent_timestamp_index][parent_candidate_index]; + parent_timestamp_index = next.first; + parent_candidate_index = next.second; } reconstructed_indices.emplace_front(parent_timestamp_index, parent_candidate_index); if (reconstructed_indices.size() < 2) From 70703c39f3424574cb686d29683e8b09ac12201c Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 20 Feb 2015 15:21:50 +0100 Subject: [PATCH 256/360] Add timestamp parameters and reset to beginning of breakage --- data_structures/route_parameters.cpp | 9 +++ include/osrm/route_parameters.hpp | 3 + plugins/map_matching.hpp | 7 ++- routing_algorithms/map_matching.hpp | 82 ++++++++++++++++++---------- server/api_grammar.hpp | 6 +- 5 files changed, 76 insertions(+), 31 deletions(-) diff --git a/data_structures/route_parameters.cpp b/data_structures/route_parameters.cpp index 9416a6d69..7429e4902 100644 --- a/data_structures/route_parameters.cpp +++ b/data_structures/route_parameters.cpp @@ -99,6 +99,15 @@ void RouteParameters::addHint(const std::string &hint) } } +void RouteParameters::addTimestamp(const unsigned timestamp) +{ + timestamps.resize(coordinates.size()); + if (!timestamps.empty()) + { + timestamps.back() = timestamp; + } +} + void RouteParameters::setLanguage(const std::string &language_string) { language = language_string; diff --git a/include/osrm/route_parameters.hpp b/include/osrm/route_parameters.hpp index 04538986e..5fe454cee 100644 --- a/include/osrm/route_parameters.hpp +++ b/include/osrm/route_parameters.hpp @@ -63,6 +63,8 @@ struct RouteParameters void addHint(const std::string &hint); + void addTimestamp(const unsigned timestamp); + void setLanguage(const std::string &language); void setGeometryFlag(const bool flag); @@ -85,6 +87,7 @@ struct RouteParameters std::string jsonp_parameter; std::string language; std::vector hints; + std::vector timestamps; std::vector uturns; std::vector coordinates; }; diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 57717581c..03ada65bc 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -172,6 +172,11 @@ template class MapMatchingPlugin : public BasePlugin std::vector sub_trace_lengths; Matching::CandidateLists candidates_lists; const auto& input_coords = route_parameters.coordinates; + const auto& input_timestamps = route_parameters.timestamps; + if (input_timestamps.size() > 0 && input_coords.size() != input_timestamps.size()) + { + return 400; + } bool found_candidates = get_candiates(input_coords, sub_trace_lengths, candidates_lists); if (!found_candidates) { @@ -181,7 +186,7 @@ template class MapMatchingPlugin : public BasePlugin // call the actual map matching JSON::Object debug_info; Matching::SubMatchingList sub_matchings; - search_engine_ptr->map_matching(candidates_lists, input_coords, sub_matchings, debug_info); + search_engine_ptr->map_matching(candidates_lists, input_coords, input_timestamps, sub_matchings, debug_info); if (1 > sub_matchings.size()) { diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index ceca02214..03ec5d097 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -86,8 +86,8 @@ constexpr static const unsigned max_number_of_candidates = 10; constexpr static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits::infinity(); constexpr static const double MINIMAL_LOG_PROB = -std::numeric_limits::max(); constexpr static const unsigned INVALID_STATE = std::numeric_limits::max(); -// FIXME that should be a time threshold. constexpr static const unsigned MAX_BROKEN_STATES = 6; +constexpr static const unsigned MAX_BROKEN_TIME = 180; } // implements a hidden markov model map matching algorithm @@ -252,14 +252,14 @@ template class MapMatching final std::vector> pruned; std::vector breakage; - const Matching::CandidateLists& timestamp_list; + const Matching::CandidateLists& candidates_list; - HiddenMarkovModel(const Matching::CandidateLists& timestamp_list) - : breakage(timestamp_list.size()) - , timestamp_list(timestamp_list) + HiddenMarkovModel(const Matching::CandidateLists& candidates_list) + : breakage(candidates_list.size()) + , candidates_list(candidates_list) { - for (const auto& l : timestamp_list) + for (const auto& l : candidates_list) { viterbi.emplace_back(l.size()); parents.emplace_back(l.size()); @@ -289,13 +289,13 @@ template class MapMatching final unsigned initialize(unsigned initial_timestamp) { - BOOST_ASSERT(initial_timestamp < timestamp_list.size()); + BOOST_ASSERT(initial_timestamp < candidates_list.size()); do { for (auto s = 0u; s < viterbi[initial_timestamp].size(); ++s) { - viterbi[initial_timestamp][s] = log_emission_probability(timestamp_list[initial_timestamp][s].second); + viterbi[initial_timestamp][s] = log_emission_probability(candidates_list[initial_timestamp][s].second); parents[initial_timestamp][s] = std::make_pair(initial_timestamp, s); pruned[initial_timestamp][s] = viterbi[initial_timestamp][s] < Matching::MINIMAL_LOG_PROB; @@ -328,14 +328,15 @@ template class MapMatching final } - void operator()(const Matching::CandidateLists ×tamp_list, - const std::vector coordinate_list, + void operator()(const Matching::CandidateLists &candidates_list, + const std::vector& trace_coordinates, + const std::vector& trace_timestamps, Matching::SubMatchingList& sub_matchings, JSON::Object& _debug_info) const { - BOOST_ASSERT(timestamp_list.size() > 0); + BOOST_ASSERT(candidates_list.size() > 0); - HiddenMarkovModel model(timestamp_list); + HiddenMarkovModel model(candidates_list); unsigned initial_timestamp = model.initialize(0); if (initial_timestamp == Matching::INVALID_STATE) @@ -344,15 +345,15 @@ template class MapMatching final } JSON::Array _debug_states; - for (unsigned t = 0; t < timestamp_list.size(); t++) + for (unsigned t = 0; t < candidates_list.size(); t++) { JSON::Array _debug_timestamps; - for (unsigned s = 0; s < timestamp_list[t].size(); s++) + for (unsigned s = 0; s < candidates_list[t].size(); s++) { JSON::Object _debug_state; _debug_state.values["transitions"] = JSON::Array(); - _debug_state.values["coordinate"] = makeJSONArray(timestamp_list[t][s].first.location.lat / COORDINATE_PRECISION, - timestamp_list[t][s].first.location.lon / COORDINATE_PRECISION); + _debug_state.values["coordinate"] = makeJSONArray(candidates_list[t][s].first.location.lat / COORDINATE_PRECISION, + candidates_list[t][s].first.location.lon / COORDINATE_PRECISION); if (t < initial_timestamp) { _debug_state.values["viterbi"] = makeJSONSafe(Matching::IMPOSSIBLE_LOG_PROB); @@ -368,24 +369,25 @@ template class MapMatching final _debug_states.values.push_back(_debug_timestamps); } + unsigned breakage_begin = std::numeric_limits::max(); std::vector split_points; std::vector prev_unbroken_timestamps; - prev_unbroken_timestamps.reserve(timestamp_list.size()); + prev_unbroken_timestamps.reserve(candidates_list.size()); prev_unbroken_timestamps.push_back(initial_timestamp); - for (auto t = initial_timestamp + 1; t < timestamp_list.size(); ++t) + for (auto t = initial_timestamp + 1; t < candidates_list.size(); ++t) { unsigned prev_unbroken_timestamp = prev_unbroken_timestamps.back(); const auto& prev_viterbi = model.viterbi[prev_unbroken_timestamp]; const auto& prev_pruned = model.pruned[prev_unbroken_timestamp]; - const auto& prev_unbroken_timestamps_list = timestamp_list[prev_unbroken_timestamp]; - const auto& prev_coordinate = coordinate_list[prev_unbroken_timestamp]; + const auto& prev_unbroken_timestamps_list = candidates_list[prev_unbroken_timestamp]; + const auto& prev_coordinate = trace_coordinates[prev_unbroken_timestamp]; auto& current_viterbi = model.viterbi[t]; auto& current_pruned = model.pruned[t]; auto& current_parents = model.parents[t]; auto& current_lengths = model.path_lengths[t]; - const auto& current_timestamps_list = timestamp_list[t]; - const auto& current_coordinate = coordinate_list[t]; + const auto& current_timestamps_list = candidates_list[t]; + const auto& current_coordinate = trace_coordinates[t]; // compute d_t for this timestamp and the next one for (auto s = 0u; s < prev_viterbi.size(); ++s) @@ -396,7 +398,7 @@ template class MapMatching final for (auto s_prime = 0u; s_prime < current_viterbi.size(); ++s_prime) { // how likely is candidate s_prime at time t to be emitted? - const double emission_pr = log_emission_probability(timestamp_list[t][s_prime].second); + const double emission_pr = log_emission_probability(candidates_list[t][s_prime].second); double new_value = prev_viterbi[s] + emission_pr; if (current_viterbi[s_prime] > new_value) continue; @@ -456,23 +458,47 @@ template class MapMatching final { BOOST_ASSERT(prev_unbroken_timestamps.size() > 0); + // save start of breakage -> we need this as split point + if (t < breakage_begin) + { + breakage_begin = t; + } + // remove both ends of the breakage prev_unbroken_timestamps.pop_back(); + bool trace_split = prev_unbroken_timestamps.size() < 1; + + // use temporal information to determine a split if available + if (trace_timestamps.size() > 0) + { + trace_split = trace_split || (trace_timestamps[t] - trace_timestamps[prev_unbroken_timestamps.back()] > Matching::MAX_BROKEN_TIME); + } + else + { + trace_split = trace_split || (t - prev_unbroken_timestamps.back() > Matching::MAX_BROKEN_STATES); + } + // we reached the beginning of the trace and it is still broken // -> split the trace here - if (prev_unbroken_timestamps.size() < 1 || t - prev_unbroken_timestamps.back() > Matching::MAX_BROKEN_STATES) + if (trace_split) { - split_points.push_back(t); + split_points.push_back(breakage_begin); // note this preserves everything before t - model.clear(t); - unsigned new_start = model.initialize(t); + model.clear(breakage_begin); + unsigned new_start = model.initialize(breakage_begin); // no new start was found -> stop viterbi calculation if (new_start == Matching::INVALID_STATE) { break; } + prev_unbroken_timestamps.clear(); prev_unbroken_timestamps.push_back(new_start); + // Important: We potentially go back here! + // However since t+1 > new_start >= breakge_begin + // we can only reset trace_coordindates.size() times. + t = new_start; + breakage_begin = std::numeric_limits::max(); } } else @@ -540,7 +566,7 @@ template class MapMatching final auto location_index = reconstructed_indices[i].second; matching.indices[i] = timestamp_index; - matching.nodes[i] = timestamp_list[timestamp_index][location_index].first; + matching.nodes[i] = candidates_list[timestamp_index][location_index].first; matching.length += model.path_lengths[timestamp_index][location_index]; _debug_states.values[timestamp_index] diff --git a/server/api_grammar.hpp b/server/api_grammar.hpp index fecbb92cc..3d7f4ea4b 100644 --- a/server/api_grammar.hpp +++ b/server/api_grammar.hpp @@ -40,7 +40,7 @@ template struct APIGrammar : qi::grammar> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query) >> -(uturns); - query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | u | cmp | + query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | timestamp | u | cmp | language | instruction | geometry | alt_route | old_API | num_results)); zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> @@ -62,6 +62,8 @@ template struct APIGrammar : qi::grammar> qi::lit("hint") >> '=' >> stringwithDot[boost::bind(&HandlerT::addHint, handler, ::_1)]; + timestamp = (-qi::lit('&')) >> qi::lit("t") >> '=' >> + qi::uint_[boost::bind(&HandlerT::addTimestamp, handler, ::_1)]; u = (-qi::lit('&')) >> qi::lit("u") >> '=' >> qi::bool_[boost::bind(&HandlerT::setUTurn, handler, ::_1)]; uturns = (-qi::lit('&')) >> qi::lit("uturns") >> '=' >> @@ -83,7 +85,7 @@ template struct APIGrammar : qi::grammar api_call, query; qi::rule service, zoom, output, string, jsonp, checksum, location, - hint, stringwithDot, stringwithPercent, language, instruction, geometry, cmp, alt_route, u, + hint, timestamp, stringwithDot, stringwithPercent, language, instruction, geometry, cmp, alt_route, u, uturns, old_API, num_results; HandlerT *handler; From c4f193b13ee451c572cfb6e6ace3000b6d4123c9 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 20 Feb 2015 15:24:51 +0100 Subject: [PATCH 257/360] Fix comment --- routing_algorithms/map_matching.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 03ec5d097..2f1e618c1 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -484,7 +484,7 @@ template class MapMatching final if (trace_split) { split_points.push_back(breakage_begin); - // note this preserves everything before t + // note: this preserves everything before breakage_begin model.clear(breakage_begin); unsigned new_start = model.initialize(breakage_begin); // no new start was found -> stop viterbi calculation From fd6c70afe14aa13cbb606f97cfe00a843a8439a6 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sat, 21 Feb 2015 14:54:29 +0100 Subject: [PATCH 258/360] Fix regression in sub-matching length check --- routing_algorithms/map_matching.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 2f1e618c1..71d8686dd 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -526,7 +526,7 @@ template class MapMatching final } // matchings that only consist of one candidate are invalid - if (parent_timestamp_index - sub_matching_begin < 2) + if (parent_timestamp_index - sub_matching_begin + 1 < 2) { sub_matching_begin = sub_matching_end; continue; @@ -554,6 +554,7 @@ template class MapMatching final reconstructed_indices.emplace_front(parent_timestamp_index, parent_candidate_index); if (reconstructed_indices.size() < 2) { + sub_matching_begin = sub_matching_end; continue; } From 0e6ed53cee4ebfe1a749f6047eda9b80ab268f1b Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sun, 22 Feb 2015 17:13:08 +0100 Subject: [PATCH 259/360] Adapt to JSON container rename --- plugins/map_matching.hpp | 12 ++++++------ routing_algorithms/map_matching.hpp | 26 +++++++++++++------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 03ada65bc..1aa362120 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -161,7 +161,7 @@ template class MapMatchingPlugin : public BasePlugin return true; } - int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final + int HandleRequest(const RouteParameters &route_parameters, osrm::json::Object &json_result) final { // check number of parameters if (!check_all_coordinates(route_parameters.coordinates)) @@ -184,7 +184,7 @@ template class MapMatchingPlugin : public BasePlugin } // call the actual map matching - JSON::Object debug_info; + osrm::json::Object debug_info; Matching::SubMatchingList sub_matchings; search_engine_ptr->map_matching(candidates_lists, input_coords, input_timestamps, sub_matchings, debug_info); @@ -193,7 +193,7 @@ template class MapMatchingPlugin : public BasePlugin return 400; } - JSON::Array traces; + osrm::json::Array traces; for (auto& sub : sub_matchings) { // classify result @@ -256,17 +256,17 @@ template class MapMatchingPlugin : public BasePlugin break; } - JSON::Object temp_result; + osrm::json::Object temp_result; descriptor->SetConfig(descriptor_config); descriptor->Run(raw_route, temp_result); - JSON::Array indices; + osrm::json::Array indices; for (const auto& i : sub.indices) { indices.values.emplace_back(i); } - JSON::Object subtrace; + osrm::json::Object subtrace; subtrace.values["geometry"] = temp_result.values["route_geometry"]; subtrace.values["confidence"] = sub.confidence; subtrace.values["indices"] = indices; diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 71d8686dd..a9fdd1676 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -35,8 +35,8 @@ or see http://www.gnu.org/licenses/agpl.txt. #include -using JSONVariantArray = mapbox::util::recursive_wrapper; -using JSONVariantObject = mapbox::util::recursive_wrapper; +using JSONVariantArray = mapbox::util::recursive_wrapper; +using JSONVariantObject = mapbox::util::recursive_wrapper; template T makeJSONSafe(T d) @@ -51,19 +51,19 @@ T makeJSONSafe(T d) return d; } -void appendToJSONArray(JSON::Array& a) { } +void appendToJSONArray(osrm::json::Array& a) { } template -void appendToJSONArray(JSON::Array& a, T value, Args... args) +void appendToJSONArray(osrm::json::Array& a, T value, Args... args) { a.values.emplace_back(value); appendToJSONArray(a, args...); } template -JSON::Array makeJSONArray(Args... args) +osrm::json::Array makeJSONArray(Args... args) { - JSON::Array a; + osrm::json::Array a; appendToJSONArray(a, args...); return a; } @@ -332,7 +332,7 @@ template class MapMatching final const std::vector& trace_coordinates, const std::vector& trace_timestamps, Matching::SubMatchingList& sub_matchings, - JSON::Object& _debug_info) const + osrm::json::Object& _debug_info) const { BOOST_ASSERT(candidates_list.size() > 0); @@ -344,14 +344,14 @@ template class MapMatching final return; } - JSON::Array _debug_states; + osrm::json::Array _debug_states; for (unsigned t = 0; t < candidates_list.size(); t++) { - JSON::Array _debug_timestamps; + osrm::json::Array _debug_timestamps; for (unsigned s = 0; s < candidates_list[t].size(); s++) { - JSON::Object _debug_state; - _debug_state.values["transitions"] = JSON::Array(); + osrm::json::Object _debug_state; + _debug_state.values["transitions"] = osrm::json::Array(); _debug_state.values["coordinate"] = makeJSONArray(candidates_list[t][s].first.location.lat / COORDINATE_PRECISION, candidates_list[t][s].first.location.lon / COORDINATE_PRECISION); if (t < initial_timestamp) @@ -419,7 +419,7 @@ template class MapMatching final const double transition_pr = log_transition_probability(d_t, beta); new_value += transition_pr; - JSON::Object _debug_transistion; + osrm::json::Object _debug_transistion; _debug_transistion.values["to"] = makeJSONArray(t, s_prime); _debug_transistion.values["properties"] = makeJSONArray( makeJSONSafe(prev_viterbi[s]), @@ -580,7 +580,7 @@ template class MapMatching final sub_matching_begin = sub_matching_end; } - JSON::Array _debug_breakage; + osrm::json::Array _debug_breakage; for (auto b : model.breakage) { _debug_breakage.values.push_back(static_cast(b)); } From dec73b02e926154e385cd82e59ff196b7cacfd62 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sun, 22 Feb 2015 23:21:37 +0100 Subject: [PATCH 260/360] Rename traces to matchings in response --- plugins/map_matching.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 1aa362120..d4fa22dd9 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -193,7 +193,7 @@ template class MapMatchingPlugin : public BasePlugin return 400; } - osrm::json::Array traces; + osrm::json::Array matchings; for (auto& sub : sub_matchings) { // classify result @@ -272,11 +272,11 @@ template class MapMatchingPlugin : public BasePlugin subtrace.values["indices"] = indices; subtrace.values["matched_points"] = temp_result.values["via_points"]; - traces.values.push_back(subtrace); + matchings.values.push_back(subtrace); } json_result.values["debug"] = debug_info; - json_result.values["traces"] = traces; + json_result.values["matchings"] = matchings; return 200; } From 2115a67d24cf9008a5056bcf9c0b47ad2f896836 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Mon, 23 Feb 2015 11:59:27 +0100 Subject: [PATCH 261/360] Link libOSRM with compute_angle --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e3dac8ba9..bbebb485a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,7 +76,7 @@ list(REMOVE_ITEM DatastructureGlob data_structures/Coordinate.cpp) file(GLOB CoordinateGlob data_structures/coordinate*.cpp) file(GLOB AlgorithmGlob algorithms/*.cpp) file(GLOB HttpGlob server/http/*.cpp) -file(GLOB LibOSRMGlob library/*.cpp) +file(GLOB LibOSRMGlob library/*.cpp util/compute_angle.cpp) file(GLOB DataStructureTestsGlob unit_tests/data_structures/*.cpp data_structures/hilbert_value.cpp) file(GLOB AlgorithmTestsGlob unit_tests/algorithms/*.cpp) From a2c88b607fd47c12d38ff39800529a0192e8025c Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 26 Feb 2015 18:50:18 +0100 Subject: [PATCH 262/360] lint corrections - fix license header - let shared_ptr autodestruct as it's shared - rename fences to resemble file names - reorder includes into lexicographic order --- plugins/map_matching.hpp | 57 ++++++++++++++++------------- routing_algorithms/map_matching.hpp | 49 ++++++++++++++----------- 2 files changed, 60 insertions(+), 46 deletions(-) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index d4fa22dd9..b4f65ad1e 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -1,39 +1,46 @@ - /* - open source routing machine - Copyright (C) Dennis Luxen, others 2010 +/* -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU AFFERO General Public License as published by -the Free Software Foundation; either version 3 of the License, or -any later version. +Copyright (c) 2015, Project OSRM contributors +All rights reserved. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: -You should have received a copy of the GNU Affero General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -or see http://www.gnu.org/licenses/agpl.txt. - */ +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. -#ifndef MAP_MATCHING_PLUGIN_H -#define MAP_MATCHING_PLUGIN_H +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef MAP_MATCHING_HPP +#define MAP_MATCHING_HPP #include "plugin_base.hpp" #include "../algorithms/bayes_classifier.hpp" #include "../algorithms/object_encoder.hpp" -#include "../util/integer_range.hpp" #include "../data_structures/search_engine.hpp" -#include "../routing_algorithms/map_matching.hpp" -#include "../util/compute_angle.hpp" -#include "../util/simple_logger.hpp" -#include "../util/string_util.hpp" #include "../descriptors/descriptor_base.hpp" #include "../descriptors/gpx_descriptor.hpp" #include "../descriptors/json_descriptor.hpp" +#include "../routing_algorithms/map_matching.hpp" +#include "../util/compute_angle.hpp" +#include "../util/integer_range.hpp" +#include "../util/simple_logger.hpp" +#include "../util/string_util.hpp" #include @@ -65,7 +72,7 @@ template class MapMatchingPlugin : public BasePlugin search_engine_ptr = std::make_shared>(facade); } - virtual ~MapMatchingPlugin() { search_engine_ptr.reset(); } + virtual ~MapMatchingPlugin() { } const std::string GetDescriptor() const final { return descriptor_string; } @@ -287,4 +294,4 @@ template class MapMatchingPlugin : public BasePlugin ClassifierT classifier; }; -#endif /* MAP_MATCHING_PLUGIN_H */ +#endif /* MAP_MATCHING_HPP */ diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index a9fdd1676..f9691d1b2 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -1,40 +1,47 @@ /* - open source routing machine - Copyright (C) Dennis Luxen, others 2010 -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU AFFERO General Public License as published by -the Free Software Foundation; either version 3 of the License, or -any later version. +Copyright (c) 2015, Project OSRM contributors +All rights reserved. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: -You should have received a copy of the GNU Affero General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -or see http://www.gnu.org/licenses/agpl.txt. - */ +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. -#ifndef MAP_MATCHING_H -#define MAP_MATCHING_H +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef MAP_MATCHING_HPP +#define MAP_MATCHING_HPP #include "routing_base.hpp" #include "../data_structures/coordinate_calculation.hpp" #include "../util/simple_logger.hpp" -#include #include +#include + +#include #include #include #include -#include - using JSONVariantArray = mapbox::util::recursive_wrapper; using JSONVariantObject = mapbox::util::recursive_wrapper; @@ -592,4 +599,4 @@ template class MapMatching final //[1] "Hidden Markov Map Matching Through Noise and Sparseness"; P. Newson and J. Krumm; 2009; ACM GIS -#endif /* MAP_MATCHING_H */ +#endif /* MAP_MATCHING_HPP */ From adbca39fef3402e5ce3b3b906c844fcd5a1d0472 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 27 Feb 2015 10:59:06 +0100 Subject: [PATCH 263/360] Fix include guard --- plugins/map_matching.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index b4f65ad1e..d3fcccac3 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef MAP_MATCHING_HPP -#define MAP_MATCHING_HPP +#ifndef MAP_MATCHING_PLUGIN_HPP +#define MAP_MATCHING_PLUGIN_HPP #include "plugin_base.hpp" From e8e637c4f2bb7247800808a32b8600d01c1cb537 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 27 Feb 2015 10:59:36 +0100 Subject: [PATCH 264/360] Replace descriptor code with code that generates only geometry --- plugins/map_matching.hpp | 105 ++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index d3fcccac3..3868572ff 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -52,7 +52,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. template class MapMatchingPlugin : public BasePlugin { private: - std::unordered_map descriptor_table; std::shared_ptr> search_engine_ptr; using ClassifierT = BayesClassifier; @@ -68,7 +67,6 @@ template class MapMatchingPlugin : public BasePlugin LaplaceDistribution(0.11467696742821254, 0.49918444000368756), 0.7977883096366508) // valid apriori probability { - descriptor_table.emplace("json", 0); search_engine_ptr = std::make_shared>(facade); } @@ -97,7 +95,7 @@ template class MapMatchingPlugin : public BasePlugin return label_with_confidence; } - bool get_candiates(const std::vector& input_coords, std::vector& sub_trace_lengths, Matching::CandidateLists& candidates_lists) + bool getCandiates(const std::vector& input_coords, std::vector& sub_trace_lengths, Matching::CandidateLists& candidates_lists) { double last_distance = coordinate_calculation::great_circle_distance( input_coords[0], @@ -168,6 +166,54 @@ template class MapMatchingPlugin : public BasePlugin return true; } + osrm::json::Object submatchingToJSON(const Matching::SubMatching& sub, const RouteParameters& route_parameters, const InternalRouteResult& raw_route) + { + osrm::json::Object subtrace; + + subtrace.values["confidence"] = sub.confidence; + + if (route_parameters.geometry) + { + DescriptionFactory factory; + FixedPointCoordinate current_coordinate; + factory.SetStartSegment( + raw_route.segment_end_coordinates.front().source_phantom, + raw_route.source_traversed_in_reverse.front()); + for (const auto i : osrm::irange(0, raw_route.unpacked_path_segments.size())) + { + for (const PathData &path_data : raw_route.unpacked_path_segments[i]) + { + current_coordinate = facade->GetCoordinateOfNode(path_data.node); + factory.AppendSegment(current_coordinate, path_data); + } + factory.SetEndSegment(raw_route.segment_end_coordinates[i].target_phantom, + raw_route.target_traversed_in_reverse[i], + raw_route.is_via_leg(i)); + } + subtrace.values["geometry"] = factory.AppendGeometryString(route_parameters.compression); + } + + osrm::json::Array indices; + for (const auto& i : sub.indices) + { + indices.values.emplace_back(i); + } + subtrace.values["indices"] = indices; + + + osrm::json::Array points; + for (const auto& node : sub.nodes) + { + osrm::json::Array coordinate; + coordinate.values.emplace_back(node.location.lat / COORDINATE_PRECISION); + coordinate.values.emplace_back(node.location.lon / COORDINATE_PRECISION); + points.values.emplace_back(coordinate); + } + subtrace.values["matched_points"] = points; + + return subtrace; + } + int HandleRequest(const RouteParameters &route_parameters, osrm::json::Object &json_result) final { // check number of parameters @@ -184,7 +230,7 @@ template class MapMatchingPlugin : public BasePlugin { return 400; } - bool found_candidates = get_candiates(input_coords, sub_trace_lengths, candidates_lists); + bool found_candidates = getCandiates(input_coords, sub_trace_lengths, candidates_lists); if (!found_candidates) { return 400; @@ -219,9 +265,8 @@ template class MapMatchingPlugin : public BasePlugin BOOST_ASSERT(sub.nodes.size() > 1); - // FIXME this is a pretty bad hack. Geometries should obtained directly - // from map_matching. - // run shortest path routing to obtain geometry + // FIXME we only run this to obtain the geometry + // The clean way would be to get this directly from the map matching plugin InternalRouteResult raw_route; PhantomNodes current_phantom_node_pair; for (unsigned i = 0; i < sub.nodes.size() - 1; ++i) @@ -235,51 +280,7 @@ template class MapMatchingPlugin : public BasePlugin std::vector(raw_route.segment_end_coordinates.size(), true), raw_route); - - DescriptorConfig descriptor_config; - - auto iter = descriptor_table.find(route_parameters.output_format); - unsigned descriptor_type = (iter != descriptor_table.end() ? iter->second : 0); - - descriptor_config.zoom_level = route_parameters.zoom_level; - descriptor_config.instructions = false; - descriptor_config.geometry = route_parameters.geometry; - descriptor_config.encode_geometry = route_parameters.compression; - - std::shared_ptr> descriptor; - switch (descriptor_type) - { - // case 0: - // descriptor = std::make_shared>(); - // break; - case 1: - descriptor = std::make_shared>(facade); - break; - // case 2: - // descriptor = std::make_shared>(); - // break; - default: - descriptor = std::make_shared>(facade); - break; - } - - osrm::json::Object temp_result; - descriptor->SetConfig(descriptor_config); - descriptor->Run(raw_route, temp_result); - - osrm::json::Array indices; - for (const auto& i : sub.indices) - { - indices.values.emplace_back(i); - } - - osrm::json::Object subtrace; - subtrace.values["geometry"] = temp_result.values["route_geometry"]; - subtrace.values["confidence"] = sub.confidence; - subtrace.values["indices"] = indices; - subtrace.values["matched_points"] = temp_result.values["via_points"]; - - matchings.values.push_back(subtrace); + matchings.values.emplace_back(submatchingToJSON(sub, route_parameters, raw_route)); } json_result.values["debug"] = debug_info; From 34d5d353af71918e474672b926fd2ad3fd827f93 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 27 Feb 2015 11:17:19 +0100 Subject: [PATCH 265/360] Apply clang-format and split out json_util --- routing_algorithms/map_matching.hpp | 199 ++++++++++++++-------------- util/json_util.hpp | 75 +++++++++++ 2 files changed, 174 insertions(+), 100 deletions(-) create mode 100644 util/json_util.hpp diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index f9691d1b2..afa1b2811 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/coordinate_calculation.hpp" #include "../util/simple_logger.hpp" +#include "../util/json_util.hpp" #include #include @@ -45,36 +46,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using JSONVariantArray = mapbox::util::recursive_wrapper; using JSONVariantObject = mapbox::util::recursive_wrapper; -template -T makeJSONSafe(T d) -{ - if (std::isnan(d) || std::numeric_limits::infinity() == d) { - return std::numeric_limits::max(); - } - if (-std::numeric_limits::infinity() == d) { - return -std::numeric_limits::max(); - } - - return d; -} - -void appendToJSONArray(osrm::json::Array& a) { } - -template -void appendToJSONArray(osrm::json::Array& a, T value, Args... args) -{ - a.values.emplace_back(value); - appendToJSONArray(a, args...); -} - -template -osrm::json::Array makeJSONArray(Args... args) -{ - osrm::json::Array a; - appendToJSONArray(a, args...); - return a; -} - namespace Matching { @@ -86,7 +57,7 @@ struct SubMatching double confidence; }; -using CandidateList = std::vector>; +using CandidateList = std::vector>; using CandidateLists = std::vector; using SubMatchingList = std::vector; constexpr static const unsigned max_number_of_candidates = 10; @@ -133,8 +104,8 @@ template class MapMatching final } // TODO: needs to be estimated from the input locations - // FIXME These values seem wrong. Higher beta for more samples/minute? Should be inverse proportional. - //constexpr static const double beta = 1.; + // FIXME These values seem wrong. Higher beta for more samples/minute? Should be inverse + // proportional. // samples/min and beta // 1 0.49037673 // 2 0.82918373 @@ -239,13 +210,15 @@ template class MapMatching final FixedPointCoordinate previous_coordinate = source_phantom.location; FixedPointCoordinate current_coordinate; distance = 0; - for (const auto& p : unpacked_path) + for (const auto &p : unpacked_path) { current_coordinate = super::facade->GetCoordinateOfNode(p.node); - distance += coordinate_calculation::great_circle_distance(previous_coordinate, current_coordinate); + distance += coordinate_calculation::great_circle_distance(previous_coordinate, + current_coordinate); previous_coordinate = current_coordinate; } - distance += coordinate_calculation::great_circle_distance(previous_coordinate, target_phantom.location); + distance += coordinate_calculation::great_circle_distance(previous_coordinate, + target_phantom.location); } return distance; @@ -259,14 +232,12 @@ template class MapMatching final std::vector> pruned; std::vector breakage; - const Matching::CandidateLists& candidates_list; + const Matching::CandidateLists &candidates_list; - - HiddenMarkovModel(const Matching::CandidateLists& candidates_list) - : breakage(candidates_list.size()) - , candidates_list(candidates_list) + HiddenMarkovModel(const Matching::CandidateLists &candidates_list) + : breakage(candidates_list.size()), candidates_list(candidates_list) { - for (const auto& l : candidates_list) + for (const auto &l : candidates_list) { viterbi.emplace_back(l.size()); parents.emplace_back(l.size()); @@ -279,10 +250,9 @@ template class MapMatching final void clear(unsigned initial_timestamp) { - BOOST_ASSERT(viterbi.size() == parents.size() - && parents.size() == path_lengths.size() - && path_lengths.size() == pruned.size() - && pruned.size() == breakage.size()); + BOOST_ASSERT(viterbi.size() == parents.size() && + parents.size() == path_lengths.size() && + path_lengths.size() == pruned.size() && pruned.size() == breakage.size()); for (unsigned t = initial_timestamp; t < viterbi.size(); t++) { @@ -291,7 +261,7 @@ template class MapMatching final std::fill(path_lengths[t].begin(), path_lengths[t].end(), 0); std::fill(pruned[t].begin(), pruned[t].end(), true); } - std::fill(breakage.begin()+initial_timestamp, breakage.end(), true); + std::fill(breakage.begin() + initial_timestamp, breakage.end(), true); } unsigned initialize(unsigned initial_timestamp) @@ -302,12 +272,14 @@ template class MapMatching final { for (auto s = 0u; s < viterbi[initial_timestamp].size(); ++s) { - viterbi[initial_timestamp][s] = log_emission_probability(candidates_list[initial_timestamp][s].second); + viterbi[initial_timestamp][s] = + log_emission_probability(candidates_list[initial_timestamp][s].second); parents[initial_timestamp][s] = std::make_pair(initial_timestamp, s); - pruned[initial_timestamp][s] = viterbi[initial_timestamp][s] < Matching::MINIMAL_LOG_PROB; - - breakage[initial_timestamp] = breakage[initial_timestamp] && pruned[initial_timestamp][s]; + pruned[initial_timestamp][s] = + viterbi[initial_timestamp][s] < Matching::MINIMAL_LOG_PROB; + breakage[initial_timestamp] = + breakage[initial_timestamp] && pruned[initial_timestamp][s]; } ++initial_timestamp; @@ -325,7 +297,6 @@ template class MapMatching final return initial_timestamp; } - }; public: @@ -334,12 +305,11 @@ template class MapMatching final { } - void operator()(const Matching::CandidateLists &candidates_list, - const std::vector& trace_coordinates, - const std::vector& trace_timestamps, - Matching::SubMatchingList& sub_matchings, - osrm::json::Object& _debug_info) const + const std::vector &trace_coordinates, + const std::vector &trace_timestamps, + Matching::SubMatchingList &sub_matchings, + osrm::json::Object &_debug_info) const { BOOST_ASSERT(candidates_list.size() > 0); @@ -359,16 +329,18 @@ template class MapMatching final { osrm::json::Object _debug_state; _debug_state.values["transitions"] = osrm::json::Array(); - _debug_state.values["coordinate"] = makeJSONArray(candidates_list[t][s].first.location.lat / COORDINATE_PRECISION, - candidates_list[t][s].first.location.lon / COORDINATE_PRECISION); + _debug_state.values["coordinate"] = osrm::json::makeArray( + candidates_list[t][s].first.location.lat / COORDINATE_PRECISION, + candidates_list[t][s].first.location.lon / COORDINATE_PRECISION); if (t < initial_timestamp) { - _debug_state.values["viterbi"] = makeJSONSafe(Matching::IMPOSSIBLE_LOG_PROB); + _debug_state.values["viterbi"] = + osrm::json::clampFloat(Matching::IMPOSSIBLE_LOG_PROB); _debug_state.values["pruned"] = 0u; } else if (t == initial_timestamp) { - _debug_state.values["viterbi"] = makeJSONSafe(model.viterbi[t][s]); + _debug_state.values["viterbi"] = osrm::json::clampFloat(model.viterbi[t][s]); _debug_state.values["pruned"] = static_cast(model.pruned[t][s]); } _debug_timestamps.values.push_back(_debug_state); @@ -384,17 +356,17 @@ template class MapMatching final for (auto t = initial_timestamp + 1; t < candidates_list.size(); ++t) { unsigned prev_unbroken_timestamp = prev_unbroken_timestamps.back(); - const auto& prev_viterbi = model.viterbi[prev_unbroken_timestamp]; - const auto& prev_pruned = model.pruned[prev_unbroken_timestamp]; - const auto& prev_unbroken_timestamps_list = candidates_list[prev_unbroken_timestamp]; - const auto& prev_coordinate = trace_coordinates[prev_unbroken_timestamp]; + const auto &prev_viterbi = model.viterbi[prev_unbroken_timestamp]; + const auto &prev_pruned = model.pruned[prev_unbroken_timestamp]; + const auto &prev_unbroken_timestamps_list = candidates_list[prev_unbroken_timestamp]; + const auto &prev_coordinate = trace_coordinates[prev_unbroken_timestamp]; - auto& current_viterbi = model.viterbi[t]; - auto& current_pruned = model.pruned[t]; - auto& current_parents = model.parents[t]; - auto& current_lengths = model.path_lengths[t]; - const auto& current_timestamps_list = candidates_list[t]; - const auto& current_coordinate = trace_coordinates[t]; + auto ¤t_viterbi = model.viterbi[t]; + auto ¤t_pruned = model.pruned[t]; + auto ¤t_parents = model.parents[t]; + auto ¤t_lengths = model.path_lengths[t]; + const auto ¤t_timestamps_list = candidates_list[t]; + const auto ¤t_coordinate = trace_coordinates[t]; // compute d_t for this timestamp and the next one for (auto s = 0u; s < prev_viterbi.size(); ++s) @@ -405,14 +377,16 @@ template class MapMatching final for (auto s_prime = 0u; s_prime < current_viterbi.size(); ++s_prime) { // how likely is candidate s_prime at time t to be emitted? - const double emission_pr = log_emission_probability(candidates_list[t][s_prime].second); + const double emission_pr = + log_emission_probability(candidates_list[t][s_prime].second); double new_value = prev_viterbi[s] + emission_pr; if (current_viterbi[s_prime] > new_value) continue; // get distance diff between loc1/2 and locs/s_prime - const auto network_distance = get_network_distance(prev_unbroken_timestamps_list[s].first, - current_timestamps_list[s_prime].first); + const auto network_distance = + get_network_distance(prev_unbroken_timestamps_list[s].first, + current_timestamps_list[s_prime].first); const auto great_circle_distance = coordinate_calculation::great_circle_distance(prev_coordinate, current_coordinate); @@ -427,18 +401,23 @@ template class MapMatching final new_value += transition_pr; osrm::json::Object _debug_transistion; - _debug_transistion.values["to"] = makeJSONArray(t, s_prime); - _debug_transistion.values["properties"] = makeJSONArray( - makeJSONSafe(prev_viterbi[s]), - makeJSONSafe(emission_pr), - makeJSONSafe(transition_pr), - network_distance, - great_circle_distance - ); + _debug_transistion.values["to"] = osrm::json::makeArray(t, s_prime); + _debug_transistion.values["properties"] = + osrm::json::makeArray(osrm::json::clampFloat(prev_viterbi[s]), + osrm::json::clampFloat(emission_pr), + osrm::json::clampFloat(transition_pr), + network_distance, + great_circle_distance); _debug_states.values[prev_unbroken_timestamp] - .get().get().values[s] - .get().get().values["transitions"] - .get().get().values.push_back(_debug_transistion); + .get() + .get() + .values[s] + .get() + .get() + .values["transitions"] + .get() + .get() + .values.push_back(_debug_transistion); if (new_value > current_viterbi[s_prime]) { @@ -454,11 +433,19 @@ template class MapMatching final for (auto s_prime = 0u; s_prime < current_viterbi.size(); ++s_prime) { _debug_states.values[t] - .get().get().values[s_prime] - .get().get().values["viterbi"] = makeJSONSafe(current_viterbi[s_prime]); + .get() + .get() + .values[s_prime] + .get() + .get() + .values["viterbi"] = osrm::json::clampFloat(current_viterbi[s_prime]); _debug_states.values[t] - .get().get().values[s_prime] - .get().get().values["pruned"] = static_cast(current_pruned[s_prime]); + .get() + .get() + .values[s_prime] + .get() + .get() + .values["pruned"] = static_cast(current_pruned[s_prime]); } if (model.breakage[t]) @@ -479,11 +466,15 @@ template class MapMatching final // use temporal information to determine a split if available if (trace_timestamps.size() > 0) { - trace_split = trace_split || (trace_timestamps[t] - trace_timestamps[prev_unbroken_timestamps.back()] > Matching::MAX_BROKEN_TIME); + trace_split = + trace_split || + (trace_timestamps[t] - trace_timestamps[prev_unbroken_timestamps.back()] > + Matching::MAX_BROKEN_TIME); } else { - trace_split = trace_split || (t - prev_unbroken_timestamps.back() > Matching::MAX_BROKEN_STATES); + trace_split = trace_split || (t - prev_unbroken_timestamps.back() > + Matching::MAX_BROKEN_STATES); } // we reached the beginning of the trace and it is still broken @@ -516,7 +507,7 @@ template class MapMatching final if (prev_unbroken_timestamps.size() > 0) { - split_points.push_back(prev_unbroken_timestamps.back()+1); + split_points.push_back(prev_unbroken_timestamps.back() + 1); } unsigned sub_matching_begin = initial_timestamp; @@ -526,8 +517,9 @@ template class MapMatching final // find real end of trace // not sure if this is really needed - unsigned parent_timestamp_index = sub_matching_end-1; - while (parent_timestamp_index >= sub_matching_begin && model.breakage[parent_timestamp_index]) + unsigned parent_timestamp_index = sub_matching_end - 1; + while (parent_timestamp_index >= sub_matching_begin && + model.breakage[parent_timestamp_index]) { parent_timestamp_index--; } @@ -543,7 +535,8 @@ template class MapMatching final auto max_element_iter = std::max_element(model.viterbi[parent_timestamp_index].begin(), model.viterbi[parent_timestamp_index].end()); - unsigned parent_candidate_index = std::distance(model.viterbi[parent_timestamp_index].begin(), max_element_iter); + unsigned parent_candidate_index = + std::distance(model.viterbi[parent_timestamp_index].begin(), max_element_iter); std::deque> reconstructed_indices; while (parent_timestamp_index > sub_matching_begin) @@ -554,7 +547,7 @@ template class MapMatching final } reconstructed_indices.emplace_front(parent_timestamp_index, parent_candidate_index); - const auto& next = model.parents[parent_timestamp_index][parent_candidate_index]; + const auto &next = model.parents[parent_timestamp_index][parent_candidate_index]; parent_timestamp_index = next.first; parent_candidate_index = next.second; } @@ -578,8 +571,12 @@ template class MapMatching final matching.length += model.path_lengths[timestamp_index][location_index]; _debug_states.values[timestamp_index] - .get().get().values[location_index] - .get().get().values["chosen"] = true; + .get() + .get() + .values[location_index] + .get() + .get() + .values["chosen"] = true; } sub_matchings.push_back(matching); @@ -588,7 +585,8 @@ template class MapMatching final } osrm::json::Array _debug_breakage; - for (auto b : model.breakage) { + for (auto b : model.breakage) + { _debug_breakage.values.push_back(static_cast(b)); } @@ -597,6 +595,7 @@ template class MapMatching final } }; -//[1] "Hidden Markov Map Matching Through Noise and Sparseness"; P. Newson and J. Krumm; 2009; ACM GIS +//[1] "Hidden Markov Map Matching Through Noise and Sparseness"; P. Newson and J. Krumm; 2009; ACM +//GIS #endif /* MAP_MATCHING_HPP */ diff --git a/util/json_util.hpp b/util/json_util.hpp new file mode 100644 index 000000000..0e362701a --- /dev/null +++ b/util/json_util.hpp @@ -0,0 +1,75 @@ +/* + +Copyright (c) 2015, Project OSRM contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +// based on +// https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp + +#ifndef JSON_UTIL_HPP +#define JSON_UTIL_HPP + +#include + +#include +#include + +namespace osrm +{ +namespace json +{ + +template T clampFloat(T d) +{ + if (std::isnan(d) || std::numeric_limits::infinity() == d) + { + return std::numeric_limits::max(); + } + if (-std::numeric_limits::infinity() == d) + { + return -std::numeric_limits::max(); + } + + return d; +} + +void appendToArray(osrm::json::Array &a) {} +template +void appendToArray(osrm::json::Array &a, T value, Args... args) +{ + a.values.emplace_back(value); + appendToJSONArray(a, args...); +} + +template osrm::json::Array makeArray(Args... args) +{ + osrm::json::Array a; + appendToJSONArray(a, args...); + return a; +} + +} // namespace json +} // namespace osrm +#endif // JSON_RENDERER_HPP From a760aec791cc5caf47bf54de9db8c4e5a4429566 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sat, 28 Feb 2015 18:44:17 +0100 Subject: [PATCH 266/360] Add json logger to map_matching This adds additional data to the json response, when OSRM is compiled in debug mode. --- plugins/map_matching.hpp | 9 +- routing_algorithms/map_matching.hpp | 203 +++++++++++++++++----------- util/json_logger.hpp | 77 +++++++++++ util/json_util.hpp | 38 +++++- 4 files changed, 239 insertions(+), 88 deletions(-) create mode 100644 util/json_logger.hpp diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 3868572ff..a3ef84563 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../util/compute_angle.hpp" #include "../util/integer_range.hpp" #include "../util/simple_logger.hpp" +#include "../util/json_logger.hpp" #include "../util/string_util.hpp" #include @@ -237,9 +238,10 @@ template class MapMatchingPlugin : public BasePlugin } // call the actual map matching - osrm::json::Object debug_info; + if (osrm::json::Logger::get()) + osrm::json::Logger::get()->initialize("matching"); Matching::SubMatchingList sub_matchings; - search_engine_ptr->map_matching(candidates_lists, input_coords, input_timestamps, sub_matchings, debug_info); + search_engine_ptr->map_matching(candidates_lists, input_coords, input_timestamps, sub_matchings); if (1 > sub_matchings.size()) { @@ -283,7 +285,8 @@ template class MapMatchingPlugin : public BasePlugin matchings.values.emplace_back(submatchingToJSON(sub, route_parameters, raw_route)); } - json_result.values["debug"] = debug_info; + if (osrm::json::Logger::get()) + osrm::json::Logger::get()->render("matching", json_result); json_result.values["matchings"] = matchings; return 200; diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index afa1b2811..8a751ba1f 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/coordinate_calculation.hpp" #include "../util/simple_logger.hpp" #include "../util/json_util.hpp" +#include "../util/json_logger.hpp" #include #include @@ -43,9 +44,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using JSONVariantArray = mapbox::util::recursive_wrapper; -using JSONVariantObject = mapbox::util::recursive_wrapper; - namespace Matching { @@ -299,6 +297,119 @@ template class MapMatching final } }; + struct DebugInfo + { + DebugInfo(const osrm::json::Logger* logger) + : logger(logger) + { + if (logger) + { + object = &logger->map->at("matching"); + } + } + + void initialize(const HiddenMarkovModel& model, + unsigned initial_timestamp, + const Matching::CandidateLists& candidates_list) + { + // json logger not enabled + if (!logger) + return; + + osrm::json::Array states; + for (unsigned t = 0; t < candidates_list.size(); t++) + { + osrm::json::Array timestamps; + for (unsigned s = 0; s < candidates_list[t].size(); s++) + { + osrm::json::Object state; + state.values["transitions"] = osrm::json::Array(); + state.values["coordinate"] = osrm::json::make_array( + candidates_list[t][s].first.location.lat / COORDINATE_PRECISION, + candidates_list[t][s].first.location.lon / COORDINATE_PRECISION); + if (t < initial_timestamp) + { + state.values["viterbi"] = osrm::json::clamp_float(Matching::IMPOSSIBLE_LOG_PROB); + state.values["pruned"] = 0u; + } + else if (t == initial_timestamp) + { + state.values["viterbi"] = osrm::json::clamp_float(model.viterbi[t][s]); + state.values["pruned"] = static_cast(model.pruned[t][s]); + } + timestamps.values.push_back(state); + } + states.values.push_back(timestamps); + } + osrm::json::get(*object, "states") = states; + } + + void add_transition_info(const unsigned prev_t, + const unsigned current_t, + const unsigned prev_state, + const unsigned current_state, + const double prev_viterbi, + const double emission_pr, + const double transition_pr, + const double network_distance, + const double great_circle_distance) + { + // json logger not enabled + if (!logger) + return; + + osrm::json::Object transistion; + transistion.values["to"] = osrm::json::make_array(current_t, current_state); + transistion.values["properties"] = + osrm::json::make_array(osrm::json::clamp_float(prev_viterbi), + osrm::json::clamp_float(emission_pr), + osrm::json::clamp_float(transition_pr), + network_distance, + great_circle_distance); + + osrm::json::get(*object, "states", prev_t, prev_state, "transitions") + .get>() + .get().values.push_back(transistion); + + } + + void add_viterbi(const unsigned t, + const std::vector& current_viterbi, + const std::vector& current_pruned) + { + // json logger not enabled + if (!logger) + return; + + for (auto s_prime = 0u; s_prime < current_viterbi.size(); ++s_prime) + { + osrm::json::get(*object, "states", t, s_prime, "viterbi") = osrm::json::clamp_float(current_viterbi[s_prime]); + osrm::json::get(*object, "states", t, s_prime, "pruned") = static_cast(current_pruned[s_prime]); + } + } + + void add_chosen(const unsigned t, const unsigned s) + { + // json logger not enabled + if (!logger) + return; + + osrm::json::get(*object, "states", t, s, "chosen") = true; + } + + void add_breakage(const std::vector& breakage) + { + // json logger not enabled + if (!logger) + return; + + osrm::json::get(*object, "breakage") = osrm::json::make_array(breakage); + } + + const osrm::json::Logger* logger; + osrm::json::Value* object; + }; + public: MapMatching(DataFacadeT *facade, SearchEngineData &engine_working_data) : super(facade), engine_working_data(engine_working_data) @@ -308,8 +419,7 @@ template class MapMatching final void operator()(const Matching::CandidateLists &candidates_list, const std::vector &trace_coordinates, const std::vector &trace_timestamps, - Matching::SubMatchingList &sub_matchings, - osrm::json::Object &_debug_info) const + Matching::SubMatchingList &sub_matchings) const { BOOST_ASSERT(candidates_list.size() > 0); @@ -321,32 +431,8 @@ template class MapMatching final return; } - osrm::json::Array _debug_states; - for (unsigned t = 0; t < candidates_list.size(); t++) - { - osrm::json::Array _debug_timestamps; - for (unsigned s = 0; s < candidates_list[t].size(); s++) - { - osrm::json::Object _debug_state; - _debug_state.values["transitions"] = osrm::json::Array(); - _debug_state.values["coordinate"] = osrm::json::makeArray( - candidates_list[t][s].first.location.lat / COORDINATE_PRECISION, - candidates_list[t][s].first.location.lon / COORDINATE_PRECISION); - if (t < initial_timestamp) - { - _debug_state.values["viterbi"] = - osrm::json::clampFloat(Matching::IMPOSSIBLE_LOG_PROB); - _debug_state.values["pruned"] = 0u; - } - else if (t == initial_timestamp) - { - _debug_state.values["viterbi"] = osrm::json::clampFloat(model.viterbi[t][s]); - _debug_state.values["pruned"] = static_cast(model.pruned[t][s]); - } - _debug_timestamps.values.push_back(_debug_state); - } - _debug_states.values.push_back(_debug_timestamps); - } + DebugInfo debug(osrm::json::Logger::get()); + debug.initialize(model, initial_timestamp, candidates_list); unsigned breakage_begin = std::numeric_limits::max(); std::vector split_points; @@ -400,24 +486,12 @@ template class MapMatching final const double transition_pr = log_transition_probability(d_t, beta); new_value += transition_pr; - osrm::json::Object _debug_transistion; - _debug_transistion.values["to"] = osrm::json::makeArray(t, s_prime); - _debug_transistion.values["properties"] = - osrm::json::makeArray(osrm::json::clampFloat(prev_viterbi[s]), - osrm::json::clampFloat(emission_pr), - osrm::json::clampFloat(transition_pr), + debug.add_transition_info(prev_unbroken_timestamp, t, s, s_prime, + prev_viterbi[s], + emission_pr, + transition_pr, network_distance, great_circle_distance); - _debug_states.values[prev_unbroken_timestamp] - .get() - .get() - .values[s] - .get() - .get() - .values["transitions"] - .get() - .get() - .values.push_back(_debug_transistion); if (new_value > current_viterbi[s_prime]) { @@ -430,23 +504,7 @@ template class MapMatching final } } - for (auto s_prime = 0u; s_prime < current_viterbi.size(); ++s_prime) - { - _debug_states.values[t] - .get() - .get() - .values[s_prime] - .get() - .get() - .values["viterbi"] = osrm::json::clampFloat(current_viterbi[s_prime]); - _debug_states.values[t] - .get() - .get() - .values[s_prime] - .get() - .get() - .values["pruned"] = static_cast(current_pruned[s_prime]); - } + debug.add_viterbi(t, current_viterbi, current_pruned); if (model.breakage[t]) { @@ -570,13 +628,7 @@ template class MapMatching final matching.nodes[i] = candidates_list[timestamp_index][location_index].first; matching.length += model.path_lengths[timestamp_index][location_index]; - _debug_states.values[timestamp_index] - .get() - .get() - .values[location_index] - .get() - .get() - .values["chosen"] = true; + debug.add_chosen(timestamp_index, location_index); } sub_matchings.push_back(matching); @@ -584,14 +636,7 @@ template class MapMatching final sub_matching_begin = sub_matching_end; } - osrm::json::Array _debug_breakage; - for (auto b : model.breakage) - { - _debug_breakage.values.push_back(static_cast(b)); - } - - _debug_info.values["breakage"] = _debug_breakage; - _debug_info.values["states"] = _debug_states; + debug.add_breakage(model.breakage); } }; diff --git a/util/json_logger.hpp b/util/json_logger.hpp new file mode 100644 index 000000000..872a926d5 --- /dev/null +++ b/util/json_logger.hpp @@ -0,0 +1,77 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef JSON_LOGGER_HPP +#define JSON_LOGGER_HPP + +#include + +#include + +namespace osrm +{ +namespace json +{ + +class Logger +{ + using MapT = std::unordered_map; + + public: + static Logger* get() + { + static Logger logger; + +#ifdef NDEBUG + return nullptr; +#else + return &logger; +#endif + } + + void initialize(const std::string& name) + { + if (!map.get()) + { + map.reset(new MapT()); + } + (*map)[name] = Object(); + } + + void render(const std::string& name, Object& obj) const + { + obj.values["debug"] = map->at(name); + } + + boost::thread_specific_ptr map; +}; + + +} +} + +#endif /* SIMPLE_LOGGER_HPP */ diff --git a/util/json_util.hpp b/util/json_util.hpp index 0e362701a..563440d19 100644 --- a/util/json_util.hpp +++ b/util/json_util.hpp @@ -41,7 +41,8 @@ namespace osrm namespace json { -template T clampFloat(T d) +// Make sure we don't have inf and NaN values +template T clamp_float(T d) { if (std::isnan(d) || std::numeric_limits::infinity() == d) { @@ -55,21 +56,46 @@ template T clampFloat(T d) return d; } -void appendToArray(osrm::json::Array &a) {} +void append_to_array(osrm::json::Array &a) {} template -void appendToArray(osrm::json::Array &a, T value, Args... args) +void append_to_array(osrm::json::Array &a, T value, Args... args) { a.values.emplace_back(value); - appendToJSONArray(a, args...); + append_to_array(a, args...); } -template osrm::json::Array makeArray(Args... args) +template osrm::json::Array make_array(Args... args) { osrm::json::Array a; - appendToJSONArray(a, args...); + append_to_array(a, args...); return a; } +template osrm::json::Array make_array(const std::vector& vector) +{ + osrm::json::Array a; + for (const auto& v : vector) + a.values.emplace_back(v); + return a; +} + +// Easy acces to object hierachies +osrm::json::Value& get(osrm::json::Value& value) { return value; } + +template +osrm::json::Value& get(osrm::json::Value& value, const char* key, Keys... keys) +{ + using recursive_object_t = mapbox::util::recursive_wrapper; + return get(value.get().get().values[key], keys...); +} + +template +osrm::json::Value& get(osrm::json::Value& value, unsigned key, Keys... keys) +{ + using recursive_array_t = mapbox::util::recursive_wrapper; + return get(value.get().get().values[key], keys...); +} + } // namespace json } // namespace osrm #endif // JSON_RENDERER_HPP From d89b171f495a6b823fd984009d43fad42ea468c9 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sat, 28 Feb 2015 18:50:01 +0100 Subject: [PATCH 267/360] Simplify json code in map matching plugin --- plugins/map_matching.hpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index a3ef84563..5bb58e6fc 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -34,13 +34,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../algorithms/object_encoder.hpp" #include "../data_structures/search_engine.hpp" #include "../descriptors/descriptor_base.hpp" -#include "../descriptors/gpx_descriptor.hpp" #include "../descriptors/json_descriptor.hpp" #include "../routing_algorithms/map_matching.hpp" #include "../util/compute_angle.hpp" #include "../util/integer_range.hpp" #include "../util/simple_logger.hpp" #include "../util/json_logger.hpp" +#include "../util/json_util.hpp" #include "../util/string_util.hpp" #include @@ -194,21 +194,14 @@ template class MapMatchingPlugin : public BasePlugin subtrace.values["geometry"] = factory.AppendGeometryString(route_parameters.compression); } - osrm::json::Array indices; - for (const auto& i : sub.indices) - { - indices.values.emplace_back(i); - } - subtrace.values["indices"] = indices; + subtrace.values["indices"] = osrm::json::make_array(sub.indices); osrm::json::Array points; for (const auto& node : sub.nodes) { - osrm::json::Array coordinate; - coordinate.values.emplace_back(node.location.lat / COORDINATE_PRECISION); - coordinate.values.emplace_back(node.location.lon / COORDINATE_PRECISION); - points.values.emplace_back(coordinate); + points.values.emplace_back(osrm::json::make_array(node.location.lat / COORDINATE_PRECISION, + node.location.lon / COORDINATE_PRECISION)); } subtrace.values["matched_points"] = points; From e5830b0116bd843c37d61dd915fc1eb50a61f089 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Mon, 2 Mar 2015 23:12:44 +0100 Subject: [PATCH 268/360] Add parameters for map matching --- data_structures/route_parameters.cpp | 9 ++- include/osrm/route_parameters.hpp | 9 +++ plugins/map_matching.hpp | 37 ++++++---- routing_algorithms/map_matching.hpp | 105 +++++++++++---------------- server/api_grammar.hpp | 11 ++- 5 files changed, 94 insertions(+), 77 deletions(-) diff --git a/data_structures/route_parameters.cpp b/data_structures/route_parameters.cpp index 7429e4902..3b615e2c4 100644 --- a/data_structures/route_parameters.cpp +++ b/data_structures/route_parameters.cpp @@ -33,7 +33,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. RouteParameters::RouteParameters() : zoom_level(18), print_instructions(false), alternate_route(true), geometry(true), - compression(true), deprecatedAPI(false), uturn_default(false), check_sum(-1), num_results(1) + compression(true), deprecatedAPI(false), uturn_default(false), classify(false), + matching_beta(-1.0), gps_precision(-1.0), check_sum(-1), num_results(1) { } @@ -83,6 +84,12 @@ void RouteParameters::setInstructionFlag(const bool flag) { print_instructions = void RouteParameters::setService(const std::string &service_string) { service = service_string; } +void RouteParameters::setClassify(const bool flag) { classify = flag; } + +void RouteParameters::setMatchingBeta(const double beta) { matching_beta = beta; } + +void RouteParameters::setGPSPrecision(const double precision) { gps_precision = precision; } + void RouteParameters::setOutputFormat(const std::string &format) { output_format = format; } void RouteParameters::setJSONpParameter(const std::string ¶meter) diff --git a/include/osrm/route_parameters.hpp b/include/osrm/route_parameters.hpp index 5fe454cee..9babbd763 100644 --- a/include/osrm/route_parameters.hpp +++ b/include/osrm/route_parameters.hpp @@ -49,6 +49,12 @@ struct RouteParameters void setAllUTurns(const bool flag); + void setClassify(const bool classify); + + void setMatchingBeta(const double beta); + + void setGPSPrecision(const double precision); + void setDeprecatedAPIFlag(const std::string &); void setChecksum(const unsigned check_sum); @@ -80,6 +86,9 @@ struct RouteParameters bool compression; bool deprecatedAPI; bool uturn_default; + bool classify; + double matching_beta; + double gps_precision; unsigned check_sum; short num_results; std::string service; diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 5bb58e6fc..bacddfc1b 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -171,7 +171,8 @@ template class MapMatchingPlugin : public BasePlugin { osrm::json::Object subtrace; - subtrace.values["confidence"] = sub.confidence; + if (route_parameters.classify) + subtrace.values["confidence"] = sub.confidence; if (route_parameters.geometry) { @@ -230,11 +231,18 @@ template class MapMatchingPlugin : public BasePlugin return 400; } - // call the actual map matching + // setup logging if enabled if (osrm::json::Logger::get()) osrm::json::Logger::get()->initialize("matching"); + + // call the actual map matching Matching::SubMatchingList sub_matchings; - search_engine_ptr->map_matching(candidates_lists, input_coords, input_timestamps, sub_matchings); + search_engine_ptr->map_matching(candidates_lists, + input_coords, + input_timestamps, + route_parameters.matching_beta, + route_parameters.gps_precision, + sub_matchings); if (1 > sub_matchings.size()) { @@ -245,17 +253,20 @@ template class MapMatchingPlugin : public BasePlugin for (auto& sub : sub_matchings) { // classify result - double trace_length = sub_trace_lengths[sub.indices.back()] - sub_trace_lengths[sub.indices.front()]; - TraceClassification classification = classify(trace_length, - sub.length, - (sub.indices.back() - sub.indices.front() + 1) - sub.nodes.size()); - if (classification.first == ClassifierT::ClassLabel::POSITIVE) + if (route_parameters.classify) { - sub.confidence = classification.second; - } - else - { - sub.confidence = 1-classification.second; + double trace_length = sub_trace_lengths[sub.indices.back()] - sub_trace_lengths[sub.indices.front()]; + TraceClassification classification = classify(trace_length, + sub.length, + (sub.indices.back() - sub.indices.front() + 1) - sub.nodes.size()); + if (classification.first == ClassifierT::ClassLabel::POSITIVE) + { + sub.confidence = classification.second; + } + else + { + sub.confidence = 1-classification.second; + } } BOOST_ASSERT(sub.nodes.size() > 1); diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 8a751ba1f..1fa881bf2 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -75,67 +75,42 @@ template class MapMatching final SearchEngineData &engine_working_data; // FIXME this value should be a table based on samples/meter (or samples/min) - constexpr static const double beta = 10.0; - constexpr static const double sigma_z = 4.07; - constexpr static const double log_sigma_z = std::log(sigma_z); + constexpr static const double default_beta = 10.0; + constexpr static const double default_sigma_z = 4.07; constexpr static const double log_2_pi = std::log(2 * M_PI); - constexpr static double emission_probability(const double distance) + // closures to precompute log -> only simple floating point operations + struct EmissionLogProbability { - return (1. / (std::sqrt(2. * M_PI) * sigma_z)) * - std::exp(-0.5 * std::pow((distance / sigma_z), 2.)); - } + double sigma_z; + double log_sigma_z; - constexpr static double transition_probability(const float d_t, const float beta) + EmissionLogProbability(const double sigma_z) + : sigma_z(sigma_z) + , log_sigma_z(std::log(sigma_z)) + { + } + + double operator()(const double distance) const + { + return -0.5 * (log_2_pi + (distance / sigma_z) * (distance / sigma_z)) - log_sigma_z; + } + }; + struct TransitionLogProbability { - return (1. / beta) * std::exp(-d_t / beta); - } + double beta; + double log_beta; + TransitionLogProbability(const double beta) + : beta(beta) + , log_beta(std::log(beta)) + { + } - constexpr static double log_emission_probability(const double distance) - { - return -0.5 * (log_2_pi + (distance / sigma_z) * (distance / sigma_z)) - log_sigma_z; - } - - constexpr static double log_transition_probability(const float d_t, const float beta) - { - return -std::log(beta) - d_t / beta; - } - - // TODO: needs to be estimated from the input locations - // FIXME These values seem wrong. Higher beta for more samples/minute? Should be inverse - // proportional. - // samples/min and beta - // 1 0.49037673 - // 2 0.82918373 - // 3 1.24364564 - // 4 1.67079581 - // 5 2.00719298 - // 6 2.42513007 - // 7 2.81248831 - // 8 3.15745473 - // 9 3.52645392 - // 10 4.09511775 - // 11 4.67319795 - // 21 12.55107715 - // 12 5.41088180 - // 13 6.47666590 - // 14 6.29010734 - // 15 7.80752112 - // 16 8.09074504 - // 17 8.08550528 - // 18 9.09405065 - // 19 11.09090603 - // 20 11.87752824 - // 21 12.55107715 - // 22 15.82820829 - // 23 17.69496773 - // 24 18.07655652 - // 25 19.63438911 - // 26 25.40832185 - // 27 23.76001877 - // 28 28.43289797 - // 29 32.21683062 - // 30 34.56991141 + double operator()(const double d_t) const + { + return -log_beta - d_t / beta; + } + }; double get_network_distance(const PhantomNode &source_phantom, const PhantomNode &target_phantom) const @@ -231,9 +206,10 @@ template class MapMatching final std::vector breakage; const Matching::CandidateLists &candidates_list; + const EmissionLogProbability& emission_log_probability; - HiddenMarkovModel(const Matching::CandidateLists &candidates_list) - : breakage(candidates_list.size()), candidates_list(candidates_list) + HiddenMarkovModel(const Matching::CandidateLists &candidates_list, const EmissionLogProbability& emission_log_probability) + : breakage(candidates_list.size()), candidates_list(candidates_list), emission_log_probability(emission_log_probability) { for (const auto &l : candidates_list) { @@ -271,7 +247,7 @@ template class MapMatching final for (auto s = 0u; s < viterbi[initial_timestamp].size(); ++s) { viterbi[initial_timestamp][s] = - log_emission_probability(candidates_list[initial_timestamp][s].second); + emission_log_probability(candidates_list[initial_timestamp][s].second); parents[initial_timestamp][s] = std::make_pair(initial_timestamp, s); pruned[initial_timestamp][s] = viterbi[initial_timestamp][s] < Matching::MINIMAL_LOG_PROB; @@ -297,6 +273,7 @@ template class MapMatching final } }; + // Provides the debug interface for introspection tools struct DebugInfo { DebugInfo(const osrm::json::Logger* logger) @@ -419,11 +396,17 @@ template class MapMatching final void operator()(const Matching::CandidateLists &candidates_list, const std::vector &trace_coordinates, const std::vector &trace_timestamps, + const double matching_beta, + const double gps_precision, Matching::SubMatchingList &sub_matchings) const { BOOST_ASSERT(candidates_list.size() > 0); - HiddenMarkovModel model(candidates_list); + // TODO replace default values with table lookup based on sampling frequency + EmissionLogProbability emission_log_probability(gps_precision > 0 ? gps_precision : default_sigma_z); + TransitionLogProbability transition_log_probability(matching_beta > 0 ? matching_beta : default_beta); + + HiddenMarkovModel model(candidates_list, emission_log_probability); unsigned initial_timestamp = model.initialize(0); if (initial_timestamp == Matching::INVALID_STATE) @@ -464,7 +447,7 @@ template class MapMatching final { // how likely is candidate s_prime at time t to be emitted? const double emission_pr = - log_emission_probability(candidates_list[t][s_prime].second); + emission_log_probability(candidates_list[t][s_prime].second); double new_value = prev_viterbi[s] + emission_pr; if (current_viterbi[s_prime] > new_value) continue; @@ -483,7 +466,7 @@ template class MapMatching final if (d_t > 500) continue; - const double transition_pr = log_transition_probability(d_t, beta); + const double transition_pr = transition_log_probability(d_t); new_value += transition_pr; debug.add_transition_info(prev_unbroken_timestamp, t, s, s_prime, diff --git a/server/api_grammar.hpp b/server/api_grammar.hpp index 3d7f4ea4b..5c7dcde45 100644 --- a/server/api_grammar.hpp +++ b/server/api_grammar.hpp @@ -41,7 +41,8 @@ template struct APIGrammar : qi::grammar> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query) >> -(uturns); query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | timestamp | u | cmp | - language | instruction | geometry | alt_route | old_API | num_results)); + language | instruction | geometry | alt_route | old_API | num_results | + matching_beta | gps_precision | classify)); zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)]; @@ -64,6 +65,12 @@ template struct APIGrammar : qi::grammar> qi::lit("t") >> '=' >> qi::uint_[boost::bind(&HandlerT::addTimestamp, handler, ::_1)]; + matching_beta = (-qi::lit('&')) >> qi::lit("matching_beta") >> '=' >> + qi::short_[boost::bind(&HandlerT::setMatchingBeta, handler, ::_1)]; + gps_precision = (-qi::lit('&')) >> qi::lit("gps_precision") >> '=' >> + qi::short_[boost::bind(&HandlerT::setGPSPrecision, handler, ::_1)]; + classify = (-qi::lit('&')) >> qi::lit("classify") >> '=' >> + qi::bool_[boost::bind(&HandlerT::setClassify, handler, ::_1)]; u = (-qi::lit('&')) >> qi::lit("u") >> '=' >> qi::bool_[boost::bind(&HandlerT::setUTurn, handler, ::_1)]; uturns = (-qi::lit('&')) >> qi::lit("uturns") >> '=' >> @@ -85,7 +92,7 @@ template struct APIGrammar : qi::grammar api_call, query; qi::rule service, zoom, output, string, jsonp, checksum, location, - hint, timestamp, stringwithDot, stringwithPercent, language, instruction, geometry, cmp, alt_route, u, + hint, timestamp, matching_beta, gps_precision, classify, stringwithDot, stringwithPercent, language, instruction, geometry, cmp, alt_route, u, uturns, old_API, num_results; HandlerT *handler; From d8d46e0f3e0ea789e0a2884a10ca0effcf5ce9f2 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Mon, 2 Mar 2015 23:39:53 +0100 Subject: [PATCH 269/360] Add routed parameter to limit matching size --- include/osrm/libosrm_config.hpp | 12 +++++-- library/osrm_impl.cpp | 3 +- plugins/map_matching.hpp | 11 +++++- routed.cpp | 3 +- util/routed_options.hpp | 64 ++++++++++++++++++--------------- 5 files changed, 58 insertions(+), 35 deletions(-) diff --git a/include/osrm/libosrm_config.hpp b/include/osrm/libosrm_config.hpp index 777a0ccb9..500abf5bd 100644 --- a/include/osrm/libosrm_config.hpp +++ b/include/osrm/libosrm_config.hpp @@ -33,15 +33,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct libosrm_config { libosrm_config(const libosrm_config &) = delete; - libosrm_config() : max_locations_distance_table(100), use_shared_memory(false) {} + libosrm_config() + : max_locations_distance_table(100), max_locations_map_matching(-1), + use_shared_memory(false) + { + } - libosrm_config(const ServerPaths &paths, const bool flag, const int max) - : server_paths(paths), max_locations_distance_table(max), use_shared_memory(flag) + libosrm_config(const ServerPaths &paths, const bool flag, const int max_table, const int max_matching) + : server_paths(paths), max_locations_distance_table(max_table), + max_locations_map_matching(max_matching), use_shared_memory(flag) { } ServerPaths server_paths; int max_locations_distance_table; + int max_locations_map_matching; bool use_shared_memory; }; diff --git a/library/osrm_impl.cpp b/library/osrm_impl.cpp index 9ea009912..f12445f2f 100644 --- a/library/osrm_impl.cpp +++ b/library/osrm_impl.cpp @@ -82,7 +82,8 @@ OSRM_impl::OSRM_impl(libosrm_config &lib_config) RegisterPlugin(new HelloWorldPlugin()); RegisterPlugin(new LocatePlugin>(query_data_facade)); RegisterPlugin(new NearestPlugin>(query_data_facade)); - RegisterPlugin(new MapMatchingPlugin>(query_data_facade)); + RegisterPlugin(new MapMatchingPlugin>( + query_data_facade, lib_config.max_locations_map_matching)); RegisterPlugin(new TimestampPlugin>(query_data_facade)); RegisterPlugin(new ViaRoutePlugin>(query_data_facade)); } diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index bacddfc1b..3bf2026f8 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -59,9 +59,10 @@ template class MapMatchingPlugin : public BasePlugin using TraceClassification = ClassifierT::ClassificationT; public: - MapMatchingPlugin(DataFacadeT *facade) + MapMatchingPlugin(DataFacadeT *facade, const int max_locations_map_matching) : descriptor_string("match") , facade(facade) + , max_locations_map_matching(max_locations_map_matching) // the values where derived from fitting a laplace distribution // to the values of manually classified traces , classifier(LaplaceDistribution(0.0057154021891018675, 0.020294704891166186), @@ -225,6 +226,13 @@ template class MapMatchingPlugin : public BasePlugin { return 400; } + + // enforce maximum number of locations for performance reasons + if (max_locations_map_matching > 0 && static_cast(input_coords.size()) > max_locations_map_matching) + { + return 400; + } + bool found_candidates = getCandiates(input_coords, sub_trace_lengths, candidates_lists); if (!found_candidates) { @@ -299,6 +307,7 @@ template class MapMatchingPlugin : public BasePlugin private: std::string descriptor_string; DataFacadeT *facade; + int max_locations_map_matching; ClassifierT classifier; }; diff --git a/routed.cpp b/routed.cpp index ce5691715..8b0e2e88b 100644 --- a/routed.cpp +++ b/routed.cpp @@ -77,7 +77,8 @@ int main(int argc, const char *argv[]) const unsigned init_result = GenerateServerProgramOptions( argc, argv, lib_config.server_paths, ip_address, ip_port, requested_thread_num, - lib_config.use_shared_memory, trial_run, lib_config.max_locations_distance_table); + lib_config.use_shared_memory, trial_run, lib_config.max_locations_distance_table, + lib_config.max_locations_map_matching); if (init_result == INIT_OK_DO_NOT_START_ENGINE) { return 0; diff --git a/util/routed_options.hpp b/util/routed_options.hpp index 322737d6d..0aef32147 100644 --- a/util/routed_options.hpp +++ b/util/routed_options.hpp @@ -151,7 +151,8 @@ inline unsigned GenerateServerProgramOptions(const int argc, int &requested_num_threads, bool &use_shared_memory, bool &trial, - int &max_locations_distance_table) + int &max_locations_distance_table, + int &max_locations_map_matching) { // declare a group of options that will be allowed only on command line boost::program_options::options_description generic_options("Options"); @@ -165,34 +166,35 @@ inline unsigned GenerateServerProgramOptions(const int argc, // declare a group of options that will be allowed both on command line // as well as in a config file boost::program_options::options_description config_options("Configuration"); - config_options.add_options()( - "hsgrdata", boost::program_options::value(&paths["hsgrdata"]), - ".hsgr file")("nodesdata", - boost::program_options::value(&paths["nodesdata"]), - ".nodes file")( - "edgesdata", boost::program_options::value(&paths["edgesdata"]), - ".edges file")("geometry", - boost::program_options::value(&paths["geometries"]), - ".geometry file")( - "ramindex", boost::program_options::value(&paths["ramindex"]), - ".ramIndex file")( - "fileindex", boost::program_options::value(&paths["fileindex"]), - "File index file")( - "namesdata", boost::program_options::value(&paths["namesdata"]), - ".names file")("timestamp", - boost::program_options::value(&paths["timestamp"]), - ".timestamp file")( - "ip,i", boost::program_options::value(&ip_address)->default_value("0.0.0.0"), - "IP address")("port,p", boost::program_options::value(&ip_port)->default_value(5000), - "TCP/IP port")( - "threads,t", boost::program_options::value(&requested_num_threads)->default_value(8), - "Number of threads to use")( - "shared-memory,s", - boost::program_options::value(&use_shared_memory)->implicit_value(true), - "Load data from shared memory")( - "max-table-size,m", - boost::program_options::value(&max_locations_distance_table)->default_value(100), - "Max. locations supported in distance table query"); + config_options.add_options() + ("hsgrdata", boost::program_options::value(&paths["hsgrdata"]), + ".hsgr file") + ("nodesdata", boost::program_options::value(&paths["nodesdata"]), + ".nodes file") + ("edgesdata", boost::program_options::value(&paths["edgesdata"]), + ".edges file") + ("geometry", boost::program_options::value(&paths["geometries"]), + ".geometry file") + ("ramindex", boost::program_options::value(&paths["ramindex"]), + ".ramIndex file") + ("fileindex", boost::program_options::value(&paths["fileindex"]), + "File index file") + ("namesdata", boost::program_options::value(&paths["namesdata"]), + ".names file") + ("timestamp", boost::program_options::value(&paths["timestamp"]), + ".timestamp file") + ("ip,i", boost::program_options::value(&ip_address)->default_value("0.0.0.0"), + "IP address") + ("port,p", boost::program_options::value(&ip_port)->default_value(5000), + "TCP/IP port") + ("threads,t", boost::program_options::value(&requested_num_threads)->default_value(8), + "Number of threads to use") + ("shared-memory,s", boost::program_options::value(&use_shared_memory)->implicit_value(true), + "Load data from shared memory") + ("max-table-size,m", boost::program_options::value(&max_locations_distance_table)->default_value(100), + "Max. locations supported in distance table query") + ("max-matching-size,m", boost::program_options::value(&max_locations_map_matching)->default_value(-1), + "Max. locations supported in map matching query"); // hidden options, will be allowed both on command line and in config // file, but will not be shown to the user @@ -269,6 +271,10 @@ inline unsigned GenerateServerProgramOptions(const int argc, { throw osrm::exception("Max location for distance table must be a positive number"); } + if (2 > max_locations_map_matching) + { + throw osrm::exception("Max location for map matching must be at least two"); + } SimpleLogger().Write() << visible_options; return INIT_OK_DO_NOT_START_ENGINE; From 0d879ed2907714b0ffb0db7e42b87187ee7e5531 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Tue, 3 Mar 2015 00:38:09 +0100 Subject: [PATCH 270/360] Split trace if timestamp delta is over threshold Even when matching is not broken we split the trace, if the sampling frequency goes below 2 samples/minute. --- routing_algorithms/map_matching.hpp | 124 ++++++++++++++-------------- 1 file changed, 61 insertions(+), 63 deletions(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 1fa881bf2..5400a74d4 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -63,7 +63,7 @@ constexpr static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits constexpr static const double MINIMAL_LOG_PROB = -std::numeric_limits::max(); constexpr static const unsigned INVALID_STATE = std::numeric_limits::max(); constexpr static const unsigned MAX_BROKEN_STATES = 6; -constexpr static const unsigned MAX_BROKEN_TIME = 180; +constexpr static const unsigned MAX_BROKEN_TIME = 30; } // implements a hidden markov model map matching algorithm @@ -285,9 +285,7 @@ template class MapMatching final } } - void initialize(const HiddenMarkovModel& model, - unsigned initial_timestamp, - const Matching::CandidateLists& candidates_list) + void initialize(const Matching::CandidateLists& candidates_list) { // json logger not enabled if (!logger) @@ -304,16 +302,8 @@ template class MapMatching final state.values["coordinate"] = osrm::json::make_array( candidates_list[t][s].first.location.lat / COORDINATE_PRECISION, candidates_list[t][s].first.location.lon / COORDINATE_PRECISION); - if (t < initial_timestamp) - { - state.values["viterbi"] = osrm::json::clamp_float(Matching::IMPOSSIBLE_LOG_PROB); - state.values["pruned"] = 0u; - } - else if (t == initial_timestamp) - { - state.values["viterbi"] = osrm::json::clamp_float(model.viterbi[t][s]); - state.values["pruned"] = static_cast(model.pruned[t][s]); - } + state.values["viterbi"] = osrm::json::clamp_float(Matching::IMPOSSIBLE_LOG_PROB); + state.values["pruned"] = 0u; timestamps.values.push_back(state); } states.values.push_back(timestamps); @@ -350,18 +340,20 @@ template class MapMatching final } - void add_viterbi(const unsigned t, - const std::vector& current_viterbi, - const std::vector& current_pruned) + void set_viterbi(const std::vector>& viterbi, + const std::vector>& pruned) { // json logger not enabled if (!logger) return; - for (auto s_prime = 0u; s_prime < current_viterbi.size(); ++s_prime) + for (auto t = 0u; t < viterbi.size(); t++) { - osrm::json::get(*object, "states", t, s_prime, "viterbi") = osrm::json::clamp_float(current_viterbi[s_prime]); - osrm::json::get(*object, "states", t, s_prime, "pruned") = static_cast(current_pruned[s_prime]); + for (auto s_prime = 0u; s_prime < viterbi[t].size(); ++s_prime) + { + osrm::json::get(*object, "states", t, s_prime, "viterbi") = osrm::json::clamp_float(viterbi[t][s_prime]); + osrm::json::get(*object, "states", t, s_prime, "pruned") = static_cast(pruned[t][s_prime]); + } } } @@ -415,7 +407,7 @@ template class MapMatching final } DebugInfo debug(osrm::json::Logger::get()); - debug.initialize(model, initial_timestamp, candidates_list); + debug.initialize(candidates_list); unsigned breakage_begin = std::numeric_limits::max(); std::vector split_points; @@ -424,7 +416,51 @@ template class MapMatching final prev_unbroken_timestamps.push_back(initial_timestamp); for (auto t = initial_timestamp + 1; t < candidates_list.size(); ++t) { + // breakage recover has removed all previous good points + bool trace_split = prev_unbroken_timestamps.size() < 1; + + // use temporal information if available to determine a split + if (trace_timestamps.size() > 0) + { + trace_split = + trace_split || + (trace_timestamps[t] - trace_timestamps[prev_unbroken_timestamps.back()] > + Matching::MAX_BROKEN_TIME); + } + else + { + trace_split = trace_split || (t - prev_unbroken_timestamps.back() > + Matching::MAX_BROKEN_STATES); + } + + if (trace_split) + { + unsigned split_index = t; + if (breakage_begin != std::numeric_limits::max()) + { + split_index = breakage_begin; + breakage_begin = std::numeric_limits::max(); + } + split_points.push_back(split_index); + + // note: this preserves everything before split_index + model.clear(split_index); + unsigned new_start = model.initialize(split_index); + // no new start was found -> stop viterbi calculation + if (new_start == Matching::INVALID_STATE) + { + break; + } + prev_unbroken_timestamps.clear(); + prev_unbroken_timestamps.push_back(new_start); + // Important: We potentially go back here! + // However since t > new_start >= breakge_begin + // we can only reset trace_coordindates.size() times. + t = new_start+1; + } + unsigned prev_unbroken_timestamp = prev_unbroken_timestamps.back(); + const auto &prev_viterbi = model.viterbi[prev_unbroken_timestamp]; const auto &prev_pruned = model.pruned[prev_unbroken_timestamp]; const auto &prev_unbroken_timestamps_list = candidates_list[prev_unbroken_timestamp]; @@ -487,58 +523,18 @@ template class MapMatching final } } - debug.add_viterbi(t, current_viterbi, current_pruned); - if (model.breakage[t]) { - BOOST_ASSERT(prev_unbroken_timestamps.size() > 0); - // save start of breakage -> we need this as split point if (t < breakage_begin) { breakage_begin = t; } + BOOST_ASSERT(prev_unbroken_timestamps.size() > 0); + // remove both ends of the breakage prev_unbroken_timestamps.pop_back(); - - bool trace_split = prev_unbroken_timestamps.size() < 1; - - // use temporal information to determine a split if available - if (trace_timestamps.size() > 0) - { - trace_split = - trace_split || - (trace_timestamps[t] - trace_timestamps[prev_unbroken_timestamps.back()] > - Matching::MAX_BROKEN_TIME); - } - else - { - trace_split = trace_split || (t - prev_unbroken_timestamps.back() > - Matching::MAX_BROKEN_STATES); - } - - // we reached the beginning of the trace and it is still broken - // -> split the trace here - if (trace_split) - { - split_points.push_back(breakage_begin); - // note: this preserves everything before breakage_begin - model.clear(breakage_begin); - unsigned new_start = model.initialize(breakage_begin); - // no new start was found -> stop viterbi calculation - if (new_start == Matching::INVALID_STATE) - { - break; - } - prev_unbroken_timestamps.clear(); - prev_unbroken_timestamps.push_back(new_start); - // Important: We potentially go back here! - // However since t+1 > new_start >= breakge_begin - // we can only reset trace_coordindates.size() times. - t = new_start; - breakage_begin = std::numeric_limits::max(); - } } else { @@ -546,6 +542,8 @@ template class MapMatching final } } + debug.set_viterbi(model.viterbi, model.pruned); + if (prev_unbroken_timestamps.size() > 0) { split_points.push_back(prev_unbroken_timestamps.back() + 1); From 6fb8fdc2bd6eb8943a46007fed82e78cddea9e91 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 3 Mar 2015 11:46:24 +0100 Subject: [PATCH 271/360] fix compilation - define max_number_of_candidates where its used - add curly braces - reformat --- plugins/map_matching.hpp | 115 ++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 57 deletions(-) diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 3bf2026f8..a67a9e075 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -52,7 +52,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. template class MapMatchingPlugin : public BasePlugin { - private: + constexpr static const unsigned max_number_of_candidates = 10; + std::shared_ptr> search_engine_ptr; using ClassifierT = BayesClassifier; @@ -60,19 +61,19 @@ template class MapMatchingPlugin : public BasePlugin public: MapMatchingPlugin(DataFacadeT *facade, const int max_locations_map_matching) - : descriptor_string("match") - , facade(facade) - , max_locations_map_matching(max_locations_map_matching) - // the values where derived from fitting a laplace distribution - // to the values of manually classified traces - , classifier(LaplaceDistribution(0.0057154021891018675, 0.020294704891166186), - LaplaceDistribution(0.11467696742821254, 0.49918444000368756), - 0.7977883096366508) // valid apriori probability + : descriptor_string("match"), facade(facade), + max_locations_map_matching(max_locations_map_matching) + // the values where derived from fitting a laplace distribution + // to the values of manually classified traces + , + classifier(LaplaceDistribution(0.0057154021891018675, 0.020294704891166186), + LaplaceDistribution(0.11467696742821254, 0.49918444000368756), + 0.7977883096366508) // valid apriori probability { search_engine_ptr = std::make_shared>(facade); } - virtual ~MapMatchingPlugin() { } + virtual ~MapMatchingPlugin() {} const std::string GetDescriptor() const final { return descriptor_string; } @@ -86,7 +87,7 @@ template class MapMatchingPlugin : public BasePlugin return std::make_pair(ClassifierT::ClassLabel::NEGATIVE, 1.0); } - auto label_with_confidence = classifier.classify(distance_feature); + auto label_with_confidence = classifier.classify(distance_feature); // "second stage classifier": if we need to remove points there is something fishy if (removed_points > 0) @@ -97,11 +98,12 @@ template class MapMatchingPlugin : public BasePlugin return label_with_confidence; } - bool getCandiates(const std::vector& input_coords, std::vector& sub_trace_lengths, Matching::CandidateLists& candidates_lists) + bool getCandiates(const std::vector &input_coords, + std::vector &sub_trace_lengths, + Matching::CandidateLists &candidates_lists) { - double last_distance = coordinate_calculation::great_circle_distance( - input_coords[0], - input_coords[1]); + double last_distance = + coordinate_calculation::great_circle_distance(input_coords[0], input_coords[1]); sub_trace_lengths.resize(input_coords.size()); sub_trace_lengths[0] = 0; for (const auto current_coordinate : osrm::irange(0, input_coords.size())) @@ -110,17 +112,16 @@ template class MapMatchingPlugin : public BasePlugin if (0 < current_coordinate) { last_distance = coordinate_calculation::great_circle_distance( - input_coords[current_coordinate - 1], - input_coords[current_coordinate]); - sub_trace_lengths[current_coordinate] += sub_trace_lengths[current_coordinate-1] + last_distance; + input_coords[current_coordinate - 1], input_coords[current_coordinate]); + sub_trace_lengths[current_coordinate] += + sub_trace_lengths[current_coordinate - 1] + last_distance; } - if (input_coords.size()-1 > current_coordinate && 0 < current_coordinate) + if (input_coords.size() - 1 > current_coordinate && 0 < current_coordinate) { double turn_angle = ComputeAngle::OfThreeFixedPointCoordinates( - input_coords[current_coordinate-1], - input_coords[current_coordinate], - input_coords[current_coordinate+1]); + input_coords[current_coordinate - 1], input_coords[current_coordinate], + input_coords[current_coordinate + 1]); // sharp turns indicate a possible uturn if (turn_angle < 100.0 || turn_angle > 260.0) @@ -131,11 +132,8 @@ template class MapMatchingPlugin : public BasePlugin std::vector> candidates; if (!facade->IncrementalFindPhantomNodeForCoordinateWithMaxDistance( - input_coords[current_coordinate], - candidates, - last_distance/2.0, - 5, - Matching::max_number_of_candidates)) + input_coords[current_coordinate], candidates, last_distance / 2.0, 5, + max_number_of_candidates)) { return false; } @@ -150,8 +148,8 @@ template class MapMatchingPlugin : public BasePlugin for (const auto i : osrm::irange(0u, compact_size)) { // Split edge if it is bidirectional and append reverse direction to end of list - if (candidates[i].first.forward_node_id != SPECIAL_NODEID - && candidates[i].first.reverse_node_id != SPECIAL_NODEID) + if (candidates[i].first.forward_node_id != SPECIAL_NODEID && + candidates[i].first.reverse_node_id != SPECIAL_NODEID) { PhantomNode reverse_node(candidates[i].first); reverse_node.forward_node_id = SPECIAL_NODEID; @@ -162,27 +160,30 @@ template class MapMatchingPlugin : public BasePlugin } candidates_lists.push_back(candidates); } - } return true; } - osrm::json::Object submatchingToJSON(const Matching::SubMatching& sub, const RouteParameters& route_parameters, const InternalRouteResult& raw_route) + osrm::json::Object submatchingToJSON(const Matching::SubMatching &sub, + const RouteParameters &route_parameters, + const InternalRouteResult &raw_route) { osrm::json::Object subtrace; if (route_parameters.classify) + { subtrace.values["confidence"] = sub.confidence; + } if (route_parameters.geometry) { DescriptionFactory factory; FixedPointCoordinate current_coordinate; - factory.SetStartSegment( - raw_route.segment_end_coordinates.front().source_phantom, - raw_route.source_traversed_in_reverse.front()); - for (const auto i : osrm::irange(0, raw_route.unpacked_path_segments.size())) + factory.SetStartSegment(raw_route.segment_end_coordinates.front().source_phantom, + raw_route.source_traversed_in_reverse.front()); + for (const auto i : + osrm::irange(0, raw_route.unpacked_path_segments.size())) { for (const PathData &path_data : raw_route.unpacked_path_segments[i]) { @@ -193,24 +194,26 @@ template class MapMatchingPlugin : public BasePlugin raw_route.target_traversed_in_reverse[i], raw_route.is_via_leg(i)); } - subtrace.values["geometry"] = factory.AppendGeometryString(route_parameters.compression); + subtrace.values["geometry"] = + factory.AppendGeometryString(route_parameters.compression); } subtrace.values["indices"] = osrm::json::make_array(sub.indices); - osrm::json::Array points; - for (const auto& node : sub.nodes) + for (const auto &node : sub.nodes) { - points.values.emplace_back(osrm::json::make_array(node.location.lat / COORDINATE_PRECISION, - node.location.lon / COORDINATE_PRECISION)); + points.values.emplace_back( + osrm::json::make_array(node.location.lat / COORDINATE_PRECISION, + node.location.lon / COORDINATE_PRECISION)); } subtrace.values["matched_points"] = points; return subtrace; } - int HandleRequest(const RouteParameters &route_parameters, osrm::json::Object &json_result) final + int HandleRequest(const RouteParameters &route_parameters, + osrm::json::Object &json_result) final { // check number of parameters if (!check_all_coordinates(route_parameters.coordinates)) @@ -220,15 +223,16 @@ template class MapMatchingPlugin : public BasePlugin std::vector sub_trace_lengths; Matching::CandidateLists candidates_lists; - const auto& input_coords = route_parameters.coordinates; - const auto& input_timestamps = route_parameters.timestamps; + const auto &input_coords = route_parameters.coordinates; + const auto &input_timestamps = route_parameters.timestamps; if (input_timestamps.size() > 0 && input_coords.size() != input_timestamps.size()) { return 400; } // enforce maximum number of locations for performance reasons - if (max_locations_map_matching > 0 && static_cast(input_coords.size()) > max_locations_map_matching) + if (max_locations_map_matching > 0 && + static_cast(input_coords.size()) > max_locations_map_matching) { return 400; } @@ -245,12 +249,9 @@ template class MapMatchingPlugin : public BasePlugin // call the actual map matching Matching::SubMatchingList sub_matchings; - search_engine_ptr->map_matching(candidates_lists, - input_coords, - input_timestamps, + search_engine_ptr->map_matching(candidates_lists, input_coords, input_timestamps, route_parameters.matching_beta, - route_parameters.gps_precision, - sub_matchings); + route_parameters.gps_precision, sub_matchings); if (1 > sub_matchings.size()) { @@ -258,22 +259,23 @@ template class MapMatchingPlugin : public BasePlugin } osrm::json::Array matchings; - for (auto& sub : sub_matchings) + for (auto &sub : sub_matchings) { // classify result if (route_parameters.classify) { - double trace_length = sub_trace_lengths[sub.indices.back()] - sub_trace_lengths[sub.indices.front()]; - TraceClassification classification = classify(trace_length, - sub.length, - (sub.indices.back() - sub.indices.front() + 1) - sub.nodes.size()); + double trace_length = + sub_trace_lengths[sub.indices.back()] - sub_trace_lengths[sub.indices.front()]; + TraceClassification classification = + classify(trace_length, sub.length, + (sub.indices.back() - sub.indices.front() + 1) - sub.nodes.size()); if (classification.first == ClassifierT::ClassLabel::POSITIVE) { sub.confidence = classification.second; } else { - sub.confidence = 1-classification.second; + sub.confidence = 1 - classification.second; } } @@ -291,8 +293,7 @@ template class MapMatchingPlugin : public BasePlugin } search_engine_ptr->shortest_path( raw_route.segment_end_coordinates, - std::vector(raw_route.segment_end_coordinates.size(), true), - raw_route); + std::vector(raw_route.segment_end_coordinates.size(), true), raw_route); matchings.values.emplace_back(submatchingToJSON(sub, route_parameters, raw_route)); } From 76aa494be4d7d346d747b74895fa6ecbe75a4869 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 3 Mar 2015 11:48:15 +0100 Subject: [PATCH 272/360] fix compilation - std::log and M_PI are not constexpr's by the standard. replace by a constant - reformat --- routing_algorithms/map_matching.hpp | 95 +++++++++++++---------------- 1 file changed, 43 insertions(+), 52 deletions(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 5400a74d4..d5fb30e12 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -58,7 +58,6 @@ struct SubMatching using CandidateList = std::vector>; using CandidateLists = std::vector; using SubMatchingList = std::vector; -constexpr static const unsigned max_number_of_candidates = 10; constexpr static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits::infinity(); constexpr static const double MINIMAL_LOG_PROB = -std::numeric_limits::max(); constexpr static const unsigned INVALID_STATE = std::numeric_limits::max(); @@ -67,8 +66,8 @@ constexpr static const unsigned MAX_BROKEN_TIME = 30; } // implements a hidden markov model map matching algorithm -template class MapMatching final - : public BasicRoutingInterface> +template +class MapMatching final : public BasicRoutingInterface> { using super = BasicRoutingInterface>; using QueryHeap = SearchEngineData::QueryHeap; @@ -77,7 +76,7 @@ template class MapMatching final // FIXME this value should be a table based on samples/meter (or samples/min) constexpr static const double default_beta = 10.0; constexpr static const double default_sigma_z = 4.07; - constexpr static const double log_2_pi = std::log(2 * M_PI); + constexpr static const double log_2_pi = 1.837877066409346; // std::log(2. * M_PI); // closures to precompute log -> only simple floating point operations struct EmissionLogProbability @@ -86,8 +85,7 @@ template class MapMatching final double log_sigma_z; EmissionLogProbability(const double sigma_z) - : sigma_z(sigma_z) - , log_sigma_z(std::log(sigma_z)) + : sigma_z(sigma_z), log_sigma_z(std::log(sigma_z)) { } @@ -100,16 +98,9 @@ template class MapMatching final { double beta; double log_beta; - TransitionLogProbability(const double beta) - : beta(beta) - , log_beta(std::log(beta)) - { - } + TransitionLogProbability(const double beta) : beta(beta), log_beta(std::log(beta)) {} - double operator()(const double d_t) const - { - return -log_beta - d_t / beta; - } + double operator()(const double d_t) const { return -log_beta - d_t / beta; } }; double get_network_distance(const PhantomNode &source_phantom, @@ -159,13 +150,13 @@ template class MapMatching final { if (0 < forward_heap.Size()) { - super::RoutingStep( - forward_heap, reverse_heap, &middle_node, &upper_bound, edge_offset, true); + super::RoutingStep(forward_heap, reverse_heap, &middle_node, &upper_bound, + edge_offset, true); } if (0 < reverse_heap.Size()) { - super::RoutingStep( - reverse_heap, forward_heap, &middle_node, &upper_bound, edge_offset, false); + super::RoutingStep(reverse_heap, forward_heap, &middle_node, &upper_bound, + edge_offset, false); } } @@ -206,10 +197,12 @@ template class MapMatching final std::vector breakage; const Matching::CandidateLists &candidates_list; - const EmissionLogProbability& emission_log_probability; + const EmissionLogProbability &emission_log_probability; - HiddenMarkovModel(const Matching::CandidateLists &candidates_list, const EmissionLogProbability& emission_log_probability) - : breakage(candidates_list.size()), candidates_list(candidates_list), emission_log_probability(emission_log_probability) + HiddenMarkovModel(const Matching::CandidateLists &candidates_list, + const EmissionLogProbability &emission_log_probability) + : breakage(candidates_list.size()), candidates_list(candidates_list), + emission_log_probability(emission_log_probability) { for (const auto &l : candidates_list) { @@ -276,8 +269,7 @@ template class MapMatching final // Provides the debug interface for introspection tools struct DebugInfo { - DebugInfo(const osrm::json::Logger* logger) - : logger(logger) + DebugInfo(const osrm::json::Logger *logger) : logger(logger) { if (logger) { @@ -285,7 +277,7 @@ template class MapMatching final } } - void initialize(const Matching::CandidateLists& candidates_list) + void initialize(const Matching::CandidateLists &candidates_list) { // json logger not enabled if (!logger) @@ -302,7 +294,8 @@ template class MapMatching final state.values["coordinate"] = osrm::json::make_array( candidates_list[t][s].first.location.lat / COORDINATE_PRECISION, candidates_list[t][s].first.location.lon / COORDINATE_PRECISION); - state.values["viterbi"] = osrm::json::clamp_float(Matching::IMPOSSIBLE_LOG_PROB); + state.values["viterbi"] = + osrm::json::clamp_float(Matching::IMPOSSIBLE_LOG_PROB); state.values["pruned"] = 0u; timestamps.values.push_back(state); } @@ -327,21 +320,18 @@ template class MapMatching final osrm::json::Object transistion; transistion.values["to"] = osrm::json::make_array(current_t, current_state); - transistion.values["properties"] = - osrm::json::make_array(osrm::json::clamp_float(prev_viterbi), - osrm::json::clamp_float(emission_pr), - osrm::json::clamp_float(transition_pr), - network_distance, - great_circle_distance); + transistion.values["properties"] = osrm::json::make_array( + osrm::json::clamp_float(prev_viterbi), osrm::json::clamp_float(emission_pr), + osrm::json::clamp_float(transition_pr), network_distance, great_circle_distance); osrm::json::get(*object, "states", prev_t, prev_state, "transitions") .get>() - .get().values.push_back(transistion); - + .get() + .values.push_back(transistion); } - void set_viterbi(const std::vector>& viterbi, - const std::vector>& pruned) + void set_viterbi(const std::vector> &viterbi, + const std::vector> &pruned) { // json logger not enabled if (!logger) @@ -351,8 +341,10 @@ template class MapMatching final { for (auto s_prime = 0u; s_prime < viterbi[t].size(); ++s_prime) { - osrm::json::get(*object, "states", t, s_prime, "viterbi") = osrm::json::clamp_float(viterbi[t][s_prime]); - osrm::json::get(*object, "states", t, s_prime, "pruned") = static_cast(pruned[t][s_prime]); + osrm::json::get(*object, "states", t, s_prime, "viterbi") = + osrm::json::clamp_float(viterbi[t][s_prime]); + osrm::json::get(*object, "states", t, s_prime, "pruned") = + static_cast(pruned[t][s_prime]); } } } @@ -366,7 +358,7 @@ template class MapMatching final osrm::json::get(*object, "states", t, s, "chosen") = true; } - void add_breakage(const std::vector& breakage) + void add_breakage(const std::vector &breakage) { // json logger not enabled if (!logger) @@ -375,8 +367,8 @@ template class MapMatching final osrm::json::get(*object, "breakage") = osrm::json::make_array(breakage); } - const osrm::json::Logger* logger; - osrm::json::Value* object; + const osrm::json::Logger *logger; + osrm::json::Value *object; }; public: @@ -395,8 +387,10 @@ template class MapMatching final BOOST_ASSERT(candidates_list.size() > 0); // TODO replace default values with table lookup based on sampling frequency - EmissionLogProbability emission_log_probability(gps_precision > 0 ? gps_precision : default_sigma_z); - TransitionLogProbability transition_log_probability(matching_beta > 0 ? matching_beta : default_beta); + EmissionLogProbability emission_log_probability(gps_precision > 0 ? gps_precision + : default_sigma_z); + TransitionLogProbability transition_log_probability(matching_beta > 0 ? matching_beta + : default_beta); HiddenMarkovModel model(candidates_list, emission_log_probability); @@ -429,8 +423,8 @@ template class MapMatching final } else { - trace_split = trace_split || (t - prev_unbroken_timestamps.back() > - Matching::MAX_BROKEN_STATES); + trace_split = trace_split || + (t - prev_unbroken_timestamps.back() > Matching::MAX_BROKEN_STATES); } if (trace_split) @@ -456,7 +450,7 @@ template class MapMatching final // Important: We potentially go back here! // However since t > new_start >= breakge_begin // we can only reset trace_coordindates.size() times. - t = new_start+1; + t = new_start + 1; } unsigned prev_unbroken_timestamp = prev_unbroken_timestamps.back(); @@ -506,11 +500,8 @@ template class MapMatching final new_value += transition_pr; debug.add_transition_info(prev_unbroken_timestamp, t, s, s_prime, - prev_viterbi[s], - emission_pr, - transition_pr, - network_distance, - great_circle_distance); + prev_viterbi[s], emission_pr, transition_pr, + network_distance, great_circle_distance); if (new_value > current_viterbi[s_prime]) { @@ -622,6 +613,6 @@ template class MapMatching final }; //[1] "Hidden Markov Map Matching Through Noise and Sparseness"; P. Newson and J. Krumm; 2009; ACM -//GIS +// GIS #endif /* MAP_MATCHING_HPP */ From 20091e94c8a7748306d82fd2907ea8e2aef212eb Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 3 Mar 2015 11:50:02 +0100 Subject: [PATCH 273/360] fix compilation - remove wrong comments - fix include guard footer - add curly braces - add template specialization for std::vector in make_array - reformat --- util/json_util.hpp | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/util/json_util.hpp b/util/json_util.hpp index 563440d19..013ada408 100644 --- a/util/json_util.hpp +++ b/util/json_util.hpp @@ -25,9 +25,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// based on -// https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp - #ifndef JSON_UTIL_HPP #define JSON_UTIL_HPP @@ -71,26 +68,39 @@ template osrm::json::Array make_array(Args... args) return a; } -template osrm::json::Array make_array(const std::vector& vector) +template osrm::json::Array make_array(const std::vector &vector) { osrm::json::Array a; - for (const auto& v : vector) + for (const auto &v : vector) + { a.values.emplace_back(v); + } + return a; +} + +// template specialization needed as clang does not play nice +template <> osrm::json::Array make_array(const std::vector &vector) +{ + osrm::json::Array a; + for (const bool v : vector) + { + a.values.emplace_back(v); + } return a; } // Easy acces to object hierachies -osrm::json::Value& get(osrm::json::Value& value) { return value; } +osrm::json::Value &get(osrm::json::Value &value) { return value; } -template -osrm::json::Value& get(osrm::json::Value& value, const char* key, Keys... keys) +template +osrm::json::Value &get(osrm::json::Value &value, const char *key, Keys... keys) { using recursive_object_t = mapbox::util::recursive_wrapper; return get(value.get().get().values[key], keys...); } -template -osrm::json::Value& get(osrm::json::Value& value, unsigned key, Keys... keys) +template +osrm::json::Value &get(osrm::json::Value &value, unsigned key, Keys... keys) { using recursive_array_t = mapbox::util::recursive_wrapper; return get(value.get().get().values[key], keys...); @@ -98,4 +108,4 @@ osrm::json::Value& get(osrm::json::Value& value, unsigned key, Keys... keys) } // namespace json } // namespace osrm -#endif // JSON_RENDERER_HPP +#endif // JSON_UTIL_HPP From 91792f45ea527398375bc1f9afacfbf6448040a8 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 3 Mar 2015 11:50:37 +0100 Subject: [PATCH 274/360] fix compilation - missing new 10th parameter to GenerateServerProgramOptions --- tools/simpleclient.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/simpleclient.cpp b/tools/simpleclient.cpp index 40407ced2..ce590ccd8 100644 --- a/tools/simpleclient.cpp +++ b/tools/simpleclient.cpp @@ -43,12 +43,13 @@ int main(int argc, const char *argv[]) try { std::string ip_address; - int ip_port, requested_thread_num; + int ip_port, requested_thread_num, max_locations_map_matching; bool trial_run = false; libosrm_config lib_config; const unsigned init_result = GenerateServerProgramOptions( argc, argv, lib_config.server_paths, ip_address, ip_port, requested_thread_num, - lib_config.use_shared_memory, trial_run, lib_config.max_locations_distance_table); + lib_config.use_shared_memory, trial_run, lib_config.max_locations_distance_table, + max_locations_map_matching); if (init_result == INIT_OK_DO_NOT_START_ENGINE) { From 4df215e67413ec07eafa0ca8adea1eb70c107968 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 3 Mar 2015 11:53:31 +0100 Subject: [PATCH 275/360] replace -std::numeric_limits::max() with ::lowest() --- util/json_util.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/json_util.hpp b/util/json_util.hpp index 013ada408..461148ea3 100644 --- a/util/json_util.hpp +++ b/util/json_util.hpp @@ -47,7 +47,7 @@ template T clamp_float(T d) } if (-std::numeric_limits::infinity() == d) { - return -std::numeric_limits::max(); + return std::numeric_limits::lowest(); } return d; From 592bebaf294446069a2cafe03d67dd45c7cea3e0 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 3 Mar 2015 12:01:40 +0100 Subject: [PATCH 276/360] renamed: plugins/map_matching.hpp -> plugins/match.hpp to avoid confusion with routing_algorithms/map_matching.hpp --- library/osrm_impl.cpp | 2 +- plugins/{map_matching.hpp => match.hpp} | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename plugins/{map_matching.hpp => match.hpp} (99%) diff --git a/library/osrm_impl.cpp b/library/osrm_impl.cpp index f12445f2f..5bb58d174 100644 --- a/library/osrm_impl.cpp +++ b/library/osrm_impl.cpp @@ -42,7 +42,7 @@ class named_mutex; #include "../plugins/nearest.hpp" #include "../plugins/timestamp.hpp" #include "../plugins/viaroute.hpp" -#include "../plugins/map_matching.hpp" +#include "../plugins/match.hpp" #include "../server/data_structures/datafacade_base.hpp" #include "../server/data_structures/internal_datafacade.hpp" #include "../server/data_structures/shared_barriers.hpp" diff --git a/plugins/map_matching.hpp b/plugins/match.hpp similarity index 99% rename from plugins/map_matching.hpp rename to plugins/match.hpp index a67a9e075..b67a4f344 100644 --- a/plugins/map_matching.hpp +++ b/plugins/match.hpp @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef MAP_MATCHING_PLUGIN_HPP -#define MAP_MATCHING_PLUGIN_HPP +#ifndef MATCH_HPP +#define MATCH_HPP #include "plugin_base.hpp" @@ -312,4 +312,4 @@ template class MapMatchingPlugin : public BasePlugin ClassifierT classifier; }; -#endif /* MAP_MATCHING_HPP */ +#endif // MATCH_HPP From a9c3b343fc25708f57d7b8542f2448662efa6857 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 3 Mar 2015 12:48:33 +0100 Subject: [PATCH 277/360] separate model and computation in HMM matching --- data_structures/hidden_markov_model.hpp | 154 ++++++++++++++ plugins/match.hpp | 8 +- routing_algorithms/map_matching.hpp | 270 +++--------------------- util/matching_debug_info.hpp | 152 +++++++++++++ 4 files changed, 342 insertions(+), 242 deletions(-) create mode 100644 data_structures/hidden_markov_model.hpp create mode 100644 util/matching_debug_info.hpp diff --git a/data_structures/hidden_markov_model.hpp b/data_structures/hidden_markov_model.hpp new file mode 100644 index 000000000..affaf3013 --- /dev/null +++ b/data_structures/hidden_markov_model.hpp @@ -0,0 +1,154 @@ +/* + +Copyright (c) 2015, Project OSRM contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef HIDDEN_MARKOV_MODEL +#define HIDDEN_MARKOV_MODEL + +#include + +#include + +#include +#include + +namespace osrm +{ +namespace matching +{ +// FIXME this value should be a table based on samples/meter (or samples/min) +constexpr static const double log_2_pi = 1.837877066409346; // std::log(2. * M_PI); + +constexpr static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits::infinity(); +constexpr static const double MINIMAL_LOG_PROB = std::numeric_limits::lowest(); +constexpr static const unsigned INVALID_STATE = std::numeric_limits::max(); +} // namespace matching +} // namespace osrm + +// closures to precompute log -> only simple floating point operations +struct EmissionLogProbability +{ + double sigma_z; + double log_sigma_z; + + EmissionLogProbability(const double sigma_z) : sigma_z(sigma_z), log_sigma_z(std::log(sigma_z)) + { + } + + double operator()(const double distance) const + { + return -0.5 * (osrm::matching::log_2_pi + (distance / sigma_z) * (distance / sigma_z)) - + log_sigma_z; + } +}; + +struct TransitionLogProbability +{ + double beta; + double log_beta; + TransitionLogProbability(const double beta) : beta(beta), log_beta(std::log(beta)) {} + + double operator()(const double d_t) const { return -log_beta - d_t / beta; } +}; + +template struct HiddenMarkovModel +{ + std::vector> viterbi; + std::vector>> parents; + std::vector> path_lengths; + std::vector> pruned; + std::vector breakage; + + const CandidateLists &candidates_list; + const EmissionLogProbability &emission_log_probability; + + HiddenMarkovModel(const CandidateLists &candidates_list, + const EmissionLogProbability &emission_log_probability) + : breakage(candidates_list.size()), candidates_list(candidates_list), + emission_log_probability(emission_log_probability) + { + for (const auto &l : candidates_list) + { + viterbi.emplace_back(l.size()); + parents.emplace_back(l.size()); + path_lengths.emplace_back(l.size()); + pruned.emplace_back(l.size()); + } + + clear(0); + } + + void clear(unsigned initial_timestamp) + { + BOOST_ASSERT(viterbi.size() == parents.size() && parents.size() == path_lengths.size() && + path_lengths.size() == pruned.size() && pruned.size() == breakage.size()); + + for (unsigned t = initial_timestamp; t < viterbi.size(); t++) + { + std::fill(viterbi[t].begin(), viterbi[t].end(), osrm::matching::IMPOSSIBLE_LOG_PROB); + std::fill(parents[t].begin(), parents[t].end(), std::make_pair(0u, 0u)); + std::fill(path_lengths[t].begin(), path_lengths[t].end(), 0); + std::fill(pruned[t].begin(), pruned[t].end(), true); + } + std::fill(breakage.begin() + initial_timestamp, breakage.end(), true); + } + + unsigned initialize(unsigned initial_timestamp) + { + BOOST_ASSERT(initial_timestamp < candidates_list.size()); + + do + { + for (auto s = 0u; s < viterbi[initial_timestamp].size(); ++s) + { + viterbi[initial_timestamp][s] = + emission_log_probability(candidates_list[initial_timestamp][s].second); + parents[initial_timestamp][s] = std::make_pair(initial_timestamp, s); + pruned[initial_timestamp][s] = + viterbi[initial_timestamp][s] < osrm::matching::MINIMAL_LOG_PROB; + + breakage[initial_timestamp] = + breakage[initial_timestamp] && pruned[initial_timestamp][s]; + } + + ++initial_timestamp; + } while (breakage[initial_timestamp - 1]); + + if (initial_timestamp >= viterbi.size()) + { + return osrm::matching::INVALID_STATE; + } + + BOOST_ASSERT(initial_timestamp > 0); + --initial_timestamp; + + BOOST_ASSERT(breakage[initial_timestamp] == false); + + return initial_timestamp; + } +}; + +#endif // HIDDEN_MARKOV_MODEL diff --git a/plugins/match.hpp b/plugins/match.hpp index b67a4f344..88454eeb9 100644 --- a/plugins/match.hpp +++ b/plugins/match.hpp @@ -100,7 +100,7 @@ template class MapMatchingPlugin : public BasePlugin bool getCandiates(const std::vector &input_coords, std::vector &sub_trace_lengths, - Matching::CandidateLists &candidates_lists) + osrm::matching::CandidateLists &candidates_lists) { double last_distance = coordinate_calculation::great_circle_distance(input_coords[0], input_coords[1]); @@ -165,7 +165,7 @@ template class MapMatchingPlugin : public BasePlugin return true; } - osrm::json::Object submatchingToJSON(const Matching::SubMatching &sub, + osrm::json::Object submatchingToJSON(const osrm::matching::SubMatching &sub, const RouteParameters &route_parameters, const InternalRouteResult &raw_route) { @@ -222,7 +222,7 @@ template class MapMatchingPlugin : public BasePlugin } std::vector sub_trace_lengths; - Matching::CandidateLists candidates_lists; + osrm::matching::CandidateLists candidates_lists; const auto &input_coords = route_parameters.coordinates; const auto &input_timestamps = route_parameters.timestamps; if (input_timestamps.size() > 0 && input_coords.size() != input_timestamps.size()) @@ -248,7 +248,7 @@ template class MapMatchingPlugin : public BasePlugin osrm::json::Logger::get()->initialize("matching"); // call the actual map matching - Matching::SubMatchingList sub_matchings; + osrm::matching::SubMatchingList sub_matchings; search_engine_ptr->map_matching(candidates_lists, input_coords, input_timestamps, route_parameters.matching_beta, route_parameters.gps_precision, sub_matchings); diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index d5fb30e12..2000242d3 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -31,6 +31,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "routing_base.hpp" #include "../data_structures/coordinate_calculation.hpp" +#include "../data_structures/hidden_markov_model.hpp" +#include "../util/matching_debug_info.hpp" #include "../util/simple_logger.hpp" #include "../util/json_util.hpp" #include "../util/json_logger.hpp" @@ -44,7 +46,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -namespace Matching +namespace osrm +{ +namespace matching { struct SubMatching @@ -57,12 +61,15 @@ struct SubMatching using CandidateList = std::vector>; using CandidateLists = std::vector; +using HMM = HiddenMarkovModel; using SubMatchingList = std::vector; -constexpr static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits::infinity(); -constexpr static const double MINIMAL_LOG_PROB = -std::numeric_limits::max(); -constexpr static const unsigned INVALID_STATE = std::numeric_limits::max(); + constexpr static const unsigned MAX_BROKEN_STATES = 6; constexpr static const unsigned MAX_BROKEN_TIME = 30; + +constexpr static const double default_beta = 10.0; +constexpr static const double default_sigma_z = 4.07; +} } // implements a hidden markov model map matching algorithm @@ -73,36 +80,6 @@ class MapMatching final : public BasicRoutingInterface only simple floating point operations - struct EmissionLogProbability - { - double sigma_z; - double log_sigma_z; - - EmissionLogProbability(const double sigma_z) - : sigma_z(sigma_z), log_sigma_z(std::log(sigma_z)) - { - } - - double operator()(const double distance) const - { - return -0.5 * (log_2_pi + (distance / sigma_z) * (distance / sigma_z)) - log_sigma_z; - } - }; - struct TransitionLogProbability - { - double beta; - double log_beta; - TransitionLogProbability(const double beta) : beta(beta), log_beta(std::log(beta)) {} - - double operator()(const double d_t) const { return -log_beta - d_t / beta; } - }; - double get_network_distance(const PhantomNode &source_phantom, const PhantomNode &target_phantom) const { @@ -188,220 +165,37 @@ class MapMatching final : public BasicRoutingInterface> viterbi; - std::vector>> parents; - std::vector> path_lengths; - std::vector> pruned; - std::vector breakage; - - const Matching::CandidateLists &candidates_list; - const EmissionLogProbability &emission_log_probability; - - HiddenMarkovModel(const Matching::CandidateLists &candidates_list, - const EmissionLogProbability &emission_log_probability) - : breakage(candidates_list.size()), candidates_list(candidates_list), - emission_log_probability(emission_log_probability) - { - for (const auto &l : candidates_list) - { - viterbi.emplace_back(l.size()); - parents.emplace_back(l.size()); - path_lengths.emplace_back(l.size()); - pruned.emplace_back(l.size()); - } - - clear(0); - } - - void clear(unsigned initial_timestamp) - { - BOOST_ASSERT(viterbi.size() == parents.size() && - parents.size() == path_lengths.size() && - path_lengths.size() == pruned.size() && pruned.size() == breakage.size()); - - for (unsigned t = initial_timestamp; t < viterbi.size(); t++) - { - std::fill(viterbi[t].begin(), viterbi[t].end(), Matching::IMPOSSIBLE_LOG_PROB); - std::fill(parents[t].begin(), parents[t].end(), std::make_pair(0u, 0u)); - std::fill(path_lengths[t].begin(), path_lengths[t].end(), 0); - std::fill(pruned[t].begin(), pruned[t].end(), true); - } - std::fill(breakage.begin() + initial_timestamp, breakage.end(), true); - } - - unsigned initialize(unsigned initial_timestamp) - { - BOOST_ASSERT(initial_timestamp < candidates_list.size()); - - do - { - for (auto s = 0u; s < viterbi[initial_timestamp].size(); ++s) - { - viterbi[initial_timestamp][s] = - emission_log_probability(candidates_list[initial_timestamp][s].second); - parents[initial_timestamp][s] = std::make_pair(initial_timestamp, s); - pruned[initial_timestamp][s] = - viterbi[initial_timestamp][s] < Matching::MINIMAL_LOG_PROB; - - breakage[initial_timestamp] = - breakage[initial_timestamp] && pruned[initial_timestamp][s]; - } - - ++initial_timestamp; - } while (breakage[initial_timestamp - 1]); - - if (initial_timestamp >= viterbi.size()) - { - return Matching::INVALID_STATE; - } - - BOOST_ASSERT(initial_timestamp > 0); - --initial_timestamp; - - BOOST_ASSERT(breakage[initial_timestamp] == false); - - return initial_timestamp; - } - }; - - // Provides the debug interface for introspection tools - struct DebugInfo - { - DebugInfo(const osrm::json::Logger *logger) : logger(logger) - { - if (logger) - { - object = &logger->map->at("matching"); - } - } - - void initialize(const Matching::CandidateLists &candidates_list) - { - // json logger not enabled - if (!logger) - return; - - osrm::json::Array states; - for (unsigned t = 0; t < candidates_list.size(); t++) - { - osrm::json::Array timestamps; - for (unsigned s = 0; s < candidates_list[t].size(); s++) - { - osrm::json::Object state; - state.values["transitions"] = osrm::json::Array(); - state.values["coordinate"] = osrm::json::make_array( - candidates_list[t][s].first.location.lat / COORDINATE_PRECISION, - candidates_list[t][s].first.location.lon / COORDINATE_PRECISION); - state.values["viterbi"] = - osrm::json::clamp_float(Matching::IMPOSSIBLE_LOG_PROB); - state.values["pruned"] = 0u; - timestamps.values.push_back(state); - } - states.values.push_back(timestamps); - } - osrm::json::get(*object, "states") = states; - } - - void add_transition_info(const unsigned prev_t, - const unsigned current_t, - const unsigned prev_state, - const unsigned current_state, - const double prev_viterbi, - const double emission_pr, - const double transition_pr, - const double network_distance, - const double great_circle_distance) - { - // json logger not enabled - if (!logger) - return; - - osrm::json::Object transistion; - transistion.values["to"] = osrm::json::make_array(current_t, current_state); - transistion.values["properties"] = osrm::json::make_array( - osrm::json::clamp_float(prev_viterbi), osrm::json::clamp_float(emission_pr), - osrm::json::clamp_float(transition_pr), network_distance, great_circle_distance); - - osrm::json::get(*object, "states", prev_t, prev_state, "transitions") - .get>() - .get() - .values.push_back(transistion); - } - - void set_viterbi(const std::vector> &viterbi, - const std::vector> &pruned) - { - // json logger not enabled - if (!logger) - return; - - for (auto t = 0u; t < viterbi.size(); t++) - { - for (auto s_prime = 0u; s_prime < viterbi[t].size(); ++s_prime) - { - osrm::json::get(*object, "states", t, s_prime, "viterbi") = - osrm::json::clamp_float(viterbi[t][s_prime]); - osrm::json::get(*object, "states", t, s_prime, "pruned") = - static_cast(pruned[t][s_prime]); - } - } - } - - void add_chosen(const unsigned t, const unsigned s) - { - // json logger not enabled - if (!logger) - return; - - osrm::json::get(*object, "states", t, s, "chosen") = true; - } - - void add_breakage(const std::vector &breakage) - { - // json logger not enabled - if (!logger) - return; - - osrm::json::get(*object, "breakage") = osrm::json::make_array(breakage); - } - - const osrm::json::Logger *logger; - osrm::json::Value *object; - }; - public: MapMatching(DataFacadeT *facade, SearchEngineData &engine_working_data) : super(facade), engine_working_data(engine_working_data) { } - void operator()(const Matching::CandidateLists &candidates_list, + void operator()(const osrm::matching::CandidateLists &candidates_list, const std::vector &trace_coordinates, const std::vector &trace_timestamps, const double matching_beta, const double gps_precision, - Matching::SubMatchingList &sub_matchings) const + osrm::matching::SubMatchingList &sub_matchings) const { BOOST_ASSERT(candidates_list.size() > 0); // TODO replace default values with table lookup based on sampling frequency - EmissionLogProbability emission_log_probability(gps_precision > 0 ? gps_precision - : default_sigma_z); - TransitionLogProbability transition_log_probability(matching_beta > 0 ? matching_beta - : default_beta); + EmissionLogProbability emission_log_probability( + gps_precision > 0 ? gps_precision : osrm::matching::default_sigma_z); + TransitionLogProbability transition_log_probability( + matching_beta > 0 ? matching_beta : osrm::matching::default_beta); - HiddenMarkovModel model(candidates_list, emission_log_probability); + osrm::matching::HMM model(candidates_list, emission_log_probability); unsigned initial_timestamp = model.initialize(0); - if (initial_timestamp == Matching::INVALID_STATE) + if (initial_timestamp == osrm::matching::INVALID_STATE) { return; } - DebugInfo debug(osrm::json::Logger::get()); - debug.initialize(candidates_list); + MatchingDebugInfo matching_debug(osrm::json::Logger::get()); + matching_debug.initialize(candidates_list); unsigned breakage_begin = std::numeric_limits::max(); std::vector split_points; @@ -419,12 +213,12 @@ class MapMatching final : public BasicRoutingInterface - Matching::MAX_BROKEN_TIME); + osrm::matching::MAX_BROKEN_TIME); } else { - trace_split = trace_split || - (t - prev_unbroken_timestamps.back() > Matching::MAX_BROKEN_STATES); + trace_split = trace_split || (t - prev_unbroken_timestamps.back() > + osrm::matching::MAX_BROKEN_STATES); } if (trace_split) @@ -441,7 +235,7 @@ class MapMatching final : public BasicRoutingInterface stop viterbi calculation - if (new_start == Matching::INVALID_STATE) + if (new_start == osrm::matching::INVALID_STATE) { break; } @@ -499,9 +293,9 @@ class MapMatching final : public BasicRoutingInterface current_viterbi[s_prime]) { @@ -533,7 +327,7 @@ class MapMatching final : public BasicRoutingInterface 0) { @@ -543,7 +337,7 @@ class MapMatching final : public BasicRoutingInterface + +// Provides the debug interface for introspection tools +struct MatchingDebugInfo +{ + MatchingDebugInfo(const osrm::json::Logger *logger) : logger(logger) + { + if (logger) + { + object = &logger->map->at("matching"); + } + } + + template void initialize(const CandidateLists &candidates_list) + { + // json logger not enabled + if (!logger) + { + return; + } + + osrm::json::Array states; + for (unsigned t = 0; t < candidates_list.size(); t++) + { + osrm::json::Array timestamps; + for (unsigned s = 0; s < candidates_list[t].size(); s++) + { + osrm::json::Object state; + state.values["transitions"] = osrm::json::Array(); + state.values["coordinate"] = osrm::json::make_array( + candidates_list[t][s].first.location.lat / COORDINATE_PRECISION, + candidates_list[t][s].first.location.lon / COORDINATE_PRECISION); + state.values["viterbi"] = + osrm::json::clamp_float(osrm::matching::IMPOSSIBLE_LOG_PROB); + state.values["pruned"] = 0u; + timestamps.values.push_back(state); + } + states.values.push_back(timestamps); + } + osrm::json::get(*object, "states") = states; + } + + void add_transition_info(const unsigned prev_t, + const unsigned current_t, + const unsigned prev_state, + const unsigned current_state, + const double prev_viterbi, + const double emission_pr, + const double transition_pr, + const double network_distance, + const double great_circle_distance) + { + // json logger not enabled + if (!logger) + { + return; + } + + osrm::json::Object transistion; + transistion.values["to"] = osrm::json::make_array(current_t, current_state); + transistion.values["properties"] = osrm::json::make_array( + osrm::json::clamp_float(prev_viterbi), osrm::json::clamp_float(emission_pr), + osrm::json::clamp_float(transition_pr), network_distance, great_circle_distance); + + osrm::json::get(*object, "states", prev_t, prev_state, "transitions") + .get>() + .get() + .values.push_back(transistion); + } + + void set_viterbi(const std::vector> &viterbi, + const std::vector> &pruned) + { + // json logger not enabled + if (!logger) + { + return; + } + + for (auto t = 0u; t < viterbi.size(); t++) + { + for (auto s_prime = 0u; s_prime < viterbi[t].size(); ++s_prime) + { + osrm::json::get(*object, "states", t, s_prime, "viterbi") = + osrm::json::clamp_float(viterbi[t][s_prime]); + osrm::json::get(*object, "states", t, s_prime, "pruned") = + static_cast(pruned[t][s_prime]); + } + } + } + + void add_chosen(const unsigned t, const unsigned s) + { + // json logger not enabled + if (!logger) + { + return; + } + + osrm::json::get(*object, "states", t, s, "chosen") = true; + } + + void add_breakage(const std::vector &breakage) + { + // json logger not enabled + if (!logger) + { + return; + } + + osrm::json::get(*object, "breakage") = osrm::json::make_array(breakage); + } + + const osrm::json::Logger *logger; + osrm::json::Value *object; +}; + +#endif // MATCHING_DEBUG_INFO_HPP From 643ab92cd2f23dbeb266cd11b911fc1847f35851 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 3 Mar 2015 12:55:42 +0100 Subject: [PATCH 278/360] fix default value for max_locations_map_matching --- util/routed_options.hpp | 60 +++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/util/routed_options.hpp b/util/routed_options.hpp index 0aef32147..046ab71b3 100644 --- a/util/routed_options.hpp +++ b/util/routed_options.hpp @@ -166,35 +166,37 @@ inline unsigned GenerateServerProgramOptions(const int argc, // declare a group of options that will be allowed both on command line // as well as in a config file boost::program_options::options_description config_options("Configuration"); - config_options.add_options() - ("hsgrdata", boost::program_options::value(&paths["hsgrdata"]), - ".hsgr file") - ("nodesdata", boost::program_options::value(&paths["nodesdata"]), - ".nodes file") - ("edgesdata", boost::program_options::value(&paths["edgesdata"]), - ".edges file") - ("geometry", boost::program_options::value(&paths["geometries"]), - ".geometry file") - ("ramindex", boost::program_options::value(&paths["ramindex"]), - ".ramIndex file") - ("fileindex", boost::program_options::value(&paths["fileindex"]), - "File index file") - ("namesdata", boost::program_options::value(&paths["namesdata"]), - ".names file") - ("timestamp", boost::program_options::value(&paths["timestamp"]), - ".timestamp file") - ("ip,i", boost::program_options::value(&ip_address)->default_value("0.0.0.0"), - "IP address") - ("port,p", boost::program_options::value(&ip_port)->default_value(5000), - "TCP/IP port") - ("threads,t", boost::program_options::value(&requested_num_threads)->default_value(8), - "Number of threads to use") - ("shared-memory,s", boost::program_options::value(&use_shared_memory)->implicit_value(true), - "Load data from shared memory") - ("max-table-size,m", boost::program_options::value(&max_locations_distance_table)->default_value(100), - "Max. locations supported in distance table query") - ("max-matching-size,m", boost::program_options::value(&max_locations_map_matching)->default_value(-1), - "Max. locations supported in map matching query"); + config_options.add_options()( + "hsgrdata", boost::program_options::value(&paths["hsgrdata"]), + ".hsgr file")("nodesdata", + boost::program_options::value(&paths["nodesdata"]), + ".nodes file")( + "edgesdata", boost::program_options::value(&paths["edgesdata"]), + ".edges file")("geometry", + boost::program_options::value(&paths["geometries"]), + ".geometry file")( + "ramindex", boost::program_options::value(&paths["ramindex"]), + ".ramIndex file")( + "fileindex", boost::program_options::value(&paths["fileindex"]), + "File index file")( + "namesdata", boost::program_options::value(&paths["namesdata"]), + ".names file")("timestamp", + boost::program_options::value(&paths["timestamp"]), + ".timestamp file")( + "ip,i", boost::program_options::value(&ip_address)->default_value("0.0.0.0"), + "IP address")("port,p", boost::program_options::value(&ip_port)->default_value(5000), + "TCP/IP port")( + "threads,t", boost::program_options::value(&requested_num_threads)->default_value(8), + "Number of threads to use")( + "shared-memory,s", + boost::program_options::value(&use_shared_memory)->implicit_value(true), + "Load data from shared memory")( + "max-table-size,m", + boost::program_options::value(&max_locations_distance_table)->default_value(100), + "Max. locations supported in distance table query")( + "max-matching-size,m", + boost::program_options::value(&max_locations_map_matching)->default_value(2), + "Max. locations supported in map matching query"); // hidden options, will be allowed both on command line and in config // file, but will not be shown to the user From 402ca780bf8115b1274bc50fec4c1639519ca305 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 3 Mar 2015 12:56:37 +0100 Subject: [PATCH 279/360] fix test expectation osrm-routed help output --- features/options/routed/help.feature | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/features/options/routed/help.feature b/features/options/routed/help.feature index 4b89dcb24..c0fca4717 100644 --- a/features/options/routed/help.feature +++ b/features/options/routed/help.feature @@ -26,7 +26,8 @@ Feature: osrm-routed command line options: help And stdout should contain "--threads" And stdout should contain "--shared-memory" And stdout should contain "--max-table-size" - And stdout should contain 24 lines + And stdout should contain "--max-matching-size" + And stdout should contain 26 lines And it should exit with code 0 Scenario: osrm-routed - Help, short @@ -51,7 +52,8 @@ Feature: osrm-routed command line options: help And stdout should contain "--threads" And stdout should contain "--shared-memory" And stdout should contain "--max-table-size" - And stdout should contain 24 lines + And stdout should contain "--max-matching-size" + And stdout should contain 26 lines And it should exit with code 0 Scenario: osrm-routed - Help, long @@ -76,5 +78,6 @@ Feature: osrm-routed command line options: help And stdout should contain "--threads" And stdout should contain "--shared-memory" And stdout should contain "--max-table-size" - And stdout should contain 24 lines + And stdout should contain "--max-matching-size" + And stdout should contain 26 lines And it should exit with code 0 From 6460fdc62b5409cd867500e552050617da3c896d Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 3 Mar 2015 13:03:00 +0100 Subject: [PATCH 280/360] use std::size_t for timestamps to avoid implicit casts, use range-based for loops --- data_structures/hidden_markov_model.hpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/data_structures/hidden_markov_model.hpp b/data_structures/hidden_markov_model.hpp index affaf3013..db58d96a0 100644 --- a/data_structures/hidden_markov_model.hpp +++ b/data_structures/hidden_markov_model.hpp @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef HIDDEN_MARKOV_MODEL #define HIDDEN_MARKOV_MODEL +#include "../util/integer_range.hpp" + #include #include @@ -44,7 +46,7 @@ constexpr static const double log_2_pi = 1.837877066409346; // std::log(2. * M_P constexpr static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits::infinity(); constexpr static const double MINIMAL_LOG_PROB = std::numeric_limits::lowest(); -constexpr static const unsigned INVALID_STATE = std::numeric_limits::max(); +constexpr static const std::size_t INVALID_STATE = std::numeric_limits::max(); } // namespace matching } // namespace osrm @@ -101,12 +103,12 @@ template struct HiddenMarkovModel clear(0); } - void clear(unsigned initial_timestamp) + void clear(std::size_t initial_timestamp) { BOOST_ASSERT(viterbi.size() == parents.size() && parents.size() == path_lengths.size() && path_lengths.size() == pruned.size() && pruned.size() == breakage.size()); - for (unsigned t = initial_timestamp; t < viterbi.size(); t++) + for (const auto t : osrm::irange(initial_timestamp, viterbi.size())) { std::fill(viterbi[t].begin(), viterbi[t].end(), osrm::matching::IMPOSSIBLE_LOG_PROB); std::fill(parents[t].begin(), parents[t].end(), std::make_pair(0u, 0u)); @@ -116,13 +118,13 @@ template struct HiddenMarkovModel std::fill(breakage.begin() + initial_timestamp, breakage.end(), true); } - unsigned initialize(unsigned initial_timestamp) + std::size_t initialize(std::size_t initial_timestamp) { BOOST_ASSERT(initial_timestamp < candidates_list.size()); do { - for (auto s = 0u; s < viterbi[initial_timestamp].size(); ++s) + for (const auto s : osrm::irange(0u, viterbi[initial_timestamp].size())) { viterbi[initial_timestamp][s] = emission_log_probability(candidates_list[initial_timestamp][s].second); From 5af0ceb2d29073ce2a941023390c1bfb433c4042 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 3 Mar 2015 14:22:27 +0100 Subject: [PATCH 281/360] use range based for loop --- data_structures/hidden_markov_model.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/hidden_markov_model.hpp b/data_structures/hidden_markov_model.hpp index db58d96a0..047c5bb3c 100644 --- a/data_structures/hidden_markov_model.hpp +++ b/data_structures/hidden_markov_model.hpp @@ -124,7 +124,7 @@ template struct HiddenMarkovModel do { - for (const auto s : osrm::irange(0u, viterbi[initial_timestamp].size())) + for (const auto s : osrm::irange(0u, viterbi[initial_timestamp].size())) { viterbi[initial_timestamp][s] = emission_log_probability(candidates_list[initial_timestamp][s].second); From e02c721c2b5fec7ad3e6ff43e26603a2eb00cdd9 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 3 Mar 2015 14:22:52 +0100 Subject: [PATCH 282/360] further untangle model from functionality and put classes into seperate headers - move get_network_distance() into routing base class - don't reallocate queues every time but clear them. Should be cheaper --- routing_algorithms/map_matching.hpp | 106 +++++----------------------- routing_algorithms/routing_base.hpp | 79 +++++++++++++++++++++ 2 files changed, 97 insertions(+), 88 deletions(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 2000242d3..d2e3c395b 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -80,91 +80,6 @@ class MapMatching final : public BasicRoutingInterfaceGetNumberOfNodes()); - engine_working_data.InitializeOrClearSecondThreadLocalStorage( - super::facade->GetNumberOfNodes()); - - QueryHeap &forward_heap = *(engine_working_data.forward_heap_1); - QueryHeap &reverse_heap = *(engine_working_data.reverse_heap_1); - - if (source_phantom.forward_node_id != SPECIAL_NODEID) - { - forward_heap.Insert(source_phantom.forward_node_id, - -source_phantom.GetForwardWeightPlusOffset(), - source_phantom.forward_node_id); - } - if (source_phantom.reverse_node_id != SPECIAL_NODEID) - { - forward_heap.Insert(source_phantom.reverse_node_id, - -source_phantom.GetReverseWeightPlusOffset(), - source_phantom.reverse_node_id); - } - - if (target_phantom.forward_node_id != SPECIAL_NODEID) - { - reverse_heap.Insert(target_phantom.forward_node_id, - target_phantom.GetForwardWeightPlusOffset(), - target_phantom.forward_node_id); - } - if (target_phantom.reverse_node_id != SPECIAL_NODEID) - { - reverse_heap.Insert(target_phantom.reverse_node_id, - target_phantom.GetReverseWeightPlusOffset(), - target_phantom.reverse_node_id); - } - - // search from s and t till new_min/(1+epsilon) > length_of_shortest_path - while (0 < (forward_heap.Size() + reverse_heap.Size())) - { - if (0 < forward_heap.Size()) - { - super::RoutingStep(forward_heap, reverse_heap, &middle_node, &upper_bound, - edge_offset, true); - } - if (0 < reverse_heap.Size()) - { - super::RoutingStep(reverse_heap, forward_heap, &middle_node, &upper_bound, - edge_offset, false); - } - } - - double distance = std::numeric_limits::max(); - if (upper_bound != INVALID_EDGE_WEIGHT) - { - std::vector packed_leg; - super::RetrievePackedPathFromHeap(forward_heap, reverse_heap, middle_node, packed_leg); - std::vector unpacked_path; - PhantomNodes nodes; - nodes.source_phantom = source_phantom; - nodes.target_phantom = target_phantom; - super::UnpackPath(packed_leg, nodes, unpacked_path); - - FixedPointCoordinate previous_coordinate = source_phantom.location; - FixedPointCoordinate current_coordinate; - distance = 0; - for (const auto &p : unpacked_path) - { - current_coordinate = super::facade->GetCoordinateOfNode(p.node); - distance += coordinate_calculation::great_circle_distance(previous_coordinate, - current_coordinate); - previous_coordinate = current_coordinate; - } - distance += coordinate_calculation::great_circle_distance(previous_coordinate, - target_phantom.location); - } - - return distance; - } - public: MapMatching(DataFacadeT *facade, SearchEngineData &engine_working_data) : super(facade), engine_working_data(engine_working_data) @@ -261,6 +176,14 @@ class MapMatching final : public BasicRoutingInterfaceGetNumberOfNodes()); + engine_working_data.InitializeOrClearSecondThreadLocalStorage( + super::facade->GetNumberOfNodes()); + + QueryHeap &forward_heap = *(engine_working_data.forward_heap_1); + QueryHeap &reverse_heap = *(engine_working_data.reverse_heap_1); + // compute d_t for this timestamp and the next one for (auto s = 0u; s < prev_viterbi.size(); ++s) { @@ -274,12 +197,17 @@ class MapMatching final : public BasicRoutingInterface new_value) + { continue; + } + + forward_heap.Clear(); + reverse_heap.Clear(); // get distance diff between loc1/2 and locs/s_prime - const auto network_distance = - get_network_distance(prev_unbroken_timestamps_list[s].first, - current_timestamps_list[s_prime].first); + const auto network_distance = super::get_network_distance( + forward_heap, reverse_heap, prev_unbroken_timestamps_list[s].first, + current_timestamps_list[s_prime].first); const auto great_circle_distance = coordinate_calculation::great_circle_distance(prev_coordinate, current_coordinate); @@ -288,7 +216,9 @@ class MapMatching final : public BasicRoutingInterface prune if (d_t > 500) + { continue; + } const double transition_pr = transition_log_probability(d_t); new_value += transition_pr; diff --git a/routing_algorithms/routing_base.hpp b/routing_algorithms/routing_base.hpp index e10c86a59..52c16a77e 100644 --- a/routing_algorithms/routing_base.hpp +++ b/routing_algorithms/routing_base.hpp @@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ROUTING_BASE_HPP #define ROUTING_BASE_HPP +#include "../data_structures/coordinate_calculation.hpp" #include "../data_structures/internal_route_result.hpp" #include "../data_structures/search_engine_data.hpp" #include "../data_structures/turn_instructions.hpp" @@ -410,6 +411,84 @@ template class BasicRoutingInterface packed_path.emplace_back(current_node_id); } } + + double get_network_distance(SearchEngineData::QueryHeap &forward_heap, + SearchEngineData::QueryHeap &reverse_heap, + const PhantomNode &source_phantom, + const PhantomNode &target_phantom) const + { + EdgeWeight upper_bound = INVALID_EDGE_WEIGHT; + NodeID middle_node = SPECIAL_NODEID; + EdgeWeight edge_offset = std::min(0, -source_phantom.GetForwardWeightPlusOffset()); + edge_offset = std::min(edge_offset, -source_phantom.GetReverseWeightPlusOffset()); + + if (source_phantom.forward_node_id != SPECIAL_NODEID) + { + forward_heap.Insert(source_phantom.forward_node_id, + -source_phantom.GetForwardWeightPlusOffset(), + source_phantom.forward_node_id); + } + if (source_phantom.reverse_node_id != SPECIAL_NODEID) + { + forward_heap.Insert(source_phantom.reverse_node_id, + -source_phantom.GetReverseWeightPlusOffset(), + source_phantom.reverse_node_id); + } + + if (target_phantom.forward_node_id != SPECIAL_NODEID) + { + reverse_heap.Insert(target_phantom.forward_node_id, + target_phantom.GetForwardWeightPlusOffset(), + target_phantom.forward_node_id); + } + if (target_phantom.reverse_node_id != SPECIAL_NODEID) + { + reverse_heap.Insert(target_phantom.reverse_node_id, + target_phantom.GetReverseWeightPlusOffset(), + target_phantom.reverse_node_id); + } + + // search from s and t till new_min/(1+epsilon) > length_of_shortest_path + while (0 < (forward_heap.Size() + reverse_heap.Size())) + { + if (0 < forward_heap.Size()) + { + RoutingStep(forward_heap, reverse_heap, &middle_node, &upper_bound, edge_offset, + true); + } + if (0 < reverse_heap.Size()) + { + RoutingStep(reverse_heap, forward_heap, &middle_node, &upper_bound, edge_offset, + false); + } + } + + double distance = std::numeric_limits::max(); + if (upper_bound != INVALID_EDGE_WEIGHT) + { + std::vector packed_leg; + RetrievePackedPathFromHeap(forward_heap, reverse_heap, middle_node, packed_leg); + std::vector unpacked_path; + PhantomNodes nodes; + nodes.source_phantom = source_phantom; + nodes.target_phantom = target_phantom; + UnpackPath(packed_leg, nodes, unpacked_path); + + FixedPointCoordinate previous_coordinate = source_phantom.location; + FixedPointCoordinate current_coordinate; + distance = 0; + for (const auto &p : unpacked_path) + { + current_coordinate = facade->GetCoordinateOfNode(p.node); + distance += coordinate_calculation::great_circle_distance(previous_coordinate, + current_coordinate); + previous_coordinate = current_coordinate; + } + distance += coordinate_calculation::great_circle_distance(previous_coordinate, + target_phantom.location); + } + return distance; + } }; #endif // ROUTING_BASE_HPP From 133e382aaee25db49dcf2ef53a3d0115ee456340 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 3 Mar 2015 14:43:38 +0100 Subject: [PATCH 283/360] remove constexpr qualifier as numeric_limits is not yet constexpr on MSVC compiler --- data_structures/hidden_markov_model.hpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/data_structures/hidden_markov_model.hpp b/data_structures/hidden_markov_model.hpp index 047c5bb3c..bae2ba55a 100644 --- a/data_structures/hidden_markov_model.hpp +++ b/data_structures/hidden_markov_model.hpp @@ -42,11 +42,10 @@ namespace osrm namespace matching { // FIXME this value should be a table based on samples/meter (or samples/min) -constexpr static const double log_2_pi = 1.837877066409346; // std::log(2. * M_PI); - -constexpr static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits::infinity(); -constexpr static const double MINIMAL_LOG_PROB = std::numeric_limits::lowest(); -constexpr static const std::size_t INVALID_STATE = std::numeric_limits::max(); +static const double log_2_pi = std::log(2. * M_PI); +static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits::infinity(); +static const double MINIMAL_LOG_PROB = std::numeric_limits::lowest(); +static const std::size_t INVALID_STATE = std::numeric_limits::max(); } // namespace matching } // namespace osrm From 31cae8f05f15c946ad43c08ca86d76894d761828 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 3 Mar 2015 17:41:12 +0100 Subject: [PATCH 284/360] several copy edits to brush up the code - fix copyright header - rename probabilityDensityFunction -> density_function - use double-precision fp literal to indicate intent - remove redundant enum class start value - replace C-style comments with C++ style - make functions const --- algorithms/bayes_classifier.hpp | 59 +++++++++++++++++---------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/algorithms/bayes_classifier.hpp b/algorithms/bayes_classifier.hpp index 042259111..3358144c7 100644 --- a/algorithms/bayes_classifier.hpp +++ b/algorithms/bayes_classifier.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -28,72 +28,75 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef BAYES_CLASSIFIER_HPP #define BAYES_CLASSIFIER_HPP -#include #include +#include + struct NormalDistribution { NormalDistribution(const double mean, const double standard_deviation) - : mean(mean) - , standard_deviation(standard_deviation) + : mean(mean), standard_deviation(standard_deviation) { } // FIXME implement log-probability version since its faster - double probabilityDensityFunction(const double val) + double density_function(const double val) const { const double x = val - mean; - return 1.0 / (std::sqrt(2*M_PI) * standard_deviation) * std::exp(-x*x / (standard_deviation * standard_deviation)); + return 1.0 / (std::sqrt(2. * M_PI) * standard_deviation) * + std::exp(-x * x / (standard_deviation * standard_deviation)); } double mean; double standard_deviation; }; - struct LaplaceDistribution { LaplaceDistribution(const double location, const double scale) - : location(location) - , scale(scale) + : location(location), scale(scale) { } // FIXME implement log-probability version since its faster - double probabilityDensityFunction(const double val) const + double density_function(const double val) const { const double x = std::abs(val - location); - return 1.0 / (2*scale) * std::exp(-x / scale); + return 1.0 / (2. * scale) * std::exp(-x / scale); } double location; double scale; }; -template +template class BayesClassifier { -public: - enum class ClassLabel : unsigned {NEGATIVE = 0, POSITIVE}; + public: + enum class ClassLabel : unsigned + { + NEGATIVE, + POSITIVE + }; using ClassificationT = std::pair; - BayesClassifier(const PositiveDistributionT& positive_distribution, - const NegativeDistributionT& negative_distribution, + BayesClassifier(const PositiveDistributionT &positive_distribution, + const NegativeDistributionT &negative_distribution, const double positive_apriori_probability) - : positive_distribution(positive_distribution) - , negative_distribution(negative_distribution) - , positive_apriori_probability(positive_apriori_probability) - , negative_apriori_probability(1 - positive_apriori_probability) + : positive_distribution(positive_distribution), + negative_distribution(negative_distribution), + positive_apriori_probability(positive_apriori_probability), + negative_apriori_probability(1. - positive_apriori_probability) { } - /* - * Returns label and the probability of the label. - */ - ClassificationT classify(const ValueT& v) const + // Returns label and the probability of the label. + ClassificationT classify(const ValueT &v) const { - const double positive_postpriori = positive_apriori_probability * positive_distribution.probabilityDensityFunction(v); - const double negative_postpriori = negative_apriori_probability * negative_distribution.probabilityDensityFunction(v); + const double positive_postpriori = + positive_apriori_probability * positive_distribution.density_function(v); + const double negative_postpriori = + negative_apriori_probability * negative_distribution.density_function(v); const double norm = positive_postpriori + negative_postpriori; if (positive_postpriori > negative_postpriori) @@ -104,11 +107,11 @@ public: return std::make_pair(ClassLabel::NEGATIVE, negative_postpriori / norm); } -private: + private: PositiveDistributionT positive_distribution; NegativeDistributionT negative_distribution; double positive_apriori_probability; double negative_apriori_probability; }; -#endif /* BAYES_CLASSIFIER_HPP */ +#endif // BAYES_CLASSIFIER_HPP From b9922bc90b15d7cb7469180776c339fb88f60150 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 3 Mar 2015 17:43:37 +0100 Subject: [PATCH 285/360] replace C-style comments --- data_structures/static_rtree.hpp | 41 ++++++++++++++++---------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/data_structures/static_rtree.hpp b/data_structures/static_rtree.hpp index f9cfbfca0..f219a6475 100644 --- a/data_structures/static_rtree.hpp +++ b/data_structures/static_rtree.hpp @@ -793,12 +793,10 @@ class StaticRTree return !result_phantom_node_vector.empty(); } - /** - * Returns elements within max_distance. - * If the minium of elements could not be found in the search radius, widen - * it until the minimum can be satisfied. - * At the number of returned nodes is capped at the given maximum. - */ + // Returns elements within max_distance. + // If the minium of elements could not be found in the search radius, widen + // it until the minimum can be satisfied. + // At the number of returned nodes is capped at the given maximum. bool IncrementalFindPhantomNodeForCoordinateWithDistance( const FixedPointCoordinate &input_coordinate, std::vector> &result_phantom_node_vector, @@ -888,7 +886,7 @@ class StaticRTree // continue searching for the first segment from a big component if (number_of_elements_from_big_cc == 0 && - number_of_elements_from_tiny_cc >= max_number_of_phantom_nodes-1 && + number_of_elements_from_tiny_cc >= max_number_of_phantom_nodes - 1 && current_segment.is_in_tiny_cc()) { continue; @@ -899,14 +897,14 @@ class StaticRTree FixedPointCoordinate foot_point_coordinate_on_segment; const float current_perpendicular_distance = - coordinate_calculation::perpendicular_distance_from_projected_coordinate( - m_coordinate_list->at(current_segment.u), - m_coordinate_list->at(current_segment.v), input_coordinate, - projected_coordinate, foot_point_coordinate_on_segment, current_ratio); + coordinate_calculation::perpendicular_distance_from_projected_coordinate( + m_coordinate_list->at(current_segment.u), + m_coordinate_list->at(current_segment.v), input_coordinate, + projected_coordinate, foot_point_coordinate_on_segment, current_ratio); - if (number_of_elements_from_big_cc > 0 - && result_phantom_node_vector.size() >= min_number_of_phantom_nodes - && current_perpendicular_distance >= max_distance) + if (number_of_elements_from_big_cc > 0 && + result_phantom_node_vector.size() >= min_number_of_phantom_nodes && + current_perpendicular_distance >= max_distance) { traversal_queue = std::priority_queue{}; continue; @@ -914,13 +912,14 @@ class StaticRTree // store phantom node in result vector result_phantom_node_vector.emplace_back( - PhantomNode( current_segment.forward_edge_based_node_id, - current_segment.reverse_edge_based_node_id, current_segment.name_id, - current_segment.forward_weight, current_segment.reverse_weight, - current_segment.forward_offset, current_segment.reverse_offset, - current_segment.packed_geometry_id, current_segment.component_id, - foot_point_coordinate_on_segment, current_segment.fwd_segment_position, - current_segment.forward_travel_mode, current_segment.backward_travel_mode), + PhantomNode( + current_segment.forward_edge_based_node_id, + current_segment.reverse_edge_based_node_id, current_segment.name_id, + current_segment.forward_weight, current_segment.reverse_weight, + current_segment.forward_offset, current_segment.reverse_offset, + current_segment.packed_geometry_id, current_segment.component_id, + foot_point_coordinate_on_segment, current_segment.fwd_segment_position, + current_segment.forward_travel_mode, current_segment.backward_travel_mode), current_perpendicular_distance); // Hack to fix rounding errors and wandering via nodes. From cfaacf7cb2fcb7b8a1e5bbbc0e8bfcfbd8f71f38 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 3 Mar 2015 17:58:17 +0100 Subject: [PATCH 286/360] put util/compute_angle.cpp into OBJECT library to avoid repetetive compiles --- CMakeLists.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bbebb485a..ee97ccfdc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,24 +59,25 @@ add_library(LOGGER OBJECT util/simple_logger.cpp) add_library(PHANTOMNODE OBJECT data_structures/phantom_node.cpp) add_library(EXCEPTION OBJECT util/osrm_exception.cpp) add_library(MERCATOR OBJECT util/mercator.cpp) +add_library(ANGLE OBJECT util/compute_angle.cpp) set(ExtractorSources extract.cpp ${ExtractorGlob}) add_executable(osrm-extract ${ExtractorSources} $ $ $ $ $ $ $) add_library(RESTRICTION OBJECT data_structures/restriction_map.cpp) -file(GLOB PrepareGlob contractor/*.cpp data_structures/hilbert_value.cpp util/compute_angle.cpp {RestrictionMapGlob}) +file(GLOB PrepareGlob contractor/*.cpp data_structures/hilbert_value.cpp {RestrictionMapGlob}) set(PrepareSources prepare.cpp ${PrepareGlob}) -add_executable(osrm-prepare ${PrepareSources} $ $ $ $ $ $ $ $) +add_executable(osrm-prepare ${PrepareSources} $ $ $ $ $ $ $ $ $) -file(GLOB ServerGlob server/*.cpp util/compute_angle.cpp) +file(GLOB ServerGlob server/*.cpp) file(GLOB DescriptorGlob descriptors/*.cpp) file(GLOB DatastructureGlob data_structures/search_engine_data.cpp data_structures/route_parameters.cpp util/bearing.cpp) list(REMOVE_ITEM DatastructureGlob data_structures/Coordinate.cpp) file(GLOB CoordinateGlob data_structures/coordinate*.cpp) file(GLOB AlgorithmGlob algorithms/*.cpp) file(GLOB HttpGlob server/http/*.cpp) -file(GLOB LibOSRMGlob library/*.cpp util/compute_angle.cpp) +file(GLOB LibOSRMGlob library/*.cpp) file(GLOB DataStructureTestsGlob unit_tests/data_structures/*.cpp data_structures/hilbert_value.cpp) file(GLOB AlgorithmTestsGlob unit_tests/algorithms/*.cpp) @@ -93,7 +94,7 @@ set( add_library(COORDINATE OBJECT ${CoordinateGlob}) add_library(FINGERPRINT OBJECT util/fingerprint.cpp) add_library(GITDESCRIPTION OBJECT util/git_sha.cpp) -add_library(OSRM ${OSRMSources} $ $ $ $ $ $ $) +add_library(OSRM ${OSRMSources} $ $ $ $ $ $ $ $ $) add_dependencies(FINGERPRINT FingerPrintConfigure) add_executable(osrm-routed routed.cpp ${ServerGlob} $) From d43716612b5f7730bbc3767367c2b797957b0e2a Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 3 Mar 2015 18:17:12 +0100 Subject: [PATCH 287/360] several copyedits to brush up code - remove unneeded includes - replace size() <==> 0 comparisions with calls to empty() - use fp instead of integer literals - use range-based for loops with integer ranges - add a couple of consts --- routing_algorithms/map_matching.hpp | 36 +++++++++++++---------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index d2e3c395b..4246539ef 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -33,15 +33,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/coordinate_calculation.hpp" #include "../data_structures/hidden_markov_model.hpp" #include "../util/matching_debug_info.hpp" -#include "../util/simple_logger.hpp" -#include "../util/json_util.hpp" #include "../util/json_logger.hpp" -#include #include -#include - #include #include #include @@ -93,13 +88,13 @@ class MapMatching final : public BasicRoutingInterface 0); + BOOST_ASSERT(!candidates_list.empty()); // TODO replace default values with table lookup based on sampling frequency EmissionLogProbability emission_log_probability( - gps_precision > 0 ? gps_precision : osrm::matching::default_sigma_z); + gps_precision > 0. ? gps_precision : osrm::matching::default_sigma_z); TransitionLogProbability transition_log_probability( - matching_beta > 0 ? matching_beta : osrm::matching::default_beta); + matching_beta > 0. ? matching_beta : osrm::matching::default_beta); osrm::matching::HMM model(candidates_list, emission_log_probability); @@ -120,10 +115,10 @@ class MapMatching final : public BasicRoutingInterface 0) + if (!trace_timestamps.empty()) { trace_split = trace_split || @@ -162,7 +157,8 @@ class MapMatching final : public BasicRoutingInterface(0u, prev_viterbi.size())) { if (prev_pruned[s]) + { continue; + } - for (auto s_prime = 0u; s_prime < current_viterbi.size(); ++s_prime) + for (const auto s_prime : osrm::irange(0u, current_viterbi.size())) { // how likely is candidate s_prime at time t to be emitted? const double emission_pr = @@ -247,7 +245,6 @@ class MapMatching final : public BasicRoutingInterface 0); - // remove both ends of the breakage prev_unbroken_timestamps.pop_back(); } @@ -259,7 +256,7 @@ class MapMatching final : public BasicRoutingInterface 0) + if (!prev_unbroken_timestamps.empty()) { split_points.push_back(prev_unbroken_timestamps.back() + 1); } @@ -286,8 +283,9 @@ class MapMatching final : public BasicRoutingInterface(0u, reconstructed_indices.size())) { auto timestamp_index = reconstructed_indices[i].first; auto location_index = reconstructed_indices[i].second; @@ -328,10 +326,8 @@ class MapMatching final : public BasicRoutingInterface Date: Tue, 3 Mar 2015 18:26:38 +0100 Subject: [PATCH 288/360] add override specifier --- server/data_structures/internal_datafacade.hpp | 15 ++++++++------- server/data_structures/shared_datafacade.hpp | 15 ++++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/server/data_structures/internal_datafacade.hpp b/server/data_structures/internal_datafacade.hpp index a85a78e30..640a5f974 100644 --- a/server/data_structures/internal_datafacade.hpp +++ b/server/data_structures/internal_datafacade.hpp @@ -416,12 +416,12 @@ template class InternalDataFacade final : public BaseDataFacad input_coordinate, resulting_phantom_node_vector, number_of_results); } - bool - IncrementalFindPhantomNodeForCoordinateWithMaxDistance(const FixedPointCoordinate &input_coordinate, - std::vector> &resulting_phantom_node_vector, - const double max_distance, - const unsigned min_number_of_phantom_nodes, - const unsigned max_number_of_phantom_nodes) final + bool IncrementalFindPhantomNodeForCoordinateWithMaxDistance( + const FixedPointCoordinate &input_coordinate, + std::vector> &resulting_phantom_node_vector, + const double max_distance, + const unsigned min_number_of_phantom_nodes, + const unsigned max_number_of_phantom_nodes) override final { if (!m_static_rtree.get()) { @@ -429,7 +429,8 @@ template class InternalDataFacade final : public BaseDataFacad } return m_static_rtree->IncrementalFindPhantomNodeForCoordinateWithDistance( - input_coordinate, resulting_phantom_node_vector, max_distance, min_number_of_phantom_nodes, max_number_of_phantom_nodes); + input_coordinate, resulting_phantom_node_vector, max_distance, + min_number_of_phantom_nodes, max_number_of_phantom_nodes); } unsigned GetCheckSum() const override final { return m_check_sum; } diff --git a/server/data_structures/shared_datafacade.hpp b/server/data_structures/shared_datafacade.hpp index 87af81929..93dfdb95d 100644 --- a/server/data_structures/shared_datafacade.hpp +++ b/server/data_structures/shared_datafacade.hpp @@ -404,12 +404,12 @@ template class SharedDataFacade final : public BaseDataFacade< input_coordinate, resulting_phantom_node_vector, number_of_results); } - bool - IncrementalFindPhantomNodeForCoordinateWithMaxDistance(const FixedPointCoordinate &input_coordinate, - std::vector> &resulting_phantom_node_vector, - const double max_distance, - const unsigned min_number_of_phantom_nodes, - const unsigned max_number_of_phantom_nodes) final + bool IncrementalFindPhantomNodeForCoordinateWithMaxDistance( + const FixedPointCoordinate &input_coordinate, + std::vector> &resulting_phantom_node_vector, + const double max_distance, + const unsigned min_number_of_phantom_nodes, + const unsigned max_number_of_phantom_nodes) override final { if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first) { @@ -417,7 +417,8 @@ template class SharedDataFacade final : public BaseDataFacade< } return m_static_rtree->second->IncrementalFindPhantomNodeForCoordinateWithDistance( - input_coordinate, resulting_phantom_node_vector, max_distance, min_number_of_phantom_nodes, max_number_of_phantom_nodes); + input_coordinate, resulting_phantom_node_vector, max_distance, + min_number_of_phantom_nodes, max_number_of_phantom_nodes); } unsigned GetCheckSum() const override final { return m_check_sum; } From 98dba11c5ef9c8bf90b58e1e9b6b94618a02599e Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Wed, 4 Mar 2015 01:34:45 +0100 Subject: [PATCH 289/360] Address some of the remaining issues of the code review --- routing_algorithms/map_matching.hpp | 2 +- server/api_grammar.hpp | 16 ++++++++-------- util/json_logger.hpp | 6 ++++-- util/json_util.hpp | 12 ++---------- 4 files changed, 15 insertions(+), 21 deletions(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 4246539ef..89c4e357c 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -272,7 +272,7 @@ class MapMatching final : public BasicRoutingInterface= sub_matching_begin && model.breakage[parent_timestamp_index]) { - parent_timestamp_index--; + --parent_timestamp_index; } // matchings that only consist of one candidate are invalid diff --git a/server/api_grammar.hpp b/server/api_grammar.hpp index 5c7dcde45..a629cfbf7 100644 --- a/server/api_grammar.hpp +++ b/server/api_grammar.hpp @@ -65,12 +65,6 @@ template struct APIGrammar : qi::grammar> qi::lit("t") >> '=' >> qi::uint_[boost::bind(&HandlerT::addTimestamp, handler, ::_1)]; - matching_beta = (-qi::lit('&')) >> qi::lit("matching_beta") >> '=' >> - qi::short_[boost::bind(&HandlerT::setMatchingBeta, handler, ::_1)]; - gps_precision = (-qi::lit('&')) >> qi::lit("gps_precision") >> '=' >> - qi::short_[boost::bind(&HandlerT::setGPSPrecision, handler, ::_1)]; - classify = (-qi::lit('&')) >> qi::lit("classify") >> '=' >> - qi::bool_[boost::bind(&HandlerT::setClassify, handler, ::_1)]; u = (-qi::lit('&')) >> qi::lit("u") >> '=' >> qi::bool_[boost::bind(&HandlerT::setUTurn, handler, ::_1)]; uturns = (-qi::lit('&')) >> qi::lit("uturns") >> '=' >> @@ -83,6 +77,12 @@ template struct APIGrammar : qi::grammar> qi::lit("num_results") >> '=' >> qi::short_[boost::bind(&HandlerT::setNumberOfResults, handler, ::_1)]; + matching_beta = (-qi::lit('&')) >> qi::lit("matching_beta") >> '=' >> + qi::short_[boost::bind(&HandlerT::setMatchingBeta, handler, ::_1)]; + gps_precision = (-qi::lit('&')) >> qi::lit("gps_precision") >> '=' >> + qi::short_[boost::bind(&HandlerT::setGPSPrecision, handler, ::_1)]; + classify = (-qi::lit('&')) >> qi::lit("classify") >> '=' >> + qi::bool_[boost::bind(&HandlerT::setClassify, handler, ::_1)]; string = +(qi::char_("a-zA-Z")); stringwithDot = +(qi::char_("a-zA-Z0-9_.-")); @@ -92,8 +92,8 @@ template struct APIGrammar : qi::grammar api_call, query; qi::rule service, zoom, output, string, jsonp, checksum, location, - hint, timestamp, matching_beta, gps_precision, classify, stringwithDot, stringwithPercent, language, instruction, geometry, cmp, alt_route, u, - uturns, old_API, num_results; + hint, timestamp, stringwithDot, stringwithPercent, language, instruction, geometry, cmp, alt_route, u, + uturns, old_API, num_results, matching_beta, gps_precision, classify; HandlerT *handler; }; diff --git a/util/json_logger.hpp b/util/json_logger.hpp index 872a926d5..03f8a171a 100644 --- a/util/json_logger.hpp +++ b/util/json_logger.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -37,6 +37,8 @@ namespace osrm namespace json { +// Used to append additional debugging information to the JSON response in a +// thread safe manner. class Logger { using MapT = std::unordered_map; @@ -74,4 +76,4 @@ class Logger } } -#endif /* SIMPLE_LOGGER_HPP */ +#endif /* JSON_LOGGER_HPP */ diff --git a/util/json_util.hpp b/util/json_util.hpp index 461148ea3..bfb8a8bc4 100644 --- a/util/json_util.hpp +++ b/util/json_util.hpp @@ -30,8 +30,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -#include #include +#include namespace osrm { @@ -53,18 +53,10 @@ template T clamp_float(T d) return d; } -void append_to_array(osrm::json::Array &a) {} -template -void append_to_array(osrm::json::Array &a, T value, Args... args) -{ - a.values.emplace_back(value); - append_to_array(a, args...); -} - template osrm::json::Array make_array(Args... args) { osrm::json::Array a; - append_to_array(a, args...); + append_to_container(a.values, args...); return a; } From 76674a359410e5d6af1f52cff115f528ad8ca4d0 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 4 Mar 2015 12:48:18 +0100 Subject: [PATCH 290/360] Squashed 'third_party/variant/' changes from 24dcab2..3b02ca0 3b02ca0 add which() method returning zero based index of stored T in Types... for boost::variant() compatibility c117592 update unit test to match c64c74775a80474f2012c1a49ab2865e3666107a 36f1e12 add get() overloads for when T is stored in recursive_wrapper also makes get() a compile time error where T is not in Types... (ref #24) 7dfdfa2 clean up coverage files in test directory too [skip ci] 89f8a41 add coverage report git-subtree-dir: third_party/variant git-subtree-split: 3b02ca0e3ab1a36dd6ec9138e7f93eb3176ae5f7 --- Makefile | 2 ++ README.md | 1 + test/unit.cpp | 16 ++++++++++++---- variant.hpp | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 59 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 69761034c..cae3d46bd 100644 --- a/Makefile +++ b/Makefile @@ -89,6 +89,8 @@ clean: rm -rf *.dSYM rm -f unit.gc* rm -f *gcov + rm -f test/unit.gc* + rm -f test/*gcov pgo: out Makefile variant.hpp $(CXX) -o out/bench-variant test/bench_variant.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) -pg -fprofile-generate diff --git a/README.md b/README.md index 018163c1c..791131d39 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ An alternative to `boost::variant` for C++11. [![Build Status](https://secure.travis-ci.org/mapbox/variant.svg)](https://travis-ci.org/mapbox/variant) [![Build status](https://ci.appveyor.com/api/projects/status/v9tatx21j1k0fcgy)](https://ci.appveyor.com/project/Mapbox/variant) +[![Coverage Status](https://coveralls.io/repos/mapbox/variant/badge.svg?branch=master)](https://coveralls.io/r/mapbox/variant?branch=master) # Why use Mapbox Variant? diff --git a/test/unit.cpp b/test/unit.cpp index 3998e6a9b..9b874c707 100644 --- a/test/unit.cpp +++ b/test/unit.cpp @@ -212,11 +212,22 @@ TEST_CASE( "variant should correctly index types", "[variant]" ) { REQUIRE(variant_type(float(0.0)).get_type_index() == 0); } +// Test internal api +TEST_CASE( "variant::which() returns zero based index of stored type", "[variant]" ) { + typedef util::variant variant_type; + // Index is in reverse order + REQUIRE(variant_type(true).which() == 0); + REQUIRE(variant_type(std::string("test")).which() == 1); + REQUIRE(variant_type(std::uint64_t(0)).which() == 2); + REQUIRE(variant_type(std::int64_t(0)).which() == 3); + REQUIRE(variant_type(double(0.0)).which() == 4); + REQUIRE(variant_type(float(0.0)).which() == 5); +} + TEST_CASE( "get with type not in variant type list should throw", "[variant]" ) { typedef util::variant variant_type; variant_type var = 5; REQUIRE(var.get() == 5); - REQUIRE_THROWS(var.get()); // XXX shouldn't this be a compile time error? See https://github.com/mapbox/variant/issues/24 } TEST_CASE( "get with wrong type (here: double) should throw", "[variant]" ) { @@ -237,7 +248,6 @@ TEST_CASE( "implicit conversion", "[variant][implicit conversion]" ) { typedef util::variant variant_type; variant_type var(5.0); // converted to int REQUIRE(var.get() == 5); - REQUIRE_THROWS(var.get()); var = 6.0; // works for operator=, too REQUIRE(var.get() == 6); } @@ -247,7 +257,6 @@ TEST_CASE( "implicit conversion to first type in variant type list", "[variant][ variant_type var = 5.0; // converted to long REQUIRE(var.get() == 5); REQUIRE_THROWS(var.get()); - REQUIRE_THROWS(var.get()); } TEST_CASE( "implicit conversion to unsigned char", "[variant][implicit conversion]" ) { @@ -297,7 +306,6 @@ TEST_CASE( "variant printer", "[visitor][unary visitor][printer]" ) { REQUIRE(out.str() == "2.1,123,foo,456,foo"); } - int main (int argc, char* const argv[]) { int result = Catch::Session().run(argc, argv); diff --git a/variant.hpp b/variant.hpp index 880ca1b2a..a3cdea63a 100644 --- a/variant.hpp +++ b/variant.hpp @@ -601,7 +601,8 @@ public: type_index = detail::direct_type::index; } - template + // get() + template::index != detail::invalid_value)>::type* = nullptr> VARIANT_INLINE T& get() { if (type_index == detail::direct_type::index) @@ -610,11 +611,13 @@ public: } else { - throw std::runtime_error("in get()"); + throw std::runtime_error("in get()"); } } - template + template ::index != detail::invalid_value) + >::type* = nullptr> VARIANT_INLINE T const& get() const { if (type_index == detail::direct_type::index) @@ -623,15 +626,50 @@ public: } else { - throw std::runtime_error("in get()"); + throw std::runtime_error("in get()"); } } + // get() - T stored as recursive_wrapper + template , Types...>::index != detail::invalid_value) + >::type* = nullptr> + VARIANT_INLINE T& get() + { + if (type_index == detail::direct_type, Types...>::index) + { + return (*reinterpret_cast*>(&data)).get(); + } + else + { + throw std::runtime_error("in get()"); + } + } + + template , Types...>::index != detail::invalid_value) + >::type* = nullptr> + VARIANT_INLINE T const& get() const + { + if (type_index == detail::direct_type, Types...>::index) + { + return (*reinterpret_cast const*>(&data)).get(); + } + else + { + throw std::runtime_error("in get()"); + } + } VARIANT_INLINE std::size_t get_type_index() const { return type_index; } + VARIANT_INLINE int which() const noexcept + { + return static_cast(sizeof...(Types) - type_index - 1); + } + // visitor // unary template @@ -738,13 +776,13 @@ auto VARIANT_INLINE static apply_visitor(F f, V & v0, V & v1) -> decltype(V::bin // getter interface template -ResultType & get(T & var) +ResultType & get(T & var) { return var.template get(); } template -ResultType const& get(T const& var) +ResultType const& get(T const& var) { return var.template get(); } From 2ce0d60db190115140f6929fc15a98de343b9ae0 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 4 Mar 2015 12:50:42 +0100 Subject: [PATCH 291/360] Squashed 'third_party/libosmium/' changes from 6522da5..f074d94 f074d94 Use shorter path names in Doxygen doc. 5117d5a Make Doxygen-generated HTML docs work better on small screens. 41607ac Appveyor config: Use lowercase command names everywhere. Filter 7z output. 9e77a39 Remove debug output. 3416c4b Revert "Comment out test to see if there are dependencies between tests." fa49dde Comment out test to see if there are dependencies between tests. 5add75d Fix typo in appveyor conf: nul. 53b3778 Use different file names for tests. 1091c0b Fix Windows munmap() to return the same as the posix one. 14fdc4e Revert "CMake: Remove unneeded build type setting." 0270087 Workaround for MSVC. 56c2120 Another try... 8e96a6f Trying to fix test on Windows... 11a64c2 CMake workaround: Set CMAKE_CONFIGURATION_TYPES before project(). As per http://www.cmake.org/pipermail/cmake/2012-January/048856.html 3847e7a CMake: Remove unneeded build type setting. a1bcaf1 CMake: Make CMAKE_CONFIGURATION_TYPES a cache variable. ddab3e3 Create test file in test_typed_mmap in current dir instead of tmp. ce1d3bd Build "RelWithDebInfo" on appveyor instead of "Release". b6db34f Add README showing source of FindGem.cmake. 2c86c55 Better error message and some comments in CMake for sparsetable check. b16a5a3 Fix ctest on Windows. 2203bc8 Fix FindGem.cmake. 5d1f81d Another try to fix travis build. ddd3f5e Hopefully fix problem where travis doesn't find osm-testdata. 0e673ea More debug output to find travis problem. eb01107 Updated data-tests README. 8a971c8 Remove special case of the multipolygon test in travis/appveyor config. dce792c CMake: Check dependencies of multipolygon test and run as CMake script. b967677 Add tests for thread pool. 400e9b3 Bugfix: Handle exception in one pool threads properly. a1ba489 More detailed error reporting from zlib. 95cf621 Disable SparseMemTable if sparsetable size_type is smaller than 8. 7b601b5 Add missing overload to cast_with_assert() function. 60a7d86 Giving up on trying to remove LNK4221 warning. 35ed5df Try another way to get rid of MSV warning... f9c7d92 Disable a warning about changed behaviour on MSVC. c3c6b2d CTest: Only output failed tests. 9c99996 Try setting option in a different way for getting rid of LNK4221 on MSVC. 4ac563c Another ssize_t fix for Windows. 11db84f Fix mmap for windows. Convert macro to function. 95d8f75 Fix test on Windows (which doesn't have ssize_t). df51aa4 Do not write huge files in one system call. 9c4f772 Change mmap() implementation for Windows. 5be817c Rewrote function to work on Windows without warnings. ea84f73 Fix warnings on Windows. 572d692 Fixed the static_cast_with_assert function and added tests. 89ef86b Use SparseMemArray instead of SparseMemTable in examples. git-subtree-dir: third_party/libosmium git-subtree-split: f074d949a5585a81578d682035f2163de971beb3 --- .travis.yml | 6 +- CMakeLists.txt | 15 +- appveyor.yml | 39 +++-- cmake/FindGem.cmake | 153 ++++++++++++++++++ cmake/FindOsmium.cmake | 31 +++- cmake/README | 3 + doc/CMakeLists.txt | 1 + doc/Doxyfile.in | 4 +- doc/README.md | 8 + doc/header.html | 56 +++++++ examples/osmium_area_test.cpp | 4 +- examples/osmium_toogr2.cpp | 8 +- include/mmap_for_windows.hpp | 29 ++-- include/osmium/index/map/sparse_mem_table.hpp | 4 + include/osmium/io/compression.hpp | 6 +- include/osmium/io/detail/pbf_input_format.hpp | 7 +- include/osmium/io/detail/read_write.hpp | 8 +- include/osmium/io/detail/zlib.hpp | 38 +++-- include/osmium/thread/queue.hpp | 4 +- include/osmium/util/cast.hpp | 48 ++++-- test/CMakeLists.txt | 3 + test/data-tests/CMakeLists.txt | 41 +++-- test/data-tests/README.md | 17 +- test/data-tests/run-testdata-multipolygon.bat | 7 - .../run-testdata-multipolygon.cmake | 46 ++++++ test/data-tests/run-testdata-multipolygon.sh | 10 -- test/data-tests/testdata-xml.cpp | 2 +- test/t/index/test_id_to_location.cpp | 4 + test/t/index/test_typed_mmap.cpp | 12 +- test/t/io/test_reader.cpp | 6 +- test/t/thread/test_pool.cpp | 69 ++++++++ test/t/util/test_cast_with_assert.cpp | 89 ++++++++++ 32 files changed, 628 insertions(+), 150 deletions(-) create mode 100644 cmake/FindGem.cmake create mode 100644 cmake/README create mode 100644 doc/README.md create mode 100644 doc/header.html delete mode 100644 test/data-tests/run-testdata-multipolygon.bat create mode 100644 test/data-tests/run-testdata-multipolygon.cmake delete mode 100755 test/data-tests/run-testdata-multipolygon.sh create mode 100644 test/t/thread/test_pool.cpp create mode 100644 test/t/util/test_cast_with_assert.cpp diff --git a/.travis.yml b/.travis.yml index ea8794ecb..73dff72a1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,6 +20,7 @@ before_install: - sudo apt-get update --yes --quiet install: + - cd .. # upgrade compilers - sudo apt-get install --yes gcc-4.8 g++-4.8 # make sure 'cpp' is the just installed current one @@ -35,6 +36,7 @@ install: - make - sudo make install - cd ../.. + - cd libosmium before_script: - true @@ -45,7 +47,5 @@ script: - cd build - cmake -LA -DCMAKE_BUILD_TYPE=${CONFIGURATION} .. - make VERBOSE=1 - # Disable multipolygon test because it needs ruby and the 'json' gem, but the - # travis ruby installation doesn't find the gem it did install itself. - - ctest -V -E testdata-multipolygon + - ctest --output-on-failure diff --git a/CMakeLists.txt b/CMakeLists.txt index 373bf8eb1..b48f27166 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,11 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") # #----------------------------------------------------------------------------- +set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel;Dev" + CACHE STRING + "List of available configuration types" + FORCE) + project(libosmium) set(LIBOSMIUM_VERSION_MAJOR 0) @@ -137,8 +142,6 @@ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${USUAL_COMPILE_OPTIONS}" # Build Type # #----------------------------------------------------------------------------- -set(CMAKE_CONFIGURATION_TYPES "Debug Release RelWithDebInfo MinSizeRel Dev") - # In 'Dev' mode: compile with very strict warnings and turn them into errors. if(CMAKE_BUILD_TYPE STREQUAL "Dev") if(NOT MSVC) @@ -279,14 +282,6 @@ if(BUILD_HEADERS) # so we pretend to build a library here. add_library(${libname} STATIC ${DUMMYCPP} include/${hpp}) - if(MSVC) - # Remove warning LNK4221: "This object file does not define any - # previously undefined public symbols, so it will not be used by - # any link operation that consumes this library". This is a dummy - # library anyways. - target_link_libraries(${libname} /wd4221) - endif() - #### this is better but only supported from cmake 3.0: ###add_library(${libname} OBJECT ${DUMMYCPP} include/${hpp}) diff --git a/appveyor.yml b/appveyor.yml index c112d4f77..b3b3f51e4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,7 +7,7 @@ environment: matrix: - config: Dev - - config: Release + - config: RelWithDebInfo # branches to build branches: @@ -28,35 +28,35 @@ platform: x64 install: # show all availble env vars - - SET - - ECHO cmake on AppVeyor + - set + - echo cmake on AppVeyor - cmake -version - - CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 - - SET PATH=c:\projects\libosmium\cmake-3.1.0-win32-x86\bin;%PATH% - - SET LODEPSDIR=c:\projects\libosmium\libosmium-deps - - SET PROJ_LIB=%LODEPSDIR%\proj\share + - call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 + - set PATH=c:\projects\libosmium\cmake-3.1.0-win32-x86\bin;%PATH% + - set LODEPSDIR=c:\projects\libosmium\libosmium-deps + - set PROJ_LIB=%LODEPSDIR%\proj\share - set GDAL_DATA=%LODEPSDIR%\gdal\data #geos.dll - - SET PATH=%LODEPSDIR%\geos\lib;%PATH% + - set PATH=%LODEPSDIR%\geos\lib;%PATH% #gdal.dll - - SET PATH=%LODEPSDIR%\gdal\lib;%PATH% + - set PATH=%LODEPSDIR%\gdal\lib;%PATH% #libexpat.dll - - SET PATH=%LODEPSDIR%\expat\lib;%PATH% + - set PATH=%LODEPSDIR%\expat\lib;%PATH% #libtiff.dll - - SET PATH=%LODEPSDIR%\libtiff\lib;%PATH% + - set PATH=%LODEPSDIR%\libtiff\lib;%PATH% #zlibwapi.dll - - SET PATH=%LODEPSDIR%\zlib\lib;%PATH% + - set PATH=%LODEPSDIR%\zlib\lib;%PATH% #convert backslashes in bzip2 path to forward slashes #cmake cannot find it otherwise - - SET LIBBZIP2=%LODEPSDIR%\bzip2\lib\libbz2.lib - - SET LIBBZIP2=%LIBBZIP2:\=/% + - set LIBBZIP2=%LODEPSDIR%\bzip2\lib\libbz2.lib + - set LIBBZIP2=%LIBBZIP2:\=/% - ps: Start-FileDownload https://mapnik.s3.amazonaws.com/deps/cmake-3.1.0-win32-x86.7z -FileName cm.7z - ps: Start-FileDownload https://mapnik.s3.amazonaws.com/dist/dev/libosmium-deps-win-14.0-x64.7z -FileName lodeps.7z - - 7z x cm.7z > null - - 7z x lodeps.7z > nul + - 7z x cm.7z | %windir%\system32\find "ing archive" + - 7z x lodeps.7z | %windir%\system32\find "ing archive" - echo %LODEPSDIR% - dir %LODEPSDIR% - - ECHO our own cmake + - echo our own cmake - cmake -version - cd c:\projects - git clone https://github.com/osmcode/osm-testdata.git @@ -67,11 +67,10 @@ build_script: - cd build - echo %config% - cmake .. -LA -G "Visual Studio 14 Win64" -DOsmium_DEBUG=TRUE -DCMAKE_BUILD_TYPE=%config% -DBOOST_ROOT=%LODEPSDIR%\boost -DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_57.lib -DOSMPBF_LIBRARY=%LODEPSDIR%\osmpbf\lib\osmpbf.lib -DOSMPBF_INCLUDE_DIR=%LODEPSDIR%\osmpbf\include -DPROTOBUF_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf.lib -DPROTOBUF_LITE_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf-lite.lib -DPROTOBUF_INCLUDE_DIR=%LODEPSDIR%\protobuf\include -DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib -DZLIB_INCLUDE_DIR=%LODEPSDIR%\zlib\include -DEXPAT_LIBRARY=%LODEPSDIR%\expat\lib\libexpat.lib -DEXPAT_INCLUDE_DIR=%LODEPSDIR%\expat\include -DBZIP2_LIBRARIES=%LIBBZIP2% -DBZIP2_INCLUDE_DIR=%LODEPSDIR%\bzip2\include -DGDAL_LIBRARY=%LODEPSDIR%\gdal\lib\gdal_i.lib -DGDAL_INCLUDE_DIR=%LODEPSDIR%\gdal\include -DGEOS_LIBRARY=%LODEPSDIR%\geos\lib\geos.lib -DGEOS_INCLUDE_DIR=%LODEPSDIR%\geos\include -DPROJ_LIBRARY=%LODEPSDIR%\proj\lib\proj.lib -DPROJ_INCLUDE_DIR=%LODEPSDIR%\proj\include -DSPARSEHASH_INCLUDE_DIR=%LODEPSDIR%\sparsehash\include -DGETOPT_LIBRARY=%LODEPSDIR%\wingetopt\lib\wingetopt.lib -DGETOPT_INCLUDE_DIR=%LODEPSDIR%\wingetopt\include - - msbuild libosmium.sln /p:Configuration=Release /toolsversion:14.0 /p:Platform=x64 /p:PlatformToolset=v140 + - msbuild libosmium.sln /p:Configuration=%config% /toolsversion:14.0 /p:Platform=x64 /p:PlatformToolset=v140 #- cmake .. -LA -G "NMake Makefiles" -DOsmium_DEBUG=TRUE -DCMAKE_BUILD_TYPE=%config% -DBOOST_ROOT=%LODEPSDIR%\boost -DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_57.lib -DOSMPBF_LIBRARY=%LODEPSDIR%\osmpbf\lib\osmpbf.lib -DOSMPBF_INCLUDE_DIR=%LODEPSDIR%\osmpbf\include -DPROTOBUF_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf.lib -DPROTOBUF_LITE_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf-lite.lib -DPROTOBUF_INCLUDE_DIR=%LODEPSDIR%\protobuf\include -DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib -DZLIB_INCLUDE_DIR=%LODEPSDIR%\zlib\include -DEXPAT_LIBRARY=%LODEPSDIR%\expat\lib\libexpat.lib -DEXPAT_INCLUDE_DIR=%LODEPSDIR%\expat\include -DBZIP2_LIBRARIES=%LIBBZIP2% -DBZIP2_INCLUDE_DIR=%LODEPSDIR%\bzip2\include -DGDAL_LIBRARY=%LODEPSDIR%\gdal\lib\gdal_i.lib -DGDAL_INCLUDE_DIR=%LODEPSDIR%\gdal\include -DGEOS_LIBRARY=%LODEPSDIR%\geos\lib\geos.lib -DGEOS_INCLUDE_DIR=%LODEPSDIR%\geos\include -DPROJ_LIBRARY=%LODEPSDIR%\proj\lib\proj.lib -DPROJ_INCLUDE_DIR=%LODEPSDIR%\proj\include -DSPARSEHASH_INCLUDE_DIR=%LODEPSDIR%\sparsehash\include -DGETOPT_LIBRARY=%LODEPSDIR%\wingetopt\lib\wingetopt.lib -DGETOPT_INCLUDE_DIR=%LODEPSDIR%\wingetopt\include #- nmake test_script: - # Disable multipolygon test because it needs ruby and the 'json' gem - - ctest -V -C %config% -E testdata-multipolygon + - ctest --output-on-failure -C %config% diff --git a/cmake/FindGem.cmake b/cmake/FindGem.cmake new file mode 100644 index 000000000..f5389d1e8 --- /dev/null +++ b/cmake/FindGem.cmake @@ -0,0 +1,153 @@ +# Author thomas.roehr@dfki.de +# +# Version 0.3 2013-07-02 +# - rely on `gem content` to find library and header +# - introduce GEM_OS_PKG to allow search via pkgconfig +# Version 0.2 2010-01-14 +# - add support for searching for multiple gems +# Version 0.1 2010-12-15 +# - support basic search functionality +# - tested to find rice +# +# OUTPUT: +# +# GEM_INCLUDE_DIRS After successful search contains the include directores +# +# GEM_LIBRARIES After successful search contains the full path of each found library +# +# +# Usage: +# set(GEM_DEBUG TRUE) +# find_package(Gem COMPONENTS rice hoe) +# include_directories(${GEM_INCLUDE_DIRS}) +# target_link_libraries(${GEM_LIBRARIES} +# +# in case pkg-config should be used to search for the os pkg, set GEM_OS_PKG, i.e. +# set(GEM_OS_PKG TRUE) +# +# Check for how 'gem' should be called +include(FindPackageHandleStandardArgs) +find_program(GEM_EXECUTABLE + NAMES "gem${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}" + "gem${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}" + "gem-${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}" + "gem-${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}" + "gem${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}${RUBY_VERSION_PATCH}" + "gem${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}.${RUBY_VERSION_PATCH}" + "gem-${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}${RUBY_VERSION_PATCH}" + "gem-${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}.${RUBY_VERSION_PATCH}" + "gem") + +# Making backward compatible +if(Gem_DEBUG) + set(GEM_DEBUG TRUE) +endif() + +if(NOT GEM_EXECUTABLE) + MESSAGE(FATAL_ERROR "Could not find the gem executable - install 'gem' first") +endif() + +if(NOT Gem_FIND_COMPONENTS) + MESSAGE(FATAL_ERROR "If searching for a Gem you have to provide COMPONENTS with the name of the gem") +endif() + +foreach(Gem_NAME ${Gem_FIND_COMPONENTS}) + set(GEM_${Gem_NAME}_FOUND TRUE) + list(APPEND components_found_vars GEM_${Gem_NAME}_FOUND) + # If the gem is installed as a gem + if(NOT GEM_OS_PKG) + set(GEM_HOME ENV{GEM_HOME}) + + # Use `gem content ` to extract current information about installed gems + # Store the information into ${GEM_LOCAL_INFO} + EXECUTE_PROCESS(COMMAND ${GEM_EXECUTABLE} content ${Gem_NAME} + RESULT_VARIABLE GEM_RUN_RESULT + OUTPUT_VARIABLE GEM_LOCAL_INFO) + + if(GEM_RUN_RESULT STREQUAL "0") + list(APPEND FOUND_GEMS ${Gem_NAME}) + set(_library_NAME_PATTERN lib${Gem_NAME}.a + lib${Gem_NAME}.so + lib${Gem_NAME}.dylib + ${Gem_NAME}.a + ${Gem_NAME}.so + ${Gem_NAME}.dylib + .*.a + .*.so + .*.dylib + ) + + set(_header_SUFFIX_PATTERN + .h + .hh + .hpp + ) + + # Create a list from the output results of the gem command + string(REPLACE "\n" ";" GEM_CONTENT_LIST "${GEM_LOCAL_INFO}") + foreach(_gem_CONTENT_PATH ${GEM_CONTENT_LIST}) + + # Convert so that only '/' Unix path separator are being using + # needed to do proper regex matching + FILE(TO_CMAKE_PATH ${_gem_CONTENT_PATH} gem_CONTENT_PATH) + + # Identify library -- checking for a library in the gems 'lib' (sub)directory + # Search for an existing library, but only within the gems folder + foreach(_library_NAME ${_library_NAME_PATTERN}) + STRING(REGEX MATCH ".*${Gem_NAME}.*/lib/.*${_library_NAME}$" GEM_PATH_INFO "${gem_CONTENT_PATH}") + if(NOT "${GEM_PATH_INFO}" STREQUAL "") + list(APPEND GEM_LIBRARIES ${GEM_PATH_INFO}) + break() + endif() + endforeach() + + # Identify headers + # Checking for available headers in an include directory + foreach(_header_PATTERN ${_header_SUFFIX_PATTERN}) + STRING(REGEX MATCH ".*${Gem_NAME}.*/include/.*${_header_PATTERN}$" GEM_PATH_INFO "${gem_CONTENT_PATH}") + if(NOT "${GEM_PATH_INFO}" STREQUAL "") + STRING(REGEX REPLACE "(.*${Gem_NAME}.*/include/).*${_header_PATTERN}$" "\\1" GEM_PATH_INFO "${gem_CONTENT_PATH}") + list(APPEND GEM_INCLUDE_DIRS ${GEM_PATH_INFO}) + break() + endif() + endforeach() + endforeach() + else() + set(GEM_${Gem_NAME}_FOUND FALSE) + endif() + else(NOT GEM_OS_PKG) + pkg_check_modules(GEM_PKG ${Gem_NAME}) + set(GEM_${GEM_NAME}_FOUND GEM_PKG_FOUND) + set(GEM_INCLUDE_DIRS ${GEM_PKG_INCLUDE_DIRS}) + set(GEM_LIBRARIES ${GEM_PKG_LIBRARIES} ${GEM_PKG_STATIC_LIBRARIES}) + list(APPEND GEM_LIBRARIES ${GEM_PKG_LDFLAGS} ${GEM_PKG_STATIC_LDFLAGS}) + list(APPEND GEM_LIBRARIES ${GEM_PKG_LDFLAGS_OTHER} ${GEM_PKG_STATIC_LDFLAGS_OTHER}) + + if(GEM_DEBUG) + message(STATUS "GEM_OS_PKG is defined") + message(STATUS "GEM_INCLUDE_DIRS ${GEM_INCLUDE_DIRS}") + message(STATUS "GEM_STATIC_LIBRARY_DIRS ${GEM_PKG_STATIC_LIBRARY_DIRS}") + message(STATUS "GEM_LIBRARY_DIRS ${GEM_PKG_STATIC_LIBRARY_DIRS}") + message(STATUS "GEM_STATIC_LIBRARIES ${GEM_PKG_STATIC_LIBRARIES}") + message(STATUS "GEM_LIBRARIES ${GEM_LIBRARIES}") + endif() + endif() + + if(GEM_DEBUG) + message(STATUS "${Gem_NAME} library dir: ${GEM_LIBRARIES}") + message(STATUS "${Gem_NAME} include dir: ${GEM_INCLUDE_DIRS}") + endif() +endforeach() + +# Compact the lists +if(DEFINED GEM_LIBRARIES) + LIST(REMOVE_DUPLICATES GEM_LIBRARIES) +endif() +if(DEFINED GEM_INCLUDE_DIRS) + LIST(REMOVE_DUPLICATES GEM_INCLUDE_DIRS) +endif() + +find_package_handle_standard_args(GEM + REQUIRED_VARS ${components_found_vars} + FAIL_MESSAGE "Could not find all required gems") + diff --git a/cmake/FindOsmium.cmake b/cmake/FindOsmium.cmake index 15b1e013f..4c3370843 100644 --- a/cmake/FindOsmium.cmake +++ b/cmake/FindOsmium.cmake @@ -224,8 +224,27 @@ if(Osmium_USE_SPARSEHASH) find_path(SPARSEHASH_INCLUDE_DIR google/sparsetable) if(SPARSEHASH_INCLUDE_DIR) - set(SPARSEHASH_FOUND 1) - list(APPEND OSMIUM_INCLUDE_DIRS ${SPARSEHASH_INCLUDE_DIR}) + # 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++. + # Until we find a better way, we'll live with that. + include(CheckTypeSize) + set(CMAKE_REQUIRED_INCLUDES ${SPARSEHASH_INCLUDE_DIR}) + set(CMAKE_EXTRA_INCLUDE_FILES "google/sparsetable") + check_type_size("google::sparsetable::size_type" SPARSETABLE_SIZE_TYPE LANGUAGE CXX) + set(CMAKE_EXTRA_INCLUDE_FILES) + set(CMAKE_REQUIRED_INCLUDES) + + # Sparsetable::size_type must be at least 8 bytes (64bit), otherwise + # OSM object IDs will not fit. + if(SPARSETABLE_SIZE_TYPE GREATER 7) + set(SPARSEHASH_FOUND 1) + add_definitions(-DOSMIUM_WITH_SPARSEHASH=${SPARSEHASH_FOUND}) + list(APPEND OSMIUM_INCLUDE_DIRS ${SPARSEHASH_INCLUDE_DIR}) + elseif(SPARSETABLE_SIZE_TYPE STREQUAL "") + message(WARNING "Osmium: Disabled Google SparseHash library because we can't detect whether we are on a 64bit system.") + else() + message(WARNING "Osmium: Disabled Google SparseHash library on 32bit system (size_type=${SPARSETABLE_SIZE_TYPE}).") + endif() else() set(_missing_libraries 1) message(WARNING "Osmium: Google SparseHash library is required but not found, please install it or configure the paths.") @@ -270,12 +289,20 @@ add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64) if(MSVC) add_definitions(-wd4996) + + # Disable warning C4068: "unknown pragma" because we want it to ignore + # pragmas for other compilers. add_definitions(-wd4068) # Disable warning C4715: "not all control paths return a value" because # it generates too many false positives. add_definitions(-wd4715) + # Disable warning C4351: new behavior: elements of array '...' will be + # default initialized. The new behaviour is correct and we don't support + # old compilers anyway. + add_definitions(-wd4351) + add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_WARNINGS) endif() diff --git a/cmake/README b/cmake/README new file mode 100644 index 000000000..4a035f7b2 --- /dev/null +++ b/cmake/README @@ -0,0 +1,3 @@ + +FindGem.cmake from https://github.com/rock-core/base-cmake + diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 903aad12e..9d69a16bd 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -13,6 +13,7 @@ find_package(Doxygen) if(DOXYGEN_FOUND) message(STATUS "Looking for doxygen - found") + configure_file(header.html ${CMAKE_CURRENT_BINARY_DIR}/header.html @ONLY) configure_file(Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) add_custom_target(doc ${DOXYGEN_EXECUTABLE} diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 5ce78ab59..6535259f3 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -152,7 +152,7 @@ FULL_PATH_NAMES = YES # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. -STRIP_FROM_PATH = +STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@/include # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which @@ -1047,7 +1047,7 @@ HTML_FILE_EXTENSION = .html # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_HEADER = +HTML_HEADER = header.html # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 000000000..7ca8e7cf7 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,8 @@ + +The `header.html` is created with: + +`doxygen -w html header.html footer.html stylesheet.css` + +This might have to be rn again for newer Doxygen versions. After that add +changes back in. + diff --git a/doc/header.html b/doc/header.html new file mode 100644 index 000000000..495d50024 --- /dev/null +++ b/doc/header.html @@ -0,0 +1,56 @@ + + + + + + + + +$projectname: $title +$title + + + +$treeview +$search +$mathjax + +$extrastylesheet + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + +
+
$projectname +  $projectnumber +
+
$projectbrief
+
+
$projectbrief
+
$searchbox
+
+ + diff --git a/examples/osmium_area_test.cpp b/examples/osmium_area_test.cpp index b3030a354..ee2ba1296 100644 --- a/examples/osmium_area_test.cpp +++ b/examples/osmium_area_test.cpp @@ -18,12 +18,12 @@ #include #include #include -#include +#include #include #include typedef osmium::index::map::Dummy index_neg_type; -typedef osmium::index::map::SparseMemTable index_pos_type; +typedef osmium::index::map::SparseMemArray index_pos_type; typedef osmium::handler::NodeLocationsForWays location_handler_type; class WKTDump : public osmium::handler::Handler { diff --git a/examples/osmium_toogr2.cpp b/examples/osmium_toogr2.cpp index dc5c77325..a966c5edc 100644 --- a/examples/osmium_toogr2.cpp +++ b/examples/osmium_toogr2.cpp @@ -15,9 +15,7 @@ // usually you only need one or two of these #include -#include -#include -#include +#include #include #include @@ -32,9 +30,7 @@ typedef osmium::index::map::Dummy index_neg_type; -//typedef osmium::index::map::SparseMemArray index_pos_type; -//typedef osmium::index::map::SparseMmapArray index_pos_type; -typedef osmium::index::map::SparseMemTable index_pos_type; +typedef osmium::index::map::SparseMemArray index_pos_type; typedef osmium::handler::NodeLocationsForWays location_handler_type; diff --git a/include/mmap_for_windows.hpp b/include/mmap_for_windows.hpp index d14c81148..abe62d640 100644 --- a/include/mmap_for_windows.hpp +++ b/include/mmap_for_windows.hpp @@ -34,13 +34,13 @@ #define MAP_ANON MAP_ANONYMOUS #define MAP_FAILED ((void *) -1) -#ifdef __USE_FILE_OFFSET64 -# define DWORD_HI(x) (x >> 32) -# define DWORD_LO(x) ((x) & 0xffffffff) -#else -# define DWORD_HI(x) (0) -# define DWORD_LO(x) (x) -#endif +static DWORD dword_hi(uint64_t x) { + return static_cast(x >> 32); +} + +static DWORD dword_lo(uint64_t x) { + return static_cast(x & 0xffffffff); +} static void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) { @@ -66,13 +66,14 @@ static void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t } else flProtect = PAGE_READONLY; - off_t end = length + offset; - HANDLE mmap_fd, h; + uint64_t end = static_cast(length) + offset; + HANDLE mmap_fd; if (fd == -1) mmap_fd = INVALID_HANDLE_VALUE; else mmap_fd = (HANDLE)_get_osfhandle(fd); - h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL); + + HANDLE h = CreateFileMapping(mmap_fd, NULL, flProtect, dword_hi(end), dword_lo(end), NULL); if (h == NULL) return MAP_FAILED; @@ -85,7 +86,7 @@ static void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t dwDesiredAccess |= FILE_MAP_EXECUTE; if (flags & MAP_PRIVATE) dwDesiredAccess |= FILE_MAP_COPY; - void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length); + void *ret = MapViewOfFile(h, dwDesiredAccess, dword_hi(offset), dword_lo(offset), length); if (ret == NULL) { CloseHandle(h); ret = MAP_FAILED; @@ -95,12 +96,8 @@ static void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t static int munmap(void *addr, size_t length) { - UnmapViewOfFile(addr); - return 0; + return UnmapViewOfFile(addr) ? 0 : -1; /* ruh-ro, we leaked handle from CreateFileMapping() ... */ } -#undef DWORD_HI -#undef DWORD_LO - #endif diff --git a/include/osmium/index/map/sparse_mem_table.hpp b/include/osmium/index/map/sparse_mem_table.hpp index 27b8f3963..8998a91f5 100644 --- a/include/osmium/index/map/sparse_mem_table.hpp +++ b/include/osmium/index/map/sparse_mem_table.hpp @@ -33,6 +33,8 @@ DEALINGS IN THE SOFTWARE. */ +#ifdef OSMIUM_WITH_SPARSEHASH + #include #include #include @@ -139,4 +141,6 @@ namespace osmium { } // namespace osmium +#endif // OSMIUM_WITH_SPARSEHASH + #endif // OSMIUM_INDEX_BYID_SPARSE_MEM_TABLE_HPP diff --git a/include/osmium/io/compression.hpp b/include/osmium/io/compression.hpp index f5308eacb..c1f8de2e7 100644 --- a/include/osmium/io/compression.hpp +++ b/include/osmium/io/compression.hpp @@ -75,7 +75,7 @@ namespace osmium { public: - static constexpr size_t input_buffer_size = 256 * 1024; + static constexpr unsigned int input_buffer_size = 1024 * 1024; Decompressor() = default; @@ -245,11 +245,11 @@ namespace osmium { } } else { buffer.resize(osmium::io::Decompressor::input_buffer_size); - ssize_t nread = ::read(m_fd, const_cast(buffer.data()), buffer.size()); + auto nread = ::read(m_fd, const_cast(buffer.data()), osmium::io::Decompressor::input_buffer_size); if (nread < 0) { throw std::system_error(errno, std::system_category(), "Read failed"); } - buffer.resize(static_cast(nread)); + buffer.resize(nread); } return buffer; diff --git a/include/osmium/io/detail/pbf_input_format.hpp b/include/osmium/io/detail/pbf_input_format.hpp index dc161ebab..8b997ec25 100644 --- a/include/osmium/io/detail/pbf_input_format.hpp +++ b/include/osmium/io/detail/pbf_input_format.hpp @@ -214,7 +214,12 @@ namespace osmium { if (!m_done || !m_queue.empty()) { std::future buffer_future; m_queue.wait_and_pop(buffer_future); - return buffer_future.get(); + try { + return buffer_future.get(); + } catch (...) { + m_done = true; + throw; + } } return osmium::memory::Buffer(); diff --git a/include/osmium/io/detail/read_write.hpp b/include/osmium/io/detail/read_write.hpp index 564d72147..6651cced9 100644 --- a/include/osmium/io/detail/read_write.hpp +++ b/include/osmium/io/detail/read_write.hpp @@ -43,7 +43,6 @@ DEALINGS IN THE SOFTWARE. # include #else # include -typedef int ssize_t; #endif #include @@ -123,9 +122,14 @@ namespace osmium { * @throws std::system_error On error. */ inline void reliable_write(const int fd, const unsigned char* output_buffer, const size_t size) { + constexpr size_t max_write = 100 * 1024 * 1024; // Max 100 MByte per write size_t offset = 0; do { - ssize_t length = ::write(fd, output_buffer + offset, size - offset); + auto write_count = size - offset; + if (write_count > max_write) { + write_count = max_write; + } + auto length = ::write(fd, output_buffer + offset, static_cast(write_count)); if (length < 0) { throw std::system_error(errno, std::system_category(), "Write failed"); } diff --git a/include/osmium/io/detail/zlib.hpp b/include/osmium/io/detail/zlib.hpp index d78949c08..a402bf7e6 100644 --- a/include/osmium/io/detail/zlib.hpp +++ b/include/osmium/io/detail/zlib.hpp @@ -39,6 +39,8 @@ DEALINGS IN THE SOFTWARE. #include +#include + namespace osmium { namespace io { @@ -48,19 +50,26 @@ namespace osmium { /** * Compress data using zlib. * + * Note that this function can not compress data larger than + * what fits in an unsigned long, on Windows this is usually 32bit. + * * @param input Data to compress. * @returns Compressed data. */ inline std::string zlib_compress(const std::string& input) { - unsigned long output_size = ::compressBound(input.size()); + unsigned long output_size = ::compressBound(osmium::static_cast_with_assert(input.size())); std::string output(output_size, '\0'); - if (::compress(reinterpret_cast(const_cast(output.data())), - &output_size, - reinterpret_cast(input.data()), - input.size()) != Z_OK) { - throw std::runtime_error("failed to compress data"); + auto result = ::compress( + reinterpret_cast(const_cast(output.data())), + &output_size, + reinterpret_cast(input.data()), + osmium::static_cast_with_assert(input.size()) + ); + + if (result != Z_OK) { + throw std::runtime_error(std::string("failed to compress data: ") + zError(result)); } output.resize(output_size); @@ -71,6 +80,9 @@ namespace osmium { /** * Uncompress data using zlib. * + * Note that this function can not uncompress data larger than + * what fits in an unsigned long, on Windows this is usually 32bit. + * * @param input Compressed input data. * @param raw_size Size of uncompressed data. * @returns Uncompressed data. @@ -78,11 +90,15 @@ namespace osmium { inline std::unique_ptr zlib_uncompress(const std::string& input, unsigned long raw_size) { auto output = std::unique_ptr(new std::string(raw_size, '\0')); - if (::uncompress(reinterpret_cast(const_cast(output->data())), - &raw_size, - reinterpret_cast(input.data()), - input.size()) != Z_OK) { - throw std::runtime_error("failed to uncompress data"); + auto result = ::uncompress( + reinterpret_cast(const_cast(output->data())), + &raw_size, + reinterpret_cast(input.data()), + osmium::static_cast_with_assert(input.size()) + ); + + if (result != Z_OK) { + throw std::runtime_error(std::string("failed to uncompress data: ") + zError(result)); } return output; diff --git a/include/osmium/thread/queue.hpp b/include/osmium/thread/queue.hpp index 5c5f8e768..12e593274 100644 --- a/include/osmium/thread/queue.hpp +++ b/include/osmium/thread/queue.hpp @@ -43,11 +43,13 @@ DEALINGS IN THE SOFTWARE. #include #include +#include + namespace osmium { namespace thread { - constexpr std::chrono::milliseconds full_queue_sleep_duration { 10 }; // XXX + OSMIUM_CONSTEXPR std::chrono::milliseconds full_queue_sleep_duration { 10 }; // XXX /** * A thread-safe queue. diff --git a/include/osmium/util/cast.hpp b/include/osmium/util/cast.hpp index 13e6e3a9c..80adadf80 100644 --- a/include/osmium/util/cast.hpp +++ b/include/osmium/util/cast.hpp @@ -33,36 +33,66 @@ DEALINGS IN THE SOFTWARE. */ -#include +#ifndef assert +# include +#endif + #include #include namespace osmium { - template ::value && std::is_integral::value && std::is_signed::value && std::is_signed::value, int>::type = 0> + // These functions are wrappers around static_cast<>() that call assert() + // to check that there is no integer overflow happening before doing the + // cast. There are several versions of this templated function here + // depending on the types of the input and output. In any case, both input + // and output have to be integral types. If the cast can't overflow, no + // check is done. + + template + struct are_real_integers : + std::integral_constant::value && + std::is_integral::value && + !std::is_same::value && + !std::is_same::value> { + }; + + template ::value && std::is_same::value, int>::type = 0> + inline T static_cast_with_assert(const F value) { + return value; + } + + template ::value && !std::is_same::value && (sizeof(T) > sizeof(F)), int>::type = 0> + inline T static_cast_with_assert(const F value) { + return static_cast(value); + } + + template ::value && !std::is_same::value && std::is_signed::value == std::is_signed::value && (sizeof(T) == sizeof(F)), int>::type = 0> + inline T static_cast_with_assert(const F value) { + return static_cast(value); + } + + template ::value && !std::is_same::value && (sizeof(T) < sizeof(F)) && std::is_signed::value && std::is_signed::value, int>::type = 0> inline T static_cast_with_assert(const F value) { - static_assert(sizeof(T) < sizeof(F), "unnecessary static_cast_with_assert when casting into type of equal or larger size"); assert(value >= std::numeric_limits::min() && value <= std::numeric_limits::max()); return static_cast(value); } - template ::value && std::is_integral::value && std::is_unsigned::value && std::is_signed::value, int>::type = 0> + template ::value && !std::is_same::value && (sizeof(T) <= sizeof(F)) && std::is_unsigned::value && std::is_signed::value, int>::type = 0> inline T static_cast_with_assert(const F value) { - static_assert(sizeof(T) <= sizeof(F), "unnecessary static_cast_with_assert when casting into type of larger size"); assert(value >= 0 && static_cast::type>(value) <= std::numeric_limits::max()); return static_cast(value); } - template ::value && std::is_integral::value && std::is_unsigned::value && std::is_unsigned::value, int>::type = 0> + template ::value && !std::is_same::value && (sizeof(T) < sizeof(F)) && std::is_unsigned::value && std::is_unsigned::value, int>::type = 0> inline T static_cast_with_assert(const F value) { - static_assert(sizeof(T) < sizeof(F), "unnecessary static_cast_with_assert when casting into type of equal or larger size"); assert(value <= std::numeric_limits::max()); return static_cast(value); } - template ::value && std::is_integral::value && std::is_signed::value && std::is_unsigned::value, int>::type = 0> + template ::value && !std::is_same::value && (sizeof(T) <= sizeof(F)) && std::is_signed::value && std::is_unsigned::value, int>::type = 0> inline T static_cast_with_assert(const F value) { - static_assert(sizeof(T) <= sizeof(F), "unnecessary static_cast_with_assert when casting into type of larger size"); assert(value <= std::numeric_limits::max()); return static_cast(value); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9e27b120c..334fe3130 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -109,6 +109,9 @@ add_unit_test(tags test_filter) add_unit_test(tags test_operators) add_unit_test(tags test_tag_list) +add_unit_test(thread test_pool ${Threads_FOUND} ${CMAKE_THREAD_LIBS_INIT}) + +add_unit_test(util test_cast_with_assert) add_unit_test(util test_double) add_unit_test(util test_options) add_unit_test(util test_string) diff --git a/test/data-tests/CMakeLists.txt b/test/data-tests/CMakeLists.txt index a2938e519..89aead98e 100644 --- a/test/data-tests/CMakeLists.txt +++ b/test/data-tests/CMakeLists.txt @@ -87,32 +87,29 @@ set_tests_properties(testdata-overview PROPERTIES # multipolygon # #----------------------------------------------------------------------------- -add_executable(testdata-multipolygon testdata-multipolygon.cpp) -target_link_libraries(testdata-multipolygon - ${OSMIUM_XML_LIBRARIES} - ${GDAL_LIBRARIES} -) -if(WIN32) - set(MULTIPOLYGON_TEST_SCRIPT "run-testdata-multipolygon.bat") +find_package(Ruby 1.9) +find_package(Gem COMPONENTS json) +find_program(SPATIALITE spatialite) + +if(RUBY_FOUND AND GEM_json_FOUND AND SPATIALITE) + add_executable(testdata-multipolygon testdata-multipolygon.cpp) + target_link_libraries(testdata-multipolygon + ${OSMIUM_XML_LIBRARIES} + ${GDAL_LIBRARIES} + ) + + add_test(NAME testdata-multipolygon + COMMAND ${CMAKE_COMMAND} + -D OSM_TESTDATA=${OSM_TESTDATA} + -D RUBY=${RUBY_EXECUTABLE} + -P ${CMAKE_CURRENT_SOURCE_DIR}/run-testdata-multipolygon.cmake) + + set_tests_properties(testdata-multipolygon PROPERTIES LABELS "data;slow") else() - set(MULTIPOLYGON_TEST_SCRIPT "run-testdata-multipolygon.sh") + message(WARNING "Disabled testdata-multipolygon test because 'ruby' and/or 'json' ruby gem and/or 'spatialite' was not found") endif() -if(MSVC) - set(EXE_DIR ${CMAKE_BUILD_TYPE}) -else() - set(EXE_DIR .) -endif() - -add_test(NAME testdata-multipolygon - COMMAND ${CMAKE_SOURCE_DIR}/test/data-tests/${MULTIPOLYGON_TEST_SCRIPT} - ${OSM_TESTDATA} - ${EXE_DIR} -) -set_tests_properties(testdata-multipolygon PROPERTIES - LABELS "data;slow") - #----------------------------------------------------------------------------- message(STATUS "Configuring data tests - done") diff --git a/test/data-tests/README.md b/test/data-tests/README.md index d381f6540..5138bf856 100644 --- a/test/data-tests/README.md +++ b/test/data-tests/README.md @@ -5,19 +5,6 @@ repository at https://github.com/osmcode/osm-testdata . To use it, clone the `osm-testdata` repository in the same directory where you cloned the `libosmium` repository. -## Overview - -The `testdata-overview` program can be used to create a Spatialite file -containing all the nodes and ways from the test data files. - -Compile it by running `make testdata-overview`, run it my calling -`make overview`. - -## Running the Tests - -Actual tests are in `testcases` subdirectory, one per test from the -osm-testdata repository. - -To compile the tests, call `make runtests`, to run them call -`make test`. +Tests will be built if the CMake option `BUILD_DATA_TESTS` is set and run as +part of the `ctest` run. diff --git a/test/data-tests/run-testdata-multipolygon.bat b/test/data-tests/run-testdata-multipolygon.bat deleted file mode 100644 index 838ce9f7f..000000000 --- a/test/data-tests/run-testdata-multipolygon.bat +++ /dev/null @@ -1,7 +0,0 @@ -set TESTDATA_DIR=%1 - -del multipolygon.db multipolygon-tests.json -%2\testdata-multipolygon %TESTDATA_DIR%\grid\data\all.osm >multipolygon.log 2>&1 -if ERRORLEVEL 1 (exit /b 1) -ruby %TESTDATA_DIR%\bin\compare-areas.rb %TESTDATA_DIR%\grid\data\tests.json multipolygon-tests.json -if ERRORLEVEL 1 (exit /b 1) diff --git a/test/data-tests/run-testdata-multipolygon.cmake b/test/data-tests/run-testdata-multipolygon.cmake new file mode 100644 index 000000000..0d08f5a52 --- /dev/null +++ b/test/data-tests/run-testdata-multipolygon.cmake @@ -0,0 +1,46 @@ +#----------------------------------------------------------------------------- +# +# Helper script that runs the 'multipolygon' test. +# +#----------------------------------------------------------------------------- + +# Remove files that might be left over from previous run +file(REMOVE multipolygon.db multipolygon-tests.json) + + +#----------------------------------------------------------------------------- +# +# Create multipolygons from test data. +# +#----------------------------------------------------------------------------- +execute_process( + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/testdata-multipolygon + ${OSM_TESTDATA}/grid/data/all.osm + RESULT_VARIABLE _result + OUTPUT_FILE multipolygon.log + ERROR_FILE multipolygon.log +) + +if(_result) + message(FATAL_ERROR "Error running testdata-multipolygon command") +endif() + + +#----------------------------------------------------------------------------- +# +# Compare created multipolygons with reference data. +# +#----------------------------------------------------------------------------- +execute_process( + COMMAND ${RUBY} ${OSM_TESTDATA}/bin/compare-areas.rb + ${OSM_TESTDATA}/grid/data/tests.json + multipolygon-tests.json + RESULT_VARIABLE _result +) + +if(_result) + message(FATAL_ERROR "Error running compare-areas command") +endif() + + +#----------------------------------------------------------------------------- diff --git a/test/data-tests/run-testdata-multipolygon.sh b/test/data-tests/run-testdata-multipolygon.sh deleted file mode 100755 index dcd57a84a..000000000 --- a/test/data-tests/run-testdata-multipolygon.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -# helper script needed by cmake to run test - -TESTDATA_DIR=$1 - -rm -f multipolygon.db multipolygon-tests.json -./testdata-multipolygon ${TESTDATA_DIR}/grid/data/all.osm >multipolygon.log 2>&1 && - ${TESTDATA_DIR}/bin/compare-areas.rb ${TESTDATA_DIR}/grid/data/tests.json multipolygon-tests.json - diff --git a/test/data-tests/testdata-xml.cpp b/test/data-tests/testdata-xml.cpp index 16133a92a..94af6f961 100644 --- a/test/data-tests/testdata-xml.cpp +++ b/test/data-tests/testdata-xml.cpp @@ -46,7 +46,7 @@ std::string read_file(const char* test_id) { assert(fd >= 0); std::string input(10000, '\0'); - ssize_t n = ::read(fd, reinterpret_cast(const_cast(input.data())), 10000); + auto n = ::read(fd, reinterpret_cast(const_cast(input.data())), 10000); assert(n >= 0); input.resize(static_cast(n)); diff --git a/test/t/index/test_id_to_location.cpp b/test/t/index/test_id_to_location.cpp index bc2ec446a..fbb3f6a97 100644 --- a/test/t/index/test_id_to_location.cpp +++ b/test/t/index/test_id_to_location.cpp @@ -108,6 +108,8 @@ SECTION("DenseFileArray") { test_func_real(index2); } +#ifdef OSMIUM_WITH_SPARSEHASH + SECTION("SparseMemTable") { typedef osmium::index::map::SparseMemTable index_type; @@ -118,6 +120,8 @@ SECTION("SparseMemTable") { test_func_real(index2); } +#endif + SECTION("SparseMemMap") { typedef osmium::index::map::SparseMemMap index_type; diff --git a/test/t/index/test_typed_mmap.cpp b/test/t/index/test_typed_mmap.cpp index 745535d95..df95dc267 100644 --- a/test/t/index/test_typed_mmap.cpp +++ b/test/t/index/test_typed_mmap.cpp @@ -53,10 +53,9 @@ SECTION("Remap") { SECTION("FileSize") { const int size = 100; - char filename[] = "/tmp/osmium_unit_test_XXXXXX"; + char filename[] = "test_mmap_file_size_XXXXXX"; const int fd = mkstemp(filename); REQUIRE(fd > 0); - REQUIRE(0 == unlink(filename)); REQUIRE(0 == osmium::detail::typed_mmap::file_size(fd)); REQUIRE(0 == ftruncate(fd, size * sizeof(uint64_t))); REQUIRE(size == osmium::detail::typed_mmap::file_size(fd)); @@ -69,14 +68,16 @@ SECTION("FileSize") { osmium::detail::typed_mmap::grow_file(size * 2, fd); REQUIRE((size * 2) == osmium::detail::typed_mmap::file_size(fd)); + + REQUIRE(0 == close(fd)); + REQUIRE(0 == unlink(filename)); } SECTION("GrowAndMap") { const int size = 100; - char filename[] = "/tmp/osmium_unit_test_XXXXXX"; + char filename[] = "test_mmap_grow_and_map_XXXXXX"; const int fd = mkstemp(filename); REQUIRE(fd > 0); - REQUIRE(0 == unlink(filename)); uint64_t* data = osmium::detail::typed_mmap::grow_and_map(size, fd); REQUIRE(size == osmium::detail::typed_mmap::file_size(fd)); @@ -90,6 +91,9 @@ SECTION("GrowAndMap") { REQUIRE(27ul == data[99]); osmium::detail::typed_mmap::unmap(data, size); + + REQUIRE(0 == close(fd)); + REQUIRE(0 == unlink(filename)); } } diff --git a/test/t/io/test_reader.cpp b/test/t/io/test_reader.cpp index 22f1aa24b..9a06d8408 100644 --- a/test/t/io/test_reader.cpp +++ b/test/t/io/test_reader.cpp @@ -65,7 +65,7 @@ TEST_CASE("Reader") { const size_t buffer_size = 1000; char buffer[buffer_size]; - ssize_t length = ::read(fd, buffer, buffer_size); + auto length = ::read(fd, buffer, buffer_size); REQUIRE(length > 0); osmium::io::File file(buffer, static_cast(length), "osm"); @@ -83,7 +83,7 @@ TEST_CASE("Reader") { const size_t buffer_size = 1000; char buffer[buffer_size]; - ssize_t length = ::read(fd, buffer, buffer_size); + auto length = ::read(fd, buffer, buffer_size); REQUIRE(length > 0); osmium::io::File file(buffer, static_cast(length), "osm.gz"); @@ -101,7 +101,7 @@ TEST_CASE("Reader") { const size_t buffer_size = 1000; char buffer[buffer_size]; - ssize_t length = ::read(fd, buffer, buffer_size); + auto length = ::read(fd, buffer, buffer_size); REQUIRE(length > 0); osmium::io::File file(buffer, static_cast(length), "osm.bz2"); diff --git a/test/t/thread/test_pool.cpp b/test/t/thread/test_pool.cpp new file mode 100644 index 000000000..4bbf9ee59 --- /dev/null +++ b/test/t/thread/test_pool.cpp @@ -0,0 +1,69 @@ +#include "catch.hpp" + +#include +#include +#include + +#include + +static std::atomic result; + +struct test_job_ok { + void operator()() const { + result = 1; + } +}; + +struct test_job_with_result { + int operator()() const { + return 42; + } +}; + +struct test_job_throw { + void operator()() const { + throw std::runtime_error("exception in pool thread"); + } +}; + +TEST_CASE("thread") { + + SECTION("can get access to thread pool") { + auto& pool = osmium::thread::Pool::instance(); + REQUIRE(pool.queue_empty()); + } + + SECTION("can send job to thread pool") { + auto& pool = osmium::thread::Pool::instance(); + result = 0; + auto future = pool.submit(test_job_ok{}); + + // wait a bit for the other thread to get a chance to run + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + + REQUIRE(result == 1); + + future.get(); + + REQUIRE(true); + } + + SECTION("can send job to thread pool") { + auto& pool = osmium::thread::Pool::instance(); + auto future = pool.submit(test_job_with_result{}); + + REQUIRE(future.get() == 42); + } + + SECTION("can throw from job in thread pool") { + auto& pool = osmium::thread::Pool::instance(); + result = 0; + + bool got_exception = false; + auto future = pool.submit(test_job_throw{}); + + REQUIRE_THROWS_AS(future.get(), std::runtime_error); + } + +} + diff --git a/test/t/util/test_cast_with_assert.cpp b/test/t/util/test_cast_with_assert.cpp new file mode 100644 index 000000000..0231f30e1 --- /dev/null +++ b/test/t/util/test_cast_with_assert.cpp @@ -0,0 +1,89 @@ +#include "catch.hpp" + +// Define assert() to throw this error. This enables the tests to check that +// the assert() fails. +struct assert_error : public std::runtime_error { + assert_error(const char* what_arg) : std::runtime_error(what_arg) { + } +}; +#define assert(x) if (!(x)) { throw(assert_error(#x)); } + +#include + +TEST_CASE("static_cast_with_assert") { + + SECTION("same types is always okay") { + int f = 10; + auto t = osmium::static_cast_with_assert(f); + REQUIRE(t == f); + } + + SECTION("casting to larger type is always okay") { + int16_t f = 10; + auto t = osmium::static_cast_with_assert(f); + REQUIRE(t == f); + } + + + SECTION("cast int32_t -> int_16t should not trigger assert for small int") { + int32_t f = 100; + auto t = osmium::static_cast_with_assert(f); + REQUIRE(t == f); + } + + SECTION("cast int32_t -> int_16t should trigger assert for large int") { + int32_t f = 100000; + REQUIRE_THROWS_AS(osmium::static_cast_with_assert(f), assert_error); + } + + + SECTION("cast int16_t -> uint16_t should not trigger assert for zero") { + int16_t f = 0; + auto t = osmium::static_cast_with_assert(f); + REQUIRE(t == f); + } + + SECTION("cast int16_t -> uint16_t should not trigger assert for positive int") { + int16_t f = 1; + auto t = osmium::static_cast_with_assert(f); + REQUIRE(t == f); + } + + SECTION("cast int16_t -> uint16_t should trigger assert for negative int") { + int16_t f = -1; + REQUIRE_THROWS_AS(osmium::static_cast_with_assert(f), assert_error); + } + + + SECTION("cast uint32_t -> uint_16t should not trigger assert for zero") { + uint32_t f = 0; + auto t = osmium::static_cast_with_assert(f); + REQUIRE(t == f); + } + + SECTION("cast uint32_t -> uint_16t should not trigger assert for small int") { + uint32_t f = 100; + auto t = osmium::static_cast_with_assert(f); + REQUIRE(t == f); + } + + SECTION("cast int32_t -> int_16t should trigger assert for large int") { + uint32_t f = 100000; + REQUIRE_THROWS_AS(osmium::static_cast_with_assert(f), assert_error); + } + + + SECTION("cast uint16_t -> int16_t should not trigger assert for small int") { + uint16_t f = 1; + auto t = osmium::static_cast_with_assert(f); + REQUIRE(t == f); + } + + SECTION("cast uint16_t -> int16_t should trigger assert for large int") { + uint16_t f = 65000; + REQUIRE_THROWS_AS(osmium::static_cast_with_assert(f), assert_error); + } + + +} + From 7829e3c132e31bed27a625c34067dab4b735187c Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Thu, 5 Mar 2015 00:12:26 +0100 Subject: [PATCH 292/360] Add step definition and support code for matching --- features/step_definitions/matching.rb | 88 +++++++++++++++++++++++++++ features/support/match.rb | 30 +++++++++ 2 files changed, 118 insertions(+) create mode 100644 features/step_definitions/matching.rb create mode 100644 features/support/match.rb diff --git a/features/step_definitions/matching.rb b/features/step_definitions/matching.rb new file mode 100644 index 000000000..c5d25f3d8 --- /dev/null +++ b/features/step_definitions/matching.rb @@ -0,0 +1,88 @@ +When /^I match I should get$/ do |table| + reprocess + actual = [] + OSRMLoader.load(self,"#{prepared_file}.osrm") do + table.hashes.each_with_index do |row,ri| + if row['request'] + got = {'request' => row['request'] } + response = request_url row['request'] + else + params = @query_params + trace = [] + timestamps = [] + if row['trace'] + row['trace'].split(',').each do |n| + node = find_node_by_name(n.strip) + raise "*** unknown waypoint node '#{n.strip}" unless node + trace << node + end + got = {'trace' => row['trace'] } + response = request_matching trace, timestamps, params + else + raise "*** no waypoints" + end + end + + row.each_pair do |k,v| + if k =~ /param:(.*)/ + if v=='(nil)' + params[$1]=nil + elsif v!=nil + params[$1]=v + end + got[k]=v + end + end + + if response.body.empty? == false + json = JSON.parse response.body + end + + if table.headers.include? 'status' + got['status'] = json['status'].to_s + end + if table.headers.include? 'message' + got['message'] = json['status_message'] + end + if table.headers.include? '#' # comment column + got['#'] = row['#'] # copy value so it always match + end + + sub_matchings = [] + if response.code == "200" + if table.headers.include? 'matchings' + sub_matchings = json['matchings'].compact.map { |sub| sub['matched_points']} + end + end + + ok = true + encoded_result = "" + extended_target = "" + row['matchings'].split(',').each_with_index do |sub, sub_idx| + sub.length.times do |node_idx| + node = find_node_by_name(sub[node_idx]) + out_node = sub_matchings[sub_idx][node_idx] + if FuzzyMatch.match_location out_node, node + encoded_result += sub[node_idx] + extended_target += sub[node_idx] + else + encoded_result += "[#{out_node[0]},#{out_node[1]}]" + extended_target += "#{sub[node_idx]} [#{node.lat},#{node.lon}]" + ok = false + end + end + end + if ok + got['matchings'] = row['matchings'] + else + got['matchings'] = encoded_result + row['matchings'] = extended_target + log_fail row,got, { 'matching' => {:query => @query, :response => response} } + end + + actual << got + end + end + table.routing_diff! actual +end + diff --git a/features/support/match.rb b/features/support/match.rb new file mode 100644 index 000000000..9a18a3a15 --- /dev/null +++ b/features/support/match.rb @@ -0,0 +1,30 @@ +require 'net/http' + +HOST = "http://127.0.0.1:#{OSRM_PORT}" +DESTINATION_REACHED = 15 #OSRM instruction code + +class Hash + def to_param(namespace = nil) + collect do |key, value| + "#{key}=#{value}" + end.sort + end +end + +def request_matching trace=[], timestamps=[], options={} + defaults = { 'output' => 'json' } + locs = waypoints.compact.map { |w| "loc=#{w.lat},#{w.lon}" } + ts = timestamps.compact.map { |t| "t=#{t}" } + params = (locs + ts + defaults.merge(options).to_param).join('&') + params = nil if params=="" + uri = URI.parse ["#{HOST}/match", params].compact.join('?') + @query = uri.to_s + Timeout.timeout(OSRM_TIMEOUT) do + Net::HTTP.get_response uri + end +rescue Errno::ECONNREFUSED => e + raise "*** osrm-routed is not running." +rescue Timeout::Error + raise "*** osrm-routed did not respond." +end + From 5694aeda5f94ddd3b820854b05b34101618e1dca Mon Sep 17 00:00:00 2001 From: RockLobster Date: Thu, 5 Mar 2015 11:30:52 +0100 Subject: [PATCH 293/360] FIX: Moved the GeometryCompressor's free_list_maximum into a member variable of the class. (+UniqueNumber() commented out since it is not being used anywhere in all of OSRM) There was absolutely no need for free_list_maximum to be a static variable and it caused major issues in my code. Short description: - I ran osrm-prepare's Prepare().Process(..) function in my own code multiple times for multiple files => After the first file is done, free_list_maximum is still on the same size, but a new GeometryCompressor will start at a size of 100 again. => Indices broken. --- contractor/geometry_compressor.cpp | 3 +-- contractor/geometry_compressor.hpp | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/contractor/geometry_compressor.cpp b/contractor/geometry_compressor.cpp index 5af89c297..e40143ad5 100644 --- a/contractor/geometry_compressor.cpp +++ b/contractor/geometry_compressor.cpp @@ -35,8 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -int free_list_maximum = 0; -int UniqueNumber() { return ++free_list_maximum; } +//int UniqueNumber() { return ++free_list_maximum; } GeometryCompressor::GeometryCompressor() { diff --git a/contractor/geometry_compressor.hpp b/contractor/geometry_compressor.hpp index dd5748d91..ca83fa44c 100644 --- a/contractor/geometry_compressor.hpp +++ b/contractor/geometry_compressor.hpp @@ -58,6 +58,8 @@ class GeometryCompressor NodeID GetLastNodeIDOfBucket(const EdgeID edge_id) const; private: + int free_list_maximum = 0; + void IncreaseFreeList(); std::vector> m_compressed_geometries; std::vector m_free_list; From dd94a640488b4bd1573fd6fd0293b5de2119fce2 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 5 Mar 2015 14:03:35 +0100 Subject: [PATCH 294/360] remove lint from #1409 - fix copyright header - remove dead code --- contractor/geometry_compressor.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contractor/geometry_compressor.cpp b/contractor/geometry_compressor.cpp index e40143ad5..3997cdc99 100644 --- a/contractor/geometry_compressor.cpp +++ b/contractor/geometry_compressor.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2015, Project OSRM, Dennis Luxen, others +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -35,8 +35,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -//int UniqueNumber() { return ++free_list_maximum; } - GeometryCompressor::GeometryCompressor() { m_free_list.reserve(100); From 736bc87480309ddf3cd20b534d1c6d0243607b35 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sat, 7 Mar 2015 23:02:14 +0100 Subject: [PATCH 295/360] Fix inverted operator in maximum check --- plugins/match.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/match.hpp b/plugins/match.hpp index 88454eeb9..74e0c8491 100644 --- a/plugins/match.hpp +++ b/plugins/match.hpp @@ -232,7 +232,7 @@ template class MapMatchingPlugin : public BasePlugin // enforce maximum number of locations for performance reasons if (max_locations_map_matching > 0 && - static_cast(input_coords.size()) > max_locations_map_matching) + static_cast(input_coords.size()) < max_locations_map_matching) { return 400; } From 0c735953c9408fe69fe3da64c983ea78e85a744c Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sun, 8 Mar 2015 00:51:07 +0100 Subject: [PATCH 296/360] Make uturn detection a little less sensitive. --- plugins/match.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/match.hpp b/plugins/match.hpp index 74e0c8491..2a9fa043f 100644 --- a/plugins/match.hpp +++ b/plugins/match.hpp @@ -124,7 +124,7 @@ template class MapMatchingPlugin : public BasePlugin input_coords[current_coordinate + 1]); // sharp turns indicate a possible uturn - if (turn_angle < 100.0 || turn_angle > 260.0) + if (turn_angle <= 90.0 || turn_angle >= 270.0) { allow_uturn = true; } From 028fad94af5348965d2530ce37cea5df88e3ca1a Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sun, 8 Mar 2015 00:53:15 +0100 Subject: [PATCH 297/360] Fix overflows when handling size_t --- data_structures/hidden_markov_model.hpp | 1 - routing_algorithms/map_matching.hpp | 31 +++++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/data_structures/hidden_markov_model.hpp b/data_structures/hidden_markov_model.hpp index bae2ba55a..403f76608 100644 --- a/data_structures/hidden_markov_model.hpp +++ b/data_structures/hidden_markov_model.hpp @@ -41,7 +41,6 @@ namespace osrm { namespace matching { -// FIXME this value should be a table based on samples/meter (or samples/min) static const double log_2_pi = std::log(2. * M_PI); static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits::infinity(); static const double MINIMAL_LOG_PROB = std::numeric_limits::lowest(); diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 89c4e357c..80fe49cce 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -88,7 +88,7 @@ class MapMatching final : public BasicRoutingInterface::max(); - std::vector split_points; - std::vector prev_unbroken_timestamps; + std::size_t breakage_begin = osrm::matching::INVALID_STATE; + std::vector split_points; + std::vector prev_unbroken_timestamps; prev_unbroken_timestamps.reserve(candidates_list.size()); prev_unbroken_timestamps.push_back(initial_timestamp); for (auto t = initial_timestamp + 1; t < candidates_list.size(); ++t) @@ -133,22 +133,23 @@ class MapMatching final : public BasicRoutingInterface::max()) + std::size_t split_index = t; + if (breakage_begin != osrm::matching::INVALID_STATE) { split_index = breakage_begin; - breakage_begin = std::numeric_limits::max(); + breakage_begin = osrm::matching::INVALID_STATE; } split_points.push_back(split_index); // note: this preserves everything before split_index model.clear(split_index); - unsigned new_start = model.initialize(split_index); + std::size_t new_start = model.initialize(split_index); // no new start was found -> stop viterbi calculation if (new_start == osrm::matching::INVALID_STATE) { break; } + prev_unbroken_timestamps.clear(); prev_unbroken_timestamps.push_back(new_start); // Important: We potentially go back here! @@ -158,7 +159,7 @@ class MapMatching final : public BasicRoutingInterface= sub_matching_begin && model.breakage[parent_timestamp_index]) { @@ -287,10 +288,10 @@ class MapMatching final : public BasicRoutingInterface> reconstructed_indices; + std::deque> reconstructed_indices; while (parent_timestamp_index > sub_matching_begin) { if (model.breakage[parent_timestamp_index]) From bc8666df8318dd5118bfbdda21ca63737bff961a Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sun, 8 Mar 2015 01:32:13 +0100 Subject: [PATCH 298/360] Add tests for matching --- features/step_definitions/matching.rb | 20 +++++++--- features/support/match.rb | 18 ++++----- features/testbot/matching.feature | 55 +++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 17 deletions(-) create mode 100644 features/testbot/matching.feature diff --git a/features/step_definitions/matching.rb b/features/step_definitions/matching.rb index c5d25f3d8..3f3181f64 100644 --- a/features/step_definitions/matching.rb +++ b/features/step_definitions/matching.rb @@ -11,15 +11,18 @@ When /^I match I should get$/ do |table| trace = [] timestamps = [] if row['trace'] - row['trace'].split(',').each do |n| + row['trace'].each_char do |n| node = find_node_by_name(n.strip) raise "*** unknown waypoint node '#{n.strip}" unless node trace << node end + if row['timestamps'] + timestamps = row['timestamps'].split(" ").compact.map { |t| t.to_i} + end got = {'trace' => row['trace'] } response = request_matching trace, timestamps, params else - raise "*** no waypoints" + raise "*** no trace" end end @@ -59,6 +62,10 @@ When /^I match I should get$/ do |table| encoded_result = "" extended_target = "" row['matchings'].split(',').each_with_index do |sub, sub_idx| + if sub_idx >= sub_matchings.length + ok = false + break + end sub.length.times do |node_idx| node = find_node_by_name(sub[node_idx]) out_node = sub_matchings[sub_idx][node_idx] @@ -66,17 +73,18 @@ When /^I match I should get$/ do |table| encoded_result += sub[node_idx] extended_target += sub[node_idx] else - encoded_result += "[#{out_node[0]},#{out_node[1]}]" + encoded_result += "? [#{out_node[0]},#{out_node[1]}]" extended_target += "#{sub[node_idx]} [#{node.lat},#{node.lon}]" ok = false end end end if ok - got['matchings'] = row['matchings'] + got['matchings'] = row['matchings'] + got['timestamps'] = row['timestamps'] else - got['matchings'] = encoded_result - row['matchings'] = extended_target + got['matchings'] = encoded_result + row['matchings'] = extended_target log_fail row,got, { 'matching' => {:query => @query, :response => response} } end diff --git a/features/support/match.rb b/features/support/match.rb index 9a18a3a15..bf51189a4 100644 --- a/features/support/match.rb +++ b/features/support/match.rb @@ -1,21 +1,17 @@ require 'net/http' HOST = "http://127.0.0.1:#{OSRM_PORT}" -DESTINATION_REACHED = 15 #OSRM instruction code - -class Hash - def to_param(namespace = nil) - collect do |key, value| - "#{key}=#{value}" - end.sort - end -end def request_matching trace=[], timestamps=[], options={} defaults = { 'output' => 'json' } - locs = waypoints.compact.map { |w| "loc=#{w.lat},#{w.lon}" } + locs = trace.compact.map { |w| "loc=#{w.lat},#{w.lon}" } ts = timestamps.compact.map { |t| "t=#{t}" } - params = (locs + ts + defaults.merge(options).to_param).join('&') + if ts.length > 0 + trace_params = locs.zip(ts).map { |a| a.join('&')} + else + trace_params = locs + end + params = (trace_params + defaults.merge(options).to_param).join('&') params = nil if params=="" uri = URI.parse ["#{HOST}/match", params].compact.join('?') @query = uri.to_s diff --git a/features/testbot/matching.feature b/features/testbot/matching.feature new file mode 100644 index 000000000..47630e9b6 --- /dev/null +++ b/features/testbot/matching.feature @@ -0,0 +1,55 @@ +@match @testbot +Feature: Basic Map Matching + + Background: + Given the profile "testbot" + Given a grid size of 10 meters + + Scenario: Testbot - Map matching with trace splitting + Given the node map + | a | b | c | d | + | | | e | | + + And the ways + | nodes | oneway | + | abcd | no | + + When I match I should get + | trace | timestamps | matchings | + | abcd | 0 1 42 43 | ab,cd | + + Scenario: Testbot - Map matching with small distortion + Given the node map + | a | b | c | d | e | + | | f | | | | + | | | | | | + | | | | | | + | | | | | | + | | h | | | k | + + # The second way does not need to be a oneway + # but the grid spacing triggers the uturn + # detection on f + And the ways + | nodes | oneway | + | abcde | no | + | bfhke | yes | + + When I match I should get + | trace | matchings | + | afcde | abcde | + + Scenario: Testbot - Map matching with oneways + Given the node map + | a | b | c | d | + | e | f | g | h | + + And the ways + | nodes | oneway | + | abcd | yes | + | hgfe | yes | + + When I match I should get + | trace | matchings | + | dcba | hgfe | + From 02b561edd222def8c0abd74667acbdbf74d8feab Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Tue, 17 Mar 2015 23:24:31 +0100 Subject: [PATCH 299/360] Pass route leg by reference, not by value --- descriptors/json_descriptor.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/descriptors/json_descriptor.hpp b/descriptors/json_descriptor.hpp index 352b55a94..13b68c6ec 100644 --- a/descriptors/json_descriptor.hpp +++ b/descriptors/json_descriptor.hpp @@ -79,7 +79,7 @@ template class JSONDescriptor final : public BaseDescriptor< virtual void SetConfig(const DescriptorConfig &c) override final { config = c; } - unsigned DescribeLeg(const std::vector route_leg, + unsigned DescribeLeg(const std::vector &route_leg, const PhantomNodes &leg_phantoms, const bool target_traversed_in_reverse, const bool is_via_leg) From 7813dafc96ea5789df31a6782d7a36dcce494628 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Tue, 17 Mar 2015 02:13:20 +0100 Subject: [PATCH 300/360] Increase the time split threshold to a more reasonable value --- routing_algorithms/map_matching.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 80fe49cce..580e9d980 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -60,7 +60,7 @@ using HMM = HiddenMarkovModel; using SubMatchingList = std::vector; constexpr static const unsigned MAX_BROKEN_STATES = 6; -constexpr static const unsigned MAX_BROKEN_TIME = 30; +constexpr static const unsigned MAX_BROKEN_TIME = 60; constexpr static const double default_beta = 10.0; constexpr static const double default_sigma_z = 4.07; From d3b9911445c86058d97647b95753bcc34c0780bd Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Tue, 17 Mar 2015 23:50:20 +0100 Subject: [PATCH 301/360] Fix match geometry output --- plugins/match.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/match.hpp b/plugins/match.hpp index 2a9fa043f..bc4738d50 100644 --- a/plugins/match.hpp +++ b/plugins/match.hpp @@ -194,6 +194,11 @@ template class MapMatchingPlugin : public BasePlugin raw_route.target_traversed_in_reverse[i], raw_route.is_via_leg(i)); } + // we need this because we don't run DP + for (auto& segment : factory.path_description) + { + segment.necessary = true; + } subtrace.values["geometry"] = factory.AppendGeometryString(route_parameters.compression); } From 78735fae6b24989298209b86fde09d2eacc0cd3a Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Wed, 18 Mar 2015 00:21:04 +0100 Subject: [PATCH 302/360] Fix match test by using the new threshold --- features/testbot/matching.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/testbot/matching.feature b/features/testbot/matching.feature index 47630e9b6..774e8a9d6 100644 --- a/features/testbot/matching.feature +++ b/features/testbot/matching.feature @@ -16,7 +16,7 @@ Feature: Basic Map Matching When I match I should get | trace | timestamps | matchings | - | abcd | 0 1 42 43 | ab,cd | + | abcd | 0 1 62 63 | ab,cd | Scenario: Testbot - Map matching with small distortion Given the node map From 5565662d87abf09552b4faaaadb778f46ce2024e Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 23 Mar 2015 16:14:24 +0100 Subject: [PATCH 303/360] fix compilation with CMake 3.2, closes #1422 CMake 3.2 changed the behavior of add_custom_command and ungenerated dependencies. Replaced with add_custom_target that works on version 2.8+ --- CMakeLists.txt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ee97ccfdc..923961378 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,15 +34,12 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/third_party/) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/include/) -add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/util/fingerprint.cpp fingerprint.cpp.alwaysbuild - COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} +add_custom_target(FingerPrintConfigure ALL + ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FingerPrint-Config.cmake - DEPENDS - ${CMAKE_CURRENT_SOURCE_DIR}/util/fingerprint.cpp.in - COMMENT "Configuring fingerprint.cpp" + COMMENT "Configuring revision fingerprint" VERBATIM) -add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/util/fingerprint.cpp) add_custom_target(tests DEPENDS datastructure-tests algorithm-tests) add_custom_target(benchmarks DEPENDS rtree-bench) From 8ee82d1e034642a49ff059d0421045275faf5511 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 23 Mar 2015 17:06:10 +0100 Subject: [PATCH 304/360] replace old-style typefs with using --- data_structures/restriction.hpp | 4 +- include/osrm/server_paths.hpp | 2 +- server/data_structures/datafacade_base.hpp | 18 +- .../data_structures/internal_datafacade.hpp | 8 +- server/data_structures/shared_datafacade.hpp | 16 +- util/cast.hpp | 4 +- util/graph_loader.hpp | 217 ++++++++++++++++++ 7 files changed, 243 insertions(+), 26 deletions(-) diff --git a/data_structures/restriction.hpp b/data_structures/restriction.hpp index f278bd8d2..b808d3070 100644 --- a/data_structures/restriction.hpp +++ b/data_structures/restriction.hpp @@ -107,7 +107,7 @@ struct InputRestrictionContainer struct CmpRestrictionContainerByFrom { - typedef InputRestrictionContainer value_type; + using value_type = InputRestrictionContainer; bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b) const { return a.restriction.from.way < b.restriction.from.way; @@ -118,7 +118,7 @@ struct CmpRestrictionContainerByFrom struct CmpRestrictionContainerByTo { - typedef InputRestrictionContainer value_type; + using value_type = InputRestrictionContainer; bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b) const { return a.restriction.to.way < b.restriction.to.way; diff --git a/include/osrm/server_paths.hpp b/include/osrm/server_paths.hpp index 60553a632..669ee7de0 100644 --- a/include/osrm/server_paths.hpp +++ b/include/osrm/server_paths.hpp @@ -33,6 +33,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -typedef std::unordered_map ServerPaths; +using ServerPaths = std::unordered_map; #endif // SERVER_PATH_H diff --git a/server/data_structures/datafacade_base.hpp b/server/data_structures/datafacade_base.hpp index 04486532d..20d043057 100644 --- a/server/data_structures/datafacade_base.hpp +++ b/server/data_structures/datafacade_base.hpp @@ -43,13 +43,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -typedef osrm::range EdgeRange; +using EdgeRange = osrm::range; template class BaseDataFacade { public: - typedef EdgeBasedNode RTreeLeaf; - typedef EdgeDataT EdgeData; + using RTreeLeaf = EdgeBasedNode; + using EdgeData = EdgeDataT; BaseDataFacade() {} virtual ~BaseDataFacade() {} @@ -104,12 +104,12 @@ template class BaseDataFacade virtual bool IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, PhantomNode &resulting_phantom_node) = 0; - virtual bool - IncrementalFindPhantomNodeForCoordinateWithMaxDistance(const FixedPointCoordinate &input_coordinate, - std::vector> &resulting_phantom_node_vector, - const double max_distance, - const unsigned min_number_of_phantom_nodes, - const unsigned max_number_of_phantom_nodes) = 0; + virtual bool IncrementalFindPhantomNodeForCoordinateWithMaxDistance( + const FixedPointCoordinate &input_coordinate, + std::vector> &resulting_phantom_node_vector, + const double max_distance, + const unsigned min_number_of_phantom_nodes, + const unsigned max_number_of_phantom_nodes) = 0; virtual unsigned GetCheckSum() const = 0; diff --git a/server/data_structures/internal_datafacade.hpp b/server/data_structures/internal_datafacade.hpp index 640a5f974..823ac3329 100644 --- a/server/data_structures/internal_datafacade.hpp +++ b/server/data_structures/internal_datafacade.hpp @@ -52,10 +52,10 @@ template class InternalDataFacade final : public BaseDataFacad { private: - typedef BaseDataFacade super; - typedef StaticGraph QueryGraph; - typedef typename QueryGraph::InputEdge InputEdge; - typedef typename super::RTreeLeaf RTreeLeaf; + using super = BaseDataFacade; + using QueryGraph = StaticGraph; + using InputEdge = typename QueryGraph::InputEdge; + using RTreeLeaf = typename super::RTreeLeaf; InternalDataFacade() {} diff --git a/server/data_structures/shared_datafacade.hpp b/server/data_structures/shared_datafacade.hpp index 93dfdb95d..b15642316 100644 --- a/server/data_structures/shared_datafacade.hpp +++ b/server/data_structures/shared_datafacade.hpp @@ -48,14 +48,14 @@ template class SharedDataFacade final : public BaseDataFacade< { private: - typedef EdgeDataT EdgeData; - typedef BaseDataFacade super; - typedef StaticGraph QueryGraph; - typedef typename StaticGraph::NodeArrayEntry GraphNode; - typedef typename StaticGraph::EdgeArrayEntry GraphEdge; - typedef typename RangeTable<16, true>::BlockT NameIndexBlock; - typedef typename QueryGraph::InputEdge InputEdge; - typedef typename super::RTreeLeaf RTreeLeaf; + using EdgeData = EdgeDataT; + using super = BaseDataFacade; + using QueryGraph = StaticGraph; + using GraphNode = typename StaticGraph::NodeArrayEntry; + using GraphEdge = typename StaticGraph::EdgeArrayEntry; + using NameIndexBlock = typename RangeTable<16, true>::BlockT; + using InputEdge = typename QueryGraph::InputEdge; + using RTreeLeaf = typename super::RTreeLeaf; using SharedRTree = StaticRTree::vector, true>; using TimeStampedRTreePair = std::pair>; using RTreeNode = typename SharedRTree::TreeNode; diff --git a/util/cast.hpp b/util/cast.hpp index c031e22b6..e396471e4 100644 --- a/util/cast.hpp +++ b/util/cast.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2013, Project OSRM contributors +Copyright (c) 2015, Project OSRM contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -149,7 +149,7 @@ struct cast static int floatfield(T) { return boost::spirit::karma::real_policies::fmtflags::fixed; } static unsigned int precision(T) { return 6; } }; - typedef boost::spirit::karma::real_generator> science_type; + using science_type = boost::spirit::karma::real_generator>; static std::string double_fixed_to_string(const double value) { diff --git a/util/graph_loader.hpp b/util/graph_loader.hpp index 0dfd72aef..d741334ba 100644 --- a/util/graph_loader.hpp +++ b/util/graph_loader.hpp @@ -52,6 +52,223 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +template +NodeID read_undirected_osrm_stream(std::istream &input_stream, + std::vector &edge_list, + std::vector &coordinate_list) +{ + const FingerPrint fingerprint_orig; + FingerPrint fingerprint_loaded; + input_stream.read(reinterpret_cast(&fingerprint_loaded), sizeof(FingerPrint)); + + if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig)) + { + SimpleLogger().Write(logWARNING) << ".osrm was prepared with different build.\n" + "Reprocess to get rid of this warning."; + } + + std::unordered_map ext_to_int_id_map; + + NodeID n; + input_stream.read(reinterpret_cast(&n), sizeof(NodeID)); + SimpleLogger().Write() << "Importing n = " << n << " nodes "; + + ExternalMemoryNode current_node; + for (NodeID i = 0; i < n; ++i) + { + input_stream.read(reinterpret_cast(¤t_node), sizeof(ExternalMemoryNode)); + coordinate_list.emplace_back(current_node.lat, current_node.lon); + ext_to_int_id_map.emplace(current_node.node_id, i); + // if (current_node.barrier) + // { + // barrier_node_list.emplace_back(i); + // } + // if (current_node.traffic_lights) + // { + // traffic_light_node_list.emplace_back(i); + // } + } + + // tighten vector sizes + // barrier_node_list.shrink_to_fit(); + // traffic_light_node_list.shrink_to_fit(); + + // renumber nodes in turn restrictions + // for (TurnRestriction ¤t_restriction : restriction_list) + // { + // auto internal_id_iter = ext_to_int_id_map.find(current_restriction.from.node); + // if (internal_id_iter == ext_to_int_id_map.end()) + // { + // SimpleLogger().Write(logDEBUG) << "Unmapped from node " << + // current_restriction.from.node + // << " of restriction"; + // continue; + // } + // current_restriction.from.node = internal_id_iter->second; + + // internal_id_iter = ext_to_int_id_map.find(current_restriction.via.node); + // if (internal_id_iter == ext_to_int_id_map.end()) + // { + // SimpleLogger().Write(logDEBUG) << "Unmapped via node " << + // current_restriction.via.node + // << " of restriction"; + // continue; + // } + + // current_restriction.via.node = internal_id_iter->second; + + // internal_id_iter = ext_to_int_id_map.find(current_restriction.to.node); + // if (internal_id_iter == ext_to_int_id_map.end()) + // { + // SimpleLogger().Write(logDEBUG) << "Unmapped to node " << current_restriction.to.node + // << " of restriction"; + // continue; + // } + // current_restriction.to.node = internal_id_iter->second; + // } + + EdgeWeight weight; + NodeID source, target; + unsigned nameID; + int length; + short dir; // direction (0 = open, 1 = forward, 2+ = open) + bool is_roundabout, ignore_in_grid, is_access_restricted, is_split; + TravelMode travel_mode; + + EdgeID m; + input_stream.read(reinterpret_cast(&m), sizeof(unsigned)); + edge_list.reserve(m); + SimpleLogger().Write() << " and " << m << " edges "; + + for (EdgeID i = 0; i < m; ++i) + { + input_stream.read(reinterpret_cast(&source), sizeof(unsigned)); + input_stream.read(reinterpret_cast(&target), sizeof(unsigned)); + input_stream.read(reinterpret_cast(&length), sizeof(int)); + input_stream.read(reinterpret_cast(&dir), sizeof(short)); + input_stream.read(reinterpret_cast(&weight), sizeof(int)); + input_stream.read(reinterpret_cast(&nameID), sizeof(unsigned)); + input_stream.read(reinterpret_cast(&is_roundabout), sizeof(bool)); + input_stream.read(reinterpret_cast(&ignore_in_grid), sizeof(bool)); + input_stream.read(reinterpret_cast(&is_access_restricted), sizeof(bool)); + input_stream.read(reinterpret_cast(&travel_mode), sizeof(TravelMode)); + input_stream.read(reinterpret_cast(&is_split), sizeof(bool)); + + BOOST_ASSERT_MSG(length > 0, "loaded null length edge"); + BOOST_ASSERT_MSG(weight > 0, "loaded null weight"); + BOOST_ASSERT_MSG(0 <= dir && dir <= 2, "loaded bogus direction"); + + // bool forward = true; + // bool backward = true; + // if (1 == dir) + // { + // backward = false; + // } + // if (2 == dir) + // { + // forward = false; + // } + + // translate the external NodeIDs to internal IDs + auto internal_id_iter = ext_to_int_id_map.find(source); + if (ext_to_int_id_map.find(source) == ext_to_int_id_map.end()) + { +#ifndef NDEBUG + SimpleLogger().Write(logWARNING) << " unresolved source NodeID: " << source; +#endif + continue; + } + source = internal_id_iter->second; + internal_id_iter = ext_to_int_id_map.find(target); + if (ext_to_int_id_map.find(target) == ext_to_int_id_map.end()) + { +#ifndef NDEBUG + SimpleLogger().Write(logWARNING) << "unresolved target NodeID : " << target; +#endif + continue; + } + target = internal_id_iter->second; + BOOST_ASSERT_MSG(source != SPECIAL_NODEID && target != SPECIAL_NODEID, + "nonexisting source or target"); + + if (source > target) + { + std::swap(source, target); + // std::swap(forward, backward); + } + + edge_list.emplace_back(source, target); + } + ext_to_int_id_map.clear(); + + tbb::parallel_sort(edge_list.begin(), edge_list.end()); + + // for (unsigned i = 1; i < edge_list.size(); ++i) + // { + // if ((edge_list[i - 1].target == edge_list[i].target) && + // (edge_list[i - 1].source == edge_list[i].source)) + // { + // const bool edge_flags_equivalent = (edge_list[i - 1].forward == edge_list[i].forward) + // && + // (edge_list[i - 1].backward == + // edge_list[i].backward); + // const bool edge_flags_are_superset1 = + // (edge_list[i - 1].forward && edge_list[i - 1].backward) && + // (edge_list[i].forward != edge_list[i].backward); + // const bool edge_flags_are_superset_2 = + // (edge_list[i].forward && edge_list[i].backward) && + // (edge_list[i - 1].forward != edge_list[i - 1].backward); + + // if (edge_flags_equivalent) + // { + // edge_list[i].weight = std::min(edge_list[i - 1].weight, edge_list[i].weight); + // edge_list[i - 1].source = SPECIAL_NODEID; + // } + // else if (edge_flags_are_superset1) + // { + // if (edge_list[i - 1].weight <= edge_list[i].weight) + // { + // // edge i-1 is smaller and goes in both directions. Throw away the other edge + // edge_list[i].source = SPECIAL_NODEID; + // } + // else + // { + // // edge i-1 is open in both directions, but edge i is smaller in one + // direction. + // // Close edge i-1 in this direction + // edge_list[i - 1].forward = !edge_list[i].forward; + // edge_list[i - 1].backward = !edge_list[i].backward; + // } + // } + // else if (edge_flags_are_superset_2) + // { + // if (edge_list[i - 1].weight <= edge_list[i].weight) + // { + // // edge i-1 is smaller for one direction. edge i is open in both. close edge + // i + // // in the other direction + // edge_list[i].forward = !edge_list[i - 1].forward; + // edge_list[i].backward = !edge_list[i - 1].backward; + // } + // else + // { + // // edge i is smaller and goes in both direction. Throw away edge i-1 + // edge_list[i - 1].source = SPECIAL_NODEID; + // } + // } + // } + // } + // const auto new_end_iter = + // std::remove_if(edge_list.begin(), edge_list.end(), [](const EdgeT &edge) + // { + // return edge.source == SPECIAL_NODEID || edge.target == SPECIAL_NODEID; + // }); + // edge_list.erase(new_end_iter, edge_list.end()); // remove excess candidates. + // edge_list.shrink_to_fit(); + SimpleLogger().Write() << "Graph loaded ok and has " << edge_list.size() << " edges"; + return n; +} + template NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, std::vector &edge_list, From 4b957abc0c4f7ca0f7dfdc7130e1ddda7d138d36 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 27 Mar 2015 12:27:15 +0100 Subject: [PATCH 305/360] fix rounding error/uncertainty on some systems --- features/testbot/loop.feature | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/features/testbot/loop.feature b/features/testbot/loop.feature index fe898ecf0..72cad33c0 100644 --- a/features/testbot/loop.feature +++ b/features/testbot/loop.feature @@ -64,13 +64,13 @@ Feature: Avoid weird loops caused by rounding errors | | d | | And the ways - | nodes | highway | - | ab | primary | - | bc | primary | - | cd | primary | - | be | secondary | - | ef | secondary | - | cf | secondary | + | nodes | highway | + | ab | residential | + | bc | residential | + | cd | residential | + | be | primary | + | ef | primary | + | cf | primary | When I route I should get | waypoints | route | turns | From b15599f01e57751c306e5fd2a13d8bcb4db83f45 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 27 Mar 2015 12:28:01 +0100 Subject: [PATCH 306/360] simplify logic to compute edge offset --- routing_algorithms/alternative_path.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/routing_algorithms/alternative_path.hpp b/routing_algorithms/alternative_path.hpp index 3b509573a..1dcc02096 100644 --- a/routing_algorithms/alternative_path.hpp +++ b/routing_algorithms/alternative_path.hpp @@ -102,10 +102,9 @@ class AlternativeRouting final int upper_bound_to_shortest_path_distance = INVALID_EDGE_WEIGHT; NodeID middle_node = SPECIAL_NODEID; - EdgeWeight min_edge_offset = - std::min(0, -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset()); - min_edge_offset = std::min(min_edge_offset, - -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()); + const EdgeWeight min_edge_offset = + std::min(phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), + phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()); if (phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID) { From 11c671354be8c791ef107e6ce6c4a38435417edb Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 27 Mar 2015 12:29:29 +0100 Subject: [PATCH 307/360] fix incorrect behavior when via point was on same one-way street as destination but should have been reached before, closes #1424 --- routing_algorithms/shortest_path.hpp | 58 +++++++--------------------- 1 file changed, 15 insertions(+), 43 deletions(-) diff --git a/routing_algorithms/shortest_path.hpp b/routing_algorithms/shortest_path.hpp index 4b3cc49a4..3dedc2b76 100644 --- a/routing_algorithms/shortest_path.hpp +++ b/routing_algorithms/shortest_path.hpp @@ -92,7 +92,9 @@ class ShortestPathRouting final const bool allow_u_turn = current_leg > 0 && uturn_indicators.size() > current_leg && uturn_indicators[current_leg - 1]; - EdgeWeight min_edge_offset = 0; + const EdgeWeight min_edge_offset = + std::min(phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), + phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()); // insert new starting nodes into forward heap, adjusted by previous distances. if ((allow_u_turn || search_from_1st_node) && @@ -100,58 +102,32 @@ class ShortestPathRouting final { forward_heap1.Insert( phantom_node_pair.source_phantom.forward_node_id, - (allow_u_turn ? 0 : distance1) - - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), + -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), phantom_node_pair.source_phantom.forward_node_id); - min_edge_offset = - std::min(min_edge_offset, - (allow_u_turn ? 0 : distance1) - - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset()); // SimpleLogger().Write(logDEBUG) << "fwd-a2 insert: " << - // phantom_node_pair.source_phantom.forward_node_id << ", w: " << (allow_u_turn ? 0 - // : distance1) - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(); + // phantom_node_pair.source_phantom.forward_node_id << ", w: " << -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(); forward_heap2.Insert( phantom_node_pair.source_phantom.forward_node_id, - (allow_u_turn ? 0 : distance1) - - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), + -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), phantom_node_pair.source_phantom.forward_node_id); - min_edge_offset = - std::min(min_edge_offset, - (allow_u_turn ? 0 : distance1) - - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset()); // SimpleLogger().Write(logDEBUG) << "fwd-b2 insert: " << - // phantom_node_pair.source_phantom.forward_node_id << ", w: " << (allow_u_turn ? 0 - // : distance1) - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(); + // phantom_node_pair.source_phantom.forward_node_id << ", w: " << -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(); } if ((allow_u_turn || search_from_2nd_node) && phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID) { forward_heap1.Insert( phantom_node_pair.source_phantom.reverse_node_id, - (allow_u_turn ? 0 : distance2) - - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), + -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), phantom_node_pair.source_phantom.reverse_node_id); - min_edge_offset = - std::min(min_edge_offset, - (allow_u_turn ? 0 : distance2) - - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()); // SimpleLogger().Write(logDEBUG) << "fwd-a2 insert: " << - // phantom_node_pair.source_phantom.reverse_node_id << - // ", w: " << (allow_u_turn ? 0 : distance2) - - // phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(); + // phantom_node_pair.source_phantom.reverse_node_id << ", w: " << -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(); forward_heap2.Insert( phantom_node_pair.source_phantom.reverse_node_id, - (allow_u_turn ? 0 : distance2) - - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), + -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), phantom_node_pair.source_phantom.reverse_node_id); - min_edge_offset = - std::min(min_edge_offset, - (allow_u_turn ? 0 : distance2) - - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()); // SimpleLogger().Write(logDEBUG) << "fwd-b2 insert: " << - // phantom_node_pair.source_phantom.reverse_node_id << - // ", w: " << (allow_u_turn ? 0 : distance2) - - // phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(); + // phantom_node_pair.source_phantom.reverse_node_id << ", w: " << -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(); } // insert new backward nodes into backward heap, unadjusted. @@ -161,9 +137,7 @@ class ShortestPathRouting final phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(), phantom_node_pair.target_phantom.forward_node_id); // SimpleLogger().Write(logDEBUG) << "rev-a insert: " << - // phantom_node_pair.target_phantom.forward_node_id << - // ", w: " << - // phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(); + // phantom_node_pair.target_phantom.forward_node_id << ", w: " << phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(); } if (phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID) @@ -172,9 +146,7 @@ class ShortestPathRouting final phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(), phantom_node_pair.target_phantom.reverse_node_id); // SimpleLogger().Write(logDEBUG) << "rev-a insert: " << - // phantom_node_pair.target_phantom.reverse_node_id << - // ", w: " << - // phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(); + // phantom_node_pair.target_phantom.reverse_node_id << ", w: " << phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(); } // run two-Target Dijkstra routing step. @@ -332,8 +304,8 @@ class ShortestPathRouting final BOOST_ASSERT(search_from_1st_node != search_from_2nd_node); } - distance1 = local_upper_bound1; - distance2 = local_upper_bound2; + distance1 += local_upper_bound1; + distance2 += local_upper_bound2; ++current_leg; } From d853310bee0dfaf0983af106dadf1630a06631e6 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 27 Mar 2015 18:15:13 +0100 Subject: [PATCH 308/360] use range-based for in escape_JSON() function --- util/string_util.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util/string_util.hpp b/util/string_util.hpp index 31be0444b..6350c426d 100644 --- a/util/string_util.hpp +++ b/util/string_util.hpp @@ -88,9 +88,9 @@ inline std::string escape_JSON(const std::string &input) // escape and skip reallocations if possible std::string output; output.reserve(input.size() + 4); // +4 assumes two backslashes on avg - for (auto iter = input.begin(); iter != input.end(); ++iter) + for (const char letter : input) { - switch (iter[0]) + switch (letter) { case '\\': output += "\\\\"; @@ -117,7 +117,7 @@ inline std::string escape_JSON(const std::string &input) output += "\\t"; break; default: - output += *iter; + output.append(1, letter); break; } } From 1851a31e66426ac5e45a4b38c6c5794f5341bcae Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 27 Mar 2015 18:15:58 +0100 Subject: [PATCH 309/360] add unit tests for functions escape_JSON, printInt and replaceAll in string_util.hpp --- unit_tests/algorithms/string_util.cpp | 65 +++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 unit_tests/algorithms/string_util.cpp diff --git a/unit_tests/algorithms/string_util.cpp b/unit_tests/algorithms/string_util.cpp new file mode 100644 index 000000000..6bbb119b8 --- /dev/null +++ b/unit_tests/algorithms/string_util.cpp @@ -0,0 +1,65 @@ +/* + +Copyright (c) 2014, Project OSRM contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "../../util/string_util.hpp" + +#include +#include + +#include + +BOOST_AUTO_TEST_SUITE(string_util) + +BOOST_AUTO_TEST_CASE(replace_all_test) +{ + std::string input {"ababababababa"}; + const std::string sub {"a"}; + const std::string other {"c"}; + replaceAll(input, sub, other); + + BOOST_CHECK_EQUAL(input, "cbcbcbcbcbcbc"); +} + +BOOST_AUTO_TEST_CASE(json_escaping) +{ + const std::string input {"\b\\"}; + const std::string output { escape_JSON(input) }; + + BOOST_CHECK_EQUAL(output, "\\b\\\\"); +} + +BOOST_AUTO_TEST_CASE(print_int) +{ + const std::string input {"\b\\"}; + char buffer[12]; + buffer[11] = 0; // zero termination + std::string output = printInt<11, 8>(buffer, 314158976); + + BOOST_CHECK_EQUAL(output, "3.14158976"); +} + +BOOST_AUTO_TEST_SUITE_END() From 60663b5433b574e862131541c600a09deac1998e Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 30 Mar 2015 11:09:41 +0200 Subject: [PATCH 310/360] reorder build dependencies --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 923961378..f88685970 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -320,7 +320,7 @@ if(WITH_TOOLS OR BUILD_TOOLS) if(UNIX AND NOT APPLE) target_link_libraries(osrm-unlock-all rt) endif() - add_executable(osrm-check-hsgr tools/check-hsgr.cpp $ $ $) + add_executable(osrm-check-hsgr tools/check-hsgr.cpp $ $ $) target_link_libraries(osrm-check-hsgr ${Boost_LIBRARIES}) add_executable(osrm-springclean tools/springclean.cpp $ $ $ $) target_link_libraries(osrm-springclean ${Boost_LIBRARIES}) From f553896e2ded0ce3575a5c469bff1cf41edd7362 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 30 Mar 2015 12:36:39 +0200 Subject: [PATCH 311/360] printInt(): fix sign issue when outputting 0, use postfix in/decrement --- util/string_util.hpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/util/string_util.hpp b/util/string_util.hpp index 6350c426d..63904c43c 100644 --- a/util/string_util.hpp +++ b/util/string_util.hpp @@ -42,31 +42,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. template static inline char *printInt(char *buffer, int value) { bool minus = true; - if (value > 0) + if (value >= 0) { minus = false; value = -value; } buffer += length - 1; - for (int i = 0; i < precision; i++) + for (int i = 0; i < precision; ++i) { *buffer = '0' - (value % 10); value /= 10; - buffer--; + --buffer; } *buffer = '.'; - buffer--; - for (int i = precision + 1; i < length; i++) + --buffer; + for (int i = precision + 1; i < length; ++i) { *buffer = '0' - (value % 10); value /= 10; if (value == 0) + { break; - buffer--; + } + --buffer; } if (minus) { - buffer--; + --buffer; *buffer = '-'; } return buffer; From 5bed7f292f3cbd102df0fc8d87a28ca74f785d3a Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 30 Mar 2015 12:37:39 +0200 Subject: [PATCH 312/360] add test for printInt() sign correctness --- unit_tests/algorithms/string_util.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/unit_tests/algorithms/string_util.cpp b/unit_tests/algorithms/string_util.cpp index 6bbb119b8..285b18a44 100644 --- a/unit_tests/algorithms/string_util.cpp +++ b/unit_tests/algorithms/string_util.cpp @@ -58,8 +58,13 @@ BOOST_AUTO_TEST_CASE(print_int) char buffer[12]; buffer[11] = 0; // zero termination std::string output = printInt<11, 8>(buffer, 314158976); - BOOST_CHECK_EQUAL(output, "3.14158976"); -} + + buffer[11] = 0; + output = printInt<11, 8>(buffer, 0); + BOOST_CHECK_EQUAL(output, "0.00000000"); + + output = printInt<11, 8>(buffer, -314158976); + BOOST_CHECK_EQUAL(output, "-3.14158976");} BOOST_AUTO_TEST_SUITE_END() From 6933804aa44870cd96e39a3e8197aef297316612 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 30 Mar 2015 12:40:54 +0200 Subject: [PATCH 313/360] remove unused html en/decoding entities, we use JSON now --- util/string_util.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/util/string_util.hpp b/util/string_util.hpp index 63904c43c..e65290d09 100644 --- a/util/string_util.hpp +++ b/util/string_util.hpp @@ -126,10 +126,6 @@ inline std::string escape_JSON(const std::string &input) return output; } -static std::string originals[] = {"&", "\"", "<", ">", "'", "[", "]", "\\"}; -static std::string entities[] = { - "&", """, "<", ">", "'", "&91;", "&93;", " \"}; - inline std::size_t URIDecode(const std::string &input, std::string &output) { auto src_iter = input.begin(); From d6badca6106ce0a9986df0f5877e6e63f8d85643 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 30 Mar 2015 13:01:16 +0200 Subject: [PATCH 314/360] use lamda function to do complex initialization with a (wanted) side-effect --- util/string_util.hpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/util/string_util.hpp b/util/string_util.hpp index e65290d09..cb67fa9db 100644 --- a/util/string_util.hpp +++ b/util/string_util.hpp @@ -41,12 +41,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // work with negative values to prevent overflowing when taking -value template static inline char *printInt(char *buffer, int value) { - bool minus = true; - if (value >= 0) - { - minus = false; - value = -value; - } + static_assert(length > 0, "length must be positive"); + static_assert(precision > 0, "precision must be positive"); + + const bool minus = [&value]{ + if (value >= 0) + { + value = -value; + return false; + } + return true; + }(); + buffer += length - 1; for (int i = 0; i < precision; ++i) { @@ -56,6 +62,7 @@ template static inline char *printInt(char *buffer, } *buffer = '.'; --buffer; + for (int i = precision + 1; i < length; ++i) { *buffer = '0' - (value % 10); @@ -66,6 +73,7 @@ template static inline char *printInt(char *buffer, } --buffer; } + if (minus) { --buffer; @@ -128,10 +136,10 @@ inline std::string escape_JSON(const std::string &input) inline std::size_t URIDecode(const std::string &input, std::string &output) { - auto src_iter = input.begin(); + auto src_iter = std::begin(input); output.resize(input.size() + 1); std::size_t decoded_length = 0; - for (decoded_length = 0; src_iter != input.end(); ++decoded_length) + for (decoded_length = 0; src_iter != std::end(input); ++decoded_length) { if (src_iter[0] == '%' && src_iter[1] && src_iter[2] && isxdigit(src_iter[1]) && isxdigit(src_iter[2])) From 19765cfa14b81ccc2c727a053b940ca71258732c Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 30 Mar 2015 13:10:03 +0200 Subject: [PATCH 315/360] remove unneeded include --- plugins/match.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/match.hpp b/plugins/match.hpp index bc4738d50..1e3f18d9b 100644 --- a/plugins/match.hpp +++ b/plugins/match.hpp @@ -38,7 +38,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../routing_algorithms/map_matching.hpp" #include "../util/compute_angle.hpp" #include "../util/integer_range.hpp" -#include "../util/simple_logger.hpp" #include "../util/json_logger.hpp" #include "../util/json_util.hpp" #include "../util/string_util.hpp" From 9bbbebf31dcc31e74a1857d97f2afbfc986c9026 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 30 Mar 2015 13:13:13 +0200 Subject: [PATCH 316/360] use empty() instead of 1>size() to make intent more clear --- plugins/match.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/match.hpp b/plugins/match.hpp index 1e3f18d9b..529b7ed85 100644 --- a/plugins/match.hpp +++ b/plugins/match.hpp @@ -257,7 +257,7 @@ template class MapMatchingPlugin : public BasePlugin route_parameters.matching_beta, route_parameters.gps_precision, sub_matchings); - if (1 > sub_matchings.size()) + if (sub_matchings.empty()) { return 400; } From 66b038a010f87517aecf99faf1d1a264e9eec0ca Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 30 Mar 2015 13:14:13 +0200 Subject: [PATCH 317/360] reorder includes --- routing_algorithms/map_matching.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 580e9d980..39cc154b1 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -32,8 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/coordinate_calculation.hpp" #include "../data_structures/hidden_markov_model.hpp" -#include "../util/matching_debug_info.hpp" #include "../util/json_logger.hpp" +#include "../util/matching_debug_info.hpp" #include From 3e49bf4f4232c7f2178a3588bc26ec52da662941 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 30 Mar 2015 13:16:22 +0200 Subject: [PATCH 318/360] add const keywords where possible --- routing_algorithms/map_matching.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 39cc154b1..75598ca2c 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -316,8 +316,8 @@ class MapMatching final : public BasicRoutingInterface(0u, reconstructed_indices.size())) { - auto timestamp_index = reconstructed_indices[i].first; - auto location_index = reconstructed_indices[i].second; + const auto timestamp_index = reconstructed_indices[i].first; + const auto location_index = reconstructed_indices[i].second; matching.indices[i] = timestamp_index; matching.nodes[i] = candidates_list[timestamp_index][location_index].first; From 0640ce96327fd6d1ec1d7d106fa2377ea350df51 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 30 Mar 2015 13:21:03 +0200 Subject: [PATCH 319/360] set project and fingerprint target language to CXX explicitly, fixes AppVeyor build. Potentially Travis, too. --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f88685970..b7260f4ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ Please create a directory and run cmake from there, passing the path to this sou This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. Please delete them.") endif() -project(OSRM) +project(OSRM CXX) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) include(CheckCXXCompilerFlag) include(FindPackageHandleStandardArgs) @@ -93,6 +93,7 @@ add_library(FINGERPRINT OBJECT util/fingerprint.cpp) add_library(GITDESCRIPTION OBJECT util/git_sha.cpp) add_library(OSRM ${OSRMSources} $ $ $ $ $ $ $ $ $) add_dependencies(FINGERPRINT FingerPrintConfigure) +set_target_properties(FINGERPRINT PROPERTIES LINKER_LANGUAGE CXX) add_executable(osrm-routed routed.cpp ${ServerGlob} $) add_executable(osrm-datastore datastore.cpp $ $ $ $ $ $) From 23e4e0786dec3463c61ef0cdfc9778be5af10e09 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 30 Mar 2015 13:26:06 +0200 Subject: [PATCH 320/360] also enable C as a project language --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b7260f4ac..dc5c1aac4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ Please create a directory and run cmake from there, passing the path to this sou This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. Please delete them.") endif() -project(OSRM CXX) +project(OSRM C CXX) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) include(CheckCXXCompilerFlag) include(FindPackageHandleStandardArgs) From 81af7d73a6a40de6931ebbef4e98f7fc88b393f3 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 30 Mar 2015 15:55:23 +0200 Subject: [PATCH 321/360] make FINGERPRINT a global dependency --- CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dc5c1aac4..77efc0cdb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,6 +94,7 @@ add_library(GITDESCRIPTION OBJECT util/git_sha.cpp) add_library(OSRM ${OSRMSources} $ $ $ $ $ $ $ $ $) add_dependencies(FINGERPRINT FingerPrintConfigure) set_target_properties(FINGERPRINT PROPERTIES LINKER_LANGUAGE CXX) +add_dependencies(OSRM FINGERPRINT) add_executable(osrm-routed routed.cpp ${ServerGlob} $) add_executable(osrm-datastore datastore.cpp $ $ $ $ $ $) @@ -113,8 +114,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) message(STATUS "Configuring OSRM in debug mode") if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") message(STATUS "adding profiling flags") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline") - set(CMAKE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline") +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline") +# set(CMAKE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline") endif() endif() if(CMAKE_BUILD_TYPE MATCHES Release) From 5adf792fad789d194b5419c1bec12289cdd7b4f3 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 31 Mar 2015 10:45:35 +0200 Subject: [PATCH 322/360] fix build issue where cmake does not pick up generated output of a custom target renamed: ../util/fingerprint.cpp.in -> ../util/fingerprint_impl.hpp.in --- .gitignore | 2 +- CMakeLists.txt | 5 +- cmake/FingerPrint-Config.cmake | 4 +- util/fingerprint_impl.hpp.in | 103 +++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 util/fingerprint_impl.hpp.in diff --git a/.gitignore b/.gitignore index 5d5cad2e3..6ed5d2a4e 100644 --- a/.gitignore +++ b/.gitignore @@ -36,7 +36,7 @@ Thumbs.db # build related files # ####################### /build/ -/util/fingerprint.cpp +/util/fingerprint_impl.hpp /util/git_sha.cpp /cmake/postinst diff --git a/CMakeLists.txt b/CMakeLists.txt index 77efc0cdb..23d4ab36b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,12 +89,13 @@ set( ) add_library(COORDINATE OBJECT ${CoordinateGlob}) -add_library(FINGERPRINT OBJECT util/fingerprint.cpp) add_library(GITDESCRIPTION OBJECT util/git_sha.cpp) add_library(OSRM ${OSRMSources} $ $ $ $ $ $ $ $ $) + +add_library(FINGERPRINT OBJECT util/fingerprint.cpp) add_dependencies(FINGERPRINT FingerPrintConfigure) +add_dependencies(OSRM FingerPrintConfigure) set_target_properties(FINGERPRINT PROPERTIES LINKER_LANGUAGE CXX) -add_dependencies(OSRM FINGERPRINT) add_executable(osrm-routed routed.cpp ${ServerGlob} $) add_executable(osrm-datastore datastore.cpp $ $ $ $ $ $) diff --git a/cmake/FingerPrint-Config.cmake b/cmake/FingerPrint-Config.cmake index fe710ac63..a3325d305 100644 --- a/cmake/FingerPrint-Config.cmake +++ b/cmake/FingerPrint-Config.cmake @@ -1,4 +1,4 @@ -set(OLDFILE ${SOURCE_DIR}/util/fingerprint.cpp) +set(OLDFILE ${SOURCE_DIR}/util/fingerprint_impl.hpp) if (EXISTS ${OLDFILE}) file(REMOVE_RECURSE ${OLDFILE}) endif() @@ -7,4 +7,4 @@ file(MD5 ${SOURCE_DIR}/data_structures/static_rtree.hpp MD5RTREE) file(MD5 ${SOURCE_DIR}/util/graph_loader.hpp MD5GRAPH) file(MD5 ${SOURCE_DIR}/server/data_structures/internal_datafacade.hpp MD5OBJECTS) -CONFIGURE_FILE( ${SOURCE_DIR}/util/fingerprint.cpp.in ${SOURCE_DIR}/util/fingerprint.cpp ) +CONFIGURE_FILE(${SOURCE_DIR}/util/fingerprint_impl.hpp.in ${SOURCE_DIR}/util/fingerprint_impl.hpp) diff --git a/util/fingerprint_impl.hpp.in b/util/fingerprint_impl.hpp.in new file mode 100644 index 000000000..9259afd37 --- /dev/null +++ b/util/fingerprint_impl.hpp.in @@ -0,0 +1,103 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "osrm_exception.hpp" + +#include + +#include + +#include +#include + +#cmakedefine01 HAS64BITS +#cmakedefine MD5PREPARE "${MD5PREPARE}" +#cmakedefine MD5RTREE "${MD5RTREE}" +#cmakedefine MD5GRAPH "${MD5GRAPH}" +#cmakedefine MD5OBJECTS "${MD5OBJECTS}" + +FingerPrint::FingerPrint() : magic_number(1297240911) +{ + md5_prepare[32] = md5_tree[32] = md5_graph[32] = md5_objects[32] = '\0'; + + boost::uuids::name_generator gen(named_uuid); + std::string temp_string; + + std::memcpy(md5_prepare, MD5PREPARE, strlen(MD5PREPARE)); + temp_string += md5_prepare; + std::memcpy(md5_tree, MD5RTREE, 32); + temp_string += md5_tree; + std::memcpy(md5_graph, MD5GRAPH, 32); + temp_string += md5_graph; + std::memcpy(md5_objects, MD5OBJECTS, 32); + temp_string += md5_objects; + + named_uuid = gen(temp_string); + has_64_bits = HAS64BITS; +} + +FingerPrint::~FingerPrint() {} + +const boost::uuids::uuid &FingerPrint::GetFingerPrint() const { return named_uuid; } + +bool FingerPrint::IsMagicNumberOK() const { return 1297240911 == magic_number; } + +bool FingerPrint::TestGraphUtil(const FingerPrint &other) const +{ + if (!other.IsMagicNumberOK()) + { + throw osrm::exception("hsgr input file misses magic number. Check or reprocess the file"); + } + return std::equal(md5_graph, md5_graph + 32, other.md5_graph); +} + +bool FingerPrint::TestPrepare(const FingerPrint &other) const +{ + if (!other.IsMagicNumberOK()) + { + throw osrm::exception("osrm input file misses magic number. Check or reprocess the file"); + } + return std::equal(md5_prepare, md5_prepare + 32, other.md5_prepare); +} + +bool FingerPrint::TestRTree(const FingerPrint &other) const +{ + if (!other.IsMagicNumberOK()) + { + throw osrm::exception("r-tree input file misses magic number. Check or reprocess the file"); + } + return std::equal(md5_tree, md5_tree + 32, other.md5_tree); +} + +bool FingerPrint::TestQueryObjects(const FingerPrint &other) const +{ + if (!other.IsMagicNumberOK()) + { + throw osrm::exception("missing magic number. Check or reprocess the file"); + } + return std::equal(md5_objects, md5_objects + 32, other.md5_objects); +} From c9c9edeb235d01ab8047944a69db796c2f992349 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 31 Mar 2015 10:46:55 +0200 Subject: [PATCH 323/360] deleted: util/fingerprint.cpp.in --- util/fingerprint.cpp.in | 105 ---------------------------------------- 1 file changed, 105 deletions(-) delete mode 100644 util/fingerprint.cpp.in diff --git a/util/fingerprint.cpp.in b/util/fingerprint.cpp.in deleted file mode 100644 index e30b5ab1a..000000000 --- a/util/fingerprint.cpp.in +++ /dev/null @@ -1,105 +0,0 @@ -/* - -Copyright (c) 2015, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "fingerprint.hpp" - -#include "osrm_exception.hpp" - -#include - -#include - -#include -#include - -#cmakedefine01 HAS64BITS -#cmakedefine MD5PREPARE "${MD5PREPARE}" -#cmakedefine MD5RTREE "${MD5RTREE}" -#cmakedefine MD5GRAPH "${MD5GRAPH}" -#cmakedefine MD5OBJECTS "${MD5OBJECTS}" - -FingerPrint::FingerPrint() : magic_number(1297240911) -{ - md5_prepare[32] = md5_tree[32] = md5_graph[32] = md5_objects[32] = '\0'; - - boost::uuids::name_generator gen(named_uuid); - std::string temp_string; - - std::memcpy(md5_prepare, MD5PREPARE, strlen(MD5PREPARE)); - temp_string += md5_prepare; - std::memcpy(md5_tree, MD5RTREE, 32); - temp_string += md5_tree; - std::memcpy(md5_graph, MD5GRAPH, 32); - temp_string += md5_graph; - std::memcpy(md5_objects, MD5OBJECTS, 32); - temp_string += md5_objects; - - named_uuid = gen(temp_string); - has_64_bits = HAS64BITS; -} - -FingerPrint::~FingerPrint() {} - -const boost::uuids::uuid &FingerPrint::GetFingerPrint() const { return named_uuid; } - -bool FingerPrint::IsMagicNumberOK() const { return 1297240911 == magic_number; } - -bool FingerPrint::TestGraphUtil(const FingerPrint &other) const -{ - if (!other.IsMagicNumberOK()) - { - throw osrm::exception("hsgr input file misses magic number. Check or reprocess the file"); - } - return std::equal(md5_graph, md5_graph + 32, other.md5_graph); -} - -bool FingerPrint::TestPrepare(const FingerPrint &other) const -{ - if (!other.IsMagicNumberOK()) - { - throw osrm::exception("osrm input file misses magic number. Check or reprocess the file"); - } - return std::equal(md5_prepare, md5_prepare + 32, other.md5_prepare); -} - -bool FingerPrint::TestRTree(const FingerPrint &other) const -{ - if (!other.IsMagicNumberOK()) - { - throw osrm::exception("r-tree input file misses magic number. Check or reprocess the file"); - } - return std::equal(md5_tree, md5_tree + 32, other.md5_tree); -} - -bool FingerPrint::TestQueryObjects(const FingerPrint &other) const -{ - if (!other.IsMagicNumberOK()) - { - throw osrm::exception("missing magic number. Check or reprocess the file"); - } - return std::equal(md5_objects, md5_objects + 32, other.md5_objects); -} From 27d2c31f28473ff65b4fa08a08c5106b4cb2b94d Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 31 Mar 2015 10:47:21 +0200 Subject: [PATCH 324/360] add (new) fingerprint.cpp that includes the generated headers --- util/fingerprint.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 util/fingerprint.cpp diff --git a/util/fingerprint.cpp b/util/fingerprint.cpp new file mode 100644 index 000000000..8c7ab404e --- /dev/null +++ b/util/fingerprint.cpp @@ -0,0 +1,29 @@ +/* + +Copyright (c) 2015, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "fingerprint.hpp" +#include "fingerprint_impl.hpp" From 098de196e2f619b6ca00c040edff7c8e4a26a371 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 31 Mar 2015 11:21:36 +0200 Subject: [PATCH 325/360] reactivate profiling flags for debug build --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 23d4ab36b..86fb3ecd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,8 +115,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) message(STATUS "Configuring OSRM in debug mode") if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") message(STATUS "adding profiling flags") -# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline") -# set(CMAKE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline") + set(CMAKE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline") endif() endif() if(CMAKE_BUILD_TYPE MATCHES Release) From 23b413a3989d9ced5296ab503efbe43a3fcb28b3 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 31 Mar 2015 12:35:20 +0200 Subject: [PATCH 326/360] remove quotes from string compares against variable in CMakeLists --- CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 86fb3ecd8..a5820d8bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,11 +150,11 @@ if(NOT WIN32) endif() # Configuring compilers -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") +if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") # using Clang # -Weverything -Wno-c++98-compat -Wno-shadow -Wno-exit-time-destructors set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -pedantic -fPIC") -elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") +elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") set(COLOR_FLAG "-fdiagnostics-color=auto") check_cxx_compiler_flag("-fdiagnostics-color=auto" HAS_COLOR_FLAG) if(NOT HAS_COLOR_FLAG) @@ -167,10 +167,10 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") add_definitions(-DWIN32) set(OPTIONAL_SOCKET_LIBS ws2_32 wsock32) endif() -elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") +elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "Intel") # using Intel C++ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -ipo -fPIC") -elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") +elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC") # using Visual Studio C++ set(BOOST_COMPONENTS ${BOOST_COMPONENTS} date_time chrono zlib) add_definitions(-D_CRT_SECURE_NO_WARNINGS) @@ -183,7 +183,7 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") endif() # Activate C++11 -if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") +if(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ") endif() From 19ac831c2ef3fa82e1af0dd2986dc1d01ea35dc7 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 31 Mar 2015 12:59:56 +0200 Subject: [PATCH 327/360] remove another quoted compare --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a5820d8bc..e6aa034c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,7 +113,7 @@ if(NOT CMAKE_BUILD_TYPE MATCHES Debug) endif() if(CMAKE_BUILD_TYPE MATCHES Debug) message(STATUS "Configuring OSRM in debug mode") - if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + if(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC") message(STATUS "adding profiling flags") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline") set(CMAKE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline") From c2f775fcaa6e1d29494f4ecabaded0f45cc01ed5 Mon Sep 17 00:00:00 2001 From: Matthias Kuhn Date: Mon, 9 Mar 2015 09:29:22 +0100 Subject: [PATCH 328/360] Add test for building as shared library --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index a163e0352..3cc11abe4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,6 +45,7 @@ cache: env: - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5000 OSRM_TIMEOUT=60 - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5010 OSRM_TIMEOUT=60 + - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5010 OSRM_TIMEOUT=60 notifications: slack: mapbox:4A6euphDwfxAQnhLurXbu6A1 irc: From d11c0bbd5c05180af1f22b139eca935a45b3a2c0 Mon Sep 17 00:00:00 2001 From: Matthias Kuhn Date: Mon, 9 Mar 2015 09:20:30 +0100 Subject: [PATCH 329/360] Do not compile Coordinate sources directly into the OSRM library It is already included in the COORDINATES "OBJECT" target to which the OSRM library is linked. This fixes the possibility to build OSRM as a shared library. --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e6aa034c7..c1d771d03 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,7 +83,6 @@ set( ${LibOSRMGlob} ${DescriptorGlob} ${DatastructureGlob} - ${CoordinateGlob} ${AlgorithmGlob} ${HttpGlob} ) From 559a2dcec785a288892ad5a7d5b98512f5b225a4 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 31 Mar 2015 17:33:56 +0200 Subject: [PATCH 330/360] move shared lib testing to distinct port on travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3cc11abe4..fa6ff3871 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,7 +45,7 @@ cache: env: - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5000 OSRM_TIMEOUT=60 - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5010 OSRM_TIMEOUT=60 - - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5010 OSRM_TIMEOUT=60 + - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5020 OSRM_TIMEOUT=60 notifications: slack: mapbox:4A6euphDwfxAQnhLurXbu6A1 irc: From 3a291f5c8e7a23ec2eb7a088a98da47e665bb491 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 2 Apr 2015 10:34:40 +0200 Subject: [PATCH 331/360] fix escaping of double quote in JSON response, fixes #1410 and also adds a unit test for that case. --- unit_tests/algorithms/string_util.cpp | 19 ++++++++++++------- util/string_util.hpp | 9 ++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/unit_tests/algorithms/string_util.cpp b/unit_tests/algorithms/string_util.cpp index 285b18a44..865ddd5a2 100644 --- a/unit_tests/algorithms/string_util.cpp +++ b/unit_tests/algorithms/string_util.cpp @@ -36,9 +36,9 @@ BOOST_AUTO_TEST_SUITE(string_util) BOOST_AUTO_TEST_CASE(replace_all_test) { - std::string input {"ababababababa"}; - const std::string sub {"a"}; - const std::string other {"c"}; + std::string input{"ababababababa"}; + const std::string sub{"a"}; + const std::string other{"c"}; replaceAll(input, sub, other); BOOST_CHECK_EQUAL(input, "cbcbcbcbcbcbc"); @@ -46,15 +46,19 @@ BOOST_AUTO_TEST_CASE(replace_all_test) BOOST_AUTO_TEST_CASE(json_escaping) { - const std::string input {"\b\\"}; - const std::string output { escape_JSON(input) }; + std::string input{"\b\\"}; + std::string output{escape_JSON(input)}; BOOST_CHECK_EQUAL(output, "\\b\\\\"); + + input = "Aleja \"Solidarnosci\""; + output = escape_JSON(input); + BOOST_CHECK_EQUAL(output, "Aleja \\\"Solidarnosci\\\""); } BOOST_AUTO_TEST_CASE(print_int) { - const std::string input {"\b\\"}; + const std::string input{"\b\\"}; char buffer[12]; buffer[11] = 0; // zero termination std::string output = printInt<11, 8>(buffer, 314158976); @@ -65,6 +69,7 @@ BOOST_AUTO_TEST_CASE(print_int) BOOST_CHECK_EQUAL(output, "0.00000000"); output = printInt<11, 8>(buffer, -314158976); - BOOST_CHECK_EQUAL(output, "-3.14158976");} + BOOST_CHECK_EQUAL(output, "-3.14158976"); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/util/string_util.hpp b/util/string_util.hpp index cb67fa9db..3bfce0032 100644 --- a/util/string_util.hpp +++ b/util/string_util.hpp @@ -44,7 +44,8 @@ template static inline char *printInt(char *buffer, static_assert(length > 0, "length must be positive"); static_assert(precision > 0, "precision must be positive"); - const bool minus = [&value]{ + const bool minus = [&value] + { if (value >= 0) { value = -value; @@ -89,12 +90,6 @@ inline void replaceAll(std::string &s, const std::string &sub, const std::string inline std::string escape_JSON(const std::string &input) { - // return the input if no backslash can be found -> no allocations - if (input.find_first_of('\\') == std::string::npos) - { - return input; - } - // escape and skip reallocations if possible std::string output; output.reserve(input.size() + 4); // +4 assumes two backslashes on avg From 9a61f8b8947024a88f34388df30cf305429e1c19 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 2 Apr 2015 11:24:37 +0200 Subject: [PATCH 332/360] add more const keywords, avoid implicit type conversions --- plugins/match.hpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/plugins/match.hpp b/plugins/match.hpp index 529b7ed85..93282d406 100644 --- a/plugins/match.hpp +++ b/plugins/match.hpp @@ -76,9 +76,10 @@ template class MapMatchingPlugin : public BasePlugin const std::string GetDescriptor() const final { return descriptor_string; } - TraceClassification classify(float trace_length, float matched_length, int removed_points) const + TraceClassification + classify(const float trace_length, const float matched_length, const int removed_points) const { - double distance_feature = -std::log(trace_length) + std::log(matched_length); + const double distance_feature = -std::log(trace_length) + std::log(matched_length); // matched to the same point if (!std::isfinite(distance_feature)) @@ -86,7 +87,7 @@ template class MapMatchingPlugin : public BasePlugin return std::make_pair(ClassifierT::ClassLabel::NEGATIVE, 1.0); } - auto label_with_confidence = classifier.classify(distance_feature); + const auto label_with_confidence = classifier.classify(distance_feature); // "second stage classifier": if we need to remove points there is something fishy if (removed_points > 0) @@ -143,8 +144,8 @@ template class MapMatchingPlugin : public BasePlugin } else { - unsigned compact_size = candidates.size(); - for (const auto i : osrm::irange(0u, compact_size)) + const auto compact_size = candidates.size(); + for (const auto i : osrm::irange(0, compact_size)) { // Split edge if it is bidirectional and append reverse direction to end of list if (candidates[i].first.forward_node_id != SPECIAL_NODEID && @@ -194,7 +195,7 @@ template class MapMatchingPlugin : public BasePlugin raw_route.is_via_leg(i)); } // we need this because we don't run DP - for (auto& segment : factory.path_description) + for (auto &segment : factory.path_description) { segment.necessary = true; } @@ -241,7 +242,8 @@ template class MapMatchingPlugin : public BasePlugin return 400; } - bool found_candidates = getCandiates(input_coords, sub_trace_lengths, candidates_lists); + const bool found_candidates = + getCandiates(input_coords, sub_trace_lengths, candidates_lists); if (!found_candidates) { return 400; From c2deedac8b418688f242dda0887888f31a4ef694 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 2 Apr 2015 11:36:04 +0200 Subject: [PATCH 333/360] sprinkle a number of noexcepts into the code --- util/bearing.cpp | 2 +- util/bearing.hpp | 2 +- util/cast.hpp | 2 +- util/compute_angle.cpp | 2 +- util/compute_angle.hpp | 2 +- util/container.hpp | 11 +++++++---- util/integer_range.hpp | 25 +++++++++++++------------ util/iterator_range.hpp | 13 +++++++------ util/mercator.cpp | 4 ++-- util/mercator.hpp | 4 ++-- 10 files changed, 36 insertions(+), 31 deletions(-) diff --git a/util/bearing.cpp b/util/bearing.cpp index df238277a..48fd7f92b 100644 --- a/util/bearing.cpp +++ b/util/bearing.cpp @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "bearing.hpp" -std::string bearing::get(const double heading) +std::string bearing::get(const double heading) noexcept { if (heading <= 22.5) { diff --git a/util/bearing.hpp b/util/bearing.hpp index b8a79ee97..8b16ebc16 100644 --- a/util/bearing.hpp +++ b/util/bearing.hpp @@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct bearing { - static std::string get(const double heading); + static std::string get(const double heading) noexcept; }; #endif // BEARING_HPP diff --git a/util/cast.hpp b/util/cast.hpp index e396471e4..6d6ff6548 100644 --- a/util/cast.hpp +++ b/util/cast.hpp @@ -109,7 +109,7 @@ struct cast } // source: http://tinodidriksen.com/2011/05/28/cpp-convert-string-to-double-speed/ - static double string_to_double(const char *p) + static double string_to_double(const char *p) noexcept { double r = 0.0; bool neg = false; diff --git a/util/compute_angle.cpp b/util/compute_angle.cpp index 86be5634b..8cd8aa441 100644 --- a/util/compute_angle.cpp +++ b/util/compute_angle.cpp @@ -36,7 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. double ComputeAngle::OfThreeFixedPointCoordinates(const FixedPointCoordinate &first, const FixedPointCoordinate &second, - const FixedPointCoordinate &third) + const FixedPointCoordinate &third) noexcept { const double v1x = (first.lon - second.lon) / COORDINATE_PRECISION; const double v1y = mercator::lat2y(first.lat / COORDINATE_PRECISION) - diff --git a/util/compute_angle.hpp b/util/compute_angle.hpp index 477e43689..da84cafaa 100644 --- a/util/compute_angle.hpp +++ b/util/compute_angle.hpp @@ -36,7 +36,7 @@ struct ComputeAngle // atan2 magic, formerly cosine theorem static double OfThreeFixedPointCoordinates(const FixedPointCoordinate &first, const FixedPointCoordinate &second, - const FixedPointCoordinate &third); + const FixedPointCoordinate &third) noexcept; }; #endif // COMPUTE_ANGLE_HPP diff --git a/util/container.hpp b/util/container.hpp index 49329a58b..891cc3d18 100644 --- a/util/container.hpp +++ b/util/container.hpp @@ -37,16 +37,17 @@ namespace osrm namespace detail { // Culled by SFINAE if reserve does not exist or is not accessible -template constexpr auto has_resize_method(T &t) -> decltype(t.resize(0), bool()) +template +constexpr auto has_resize_method(T &t) noexcept -> decltype(t.resize(0), bool()) { return true; } // Used as fallback when SFINAE culls the template method -constexpr bool has_resize_method(...) { return false; } +constexpr bool has_resize_method(...) noexcept { return false; } } -template void sort_unique_resize(Container &vector) +template void sort_unique_resize(Container &vector) noexcept { std::sort(std::begin(vector), std::end(vector)); const auto number_of_unique_elements = @@ -72,7 +73,9 @@ template void sort_unique_resize(Container &vector) // } template -Function for_each_pair(ForwardIterator begin, ForwardIterator end, Function function) +Function for_each_pair(ForwardIterator begin, + ForwardIterator end, + Function function) noexcept(noexcept(function)) { if (begin == end) { diff --git a/util/integer_range.hpp b/util/integer_range.hpp index 811bbbe9f..46b69ba03 100644 --- a/util/integer_range.hpp +++ b/util/integer_range.hpp @@ -40,29 +40,30 @@ template class range Integer iter; public: - range(Integer start, Integer end) : last(end), iter(start) + range(Integer start, Integer end) noexcept : last(end), iter(start) { static_assert(std::is_integral::value, "range type must be integral"); } // Iterable functions - const range &begin() const { return *this; } - const range &end() const { return *this; } - Integer front() const { return iter; } - Integer back() const { return last - 1; } - Integer size() const { return last - iter; } + const range &begin() const noexcept { return *this; } + const range &end() const noexcept { return *this; } + Integer front() const noexcept { return iter; } + Integer back() const noexcept { return last - 1; } + Integer size() const noexcept { return last - iter; } // Iterator functions - bool operator!=(const range &) const { return iter < last; } - void operator++() { ++iter; } - Integer operator*() const { return iter; } + bool operator!=(const range &) const noexcept { return iter < last; } + void operator++() noexcept { ++iter; } + Integer operator*() const noexcept { return iter; } }; // convenience function to construct an integer range with type deduction template -range irange(const Integer first, - const Integer last, - typename std::enable_if::value>::type * = 0) +range +irange(const Integer first, + const Integer last, + typename std::enable_if::value>::type * = 0) noexcept { return range(first, last); } diff --git a/util/iterator_range.hpp b/util/iterator_range.hpp index 900426863..f4fa4f828 100644 --- a/util/iterator_range.hpp +++ b/util/iterator_range.hpp @@ -33,10 +33,10 @@ namespace osrm template class iter_range { public: - iter_range(Iterator begin, Iterator end) : begin_(begin), end_(end) {} + iter_range(Iterator begin, Iterator end) noexcept : begin_(begin), end_(end) {} - Iterator begin() const { return begin_; } - Iterator end() const { return end_; } + Iterator begin() const noexcept { return begin_; } + Iterator end() const noexcept { return end_; } private: Iterator begin_; @@ -46,13 +46,14 @@ template class iter_range // Convenience functions for template parameter inference, // akin to std::make_pair. -template iter_range integer_range(Iterator begin, Iterator end) +template +iter_range integer_range(Iterator begin, Iterator end) noexcept { return iter_range(begin, end); } template -iter_range reverse(Reversable *reversable) +iter_range reverse(Reversable *reversable) noexcept { return iter_range(reversable->rbegin(), reversable->rend()); @@ -60,7 +61,7 @@ iter_range reverse(Reversable *reversable template iter_range -const_reverse(const ConstReversable *const_reversable) +const_reverse(const ConstReversable *const_reversable) noexcept { return iter_range(const_reversable->crbegin(), const_reversable->crend()); diff --git a/util/mercator.cpp b/util/mercator.cpp index 298257630..0ccd99981 100644 --- a/util/mercator.cpp +++ b/util/mercator.cpp @@ -29,12 +29,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -double mercator::y2lat(const double value) +double mercator::y2lat(const double value) noexcept { return 180. * M_1_PI * (2. * std::atan(std::exp(value * M_PI / 180.)) - M_PI_2); } -double mercator::lat2y(const double latitude) +double mercator::lat2y(const double latitude) noexcept { return 180. * M_1_PI * std::log(std::tan(M_PI_4 + latitude * (M_PI / 180.) / 2.)); } diff --git a/util/mercator.hpp b/util/mercator.hpp index 462c73e23..e994c8499 100644 --- a/util/mercator.hpp +++ b/util/mercator.hpp @@ -30,9 +30,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct mercator { - static double y2lat(const double value); + static double y2lat(const double value) noexcept; - static double lat2y(const double latitude); + static double lat2y(const double latitude) noexcept; }; #endif // MERCATOR_HPP From a4f31001e80f023e8d7beb369d4a765730b2b9e3 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 2 Apr 2015 15:11:23 +0200 Subject: [PATCH 334/360] MSVC doesnt properly support the noexcept operator --- util/container.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/util/container.hpp b/util/container.hpp index 891cc3d18..d455e94e2 100644 --- a/util/container.hpp +++ b/util/container.hpp @@ -73,9 +73,7 @@ template void sort_unique_resize(Container &vector) noexcep // } template -Function for_each_pair(ForwardIterator begin, - ForwardIterator end, - Function function) noexcept(noexcept(function)) +Function for_each_pair(ForwardIterator begin, ForwardIterator end, Function function) { if (begin == end) { From 592211cecda57bf31463afa91d8cc70e0a6615c9 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 7 Apr 2015 14:45:21 +0200 Subject: [PATCH 335/360] activate __get_cpuid on all non X64 platform, fixes #1193 --- algorithms/crc32_processor.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algorithms/crc32_processor.hpp b/algorithms/crc32_processor.hpp index b9444e7b6..a31b4ad23 100644 --- a/algorithms/crc32_processor.hpp +++ b/algorithms/crc32_processor.hpp @@ -116,7 +116,7 @@ class IteratorbasedCRC32 return ecx; } -#if defined(__MINGW64__) || defined(_MSC_VER) +#if defined(__MINGW64__) || defined(_MSC_VER) || !defined(__x86_64__) inline void __get_cpuid(int param, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx) const { From 405f08b8075d56f6e06e5011a07f008f0cc834e0 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 10 Apr 2015 11:45:24 +0200 Subject: [PATCH 336/360] Make node location accessible --- extractor/scripting_environment.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/extractor/scripting_environment.cpp b/extractor/scripting_environment.cpp index 2b34b8047..431fa1522 100644 --- a/extractor/scripting_environment.cpp +++ b/extractor/scripting_environment.cpp @@ -91,6 +91,7 @@ void ScriptingEnvironment::init_lua_state(lua_State *lua_state) luabind::class_("Node") // .def("tags", &osmium::Node::tags) + .def("location", &osmium::Node::location) .def("get_value_by_key", &osmium::Node::get_value_by_key) .def("get_value_by_key", &get_value_by_key), From 11bdfba37e3e1e2b4e3490ccec492d59b4b42397 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 13 Apr 2015 09:47:12 +0200 Subject: [PATCH 337/360] traffic signal penalty ignored on white-listed barriers, cf. #1365 --- profiles/car.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/profiles/car.lua b/profiles/car.lua index ac008a1b8..813afd19c 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -205,9 +205,7 @@ function node_function (node, result) else local barrier = node:get_value_by_key("barrier") if barrier and "" ~= barrier then - if barrier_whitelist[barrier] then - return - else + if not barrier_whitelist[barrier] then result.barrier = true end end From b76fc724fdac206a6fb159ea79f1aa63e5e401c7 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 13 Apr 2015 09:58:59 +0200 Subject: [PATCH 338/360] make node id available thru Lua bindings --- extractor/scripting_environment.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extractor/scripting_environment.cpp b/extractor/scripting_environment.cpp index 431fa1522..972772246 100644 --- a/extractor/scripting_environment.cpp +++ b/extractor/scripting_environment.cpp @@ -93,7 +93,8 @@ void ScriptingEnvironment::init_lua_state(lua_State *lua_state) // .def("tags", &osmium::Node::tags) .def("location", &osmium::Node::location) .def("get_value_by_key", &osmium::Node::get_value_by_key) - .def("get_value_by_key", &get_value_by_key), + .def("get_value_by_key", &get_value_by_key) + .def("id", &osmium::Node::id), luabind::class_("ResultNode") .def_readwrite("traffic_lights", &ExtractionNode::traffic_lights) From 147d35e40d0180727e37c7939aedfef544295656 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 13 Apr 2015 10:04:23 +0200 Subject: [PATCH 339/360] Revert "added lua binding for osmium::Way::id()" --- extractor/scripting_environment.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/extractor/scripting_environment.cpp b/extractor/scripting_environment.cpp index 1050fa9d1..c51651e40 100644 --- a/extractor/scripting_environment.cpp +++ b/extractor/scripting_environment.cpp @@ -118,7 +118,6 @@ void ScriptingEnvironment::init_lua_state(lua_State* lua_state) luabind::class_("Way") .def("get_value_by_key", &osmium::Way::get_value_by_key) .def("get_value_by_key", &get_value_by_key) - .def("id", &osmium::Way::id) ]; if (0 != luaL_dofile(lua_state, file_name.c_str())) From 6c5015811eb8c219ffd54f286b1fadb3d88a9497 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 13 Apr 2015 14:43:35 +0200 Subject: [PATCH 340/360] do not build concurrently on Travis, also build (but not run) benchmarks --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fa6ff3871..ed023e4e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,8 +27,9 @@ before_script: - cd build - cmake .. $CMAKEOPTIONS -DBUILD_TOOLS=1 script: - - make -j 2 - - make -j 2 tests + - make + - make tests + - make benchmarks - ./datastructure-tests - cd .. - cucumber -p verify From e985c9714b14750b7ca4b067c59c1a9dc4f7e869 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 13 Apr 2015 15:37:43 +0200 Subject: [PATCH 341/360] Squashed 'third_party/variant/' changes from 3b02ca0..bf485df bf485df Revert "pass F (functor) by ref/const ref" e031c53 Revert "pass by const ref in 'apply_const'" a3014f5 pass by const ref in 'apply_const' 2e0ce4a pass F (functor) by ref/const ref 5875195 add support for 'unwrapping' std::reference_wrapper and accessing std::reference_wrapper::type through get() + update test c53422f remove boost variant header 5a2d5c5 add reference_wrapper test git-subtree-dir: third_party/variant git-subtree-split: bf485dfb59aef26f3ef2183d7c8c1111ad97062b --- Jamroot | 14 +++++++ test/reference_wrapper_test.cpp | 74 +++++++++++++++++++++++++++++++++ variant.hpp | 43 +++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 test/reference_wrapper_test.cpp diff --git a/Jamroot b/Jamroot index abf312b9c..aead87091 100644 --- a/Jamroot +++ b/Jamroot @@ -59,3 +59,17 @@ exe unique-ptr-test -std=c++11 release:-march=native ; + + +exe reference_wrapper_test + : + test/reference_wrapper_test.cpp + .//system + .//timer + .//chrono + : + $(BOOST_DIR)/include + ./ + -std=c++11 + release:-march=native + ; diff --git a/test/reference_wrapper_test.cpp b/test/reference_wrapper_test.cpp new file mode 100644 index 000000000..2abf02784 --- /dev/null +++ b/test/reference_wrapper_test.cpp @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "variant.hpp" + +using namespace mapbox; + +namespace test { + +struct point +{ +public: + point (double x_, double y_) + : x(x_), y(y_) {} + double x; + double y; +}; + +struct line_string : std::vector {}; +struct polygon : std::vector {}; +using variant = util::variant, + std::reference_wrapper, + std::reference_wrapper>; + +struct print +{ + using result_type = void; + void operator() (point const& pt) const + { + std::cerr << "Point(" << pt.x << "," << pt.y << ")" << std::endl; + } + void operator() (line_string const& line) const + { + std::cerr << "Line("; + for (auto const& pt : line) + { + std::cerr << pt.x << " " << pt.y << ","; + } + std::cerr << ")" << std::endl; + } + template + void operator() (T const& val) const + { + std::cerr << typeid(T).name() << std::endl; + } +}; + + +} + +int main (int argc, char** argv) +{ + std::cerr << sizeof(test::polygon) << std::endl; + std::cerr << sizeof(test::variant) << std::endl; + test::point pt(123,456); + test::variant var = std::move(std::cref(pt)); + util::apply_visitor(test::print(), var); + test::line_string line; + line.push_back(pt); + line.push_back(pt); + line.push_back(test::point(999,333)); + var = std::move(std::cref(line)); + util::apply_visitor(test::print(), var); + std::cerr << "Is line (cref) ? " << var.is>() << std::endl; + auto const& line2 = var.get(); // accessing underlying type of std::reference_wrapper + test::print printer; + printer(line2); + return EXIT_SUCCESS; +} diff --git a/variant.hpp b/variant.hpp index a3cdea63a..837b162df 100644 --- a/variant.hpp +++ b/variant.hpp @@ -250,6 +250,17 @@ struct unwrapper> } }; +template +struct unwrapper> +{ + auto operator() (std::reference_wrapper const& obj) const + -> typename std::reference_wrapper::type const& + { + return obj.get(); + } + +}; + template struct dispatcher; @@ -660,6 +671,38 @@ public: throw std::runtime_error("in get()"); } } + + // get() - T stored as std::reference_wrapper + template , Types...>::index != detail::invalid_value) + >::type* = nullptr> + VARIANT_INLINE T& get() + { + if (type_index == detail::direct_type, Types...>::index) + { + return (*reinterpret_cast*>(&data)).get(); + } + else + { + throw std::runtime_error("in get()"); + } + } + + template , Types...>::index != detail::invalid_value) + >::type* = nullptr> + VARIANT_INLINE T const& get() const + { + if (type_index == detail::direct_type, Types...>::index) + { + return (*reinterpret_cast const*>(&data)).get(); + } + else + { + throw std::runtime_error("in get()"); + } + } + VARIANT_INLINE std::size_t get_type_index() const { return type_index; From c0402345f7d40bacccd01000fa095658cf3751b8 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 13 Apr 2015 15:44:38 +0200 Subject: [PATCH 342/360] Squashed 'third_party/libosmium/' changes from f074d94..8bcd4ea 8bcd4ea Add explicit cast operator from osmium::Timestamp to uint32_t. 0b24814 Fixed the full_queue_sleep_duration const (again). 5e19dd2 Try different workaround for windows... df5d6c9 Fix build error on Windows. 1553adf Workaround for missing support for u8 string literals on Windows. aa5e44a Do not build benchmarks in Appveyor to speed up build. 2b22b31 Remove warning generated by assert by casting to largest type. 148c5e3 Fix inclusion of our own css file into doxygen documentation. 13bce6f Split out test thats fails on Windows and do not run it on appveyor. ca04757 Make CMake add_unit_test() function more flexible. 6c04a63 Tell CMake to output json file with compile commands. c0dd848 Fix indentation in some tests. dfa7e4b Formatting: Consistently use spaces around equal signs. 08fe6db Add change log, release version 2.1.0. 667192e Add XML tests. 28acfc7 Make sorting the PBF stringtables optional. 8184781 Fix PBFInputFormat. Use member variable instead of static variable. 2b48945 Fix comment. 6d37054 Rename m_done to m_quit_input_thread to clarify what it is for. bc23083 Fix race condition in PBF reader. 7fc380e Add various docs, noexcepts, asserts, and tests. aeaf4d7 Not a good idea to how overbroad patterns in .gitignore. c1ef2f9 Bugfix: Multipolygon collector was accessing non-existent NodeRef. 0ef9a13 Add noexcept and docs to some functions in NodeRefList class. da4d764 Workaround for Doxygen bug. e67d5d9 use absolute paths to osmium in YouCompleteMe configuration 38abeac remove template parameter from NodeRefList c47adf0 Add check that osm xml file has or as top-level element. 5e4af90 Updated version number to 2.0.0. 5b2bc3e Workaround in cmake test for sparsehash size. git-subtree-dir: third_party/libosmium git-subtree-split: 8bcd4ea771696812bbb08ebc58e3ee22d0538070 --- .gitignore | 2 - .ycm_extra_conf.py | 10 +- CHANGELOG.md | 31 ++ CMakeLists.txt | 8 +- appveyor.yml | 5 +- cmake/FindOsmium.cmake | 10 +- doc/Doxyfile.in | 8 +- include/osmium/area/assembler.hpp | 6 +- include/osmium/area/detail/segment_list.hpp | 2 +- .../osmium/area/multipolygon_collector.hpp | 2 +- include/osmium/builder/builder.hpp | 7 +- include/osmium/builder/osm_object_builder.hpp | 14 +- include/osmium/geom/factory.hpp | 2 +- include/osmium/geom/haversine.hpp | 2 +- include/osmium/geom/wkb.hpp | 2 +- include/osmium/handler/dump.hpp | 2 +- .../handler/node_locations_for_ways.hpp | 6 +- include/osmium/index/map.hpp | 3 +- include/osmium/index/map/sparse_mem_table.hpp | 4 +- include/osmium/index/multimap.hpp | 3 +- include/osmium/io/bzip2_compression.hpp | 2 +- include/osmium/io/detail/pbf_input_format.hpp | 53 ++- .../osmium/io/detail/pbf_output_format.hpp | 50 ++- include/osmium/io/detail/pbf_parser.hpp | 24 +- include/osmium/io/detail/pbf_stringtable.hpp | 42 +- include/osmium/io/detail/xml_input_format.hpp | 20 +- .../osmium/io/detail/xml_output_format.hpp | 2 +- include/osmium/io/gzip_compression.hpp | 2 +- include/osmium/io/reader.hpp | 4 +- include/osmium/memory/item.hpp | 5 +- include/osmium/osm/area.hpp | 39 +- include/osmium/osm/box.hpp | 77 +++- include/osmium/osm/changeset.hpp | 3 +- include/osmium/osm/node_ref.hpp | 2 +- include/osmium/osm/node_ref_list.hpp | 91 +++- include/osmium/osm/relation.hpp | 2 +- include/osmium/osm/timestamp.hpp | 4 + include/osmium/osm/way.hpp | 6 +- include/osmium/relations/collector.hpp | 2 +- include/osmium/thread/pool.hpp | 2 +- include/osmium/thread/queue.hpp | 8 +- include/osmium/thread/sorted_queue.hpp | 4 +- include/osmium/util/cast.hpp | 3 +- include/osmium/util/verbose_output.hpp | 2 +- test/CMakeLists.txt | 88 ++-- test/data-tests/testdata-xml.cpp | 98 +++- test/t/area/test_area_id.cpp | 32 +- test/t/area/test_node_ref_segment.cpp | 168 +++---- test/t/basic/test_box.cpp | 128 +++--- test/t/basic/test_entity_bits.cpp | 36 +- test/t/basic/test_location.cpp | 234 +++++----- test/t/basic/test_node_ref.cpp | 82 ++-- test/t/basic/test_object_comparisons.cpp | 266 +++++------ test/t/basic/test_timestamp.cpp | 73 +-- test/t/buffer/test_buffer_node.cpp | 122 ++--- test/t/geom/test_factory_with_projection.cpp | 42 +- test/t/geom/test_mercator.cpp | 50 +-- test/t/index/test_id_to_location.cpp | 158 +++---- test/t/index/test_typed_mmap.cpp | 119 ++--- test/t/index/test_typed_mmap_grow.cpp | 34 ++ test/t/io/test_bzip2.cpp | 30 +- test/t/io/test_file_formats.cpp | 420 +++++++++--------- test/t/tags/test_filter.cpp | 290 ++++++------ test/t/tags/test_operators.cpp | 92 ++-- test/t/tags/test_tag_list.cpp | 110 ++--- test/t/thread/test_pool.cpp | 6 +- test/t/util/test_double.cpp | 40 +- test/t/util/test_options.cpp | 68 +-- test/t/util/test_string.cpp | 70 +-- 69 files changed, 1906 insertions(+), 1528 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 test/t/index/test_typed_mmap_grow.cpp diff --git a/.gitignore b/.gitignore index 36118e129..50139035b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,2 @@ -core *.swp -build* .ycm_extra_conf.pyc diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py index b0f9d3eaf..2b8730616 100644 --- a/.ycm_extra_conf.py +++ b/.ycm_extra_conf.py @@ -6,6 +6,10 @@ # #----------------------------------------------------------------------------- +from os.path import realpath, dirname + +basedir = dirname(realpath(__file__)) + # some default flags # for more information install clang-3.2-doc package and # check UsersManual.html @@ -26,9 +30,9 @@ flags = [ 'c++', # libosmium include dirs -'-Iinclude', -'-Itest/include', -'-Itest/data-test/include', +'-I%s/include' % basedir, +'-I%s/test/include' % basedir, +'-I%s/test/data-test/include' % basedir, # include third party libraries '-I/usr/include/gdal', diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..4c345a498 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,31 @@ + +# Change Log + +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## [unreleased] - + +## [2.1.0] - 2015-03-31 + +### Added + +- When writing PBF files, sorting the PBF stringtables is now optional. +- More tests and documentation. + +### Changed + +- Some functions are now declared `noexcept`. +- XML parser fails now if the top-level element is not `osm` or `osmChange`. + +### Fixed + +- Race condition in PBF reader. +- Multipolygon collector was accessing non-existent NodeRef. +- Doxygen documentation wan't showing all classes/functions due to a bug in + Doxygen (up to version 1.8.8). This version contains a workaround to fix + this. + +[unreleased]: https://github.com/osmcode/libosmium/compare/v2.1.0...HEAD +[2.1.0]: https://github.com/osmcode/libosmium/compare/v2.0.0...v2.1.0 + diff --git a/CMakeLists.txt b/CMakeLists.txt index b48f27166..5e70a9935 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,8 @@ cmake_minimum_required(VERSION 2.8 FATAL_ERROR) list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + #----------------------------------------------------------------------------- # @@ -23,9 +25,9 @@ set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel;Dev" project(libosmium) -set(LIBOSMIUM_VERSION_MAJOR 0) -set(LIBOSMIUM_VERSION_MINOR 0) -set(LIBOSMIUM_VERSION_PATCH 1) +set(LIBOSMIUM_VERSION_MAJOR 2) +set(LIBOSMIUM_VERSION_MINOR 1) +set(LIBOSMIUM_VERSION_PATCH 0) set(LIBOSMIUM_VERSION ${LIBOSMIUM_VERSION_MAJOR}.${LIBOSMIUM_VERSION_MINOR}.${LIBOSMIUM_VERSION_PATCH}) diff --git a/appveyor.yml b/appveyor.yml index b3b3f51e4..06c8e6974 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -66,11 +66,12 @@ build_script: - mkdir build - cd build - echo %config% - - cmake .. -LA -G "Visual Studio 14 Win64" -DOsmium_DEBUG=TRUE -DCMAKE_BUILD_TYPE=%config% -DBOOST_ROOT=%LODEPSDIR%\boost -DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_57.lib -DOSMPBF_LIBRARY=%LODEPSDIR%\osmpbf\lib\osmpbf.lib -DOSMPBF_INCLUDE_DIR=%LODEPSDIR%\osmpbf\include -DPROTOBUF_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf.lib -DPROTOBUF_LITE_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf-lite.lib -DPROTOBUF_INCLUDE_DIR=%LODEPSDIR%\protobuf\include -DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib -DZLIB_INCLUDE_DIR=%LODEPSDIR%\zlib\include -DEXPAT_LIBRARY=%LODEPSDIR%\expat\lib\libexpat.lib -DEXPAT_INCLUDE_DIR=%LODEPSDIR%\expat\include -DBZIP2_LIBRARIES=%LIBBZIP2% -DBZIP2_INCLUDE_DIR=%LODEPSDIR%\bzip2\include -DGDAL_LIBRARY=%LODEPSDIR%\gdal\lib\gdal_i.lib -DGDAL_INCLUDE_DIR=%LODEPSDIR%\gdal\include -DGEOS_LIBRARY=%LODEPSDIR%\geos\lib\geos.lib -DGEOS_INCLUDE_DIR=%LODEPSDIR%\geos\include -DPROJ_LIBRARY=%LODEPSDIR%\proj\lib\proj.lib -DPROJ_INCLUDE_DIR=%LODEPSDIR%\proj\include -DSPARSEHASH_INCLUDE_DIR=%LODEPSDIR%\sparsehash\include -DGETOPT_LIBRARY=%LODEPSDIR%\wingetopt\lib\wingetopt.lib -DGETOPT_INCLUDE_DIR=%LODEPSDIR%\wingetopt\include + - cmake .. -LA -G "Visual Studio 14 Win64" -DOsmium_DEBUG=TRUE -DCMAKE_BUILD_TYPE=%config% -DBUILD_BENCHMARKS=OFF -DBOOST_ROOT=%LODEPSDIR%\boost -DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_57.lib -DOSMPBF_LIBRARY=%LODEPSDIR%\osmpbf\lib\osmpbf.lib -DOSMPBF_INCLUDE_DIR=%LODEPSDIR%\osmpbf\include -DPROTOBUF_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf.lib -DPROTOBUF_LITE_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf-lite.lib -DPROTOBUF_INCLUDE_DIR=%LODEPSDIR%\protobuf\include -DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib -DZLIB_INCLUDE_DIR=%LODEPSDIR%\zlib\include -DEXPAT_LIBRARY=%LODEPSDIR%\expat\lib\libexpat.lib -DEXPAT_INCLUDE_DIR=%LODEPSDIR%\expat\include -DBZIP2_LIBRARIES=%LIBBZIP2% -DBZIP2_INCLUDE_DIR=%LODEPSDIR%\bzip2\include -DGDAL_LIBRARY=%LODEPSDIR%\gdal\lib\gdal_i.lib -DGDAL_INCLUDE_DIR=%LODEPSDIR%\gdal\include -DGEOS_LIBRARY=%LODEPSDIR%\geos\lib\geos.lib -DGEOS_INCLUDE_DIR=%LODEPSDIR%\geos\include -DPROJ_LIBRARY=%LODEPSDIR%\proj\lib\proj.lib -DPROJ_INCLUDE_DIR=%LODEPSDIR%\proj\include -DSPARSEHASH_INCLUDE_DIR=%LODEPSDIR%\sparsehash\include -DGETOPT_LIBRARY=%LODEPSDIR%\wingetopt\lib\wingetopt.lib -DGETOPT_INCLUDE_DIR=%LODEPSDIR%\wingetopt\include - msbuild libosmium.sln /p:Configuration=%config% /toolsversion:14.0 /p:Platform=x64 /p:PlatformToolset=v140 #- cmake .. -LA -G "NMake Makefiles" -DOsmium_DEBUG=TRUE -DCMAKE_BUILD_TYPE=%config% -DBOOST_ROOT=%LODEPSDIR%\boost -DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_57.lib -DOSMPBF_LIBRARY=%LODEPSDIR%\osmpbf\lib\osmpbf.lib -DOSMPBF_INCLUDE_DIR=%LODEPSDIR%\osmpbf\include -DPROTOBUF_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf.lib -DPROTOBUF_LITE_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf-lite.lib -DPROTOBUF_INCLUDE_DIR=%LODEPSDIR%\protobuf\include -DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib -DZLIB_INCLUDE_DIR=%LODEPSDIR%\zlib\include -DEXPAT_LIBRARY=%LODEPSDIR%\expat\lib\libexpat.lib -DEXPAT_INCLUDE_DIR=%LODEPSDIR%\expat\include -DBZIP2_LIBRARIES=%LIBBZIP2% -DBZIP2_INCLUDE_DIR=%LODEPSDIR%\bzip2\include -DGDAL_LIBRARY=%LODEPSDIR%\gdal\lib\gdal_i.lib -DGDAL_INCLUDE_DIR=%LODEPSDIR%\gdal\include -DGEOS_LIBRARY=%LODEPSDIR%\geos\lib\geos.lib -DGEOS_INCLUDE_DIR=%LODEPSDIR%\geos\include -DPROJ_LIBRARY=%LODEPSDIR%\proj\lib\proj.lib -DPROJ_INCLUDE_DIR=%LODEPSDIR%\proj\include -DSPARSEHASH_INCLUDE_DIR=%LODEPSDIR%\sparsehash\include -DGETOPT_LIBRARY=%LODEPSDIR%\wingetopt\lib\wingetopt.lib -DGETOPT_INCLUDE_DIR=%LODEPSDIR%\wingetopt\include #- nmake test_script: - - ctest --output-on-failure -C %config% + # -LE fails_on_windows exempts tests we know will fail + - ctest --output-on-failure -C %config% -LE fails_on_windows diff --git a/cmake/FindOsmium.cmake b/cmake/FindOsmium.cmake index 4c3370843..1de41a022 100644 --- a/cmake/FindOsmium.cmake +++ b/cmake/FindOsmium.cmake @@ -226,7 +226,6 @@ if(Osmium_USE_SPARSEHASH) if(SPARSEHASH_INCLUDE_DIR) # 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++. - # Until we find a better way, we'll live with that. include(CheckTypeSize) set(CMAKE_REQUIRED_INCLUDES ${SPARSEHASH_INCLUDE_DIR}) set(CMAKE_EXTRA_INCLUDE_FILES "google/sparsetable") @@ -234,14 +233,19 @@ if(Osmium_USE_SPARSEHASH) set(CMAKE_EXTRA_INCLUDE_FILES) set(CMAKE_REQUIRED_INCLUDES) + # Falling back to checking size_t if google::sparsetable::size_type + # could not be checked. + if(SPARSETABLE_SIZE_TYPE STREQUAL "") + check_type_size("void*" VOID_PTR_SIZE) + set(SPARSETABLE_SIZE_TYPE ${VOID_PTR_SIZE}) + endif() + # Sparsetable::size_type must be at least 8 bytes (64bit), otherwise # OSM object IDs will not fit. if(SPARSETABLE_SIZE_TYPE GREATER 7) set(SPARSEHASH_FOUND 1) add_definitions(-DOSMIUM_WITH_SPARSEHASH=${SPARSEHASH_FOUND}) list(APPEND OSMIUM_INCLUDE_DIRS ${SPARSEHASH_INCLUDE_DIR}) - elseif(SPARSETABLE_SIZE_TYPE STREQUAL "") - message(WARNING "Osmium: Disabled Google SparseHash library because we can't detect whether we are on a 64bit system.") else() message(WARNING "Osmium: Disabled Google SparseHash library on 32bit system (size_type=${SPARSETABLE_SIZE_TYPE}).") endif() diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 6535259f3..c03e255e9 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -694,7 +694,7 @@ CITE_BIB_FILES = # messages are off. # The default value is: NO. -QUIET = NO +QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES @@ -860,7 +860,7 @@ IMAGE_PATH = # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. -INPUT_FILTER = +INPUT_FILTER = "grep -v static_assert" # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the @@ -876,7 +876,7 @@ FILTER_PATTERNS = # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. -FILTER_SOURCE_FILES = NO +FILTER_SOURCE_FILES = YES # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and @@ -1080,7 +1080,7 @@ HTML_STYLESHEET = # see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_STYLESHEET = doc/osmium.css +HTML_EXTRA_STYLESHEET = "@PROJECT_SOURCE_DIR@/doc/osmium.css" # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note diff --git a/include/osmium/area/assembler.hpp b/include/osmium/area/assembler.hpp index db769ddf8..0a5f12323 100644 --- a/include/osmium/area/assembler.hpp +++ b/include/osmium/area/assembler.hpp @@ -65,7 +65,7 @@ namespace osmium { // Enables debug output to stderr bool debug; - explicit AssemblerConfig(osmium::area::ProblemReporter* pr = nullptr, bool d=false) : + explicit AssemblerConfig(osmium::area::ProblemReporter* pr = nullptr, bool d = false) : problem_reporter(pr), debug(d) { } @@ -74,7 +74,7 @@ namespace osmium { * Enable or disable debug output to stderr. This is for Osmium * developers only. */ - void enable_debug_output(bool d=true) { + void enable_debug_output(bool d = true) { debug = d; } @@ -445,7 +445,7 @@ namespace osmium { } bool add_to_existing_ring(osmium::area::detail::NodeRefSegment segment) { - int n=0; + int n = 0; for (auto& ring : m_rings) { if (debug()) { std::cerr << " check against ring " << n << " " << ring; diff --git a/include/osmium/area/detail/segment_list.hpp b/include/osmium/area/detail/segment_list.hpp index 12ec97fa9..ca6071ede 100644 --- a/include/osmium/area/detail/segment_list.hpp +++ b/include/osmium/area/detail/segment_list.hpp @@ -99,7 +99,7 @@ namespace osmium { * Enable or disable debug output to stderr. This is for Osmium * developers only. */ - void enable_debug_output(bool debug=true) noexcept { + void enable_debug_output(bool debug = true) noexcept { m_debug = debug; } diff --git a/include/osmium/area/multipolygon_collector.hpp b/include/osmium/area/multipolygon_collector.hpp index 0bd10f78b..84a52622b 100644 --- a/include/osmium/area/multipolygon_collector.hpp +++ b/include/osmium/area/multipolygon_collector.hpp @@ -142,7 +142,7 @@ namespace osmium { * Overwritten from the base class. */ void way_not_in_any_relation(const osmium::Way& way) { - if (way.ends_have_same_location() && way.nodes().size() > 3) { + if (way.nodes().size() > 3 && way.ends_have_same_location()) { // way is closed and has enough nodes, build simple multipolygon try { TAssembler assembler(m_assembler_config); diff --git a/include/osmium/builder/builder.hpp b/include/osmium/builder/builder.hpp index bf9cdccfc..dcb95e2ac 100644 --- a/include/osmium/builder/builder.hpp +++ b/include/osmium/builder/builder.hpp @@ -100,7 +100,7 @@ namespace osmium { * parent item (if any). * */ - void add_padding(bool self=false) { + void add_padding(bool self = false) { auto padding = osmium::memory::align_bytes - (size() % osmium::memory::align_bytes); if (padding != osmium::memory::align_bytes) { std::fill_n(m_buffer.reserve_space(padding), padding, 0); @@ -171,12 +171,11 @@ namespace osmium { template class ObjectBuilder : public Builder { - static_assert(std::is_base_of::value, - "ObjectBuilder can only build objects derived from osmium::memory::Item"); + static_assert(std::is_base_of::value, "ObjectBuilder can only build objects derived from osmium::memory::Item"); public: - explicit ObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : + explicit ObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) : Builder(buffer, parent, sizeof(TItem)) { new (&item()) TItem(); } diff --git a/include/osmium/builder/osm_object_builder.hpp b/include/osmium/builder/osm_object_builder.hpp index b88765e2a..058f89e8e 100644 --- a/include/osmium/builder/osm_object_builder.hpp +++ b/include/osmium/builder/osm_object_builder.hpp @@ -61,7 +61,7 @@ namespace osmium { public: - explicit TagListBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : + explicit TagListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) : ObjectBuilder(buffer, parent) { } @@ -97,7 +97,7 @@ namespace osmium { public: - explicit NodeRefListBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : + explicit NodeRefListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) : ObjectBuilder(buffer, parent) { } @@ -110,7 +110,7 @@ namespace osmium { static_cast(this)->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()) { add_node_ref(NodeRef(ref, location)); } @@ -160,7 +160,7 @@ namespace osmium { public: - explicit RelationMemberListBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : + explicit RelationMemberListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) : ObjectBuilder(buffer, parent) { } @@ -215,7 +215,7 @@ namespace osmium { public: - explicit OSMObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : + explicit OSMObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) : ObjectBuilder(buffer, parent) { static_cast(this)->reserve_space_for(); static_cast(this)->add_size(sizeof(string_size_type)); @@ -237,7 +237,7 @@ namespace osmium { public: - explicit WayBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : + explicit WayBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) : OSMObjectBuilder(buffer, parent) { } @@ -254,7 +254,7 @@ namespace osmium { public: - explicit AreaBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : + explicit AreaBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) : OSMObjectBuilder(buffer, parent) { } diff --git a/include/osmium/geom/factory.hpp b/include/osmium/geom/factory.hpp index a0a208075..518cbfbc2 100644 --- a/include/osmium/geom/factory.hpp +++ b/include/osmium/geom/factory.hpp @@ -214,7 +214,7 @@ namespace osmium { return m_impl.linestring_finish(num_points); } - linestring_type create_linestring(const osmium::WayNodeList& wnl, use_nodes un=use_nodes::unique, direction dir=direction::forward) { + linestring_type create_linestring(const osmium::WayNodeList& wnl, use_nodes un = use_nodes::unique, direction dir = direction::forward) { linestring_start(); size_t num_points = 0; diff --git a/include/osmium/geom/haversine.hpp b/include/osmium/geom/haversine.hpp index 14e18c59a..e62a31b03 100644 --- a/include/osmium/geom/haversine.hpp +++ b/include/osmium/geom/haversine.hpp @@ -74,7 +74,7 @@ namespace osmium { * Calculate length of way. */ inline double distance(const osmium::WayNodeList& wnl) { - double sum_length=0; + double sum_length = 0; for (auto it = wnl.begin(); it != wnl.end(); ++it) { if (std::next(it) != wnl.end()) { diff --git a/include/osmium/geom/wkb.hpp b/include/osmium/geom/wkb.hpp index 31fce71f9..2f32fe33b 100644 --- a/include/osmium/geom/wkb.hpp +++ b/include/osmium/geom/wkb.hpp @@ -161,7 +161,7 @@ namespace osmium { typedef std::string multipolygon_type; typedef std::string ring_type; - explicit WKBFactoryImpl(wkb_type wtype=wkb_type::wkb, out_type otype=out_type::binary) : + explicit WKBFactoryImpl(wkb_type wtype = wkb_type::wkb, out_type otype = out_type::binary) : m_wkb_type(wtype), m_out_type(otype) { } diff --git a/include/osmium/handler/dump.hpp b/include/osmium/handler/dump.hpp index 564035c56..a23236e10 100644 --- a/include/osmium/handler/dump.hpp +++ b/include/osmium/handler/dump.hpp @@ -136,7 +136,7 @@ namespace osmium { public: - explicit Dump(std::ostream& out, bool with_size=true, const std::string& prefix="") : + explicit Dump(std::ostream& out, bool with_size = true, const std::string& prefix = "") : m_out(&out), m_with_size(with_size), m_prefix(prefix) { diff --git a/include/osmium/handler/node_locations_for_ways.hpp b/include/osmium/handler/node_locations_for_ways.hpp index d1224a0d5..9b9fcbf3f 100644 --- a/include/osmium/handler/node_locations_for_ways.hpp +++ b/include/osmium/handler/node_locations_for_ways.hpp @@ -63,11 +63,9 @@ namespace osmium { template class NodeLocationsForWays : public osmium::handler::Handler { - static_assert(std::is_base_of, TStoragePosIDs>::value, - "Index class must be derived from osmium::index::map::Map"); + static_assert(std::is_base_of, TStoragePosIDs>::value, "Index class must be derived from osmium::index::map::Map"); - static_assert(std::is_base_of, TStorageNegIDs>::value, - "Index class must be derived from osmium::index::map::Map"); + static_assert(std::is_base_of, TStorageNegIDs>::value, "Index class must be derived from osmium::index::map::Map"); public: diff --git a/include/osmium/index/map.hpp b/include/osmium/index/map.hpp index a9fe0c3bd..7b44b8e33 100644 --- a/include/osmium/index/map.hpp +++ b/include/osmium/index/map.hpp @@ -84,8 +84,7 @@ namespace osmium { template class Map { - static_assert(std::is_integral::value && std::is_unsigned::value, - "TId template parameter for class Map must be unsigned integral type"); + static_assert(std::is_integral::value && std::is_unsigned::value, "TId template parameter for class Map must be unsigned integral type"); Map(const Map&) = delete; Map& operator=(const Map&) = delete; diff --git a/include/osmium/index/map/sparse_mem_table.hpp b/include/osmium/index/map/sparse_mem_table.hpp index 8998a91f5..09ee81bbc 100644 --- a/include/osmium/index/map/sparse_mem_table.hpp +++ b/include/osmium/index/map/sparse_mem_table.hpp @@ -83,7 +83,7 @@ namespace osmium { * The storage will grow by at least this size * every time it runs out of space. */ - explicit SparseMemTable(const TId grow_size=10000) : + explicit SparseMemTable(const TId grow_size = 10000) : m_grow_size(grow_size), m_elements(grow_size) { } @@ -123,7 +123,7 @@ namespace osmium { void dump_as_list(const int fd) override final { std::vector> v; - int n=0; + int n = 0; for (const TValue value : m_elements) { if (value != osmium::index::empty_value()) { v.emplace_back(n, value); diff --git a/include/osmium/index/multimap.hpp b/include/osmium/index/multimap.hpp index e5c6b4f4e..c817b6fb6 100644 --- a/include/osmium/index/multimap.hpp +++ b/include/osmium/index/multimap.hpp @@ -50,8 +50,7 @@ namespace osmium { template class Multimap { - static_assert(std::is_integral::value && std::is_unsigned::value, - "TId template parameter for class Multimap must be unsigned integral type"); + static_assert(std::is_integral::value && std::is_unsigned::value, "TId template parameter for class Multimap must be unsigned integral type"); typedef typename std::pair element_type; diff --git a/include/osmium/io/bzip2_compression.hpp b/include/osmium/io/bzip2_compression.hpp index de1364c69..7e86c1543 100644 --- a/include/osmium/io/bzip2_compression.hpp +++ b/include/osmium/io/bzip2_compression.hpp @@ -82,7 +82,7 @@ namespace osmium { namespace detail { - OSMIUM_NORETURN inline void throw_bzip2_error(BZFILE* bzfile, const char* msg, int bzlib_error=0) { + OSMIUM_NORETURN inline void throw_bzip2_error(BZFILE* bzfile, const char* msg, int bzlib_error = 0) { std::string error("bzip2 error: "); error += msg; error += ": "; diff --git a/include/osmium/io/detail/pbf_input_format.hpp b/include/osmium/io/detail/pbf_input_format.hpp index 8b997ec25..ba8fb42a2 100644 --- a/include/osmium/io/detail/pbf_input_format.hpp +++ b/include/osmium/io/detail/pbf_input_format.hpp @@ -84,8 +84,9 @@ namespace osmium { class PBFInputFormat : public osmium::io::detail::InputFormat { bool m_use_thread_pool; + bool m_eof { false }; queue_type m_queue; - std::atomic m_done; + std::atomic m_quit_input_thread; std::thread m_reader; osmium::thread::Queue& m_input_queue; std::string m_input_buffer; @@ -151,7 +152,7 @@ namespace osmium { void parse_osm_data(osmium::osm_entity_bits::type read_types) { osmium::thread::set_thread_name("_osmium_pbf_in"); - int n=0; + int n = 0; while (auto size = read_blob_header("OSMData")) { if (m_use_thread_pool) { @@ -164,11 +165,20 @@ namespace osmium { } ++n; - if (m_done) { + if (m_quit_input_thread) { return; } } - m_done = true; + + // Send an empty buffer to signal the reader that we are + // done. + std::promise promise; + m_queue.push(promise.get_future()); + promise.set_value(osmium::memory::Buffer{}); + } + + void signal_input_thread_to_quit() { + m_quit_input_thread = true; } public: @@ -184,7 +194,7 @@ namespace osmium { osmium::io::detail::InputFormat(file, read_which_entities), m_use_thread_pool(osmium::config::use_pool_threads_for_pbf_parsing()), m_queue(20, "pbf_parser_results"), // XXX - m_done(false), + m_quit_input_thread(false), m_input_queue(input_queue), m_input_buffer() { GOOGLE_PROTOBUF_VERIFY_VERSION; @@ -199,30 +209,37 @@ namespace osmium { } ~PBFInputFormat() { - m_done = true; + signal_input_thread_to_quit(); if (m_reader.joinable()) { m_reader.join(); } } /** - * Returns the next buffer with OSM data read from the PBF file. - * Blocks if data is not available yet. + * Returns the next buffer with OSM data read from the PBF + * file. Blocks if data is not available yet. * Returns an empty buffer at end of input. */ osmium::memory::Buffer read() override { - if (!m_done || !m_queue.empty()) { - std::future buffer_future; - m_queue.wait_and_pop(buffer_future); - try { - return buffer_future.get(); - } catch (...) { - m_done = true; - throw; - } + osmium::memory::Buffer buffer; + if (m_eof) { + return buffer; } - return osmium::memory::Buffer(); + std::future buffer_future; + m_queue.wait_and_pop(buffer_future); + + try { + buffer = std::move(buffer_future.get()); + if (!buffer) { + m_eof = true; + } + return buffer; + } catch (...) { + m_eof = true; + signal_input_thread_to_quit(); + throw; + } } }; // class PBFInputFormat diff --git a/include/osmium/io/detail/pbf_output_format.hpp b/include/osmium/io/detail/pbf_output_format.hpp index 73bc61673..288008f6a 100644 --- a/include/osmium/io/detail/pbf_output_format.hpp +++ b/include/osmium/io/detail/pbf_output_format.hpp @@ -294,6 +294,14 @@ namespace osmium { */ bool m_use_compression {true}; + /** + * Should the string tables in the data blocks be sorted? + * + * Not sorting the string tables makes writing PBF files + * slightly faster. + */ + bool m_sort_stringtables { true }; + /** * While the .osm.pbf-format is able to carry all meta information, it is * also able to omit this information to reduce size. @@ -340,6 +348,21 @@ namespace osmium { ///// Blob writing ///// + void delta_encode_string_ids() { + if (pbf_nodes && pbf_nodes->has_dense()) { + OSMPBF::DenseNodes* dense = pbf_nodes->mutable_dense(); + + if (dense->has_denseinfo()) { + OSMPBF::DenseInfo* denseinfo = dense->mutable_denseinfo(); + + for (int i = 0, l=denseinfo->user_sid_size(); iuser_sid(i); + denseinfo->set_user_sid(i, m_delta_user_sid.update(user_sid)); + } + } + } + } + /** * Before a PrimitiveBlock gets serialized, all interim StringTable-ids needs to be * mapped to the associated real StringTable ids. This is done in this function. @@ -351,7 +374,7 @@ namespace osmium { // test, if the node-block has been allocated if (pbf_nodes) { // iterate over all nodes, passing them to the map_common_string_ids function - for (int i=0, l=pbf_nodes->nodes_size(); inodes_size(); imutable_nodes(i)); } @@ -363,7 +386,7 @@ namespace osmium { // in the densenodes structure keys and vals are encoded in an intermixed // array, individual nodes are seperated by a value of 0 (0 in the StringTable // is always unused). String-ids of 0 are thus kept alone. - for (int i=0, l=dense->keys_vals_size(); ikeys_vals_size(); i 0 to real string ids auto sid = dense->keys_vals(i); if (sid > 0) { @@ -377,7 +400,7 @@ namespace osmium { OSMPBF::DenseInfo* denseinfo = dense->mutable_denseinfo(); // iterate over all username string-ids - for (int i=0, l=denseinfo->user_sid_size(); iuser_sid_size(); i 0 to real string ids auto user_sid = string_table.map_string_id(denseinfo->user_sid(i)); @@ -391,7 +414,7 @@ namespace osmium { // test, if the ways-block has been allocated if (pbf_ways) { // iterate over all ways, passing them to the map_common_string_ids function - for (int i=0, l=pbf_ways->ways_size(); iways_size(); imutable_ways(i)); } } @@ -399,7 +422,7 @@ namespace osmium { // test, if the relations-block has been allocated if (pbf_relations) { // iterate over all relations - for (int i=0, l=pbf_relations->relations_size(); irelations_size(); imutable_relations(i); @@ -408,7 +431,7 @@ namespace osmium { // iterate over all relation members, mapping the interim string-ids // of the role to real string ids - for (int mi=0; mi < relation->roles_sid_size(); ++mi) { + for (int mi = 0; mi < relation->roles_sid_size(); ++mi) { relation->set_roles_sid(mi, string_table.map_string_id(relation->roles_sid(mi))); } } @@ -431,7 +454,7 @@ namespace osmium { } // iterate over all tags and map the interim-ids of the key and the value to real ids - for (int i=0, l=in->keys_size(); ikeys_size(); iset_keys(i, string_table.map_string_id(in->keys(i))); in->set_vals(i, string_table.map_string_id(in->vals(i))); } @@ -518,11 +541,13 @@ namespace osmium { pbf_primitive_block.set_granularity(location_granularity()); pbf_primitive_block.set_date_granularity(date_granularity()); - // store the interim StringTable into the protobuf object - string_table.store_stringtable(pbf_primitive_block.mutable_stringtable()); + string_table.store_stringtable(pbf_primitive_block.mutable_stringtable(), m_sort_stringtables); - // map all interim string ids to real ids - map_string_ids(); + if (m_sort_stringtables) { + map_string_ids(); + } else { + delta_encode_string_ids(); + } std::promise promise; m_output_queue.push(promise.get_future()); @@ -743,6 +768,9 @@ namespace osmium { if (file.get("pbf_compression") == "none" || file.get("pbf_compression") == "false") { m_use_compression = false; } + if (file.get("pbf_sort_stringtables") == "false") { + m_sort_stringtables = false; + } if (file.get("pbf_add_metadata") == "false") { m_should_add_metadata = false; } diff --git a/include/osmium/io/detail/pbf_parser.hpp b/include/osmium/io/detail/pbf_parser.hpp index d99819d3d..65a11e155 100644 --- a/include/osmium/io/detail/pbf_parser.hpp +++ b/include/osmium/io/detail/pbf_parser.hpp @@ -106,7 +106,7 @@ namespace osmium { m_date_factor = pbf_primitive_block.date_granularity() / 1000; m_granularity = pbf_primitive_block.granularity(); - for (int i=0; i < pbf_primitive_block.primitivegroup_size(); ++i) { + for (int i = 0; i < pbf_primitive_block.primitivegroup_size(); ++i) { const OSMPBF::PrimitiveGroup& group = pbf_primitive_block.primitivegroup(i); if (group.has_dense()) { @@ -148,7 +148,7 @@ namespace osmium { } void parse_node_group(const OSMPBF::PrimitiveGroup& group) { - for (int i=0; i < group.nodes_size(); ++i) { + for (int i = 0; i < group.nodes_size(); ++i) { osmium::builder::NodeBuilder builder(m_buffer); const OSMPBF::Node& pbf_node = group.nodes(i); parse_attributes(builder, pbf_node); @@ -161,7 +161,7 @@ namespace osmium { if (pbf_node.keys_size() > 0) { osmium::builder::TagListBuilder tl_builder(m_buffer, &builder); - for (int tag=0; tag < pbf_node.keys_size(); ++tag) { + for (int tag = 0; tag < pbf_node.keys_size(); ++tag) { tl_builder.add_tag(m_stringtable->s(static_cast(pbf_node.keys(tag))), m_stringtable->s(static_cast(pbf_node.vals(tag)))); } @@ -172,7 +172,7 @@ namespace osmium { } void parse_way_group(const OSMPBF::PrimitiveGroup& group) { - for (int i=0; i < group.ways_size(); ++i) { + for (int i = 0; i < group.ways_size(); ++i) { osmium::builder::WayBuilder builder(m_buffer); const OSMPBF::Way& pbf_way = group.ways(i); parse_attributes(builder, pbf_way); @@ -180,7 +180,7 @@ namespace osmium { if (pbf_way.refs_size() > 0) { osmium::builder::WayNodeListBuilder wnl_builder(m_buffer, &builder); int64_t ref = 0; - for (int n=0; n < pbf_way.refs_size(); ++n) { + for (int n = 0; n < pbf_way.refs_size(); ++n) { ref += pbf_way.refs(n); wnl_builder.add_node_ref(ref); } @@ -188,7 +188,7 @@ namespace osmium { if (pbf_way.keys_size() > 0) { osmium::builder::TagListBuilder tl_builder(m_buffer, &builder); - for (int tag=0; tag < pbf_way.keys_size(); ++tag) { + for (int tag = 0; tag < pbf_way.keys_size(); ++tag) { tl_builder.add_tag(m_stringtable->s(static_cast(pbf_way.keys(tag))), m_stringtable->s(static_cast(pbf_way.vals(tag)))); } @@ -199,7 +199,7 @@ namespace osmium { } void parse_relation_group(const OSMPBF::PrimitiveGroup& group) { - for (int i=0; i < group.relations_size(); ++i) { + for (int i = 0; i < group.relations_size(); ++i) { osmium::builder::RelationBuilder builder(m_buffer); const OSMPBF::Relation& pbf_relation = group.relations(i); parse_attributes(builder, pbf_relation); @@ -207,7 +207,7 @@ namespace osmium { if (pbf_relation.types_size() > 0) { osmium::builder::RelationMemberListBuilder rml_builder(m_buffer, &builder); int64_t ref = 0; - for (int n=0; n < pbf_relation.types_size(); ++n) { + for (int n = 0; n < pbf_relation.types_size(); ++n) { ref += pbf_relation.memids(n); rml_builder.add_member(osmpbf_membertype_to_item_type(pbf_relation.types(n)), ref, m_stringtable->s(pbf_relation.roles_sid(n))); } @@ -215,7 +215,7 @@ namespace osmium { if (pbf_relation.keys_size() > 0) { osmium::builder::TagListBuilder tl_builder(m_buffer, &builder); - for (int tag=0; tag < pbf_relation.keys_size(); ++tag) { + for (int tag = 0; tag < pbf_relation.keys_size(); ++tag) { tl_builder.add_tag(m_stringtable->s(static_cast(pbf_relation.keys(tag))), m_stringtable->s(static_cast(pbf_relation.vals(tag)))); } @@ -264,7 +264,7 @@ namespace osmium { const OSMPBF::DenseNodes& dense = group.dense(); - for (int i=0; i < dense.id_size(); ++i) { + for (int i = 0; i < dense.id_size(); ++i) { bool visible = true; last_dense_id += dense.id(i); @@ -361,7 +361,7 @@ namespace osmium { } osmium::io::Header header; - for (int i=0; i < pbf_header_block.required_features_size(); ++i) { + for (int i = 0; i < pbf_header_block.required_features_size(); ++i) { const std::string& feature = pbf_header_block.required_features(i); if (feature == "OsmSchema-V0.6") continue; @@ -377,7 +377,7 @@ namespace osmium { throw osmium::pbf_error(std::string("required feature not supported: ") + feature); } - for (int i=0; i < pbf_header_block.optional_features_size(); ++i) { + for (int i = 0; i < pbf_header_block.optional_features_size(); ++i) { const std::string& feature = pbf_header_block.optional_features(i); header.set("pbf_optional_feature_" + std::to_string(i), feature); } diff --git a/include/osmium/io/detail/pbf_stringtable.hpp b/include/osmium/io/detail/pbf_stringtable.hpp index c56d549de..5f540f127 100644 --- a/include/osmium/io/detail/pbf_stringtable.hpp +++ b/include/osmium/io/detail/pbf_stringtable.hpp @@ -145,30 +145,44 @@ namespace osmium { * implementation) is that the string table is sorted first by reverse count (ie descending) * and then by reverse lexicographic order. */ - void store_stringtable(OSMPBF::StringTable* st) { + void store_stringtable(OSMPBF::StringTable* st, bool sort) { // add empty StringTable entry at index 0 // StringTable index 0 is reserved as delimiter in the densenodes key/value list // this line also ensures that there's always a valid StringTable st->add_s(""); - std::multimap sortedbycount; + if (sort) { + std::multimap sortedbycount; - m_id2id_map.resize(m_size+1); + m_id2id_map.resize(m_size+1); - std::transform(m_strings.begin(), m_strings.end(), - std::inserter(sortedbycount, sortedbycount.begin()), - [](const std::pair& p) { - return std::pair(p.second, p.first); - }); + std::transform(m_strings.begin(), m_strings.end(), + std::inserter(sortedbycount, sortedbycount.begin()), + [](const std::pair& p) { + return std::pair(p.second, p.first); + }); - string_id_type n=0; + string_id_type n = 0; - for (const auto& mapping : sortedbycount) { - // add the string of the current item to the pbf StringTable - st->add_s(mapping.second); + for (const auto& mapping : sortedbycount) { + // add the string of the current item to the pbf StringTable + st->add_s(mapping.second); - // store the mapping from the interim-id to the real id - m_id2id_map[mapping.first.interim_id] = ++n; + // store the mapping from the interim-id to the real id + m_id2id_map[mapping.first.interim_id] = ++n; + } + } else { + std::vector> sortedbyid; + sortedbyid.reserve(m_strings.size()); + + for (const auto& p : m_strings) { + sortedbyid.emplace_back(p.second.interim_id, p.first.c_str()); + } + + std::sort(sortedbyid.begin(), sortedbyid.end()); + for (const auto& mapping : sortedbyid) { + st->add_s(mapping.second); + } } } diff --git a/include/osmium/io/detail/xml_input_format.hpp b/include/osmium/io/detail/xml_input_format.hpp index 96003d874..c03f84d9b 100644 --- a/include/osmium/io/detail/xml_input_format.hpp +++ b/include/osmium/io/detail/xml_input_format.hpp @@ -74,8 +74,8 @@ namespace osmium { /** * Exception thrown when the XML parser failed. The exception contains - * information about the place where the error happened and the type of - * error. + * (if available) information about the place where the error happened + * and the type of error. */ struct xml_error : public io_error { @@ -84,7 +84,7 @@ namespace osmium { XML_Error error_code; std::string error_string; - xml_error(XML_Parser parser) : + explicit xml_error(XML_Parser parser) : io_error(std::string("XML parsing error at line ") + std::to_string(XML_GetCurrentLineNumber(parser)) + ", column " @@ -97,8 +97,20 @@ namespace osmium { error_string(XML_ErrorString(error_code)) { } + explicit xml_error(const std::string& message) : + io_error(message), + line(0), + column(0), + error_code(), + error_string(message) { + } + }; // struct xml_error + /** + * Exception thrown when an OSM XML files contains no version attribute + * on the 'osm' element or if the version is unknown. + */ struct format_version_error : public io_error { std::string version; @@ -434,6 +446,8 @@ namespace osmium { if (m_header.get("version") == "") { throw osmium::format_version_error(); } + } else { + throw osmium::xml_error(std::string("Unknown top-level element: ") + element); } m_context = context::top; break; diff --git a/include/osmium/io/detail/xml_output_format.hpp b/include/osmium/io/detail/xml_output_format.hpp index 73a7263ce..65ba171b8 100644 --- a/include/osmium/io/detail/xml_output_format.hpp +++ b/include/osmium/io/detail/xml_output_format.hpp @@ -130,7 +130,7 @@ namespace osmium { const bool m_write_change_ops; void write_spaces(int num) { - for (; num!=0; --num) { + for (; num != 0; --num) { *m_out += ' '; } } diff --git a/include/osmium/io/gzip_compression.hpp b/include/osmium/io/gzip_compression.hpp index 8bc1e5a50..272397707 100644 --- a/include/osmium/io/gzip_compression.hpp +++ b/include/osmium/io/gzip_compression.hpp @@ -76,7 +76,7 @@ namespace osmium { namespace detail { - OSMIUM_NORETURN inline void throw_gzip_error(gzFile gzfile, const char* msg, int zlib_error=0) { + OSMIUM_NORETURN inline void throw_gzip_error(gzFile gzfile, const char* msg, int zlib_error = 0) { std::string error("gzip error: "); error += msg; error += ": "; diff --git a/include/osmium/io/reader.hpp b/include/osmium/io/reader.hpp index 0bb4f1cb8..c68a8e180 100644 --- a/include/osmium/io/reader.hpp +++ b/include/osmium/io/reader.hpp @@ -109,7 +109,7 @@ namespace osmium { } if (pid == 0) { // child // close all file descriptors except one end of the pipe - for (int i=0; i < 32; ++i) { + for (int i = 0; i < 32; ++i) { if (i != pipefd[1]) { ::close(i); } @@ -260,7 +260,7 @@ namespace osmium { // m_input->read() can return an invalid buffer to signal EOF, // or a valid buffer with or without data. A valid buffer - // without data is not an error, it just means we have to get + // without data is not an error, it just means we have to // keep getting the next buffer until there is one with data. while (true) { osmium::memory::Buffer buffer = m_input->read(); diff --git a/include/osmium/memory/item.hpp b/include/osmium/memory/item.hpp index df15d0133..2679ca6f2 100644 --- a/include/osmium/memory/item.hpp +++ b/include/osmium/memory/item.hpp @@ -55,8 +55,7 @@ namespace osmium { template inline T padded_length(T length) noexcept { - static_assert(std::is_integral::value && std::is_unsigned::value, - "Template parameter must be unsigned integral type"); + static_assert(std::is_integral::value && std::is_unsigned::value, "Template parameter must be unsigned integral type"); return (length + align_bytes - 1) & ~(align_bytes - 1); } @@ -119,7 +118,7 @@ namespace osmium { protected: - explicit Item(item_size_type size=0, item_type type=item_type()) noexcept : + explicit Item(item_size_type size = 0, item_type type = item_type()) noexcept : m_size(size), m_type(type), m_removed(false), diff --git a/include/osmium/osm/area.hpp b/include/osmium/osm/area.hpp index afd127ee6..3e129d0fb 100644 --- a/include/osmium/osm/area.hpp +++ b/include/osmium/osm/area.hpp @@ -53,12 +53,14 @@ namespace osmium { /** * An outer ring of an Area. */ - class OuterRing : public NodeRefList { + class OuterRing : public NodeRefList { public: + static constexpr osmium::item_type itemtype = osmium::item_type::outer_ring; + OuterRing(): - NodeRefList() { + NodeRefList(itemtype) { } }; // class OuterRing @@ -68,12 +70,14 @@ namespace osmium { /** * An inner ring of an Area. */ - class InnerRing : public NodeRefList { + class InnerRing : public NodeRefList { public: + static constexpr osmium::item_type itemtype = osmium::item_type::inner_ring; + InnerRing(): - NodeRefList() { + NodeRefList(itemtype) { } }; // class InnerRing @@ -87,7 +91,7 @@ namespace osmium { * @param type Type of object (way or relation) * @returns Area id */ - inline osmium::object_id_type object_id_to_area_id(osmium::object_id_type id, osmium::item_type type) { + inline osmium::object_id_type object_id_to_area_id(osmium::object_id_type id, osmium::item_type type) noexcept { osmium::object_id_type area_id = std::abs(id) * 2; if (type == osmium::item_type::relation) { ++area_id; @@ -101,7 +105,7 @@ namespace osmium { * @param id Area id * @returns Way or Relation id. */ - inline osmium::object_id_type area_id_to_object_id(osmium::object_id_type id) { + inline osmium::object_id_type area_id_to_object_id(osmium::object_id_type id) noexcept { return id / 2; } @@ -131,15 +135,17 @@ namespace osmium { /** * Return the Id of the way or relation this area was created from. */ - osmium::object_id_type orig_id() const { + osmium::object_id_type orig_id() const noexcept { return osmium::area_id_to_object_id(id()); } /** * Count the number of outer and inner rings of this area. + * + * @returns Pair (number outer rings, number inner rings) */ std::pair num_rings() const { - std::pair counter; + std::pair counter { 0, 0 }; for (auto it = cbegin(); it != cend(); ++it) { switch (it->type()) { @@ -170,16 +176,31 @@ namespace osmium { } /** - * Is this area a multipolygon, ie. has it more than one outer ring? + * Check whether this area is a multipolygon, ie. whether it has more + * than one outer ring? */ bool is_multipolygon() const { return num_rings().first > 1; } + /** + * Get iterator for iterating over all inner rings in a specified outer + * ring. + * + * @param it Iterator specifying outer ring. + * @returns Iterator to first inner ring in specified outer ring. + */ osmium::memory::ItemIterator inner_ring_cbegin(const osmium::memory::ItemIterator& it) const { return it.cast(); } + /** + * Get iterator for iterating over all inner rings in a specified outer + * ring. + * + * @param it Iterator specifying outer ring. + * @returns Iterator one past last inner ring in specified outer ring. + */ osmium::memory::ItemIterator inner_ring_cend(const osmium::memory::ItemIterator& it) const { return std::next(it).cast(); } diff --git a/include/osmium/osm/box.hpp b/include/osmium/osm/box.hpp index 37baf7e33..631f91911 100644 --- a/include/osmium/osm/box.hpp +++ b/include/osmium/osm/box.hpp @@ -33,6 +33,7 @@ DEALINGS IN THE SOFTWARE. */ +#include #include #include @@ -41,7 +42,10 @@ DEALINGS IN THE SOFTWARE. namespace osmium { /** - * Bounding box. + * Bounding box. A box is defined by two locations (bottom left location + * and top right location) or, alternatively by four coordinates (minx, + * miny, maxx, and maxy). If both locations are undefined, the box is + * undefined, too. */ class Box { @@ -59,14 +63,33 @@ namespace osmium { m_top_right() { } + /** + * Create box from minimum and maximum coordinates. + * + * @pre @code minx <= maxx && miny <= maxy @endcode + */ Box(double minx, double miny, double maxx, double maxy) : m_bottom_left(minx, miny), m_top_right(maxx, maxy) { + assert(minx <= maxx && miny <= maxy); } + /** + * Create box from bottom left and top right locations. + * + * @pre Either both locations must be defined or neither. + * @pre If both locations are defined, the + * bottom left location must actually be to the left and below + * the top right location. Same coordinates for bottom/top or + * left/right are also okay. + */ Box(const osmium::Location& bottom_left, const osmium::Location& top_right) : m_bottom_left(bottom_left), m_top_right(top_right) { + assert( + (!!bottom_left && !!top_right) || + (bottom_left.x() <= top_right.x() && bottom_left.y() <= top_right.y()) + ); } Box(const Box&) = default; @@ -76,8 +99,13 @@ namespace osmium { ~Box() = default; /** - * Extend this bounding box by the given location. If the - * location is undefined, the bounding box is unchanged. + * Extend this bounding box by the specified location. If the + * location is undefined, the bounding box is unchanged. If + * the box is undefined it will only contain the location after + * this call. + * + * @param location The location we want to extend the box by. + * @returns A reference to this box. */ Box& extend(const Location& location) noexcept { if (location) { @@ -103,8 +131,11 @@ namespace osmium { } /** - * Extend this bounding box by the given box. If the - * box is undefined, the bounding box is unchanged. + * Extend this bounding box by the specified box. If the + * specified box is undefined, the bounding box is unchanged. + * + * @param box The box to extend by. + * @returns A reference to this box. */ Box& extend(const Box& box) noexcept { extend(box.bottom_left()); @@ -113,14 +144,14 @@ namespace osmium { } /** - * Box are defined, ie. contains defined coordinates. + * Box is defined, ie. contains defined locations. */ explicit constexpr operator bool() const noexcept { return static_cast(m_bottom_left); } /** - * Box are valid, ie. defined and inside usual bounds + * Box is valid, ie. defined and inside usual bounds * (-180<=lon<=180, -90<=lat<=90). */ OSMIUM_CONSTEXPR bool valid() const noexcept { @@ -128,37 +159,43 @@ namespace osmium { } /** - * Bottom-left location. + * Access bottom-left location. */ OSMIUM_CONSTEXPR Location bottom_left() const noexcept { return m_bottom_left; } /** - * Bottom-left location. + * Access bottom-left location. */ Location& bottom_left() noexcept { return m_bottom_left; } /** - * Top-right location. + * Access top-right location. */ OSMIUM_CONSTEXPR Location top_right() const noexcept { return m_top_right; } /** - * Top-right location. + * Access top-right location. */ Location& top_right() noexcept { return m_top_right; } /** - * Is the location inside the box? + * Check whether the location is inside the box. + * + * @pre Location must be defined. + * @pre Box must be defined. */ - bool contains(const osmium::Location& location) const { + bool contains(const osmium::Location& location) const noexcept { + assert(bottom_left()); + assert(top_right()); + assert(location); return location.x() >= bottom_left().x() && location.y() >= bottom_left().y() && location.x() <= top_right().x() && location.y() <= top_right().y(); } @@ -166,7 +203,7 @@ namespace osmium { /** * Calculate size of the box in square degrees. * - * @throws osmium::invalid_location unless all coordinates are valid + * @throws osmium::invalid_location unless all coordinates are valid. */ double size() const { return (m_top_right.lon() - m_bottom_left.lon()) * @@ -176,14 +213,19 @@ namespace osmium { }; // class Box /** - * Boxes are equal if both locations are equal. + * Boxes are equal if both locations are equal. Undefined boxes will + * compare equal. */ inline OSMIUM_CONSTEXPR bool operator==(const Box& lhs, const Box& rhs) noexcept { - return lhs.bottom_left() == rhs.bottom_left() && lhs.top_right() == rhs.top_right(); + return lhs.bottom_left() == rhs.bottom_left() && + lhs.top_right() == rhs.top_right(); } /** - * Output a box to a stream. + * Output a box to a stream. The format is "(LON, LAT, LON, LAT)" or + * "(undefined)" if the box is undefined. + * + * @returns Reference to basic_ostream given as first parameter. */ template inline std::basic_ostream& operator<<(std::basic_ostream& out, const osmium::Box& box) { @@ -202,6 +244,7 @@ namespace osmium { } return out; } + } // namespace osmium #endif // OSMIUM_OSM_BOX_HPP diff --git a/include/osmium/osm/changeset.hpp b/include/osmium/osm/changeset.hpp index cc1c52d4a..0ab4e9bad 100644 --- a/include/osmium/osm/changeset.hpp +++ b/include/osmium/osm/changeset.hpp @@ -298,8 +298,7 @@ namespace osmium { }; // class Changeset - static_assert(sizeof(Changeset) % osmium::memory::align_bytes == 0, - "Class osmium::Changeset has wrong size to be aligned properly!"); + static_assert(sizeof(Changeset) % osmium::memory::align_bytes == 0, "Class osmium::Changeset has wrong size to be aligned properly!"); /** * Changesets are equal if their IDs are equal. diff --git a/include/osmium/osm/node_ref.hpp b/include/osmium/osm/node_ref.hpp index 1a66607a1..76afa75fc 100644 --- a/include/osmium/osm/node_ref.hpp +++ b/include/osmium/osm/node_ref.hpp @@ -54,7 +54,7 @@ namespace osmium { public: - NodeRef(const osmium::object_id_type ref=0, const osmium::Location& location=Location()) noexcept : + NodeRef(const osmium::object_id_type ref = 0, const osmium::Location& location = Location()) noexcept : m_ref(ref), m_location(location) { } diff --git a/include/osmium/osm/node_ref_list.hpp b/include/osmium/osm/node_ref_list.hpp index f45bf6b59..f0dfedbc1 100644 --- a/include/osmium/osm/node_ref_list.hpp +++ b/include/osmium/osm/node_ref_list.hpp @@ -44,51 +44,92 @@ DEALINGS IN THE SOFTWARE. namespace osmium { /** - * A vector of NodeRef objects. Usually this is not instatiated directly, + * A vector of NodeRef objects. Usually this is not instantiated directly, * but one of its subclasses are used. */ - template class NodeRefList : public osmium::memory::Item { public: - static constexpr osmium::item_type itemtype = TItemType; - - NodeRefList() noexcept : - osmium::memory::Item(sizeof(NodeRefList), TItemType) { + NodeRefList(osmium::item_type itemtype) noexcept : + osmium::memory::Item(sizeof(NodeRefList), itemtype) { } + /** + * Checks whether the node list is empty. + */ bool empty() const noexcept { return sizeof(NodeRefList) == byte_size(); } + /** + * Returns the number of nodes in the list. + */ size_t size() const noexcept { - assert((osmium::memory::Item::byte_size() - sizeof(NodeRefList)) % sizeof(NodeRef) == 0); - return (osmium::memory::Item::byte_size() - sizeof(NodeRefList)) / sizeof(NodeRef); + auto size_node_refs = osmium::memory::Item::byte_size() - sizeof(NodeRefList); + assert(size_node_refs % sizeof(NodeRef) == 0); + return size_node_refs / sizeof(NodeRef); } - const NodeRef& operator[](size_t n) const { + /** + * Access specified element. + * + * @param n Get this element of the list. + * @pre @code n < size() @endcode + */ + const NodeRef& operator[](size_t n) const noexcept { + assert(n < size()); const NodeRef* node_ref = &*(cbegin()); return node_ref[n]; } - const NodeRef& front() const { + /** + * Access the first element. + * + * @pre @code !empty() @endcode + */ + const NodeRef& front() const noexcept { + assert(!empty()); return operator[](0); } - const NodeRef& back() const { + /** + * Access the last element. + * + * @pre @code !empty() @endcode + */ + const NodeRef& back() const noexcept { + assert(!empty()); return operator[](size()-1); } - bool is_closed() const { + /** + * Checks whether the first and last node in the list have the same ID. + * + * @pre @code !empty() @endcode + */ + bool is_closed() const noexcept { return front().ref() == back().ref(); } - bool ends_have_same_id() const { + /** + * Checks whether the first and last node in the list have the same ID. + * + * @pre @code !empty() @endcode + */ + bool ends_have_same_id() const noexcept { return front().ref() == back().ref(); } + /** + * Checks whether the first and last node in the list have the same + * location. The ID is not checked. + * + * @pre @code !empty() @endcode + * @pre @code front().location() && back().location() @endcode + */ bool ends_have_same_location() const { + assert(front().location() && back().location()); return front().location() == back().location(); } @@ -96,35 +137,43 @@ namespace osmium { typedef const NodeRef* const_iterator; typedef std::reverse_iterator const_reverse_iterator; - iterator begin() { + /// Returns an iterator to the beginning. + iterator begin() noexcept { return iterator(data() + sizeof(NodeRefList)); } - iterator end() { + /// Returns an iterator to the end. + iterator end() noexcept { return iterator(data() + byte_size()); } - const_iterator cbegin() const { + /// Returns an iterator to the beginning. + const_iterator cbegin() const noexcept { return const_iterator(data() + sizeof(NodeRefList)); } - const_iterator cend() const { + /// Returns an iterator to the end. + const_iterator cend() const noexcept { return const_iterator(data() + byte_size()); } - const_iterator begin() const { + /// Returns an iterator to the beginning. + const_iterator begin() const noexcept { return cbegin(); } - const_iterator end() const { + /// Returns an iterator to the end. + const_iterator end() const noexcept { return cend(); } - const_reverse_iterator crbegin() const { + /// Returns a reverse_iterator to the beginning. + const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); } - const_reverse_iterator crend() const { + /// Returns a reverse_iterator to the end. + const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); } diff --git a/include/osmium/osm/relation.hpp b/include/osmium/osm/relation.hpp index 6c0381539..e5b42fed5 100644 --- a/include/osmium/osm/relation.hpp +++ b/include/osmium/osm/relation.hpp @@ -101,7 +101,7 @@ namespace osmium { static constexpr item_type collection_type = item_type::relation_member_list; - RelationMember(const object_id_type ref=0, const item_type type=item_type(), const bool full=false) noexcept : + RelationMember(const object_id_type ref = 0, const item_type type = item_type(), const bool full = false) noexcept : m_ref(ref), m_type(type), m_flags(full ? 1 : 0) { diff --git a/include/osmium/osm/timestamp.hpp b/include/osmium/osm/timestamp.hpp index f36ea36a1..6b6a6e189 100644 --- a/include/osmium/osm/timestamp.hpp +++ b/include/osmium/osm/timestamp.hpp @@ -113,6 +113,10 @@ namespace osmium { return static_cast(m_timestamp); } + explicit constexpr operator uint32_t() const noexcept { + return m_timestamp; + } + template void operator+=(T time_difference) noexcept { m_timestamp += time_difference; diff --git a/include/osmium/osm/way.hpp b/include/osmium/osm/way.hpp index 6d3e2dea0..3c5f1f6dc 100644 --- a/include/osmium/osm/way.hpp +++ b/include/osmium/osm/way.hpp @@ -49,12 +49,14 @@ namespace osmium { /** * List of node references (id and location) in a way. */ - class WayNodeList : public NodeRefList { + class WayNodeList : public NodeRefList { public: + static constexpr osmium::item_type itemtype = osmium::item_type::way_node_list; + WayNodeList(): - NodeRefList() { + NodeRefList(itemtype) { } }; // class WayNodeList diff --git a/include/osmium/relations/collector.hpp b/include/osmium/relations/collector.hpp index d4af916b7..e3c498087 100644 --- a/include/osmium/relations/collector.hpp +++ b/include/osmium/relations/collector.hpp @@ -389,7 +389,7 @@ namespace osmium { RelationMeta relation_meta(offset); - int n=0; + int n = 0; for (auto& member : m_relations_buffer.get(offset).members()) { if (static_cast(this)->keep_member(relation_meta, member)) { member_meta(member.type()).emplace_back(member.ref(), m_relations.size(), n); diff --git a/include/osmium/thread/pool.hpp b/include/osmium/thread/pool.hpp index bc1e9a82b..87dd1fb93 100644 --- a/include/osmium/thread/pool.hpp +++ b/include/osmium/thread/pool.hpp @@ -128,7 +128,7 @@ namespace osmium { } try { - for (int i=0; i < m_num_threads; ++i) { + for (int i = 0; i < m_num_threads; ++i) { m_threads.push_back(std::thread(&Pool::worker_thread, this)); } } catch (...) { diff --git a/include/osmium/thread/queue.hpp b/include/osmium/thread/queue.hpp index 12e593274..baaf2dc76 100644 --- a/include/osmium/thread/queue.hpp +++ b/include/osmium/thread/queue.hpp @@ -49,7 +49,7 @@ namespace osmium { namespace thread { - OSMIUM_CONSTEXPR std::chrono::milliseconds full_queue_sleep_duration { 10 }; // XXX + static const std::chrono::milliseconds full_queue_sleep_duration { 10 }; // XXX /** * A thread-safe queue. @@ -137,7 +137,7 @@ namespace osmium { m_data_available.wait(lock, [this] { return !m_queue.empty(); }); - value=std::move(m_queue.front()); + value = std::move(m_queue.front()); m_queue.pop(); } @@ -148,7 +148,7 @@ namespace osmium { })) { return; } - value=std::move(m_queue.front()); + value = std::move(m_queue.front()); m_queue.pop(); } @@ -157,7 +157,7 @@ namespace osmium { if (m_queue.empty()) { return false; } - value=std::move(m_queue.front()); + value = std::move(m_queue.front()); m_queue.pop(); return true; } diff --git a/include/osmium/thread/sorted_queue.hpp b/include/osmium/thread/sorted_queue.hpp index e0181eb61..e76ade101 100644 --- a/include/osmium/thread/sorted_queue.hpp +++ b/include/osmium/thread/sorted_queue.hpp @@ -107,7 +107,7 @@ namespace osmium { m_data_available.wait(lock, [this] { return !empty_intern(); }); - value=std::move(m_queue.front()); + value = std::move(m_queue.front()); m_queue.pop_front(); ++m_offset; } @@ -122,7 +122,7 @@ namespace osmium { if (empty_intern()) { return false; } - value=std::move(m_queue.front()); + value = std::move(m_queue.front()); m_queue.pop_front(); ++m_offset; return true; diff --git a/include/osmium/util/cast.hpp b/include/osmium/util/cast.hpp index 80adadf80..4866fdec4 100644 --- a/include/osmium/util/cast.hpp +++ b/include/osmium/util/cast.hpp @@ -37,6 +37,7 @@ DEALINGS IN THE SOFTWARE. # include #endif +#include #include #include @@ -93,7 +94,7 @@ namespace osmium { template ::value && !std::is_same::value && (sizeof(T) <= sizeof(F)) && std::is_signed::value && std::is_unsigned::value, int>::type = 0> inline T static_cast_with_assert(const F value) { - assert(value <= std::numeric_limits::max()); + assert(static_cast(value) <= static_cast(std::numeric_limits::max())); return static_cast(value); } diff --git a/include/osmium/util/verbose_output.hpp b/include/osmium/util/verbose_output.hpp index 178781e23..249d67fbf 100644 --- a/include/osmium/util/verbose_output.hpp +++ b/include/osmium/util/verbose_output.hpp @@ -87,7 +87,7 @@ namespace osmium { public: - explicit VerboseOutput(bool verbose=false) noexcept : + explicit VerboseOutput(bool verbose = false) noexcept : m_start(time(NULL)), m_verbose(verbose), m_newline(true) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 334fe3130..7ba455b02 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -8,6 +8,7 @@ message(STATUS "Configuring unit tests") +include(CMakeParseArguments) include_directories(include) add_library(testlib STATIC test_main.cpp) @@ -19,40 +20,62 @@ set(ALL_TESTS "") # # Define function for adding tests # -# Call with parameters: -# TGROUP - test group (directory) -# TNAME - name of test -# ARGV2 - flag to enable test (optional) -# ARGV3 - libraries to add (optional) +# add_unit_tests(group name [ENABLE_IF bool] [LIBS libs] [LABELS labels]) +# +# group - test group (directory) +# name - name of test +# bool - boolean variable telling whether the test should be run (optional) +# libs - lib or libs that should be used when compiling test (optional) +# labels - additional labels this test should get (optional) # #----------------------------------------------------------------------------- -function(add_unit_test TGROUP TNAME) - set(ALL_TESTS "${ALL_TESTS};${TGROUP}/${TNAME}" PARENT_SCOPE) - if((${ARGC} EQUAL 2) OR (${ARGV2})) +function(add_unit_test _tgroup _tname) + set(_testid "${_tgroup}_${_tname}") + set(_tpath "${_tgroup}/${_tname}") + + set(ALL_TESTS "${ALL_TESTS};${_tpath}" PARENT_SCOPE) + + cmake_parse_arguments(_param "" "ENABLE_IF" "LIBS;LABELS" ${ARGN}) + + if(Osmium_DEBUG) + message("${_testid} ENABLE_IF=[${_param_ENABLE_IF}] LIBS=[${_param_LIBS}] LABELS=[${_param_LABELS}]") + endif() + + if((NOT(DEFINED _param_ENABLE_IF)) OR (_param_ENABLE_IF)) if(Osmium_DEBUG) - message("Adding test ${TGROUP}/${TNAME}") + message("Adding test: ${_tpath}") endif() - set(TESTNAME "${TGROUP}_${TNAME}") - add_executable(${TESTNAME} t/${TGROUP}/${TNAME}.cpp) - target_link_libraries(${TESTNAME} testlib) - if((${ARGV2}) AND (DEFINED ARGV3)) + add_executable(${_testid} t/${_tpath}.cpp) + target_link_libraries(${_testid} testlib) + + if(DEFINED _param_LIBS) if(Osmium_DEBUG) - message(" Adding libs ${ARGV3}") + message(" Adding libs: ${_param_LIBS}") endif() - target_link_libraries(${TESTNAME} ${ARGV3}) + target_link_libraries(${_testid} ${_param_LIBS}) endif() - add_test(NAME ${TESTNAME} + + add_test(NAME ${_testid} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${TESTNAME} + COMMAND ${_testid} ) - set_tests_properties(${TESTNAME} PROPERTIES - LABELS "unit;fast;${TGROUP}" + + set(_labels "unit;fast;${_tgroup}") + if(DEFINED _param_LABELS) + if(Osmium_DEBUG) + message(" Adding labels: ${_param_LABELS}") + endif() + set(_labels "${_labels};${_param_LABELS}") + endif() + + set_tests_properties(${_testid} PROPERTIES + LABELS "${_labels}" ENVIRONMENT "OSMIUM_TEST_DATA_DIR=${CMAKE_CURRENT_SOURCE_DIR}" ) else() - message("Skipped test ${TGROUP}/${TNAME} because a dependency was not found") + message("Skipped test ${_tpath} because a dependency was not found") set(OSMIUM_SKIPPED_TESTS - "${OSMIUM_SKIPPED_TESTS} ${TGROUP}/${TNAME}" + "${OSMIUM_SKIPPED_TESTS} ${_tpath}" CACHE STRING "Tests that were skipped because of missing dependecies") endif() endfunction() @@ -85,31 +108,32 @@ else() set(GEOS_AND_PROJ_FOUND FALSE) endif() add_unit_test(geom test_factory_with_projection - ${GEOS_AND_PROJ_FOUND} - "${GEOS_LIBRARY};${PROJ_LIBRARY}") + ENABLE_IF ${GEOS_AND_PROJ_FOUND} + LIBS ${GEOS_LIBRARY} ${PROJ_LIBRARY}) add_unit_test(geom test_geojson) -add_unit_test(geom test_geos ${GEOS_FOUND} ${GEOS_LIBRARY}) -add_unit_test(geom test_geos_wkb ${GEOS_FOUND} ${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_ogr ${GDAL_FOUND} ${GDAL_LIBRARY}) -add_unit_test(geom test_projection ${PROJ_FOUND} ${PROJ_LIBRARY}) +add_unit_test(geom test_ogr 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_wkb) add_unit_test(geom test_wkt) -add_unit_test(index test_id_to_location ${SPARSEHASH_FOUND}) +add_unit_test(index test_id_to_location ENABLE_IF ${SPARSEHASH_FOUND}) add_unit_test(index test_typed_mmap) +add_unit_test(index test_typed_mmap_grow LABELS "fails_on_windows") -add_unit_test(io test_bzip2 ${BZIP2_FOUND} ${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_reader TRUE "${OSMIUM_XML_LIBRARIES}") -add_unit_test(io test_output_iterator ${Threads_FOUND} ${CMAKE_THREAD_LIBS_INIT}) +add_unit_test(io test_reader LIBS "${OSMIUM_XML_LIBRARIES}") +add_unit_test(io test_output_iterator ENABLE_IF ${Threads_FOUND} LIBS ${CMAKE_THREAD_LIBS_INIT}) add_unit_test(tags test_filter) add_unit_test(tags test_operators) add_unit_test(tags test_tag_list) -add_unit_test(thread test_pool ${Threads_FOUND} ${CMAKE_THREAD_LIBS_INIT}) +add_unit_test(thread test_pool ENABLE_IF ${Threads_FOUND} LIBS ${CMAKE_THREAD_LIBS_INIT}) add_unit_test(util test_cast_with_assert) add_unit_test(util test_double) diff --git a/test/data-tests/testdata-xml.cpp b/test/data-tests/testdata-xml.cpp index 94af6f961..5af4c4f27 100644 --- a/test/data-tests/testdata-xml.cpp +++ b/test/data-tests/testdata-xml.cpp @@ -285,7 +285,6 @@ TEST_CASE("Reading OSM XML 121") { }, osmium::gzip_error); } -#if 0 SECTION("Using Reader") { REQUIRE_THROWS_AS({ osmium::io::Reader reader(filename("121-truncated_gzip_file", "osm.gz")); @@ -294,10 +293,105 @@ TEST_CASE("Reading OSM XML 121") { reader.close(); }, osmium::gzip_error); } -#endif } +// ============================================= + +TEST_CASE("Reading OSM XML 122") { + + SECTION("Direct") { + REQUIRE_THROWS_AS( { + read_xml("122-no_osm_element"); + }, osmium::xml_error); + } + + SECTION("Using Reader") { + REQUIRE_THROWS_AS({ + osmium::io::Reader reader(filename("122-no_osm_element")); + osmium::io::Header header = reader.header(); + osmium::memory::Buffer buffer = reader.read(); + reader.close(); + }, osmium::xml_error); + } + +} + +// ============================================= + +TEST_CASE("Reading OSM XML 140") { + + SECTION("Using Reader") { + osmium::io::Reader reader(filename("140-unicode")); + osmium::memory::Buffer buffer = reader.read(); + reader.close(); + + int count = 0; + for (auto it = buffer.begin(); it != buffer.end(); ++it) { + ++count; + REQUIRE(it->id() == count); + const osmium::TagList& t = it->tags(); + + const char* uc = t["unicode_char"]; + + auto len = atoi(t["unicode_utf8_length"]); + REQUIRE(len == strlen(uc)); + + REQUIRE(!strcmp(uc, t["unicode_xml"])); + +// workaround for missing support for u8 string literals on Windows +#if !defined(_MSC_VER) + switch (count) { + case 1: + REQUIRE(!strcmp(uc, u8"a")); + break; + case 2: + REQUIRE(!strcmp(uc, u8"\u00e4")); + break; + case 3: + REQUIRE(!strcmp(uc, u8"\u30dc")); + break; + case 4: + REQUIRE(!strcmp(uc, u8"\U0001d11e")); + break; + case 5: + REQUIRE(!strcmp(uc, u8"\U0001f6eb")); + break; + default: + REQUIRE(false); // should not be here + } +#endif + } + REQUIRE(count == 5); + } + +} + + +// ============================================= + +TEST_CASE("Reading OSM XML 141") { + + SECTION("Using Reader") { + osmium::io::Reader reader(filename("141-entities")); + osmium::memory::Buffer buffer = reader.read(); + reader.close(); + REQUIRE(buffer.committed() > 0); + REQUIRE(buffer.get(0).type() == osmium::item_type::node); + + const osmium::Node& node = buffer.get(0); + const osmium::TagList& tags = node.tags(); + + REQUIRE(!strcmp(tags["less-than"], "<")); + REQUIRE(!strcmp(tags["greater-than"], ">")); + REQUIRE(!strcmp(tags["apostrophe"], "'")); + REQUIRE(!strcmp(tags["ampersand"], "&")); + REQUIRE(!strcmp(tags["quote"], "\"")); + } + +} + + // ============================================= TEST_CASE("Reading OSM XML 200") { diff --git a/test/t/area/test_area_id.cpp b/test/t/area/test_area_id.cpp index 45bf87cbe..fbd8d784c 100644 --- a/test/t/area/test_area_id.cpp +++ b/test/t/area/test_area_id.cpp @@ -4,22 +4,22 @@ TEST_CASE("area_id") { -SECTION("object_id_to_area_id_conversion") { - REQUIRE( 46 == osmium::object_id_to_area_id( 23, osmium::item_type::way)); - REQUIRE( 47 == osmium::object_id_to_area_id( 23, osmium::item_type::relation)); - REQUIRE( 0 == osmium::object_id_to_area_id( 0, osmium::item_type::way)); - REQUIRE( 1 == osmium::object_id_to_area_id( 0, osmium::item_type::relation)); - REQUIRE(-24 == osmium::object_id_to_area_id(-12, osmium::item_type::way)); - REQUIRE(-25 == osmium::object_id_to_area_id(-12, osmium::item_type::relation)); -} + SECTION("object_id_to_area_id_conversion") { + REQUIRE( 46 == osmium::object_id_to_area_id( 23, osmium::item_type::way)); + REQUIRE( 47 == osmium::object_id_to_area_id( 23, osmium::item_type::relation)); + REQUIRE( 0 == osmium::object_id_to_area_id( 0, osmium::item_type::way)); + REQUIRE( 1 == osmium::object_id_to_area_id( 0, osmium::item_type::relation)); + REQUIRE(-24 == osmium::object_id_to_area_id(-12, osmium::item_type::way)); + REQUIRE(-25 == osmium::object_id_to_area_id(-12, osmium::item_type::relation)); + } -SECTION("area_id_to_object_id_conversion") { - REQUIRE( 23 == osmium::area_id_to_object_id( 46)); - REQUIRE( 23 == osmium::area_id_to_object_id( 47)); - REQUIRE( 0 == osmium::area_id_to_object_id( 0)); - REQUIRE( 0 == osmium::area_id_to_object_id( 1)); - REQUIRE(-12 == osmium::area_id_to_object_id(-24)); - REQUIRE(-12 == osmium::area_id_to_object_id(-25)); -} + SECTION("area_id_to_object_id_conversion") { + REQUIRE( 23 == osmium::area_id_to_object_id( 46)); + REQUIRE( 23 == osmium::area_id_to_object_id( 47)); + REQUIRE( 0 == osmium::area_id_to_object_id( 0)); + REQUIRE( 0 == osmium::area_id_to_object_id( 1)); + REQUIRE(-12 == osmium::area_id_to_object_id(-24)); + REQUIRE(-12 == osmium::area_id_to_object_id(-25)); + } } diff --git a/test/t/area/test_node_ref_segment.cpp b/test/t/area/test_node_ref_segment.cpp index fd67e6c49..309768744 100644 --- a/test/t/area/test_node_ref_segment.cpp +++ b/test/t/area/test_node_ref_segment.cpp @@ -6,110 +6,110 @@ using osmium::area::detail::NodeRefSegment; TEST_CASE("NodeRefSegmentClass") { -SECTION("instantiation_with_default_parameters") { - NodeRefSegment s; - REQUIRE(s.first().ref() == 0); - REQUIRE(s.first().location() == osmium::Location()); - REQUIRE(s.second().ref() == 0); - REQUIRE(s.second().location() == osmium::Location()); -} + SECTION("instantiation_with_default_parameters") { + NodeRefSegment s; + REQUIRE(s.first().ref() == 0); + REQUIRE(s.first().location() == osmium::Location()); + REQUIRE(s.second().ref() == 0); + REQUIRE(s.second().location() == osmium::Location()); + } -SECTION("instantiation") { - osmium::NodeRef nr1(1, { 1.2, 3.4 }); - osmium::NodeRef nr2(2, { 1.4, 3.1 }); - osmium::NodeRef nr3(3, { 1.2, 3.6 }); - osmium::NodeRef nr4(4, { 1.2, 3.7 }); + SECTION("instantiation") { + osmium::NodeRef nr1(1, { 1.2, 3.4 }); + osmium::NodeRef nr2(2, { 1.4, 3.1 }); + osmium::NodeRef nr3(3, { 1.2, 3.6 }); + osmium::NodeRef nr4(4, { 1.2, 3.7 }); - NodeRefSegment s1(nr1, nr2, nullptr, nullptr); - REQUIRE(s1.first().ref() == 1); - REQUIRE(s1.second().ref() == 2); + NodeRefSegment s1(nr1, nr2, nullptr, nullptr); + REQUIRE(s1.first().ref() == 1); + REQUIRE(s1.second().ref() == 2); - NodeRefSegment s2(nr2, nr3, nullptr, nullptr); - REQUIRE(s2.first().ref() == 3); - REQUIRE(s2.second().ref() == 2); + NodeRefSegment s2(nr2, nr3, nullptr, nullptr); + REQUIRE(s2.first().ref() == 3); + REQUIRE(s2.second().ref() == 2); - NodeRefSegment s3(nr3, nr4, nullptr, nullptr); - REQUIRE(s3.first().ref() == 3); - REQUIRE(s3.second().ref() == 4); -} + NodeRefSegment s3(nr3, nr4, nullptr, nullptr); + REQUIRE(s3.first().ref() == 3); + REQUIRE(s3.second().ref() == 4); + } -SECTION("intersection") { - NodeRefSegment s1({ 1, {0.0, 0.0}}, { 2, {2.0, 2.0}}, nullptr, nullptr); - NodeRefSegment s2({ 3, {0.0, 2.0}}, { 4, {2.0, 0.0}}, nullptr, nullptr); - NodeRefSegment s3({ 5, {2.0, 0.0}}, { 6, {4.0, 2.0}}, nullptr, nullptr); - NodeRefSegment s4({ 7, {1.0, 0.0}}, { 8, {3.0, 2.0}}, nullptr, nullptr); - NodeRefSegment s5({ 9, {0.0, 4.0}}, {10, {4.0, 0.0}}, nullptr, nullptr); - NodeRefSegment s6({11, {0.0, 0.0}}, {12, {1.0, 1.0}}, nullptr, nullptr); - NodeRefSegment s7({13, {1.0, 1.0}}, {14, {3.0, 3.0}}, nullptr, nullptr); + SECTION("intersection") { + NodeRefSegment s1({ 1, {0.0, 0.0}}, { 2, {2.0, 2.0}}, nullptr, nullptr); + NodeRefSegment s2({ 3, {0.0, 2.0}}, { 4, {2.0, 0.0}}, nullptr, nullptr); + NodeRefSegment s3({ 5, {2.0, 0.0}}, { 6, {4.0, 2.0}}, nullptr, nullptr); + NodeRefSegment s4({ 7, {1.0, 0.0}}, { 8, {3.0, 2.0}}, nullptr, nullptr); + NodeRefSegment s5({ 9, {0.0, 4.0}}, {10, {4.0, 0.0}}, nullptr, nullptr); + NodeRefSegment s6({11, {0.0, 0.0}}, {12, {1.0, 1.0}}, nullptr, nullptr); + NodeRefSegment s7({13, {1.0, 1.0}}, {14, {3.0, 3.0}}, nullptr, nullptr); - REQUIRE(calculate_intersection(s1, s2) == osmium::Location(1.0, 1.0)); - REQUIRE(calculate_intersection(s1, s3) == osmium::Location()); - REQUIRE(calculate_intersection(s2, s3) == osmium::Location()); - REQUIRE(calculate_intersection(s1, s4) == osmium::Location()); - REQUIRE(calculate_intersection(s1, s5) == osmium::Location(2.0, 2.0)); - REQUIRE(calculate_intersection(s1, s1) == osmium::Location()); - REQUIRE(calculate_intersection(s1, s6) == osmium::Location()); - REQUIRE(calculate_intersection(s1, s7) == osmium::Location()); -} + REQUIRE(calculate_intersection(s1, s2) == osmium::Location(1.0, 1.0)); + REQUIRE(calculate_intersection(s1, s3) == osmium::Location()); + REQUIRE(calculate_intersection(s2, s3) == osmium::Location()); + REQUIRE(calculate_intersection(s1, s4) == osmium::Location()); + REQUIRE(calculate_intersection(s1, s5) == osmium::Location(2.0, 2.0)); + REQUIRE(calculate_intersection(s1, s1) == osmium::Location()); + REQUIRE(calculate_intersection(s1, s6) == osmium::Location()); + REQUIRE(calculate_intersection(s1, s7) == osmium::Location()); + } -SECTION("to_left_of") { - osmium::Location loc { 2.0, 2.0 }; + SECTION("to_left_of") { + osmium::Location loc { 2.0, 2.0 }; - REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {0.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); - REQUIRE(NodeRefSegment({0, {4.0, 0.0}}, {1, {4.0, 4.0}}, nullptr, nullptr).to_left_of(loc) == false); - REQUIRE(NodeRefSegment({0, {1.0, 0.0}}, {1, {1.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {0.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {4.0, 0.0}}, {1, {4.0, 4.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {1.0, 0.0}}, {1, {1.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); - REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {1.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); - REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {2.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); - REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {3.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); - REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {4.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); - REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {4.0, 3.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {1.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {2.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {3.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {4.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {4.0, 3.0}}, nullptr, nullptr).to_left_of(loc) == false); - REQUIRE(NodeRefSegment({0, {1.0, 3.0}}, {1, {2.0, 0.0}}, nullptr, nullptr).to_left_of(loc)); - REQUIRE(NodeRefSegment({0, {1.0, 3.0}}, {1, {3.0, 1.0}}, nullptr, nullptr).to_left_of(loc)); - REQUIRE(NodeRefSegment({0, {1.0, 3.0}}, {1, {3.0, 2.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {1.0, 3.0}}, {1, {2.0, 0.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {1.0, 3.0}}, {1, {3.0, 1.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {1.0, 3.0}}, {1, {3.0, 2.0}}, nullptr, nullptr).to_left_of(loc) == false); - REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {2.0, 2.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {2.0, 2.0}}, nullptr, nullptr).to_left_of(loc) == false); - REQUIRE(NodeRefSegment({0, {2.0, 0.0}}, {1, {2.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); - REQUIRE(NodeRefSegment({0, {2.0, 0.0}}, {1, {2.0, 2.0}}, nullptr, nullptr).to_left_of(loc) == false); - REQUIRE(NodeRefSegment({0, {2.0, 2.0}}, {1, {2.0, 4.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {2.0, 0.0}}, {1, {2.0, 4.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {2.0, 0.0}}, {1, {2.0, 2.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {2.0, 2.0}}, {1, {2.0, 4.0}}, nullptr, nullptr).to_left_of(loc) == false); - REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {0.0, 1.0}}, nullptr, nullptr).to_left_of(loc) == false); - REQUIRE(NodeRefSegment({0, {1.0, 0.0}}, {1, {0.0, 1.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {0.0, 1.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {1.0, 0.0}}, {1, {0.0, 1.0}}, nullptr, nullptr).to_left_of(loc) == false); - REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {1.0, 3.0}}, nullptr, nullptr).to_left_of(loc)); - REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {2.0, 0.0}}, nullptr, nullptr).to_left_of(loc)); - REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {3.0, 4.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {1.0, 3.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {2.0, 0.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {3.0, 4.0}}, nullptr, nullptr).to_left_of(loc) == false); - REQUIRE(NodeRefSegment({0, {1.0, 0.0}}, {1, {1.0, 2.0}}, nullptr, nullptr).to_left_of(loc)); - REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {1.0, 2.0}}, nullptr, nullptr).to_left_of(loc) == false); - REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {1.0, 4.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {1.0, 0.0}}, {1, {1.0, 2.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {1.0, 2.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {1.0, 4.0}}, nullptr, nullptr).to_left_of(loc) == false); - REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {0.0, 2.0}}, nullptr, nullptr).to_left_of(loc)); - REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {4.0, 4.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {0.0, 0.0}}, {1, {0.0, 2.0}}, nullptr, nullptr).to_left_of(loc)); + REQUIRE(NodeRefSegment({0, {0.0, 2.0}}, {1, {4.0, 4.0}}, nullptr, nullptr).to_left_of(loc) == false); - REQUIRE(NodeRefSegment({0, {0.0, 1.0}}, {1, {2.0, 2.0}}, nullptr, nullptr).to_left_of(loc) == false); - REQUIRE(NodeRefSegment({0, {2.0, 2.0}}, {1, {4.0, 0.0}}, nullptr, nullptr).to_left_of(loc) == false); -} + REQUIRE(NodeRefSegment({0, {0.0, 1.0}}, {1, {2.0, 2.0}}, nullptr, nullptr).to_left_of(loc) == false); + REQUIRE(NodeRefSegment({0, {2.0, 2.0}}, {1, {4.0, 0.0}}, nullptr, nullptr).to_left_of(loc) == false); + } -SECTION("ordering") { - osmium::NodeRef node_ref1(1, { 1.0, 3.0 }); - osmium::NodeRef node_ref2(2, { 1.4, 2.9 }); - osmium::NodeRef node_ref3(3, { 1.2, 3.0 }); - osmium::NodeRef node_ref4(4, { 1.2, 3.3 }); + SECTION("ordering") { + osmium::NodeRef node_ref1(1, { 1.0, 3.0 }); + osmium::NodeRef node_ref2(2, { 1.4, 2.9 }); + osmium::NodeRef node_ref3(3, { 1.2, 3.0 }); + osmium::NodeRef node_ref4(4, { 1.2, 3.3 }); - REQUIRE(node_ref1 < node_ref2); - REQUIRE(node_ref2 < node_ref3); - REQUIRE(node_ref1 < node_ref3); - REQUIRE(node_ref1 >= node_ref1); + REQUIRE(node_ref1 < node_ref2); + REQUIRE(node_ref2 < node_ref3); + REQUIRE(node_ref1 < node_ref3); + REQUIRE(node_ref1 >= node_ref1); - REQUIRE( osmium::location_less()(node_ref1, node_ref2)); - REQUIRE(!osmium::location_less()(node_ref2, node_ref3)); - REQUIRE( osmium::location_less()(node_ref1, node_ref3)); - REQUIRE( osmium::location_less()(node_ref3, node_ref4)); - REQUIRE(!osmium::location_less()(node_ref1, node_ref1)); -} + REQUIRE( osmium::location_less()(node_ref1, node_ref2)); + REQUIRE(!osmium::location_less()(node_ref2, node_ref3)); + REQUIRE( osmium::location_less()(node_ref1, node_ref3)); + REQUIRE( osmium::location_less()(node_ref3, node_ref4)); + REQUIRE(!osmium::location_less()(node_ref1, node_ref1)); + } } diff --git a/test/t/basic/test_box.cpp b/test/t/basic/test_box.cpp index 73a45f4e2..8182fbf35 100644 --- a/test/t/basic/test_box.cpp +++ b/test/t/basic/test_box.cpp @@ -7,75 +7,85 @@ TEST_CASE("Box") { -SECTION("instantiation") { - osmium::Box b; - REQUIRE(!b); - REQUIRE(!b.bottom_left()); - REQUIRE(!b.top_right()); - REQUIRE_THROWS_AS(b.size(), osmium::invalid_location); -} + SECTION("instantiation") { + osmium::Box b; + REQUIRE(!b); + REQUIRE(!b.bottom_left()); + REQUIRE(!b.top_right()); + REQUIRE_THROWS_AS(b.size(), osmium::invalid_location); + } -SECTION("instantiation_and_extend_with_undefined") { - osmium::Box b; - REQUIRE(!b); - b.extend(osmium::Location()); - REQUIRE(!b.bottom_left()); - REQUIRE(!b.top_right()); -} + SECTION("instantiation_and_extend_with_undefined") { + osmium::Box b; + REQUIRE(!b); + b.extend(osmium::Location()); + REQUIRE(!b.bottom_left()); + REQUIRE(!b.top_right()); + } -SECTION("instantiation_and_extend") { - osmium::Box b; - b.extend(osmium::Location(1.2, 3.4)); - REQUIRE(!!b); - REQUIRE(!!b.bottom_left()); - REQUIRE(!!b.top_right()); - b.extend(osmium::Location(3.4, 4.5)); - b.extend(osmium::Location(5.6, 7.8)); - REQUIRE(b.bottom_left() == osmium::Location(1.2, 3.4)); - REQUIRE(b.top_right() == osmium::Location(5.6, 7.8)); + SECTION("instantiation_and_extend") { + osmium::Box b; + osmium::Location loc1 { 1.2, 3.4 }; + b.extend(loc1); + REQUIRE(!!b); + REQUIRE(!!b.bottom_left()); + REQUIRE(!!b.top_right()); + REQUIRE(b.contains(loc1)); - // extend with undefined doesn't change anything - b.extend(osmium::Location()); - REQUIRE(b.bottom_left() == osmium::Location(1.2, 3.4)); - REQUIRE(b.top_right() == osmium::Location(5.6, 7.8)); -} + osmium::Location loc2 { 3.4, 4.5 }; + osmium::Location loc3 { 5.6, 7.8 }; -SECTION("output_defined") { - osmium::Box b; - b.extend(osmium::Location(1.2, 3.4)); - b.extend(osmium::Location(5.6, 7.8)); - std::stringstream out; - out << b; - REQUIRE(out.str() == "(1.2,3.4,5.6,7.8)"); - REQUIRE(b.size() == Approx(19.36).epsilon(0.000001)); -} + b.extend(loc2); + b.extend(loc3); + REQUIRE(b.bottom_left() == osmium::Location(1.2, 3.4)); + REQUIRE(b.top_right() == osmium::Location(5.6, 7.8)); -SECTION("output_undefined") { - osmium::Box b; - std::stringstream out; - out << b; - REQUIRE(out.str() == "(undefined)"); -} + // extend with undefined doesn't change anything + b.extend(osmium::Location()); + REQUIRE(b.bottom_left() == osmium::Location(1.2, 3.4)); + REQUIRE(b.top_right() == osmium::Location(5.6, 7.8)); -SECTION("box_inside_box") { - osmium::Box outer; - outer.extend(osmium::Location(1, 1)); - outer.extend(osmium::Location(10, 10)); + REQUIRE(b.contains(loc1)); + REQUIRE(b.contains(loc2)); + REQUIRE(b.contains(loc3)); + } - osmium::Box inner; - inner.extend(osmium::Location(2, 2)); - inner.extend(osmium::Location(4, 4)); + SECTION("output_defined") { + osmium::Box b; + b.extend(osmium::Location(1.2, 3.4)); + b.extend(osmium::Location(5.6, 7.8)); + std::stringstream out; + out << b; + REQUIRE(out.str() == "(1.2,3.4,5.6,7.8)"); + REQUIRE(b.size() == Approx(19.36).epsilon(0.000001)); + } - osmium::Box overlap; - overlap.extend(osmium::Location(3, 3)); - overlap.extend(osmium::Location(5, 5)); + SECTION("output_undefined") { + osmium::Box b; + std::stringstream out; + out << b; + REQUIRE(out.str() == "(undefined)"); + } - REQUIRE( osmium::geom::contains(inner, outer)); - REQUIRE(!osmium::geom::contains(outer, inner)); + SECTION("box_inside_box") { + osmium::Box outer; + outer.extend(osmium::Location(1, 1)); + outer.extend(osmium::Location(10, 10)); - REQUIRE(!osmium::geom::contains(overlap, inner)); - REQUIRE(!osmium::geom::contains(inner, overlap)); -} + osmium::Box inner; + inner.extend(osmium::Location(2, 2)); + inner.extend(osmium::Location(4, 4)); + + osmium::Box overlap; + overlap.extend(osmium::Location(3, 3)); + overlap.extend(osmium::Location(5, 5)); + + REQUIRE( osmium::geom::contains(inner, outer)); + REQUIRE(!osmium::geom::contains(outer, inner)); + + REQUIRE(!osmium::geom::contains(overlap, inner)); + REQUIRE(!osmium::geom::contains(inner, overlap)); + } } diff --git a/test/t/basic/test_entity_bits.cpp b/test/t/basic/test_entity_bits.cpp index a200f480b..f15068b1c 100644 --- a/test/t/basic/test_entity_bits.cpp +++ b/test/t/basic/test_entity_bits.cpp @@ -4,28 +4,28 @@ 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)); + 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::relation; + REQUIRE((entities & osmium::osm_entity_bits::object)); - entities |= osmium::osm_entity_bits::area; - 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)); + 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); + 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::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)); -} + 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)); + } } diff --git a/test/t/basic/test_location.cpp b/test/t/basic/test_location.cpp index 25545a4ba..3fd8d155a 100644 --- a/test/t/basic/test_location.cpp +++ b/test/t/basic/test_location.cpp @@ -10,145 +10,145 @@ TEST_CASE("Location") { // fails on MSVC and doesn't really matter // static_assert(std::is_literal_type::value, "osmium::Location not literal type"); -SECTION("instantiation_with_default_parameters") { - osmium::Location loc; - REQUIRE(!loc); - REQUIRE_THROWS_AS(loc.lon(), osmium::invalid_location); - REQUIRE_THROWS_AS(loc.lat(), osmium::invalid_location); -} + SECTION("instantiation_with_default_parameters") { + osmium::Location loc; + REQUIRE(!loc); + REQUIRE_THROWS_AS(loc.lon(), osmium::invalid_location); + REQUIRE_THROWS_AS(loc.lat(), osmium::invalid_location); + } -SECTION("instantiation_with_double_parameters") { - osmium::Location loc1(1.2, 4.5); - REQUIRE(!!loc1); - REQUIRE(12000000 == loc1.x()); - REQUIRE(45000000 == loc1.y()); - REQUIRE(1.2 == loc1.lon()); - REQUIRE(4.5 == loc1.lat()); + SECTION("instantiation_with_double_parameters") { + osmium::Location loc1(1.2, 4.5); + REQUIRE(!!loc1); + REQUIRE(12000000 == loc1.x()); + REQUIRE(45000000 == loc1.y()); + REQUIRE(1.2 == loc1.lon()); + REQUIRE(4.5 == loc1.lat()); - osmium::Location loc2(loc1); - REQUIRE(4.5 == loc2.lat()); + osmium::Location loc2(loc1); + REQUIRE(4.5 == loc2.lat()); - osmium::Location loc3 = loc1; - REQUIRE(4.5 == loc3.lat()); -} + osmium::Location loc3 = loc1; + REQUIRE(4.5 == loc3.lat()); + } -SECTION("instantiation_with_double_parameters_constructor_with_universal_initializer") { - osmium::Location loc { 2.2, 3.3 }; - REQUIRE(2.2 == loc.lon()); - REQUIRE(3.3 == loc.lat()); -} + SECTION("instantiation_with_double_parameters_constructor_with_universal_initializer") { + osmium::Location loc { 2.2, 3.3 }; + REQUIRE(2.2 == loc.lon()); + REQUIRE(3.3 == loc.lat()); + } -SECTION("instantiation_with_double_parameters_constructor_with_initializer_list") { - osmium::Location loc({ 4.4, 5.5 }); - REQUIRE(4.4 == loc.lon()); - REQUIRE(5.5 == loc.lat()); -} + SECTION("instantiation_with_double_parameters_constructor_with_initializer_list") { + osmium::Location loc({ 4.4, 5.5 }); + REQUIRE(4.4 == loc.lon()); + REQUIRE(5.5 == loc.lat()); + } -SECTION("instantiation_with_double_parameters_operator_equal") { - osmium::Location loc = { 5.5, 6.6 }; - REQUIRE(5.5 == loc.lon()); - REQUIRE(6.6 == loc.lat()); -} + SECTION("instantiation_with_double_parameters_operator_equal") { + osmium::Location loc = { 5.5, 6.6 }; + REQUIRE(5.5 == loc.lon()); + REQUIRE(6.6 == loc.lat()); + } -SECTION("equality") { - osmium::Location loc1(1.2, 4.5); - osmium::Location loc2(1.2, 4.5); - osmium::Location loc3(1.5, 1.5); - REQUIRE(loc1 == loc2); - REQUIRE(loc1 != loc3); -} + SECTION("equality") { + osmium::Location loc1(1.2, 4.5); + osmium::Location loc2(1.2, 4.5); + osmium::Location loc3(1.5, 1.5); + REQUIRE(loc1 == loc2); + REQUIRE(loc1 != loc3); + } -SECTION("order") { - REQUIRE(osmium::Location(-1.2, 10.0) < osmium::Location(1.2, 10.0)); - REQUIRE(osmium::Location(1.2, 10.0) > osmium::Location(-1.2, 10.0)); + SECTION("order") { + REQUIRE(osmium::Location(-1.2, 10.0) < osmium::Location(1.2, 10.0)); + REQUIRE(osmium::Location(1.2, 10.0) > osmium::Location(-1.2, 10.0)); - REQUIRE(osmium::Location(10.2, 20.0) < osmium::Location(11.2, 20.2)); - REQUIRE(osmium::Location(10.2, 20.2) < osmium::Location(11.2, 20.0)); - REQUIRE(osmium::Location(11.2, 20.2) > osmium::Location(10.2, 20.0)); -} + REQUIRE(osmium::Location(10.2, 20.0) < osmium::Location(11.2, 20.2)); + REQUIRE(osmium::Location(10.2, 20.2) < osmium::Location(11.2, 20.0)); + REQUIRE(osmium::Location(11.2, 20.2) > osmium::Location(10.2, 20.0)); + } -SECTION("validity") { - REQUIRE(osmium::Location(0.0, 0.0).valid()); - REQUIRE(osmium::Location(1.2, 4.5).valid()); - REQUIRE(osmium::Location(-1.2, 4.5).valid()); - REQUIRE(osmium::Location(-180.0, -90.0).valid()); - REQUIRE(osmium::Location(180.0, -90.0).valid()); - REQUIRE(osmium::Location(-180.0, 90.0).valid()); - REQUIRE(osmium::Location(180.0, 90.0).valid()); + SECTION("validity") { + REQUIRE(osmium::Location(0.0, 0.0).valid()); + REQUIRE(osmium::Location(1.2, 4.5).valid()); + REQUIRE(osmium::Location(-1.2, 4.5).valid()); + REQUIRE(osmium::Location(-180.0, -90.0).valid()); + REQUIRE(osmium::Location(180.0, -90.0).valid()); + REQUIRE(osmium::Location(-180.0, 90.0).valid()); + REQUIRE(osmium::Location(180.0, 90.0).valid()); - REQUIRE(!osmium::Location(200.0, 4.5).valid()); - REQUIRE(!osmium::Location(-1.2, -100.0).valid()); - REQUIRE(!osmium::Location(-180.0, 90.005).valid()); -} + REQUIRE(!osmium::Location(200.0, 4.5).valid()); + REQUIRE(!osmium::Location(-1.2, -100.0).valid()); + REQUIRE(!osmium::Location(-180.0, 90.005).valid()); + } -SECTION("output_to_iterator_comma_separator") { - char buffer[100]; - osmium::Location loc(-3.2, 47.3); - *loc.as_string(buffer, ',') = 0; - REQUIRE(std::string("-3.2,47.3") == buffer); -} + SECTION("output_to_iterator_comma_separator") { + char buffer[100]; + osmium::Location loc(-3.2, 47.3); + *loc.as_string(buffer, ',') = 0; + REQUIRE(std::string("-3.2,47.3") == buffer); + } -SECTION("output_to_iterator_space_separator") { - char buffer[100]; - osmium::Location loc(0.0, 7.0); - *loc.as_string(buffer, ' ') = 0; - REQUIRE(std::string("0 7") == buffer); -} + SECTION("output_to_iterator_space_separator") { + char buffer[100]; + osmium::Location loc(0.0, 7.0); + *loc.as_string(buffer, ' ') = 0; + REQUIRE(std::string("0 7") == buffer); + } -SECTION("output_to_iterator_check_precision") { - char buffer[100]; - osmium::Location loc(-179.9999999, -90.0); - *loc.as_string(buffer, ' ') = 0; - REQUIRE(std::string("-179.9999999 -90") == buffer); -} + SECTION("output_to_iterator_check_precision") { + char buffer[100]; + osmium::Location loc(-179.9999999, -90.0); + *loc.as_string(buffer, ' ') = 0; + REQUIRE(std::string("-179.9999999 -90") == buffer); + } -SECTION("output_to_iterator_undefined_location") { - char buffer[100]; - osmium::Location loc; - REQUIRE_THROWS_AS(loc.as_string(buffer, ','), osmium::invalid_location); -} + SECTION("output_to_iterator_undefined_location") { + char buffer[100]; + osmium::Location loc; + REQUIRE_THROWS_AS(loc.as_string(buffer, ','), osmium::invalid_location); + } -SECTION("output_to_string_comman_separator") { - std::string s; - osmium::Location loc(-3.2, 47.3); - loc.as_string(std::back_inserter(s), ','); - REQUIRE(s == "-3.2,47.3"); -} + SECTION("output_to_string_comman_separator") { + std::string s; + osmium::Location loc(-3.2, 47.3); + loc.as_string(std::back_inserter(s), ','); + REQUIRE(s == "-3.2,47.3"); + } -SECTION("output_to_string_space_separator") { - std::string s; - osmium::Location loc(0.0, 7.0); - loc.as_string(std::back_inserter(s), ' '); - REQUIRE(s == "0 7"); -} + SECTION("output_to_string_space_separator") { + std::string s; + osmium::Location loc(0.0, 7.0); + loc.as_string(std::back_inserter(s), ' '); + REQUIRE(s == "0 7"); + } -SECTION("output_to_string_check_precision") { - std::string s; - osmium::Location loc(-179.9999999, -90.0); - loc.as_string(std::back_inserter(s), ' '); - REQUIRE(s == "-179.9999999 -90"); -} + SECTION("output_to_string_check_precision") { + std::string s; + osmium::Location loc(-179.9999999, -90.0); + loc.as_string(std::back_inserter(s), ' '); + REQUIRE(s == "-179.9999999 -90"); + } -SECTION("output_to_string_undefined_location") { - std::string s; - osmium::Location loc; - REQUIRE_THROWS_AS(loc.as_string(std::back_inserter(s), ','), osmium::invalid_location); -} + SECTION("output_to_string_undefined_location") { + std::string s; + osmium::Location loc; + REQUIRE_THROWS_AS(loc.as_string(std::back_inserter(s), ','), osmium::invalid_location); + } -SECTION("output_defined") { - osmium::Location p(-3.2, 47.3); - std::stringstream out; - out << p; - REQUIRE(out.str() == "(-3.2,47.3)"); -} + SECTION("output_defined") { + osmium::Location p(-3.2, 47.3); + std::stringstream out; + out << p; + REQUIRE(out.str() == "(-3.2,47.3)"); + } -SECTION("output_undefined") { - osmium::Location p; - std::stringstream out; - out << p; - REQUIRE(out.str() == "(undefined,undefined)"); -} + SECTION("output_undefined") { + osmium::Location p; + std::stringstream out; + out << p; + REQUIRE(out.str() == "(undefined,undefined)"); + } } diff --git a/test/t/basic/test_node_ref.cpp b/test/t/basic/test_node_ref.cpp index 5c7b670f1..ac7ccbf4b 100644 --- a/test/t/basic/test_node_ref.cpp +++ b/test/t/basic/test_node_ref.cpp @@ -4,54 +4,54 @@ TEST_CASE("NodeRef") { -SECTION("instantiation_with_default_parameters") { - osmium::NodeRef node_ref; - REQUIRE(node_ref.ref() == 0); + SECTION("instantiation_with_default_parameters") { + osmium::NodeRef node_ref; + REQUIRE(node_ref.ref() == 0); // REQUIRE(!node_ref.has_location()); -} + } -SECTION("instantiation_with_id") { - osmium::NodeRef node_ref(7); - REQUIRE(node_ref.ref() == 7); -} + SECTION("instantiation_with_id") { + osmium::NodeRef node_ref(7); + REQUIRE(node_ref.ref() == 7); + } -SECTION("equality") { - osmium::NodeRef node_ref1(7, { 1.2, 3.4 }); - osmium::NodeRef node_ref2(7, { 1.4, 3.1 }); - osmium::NodeRef node_ref3(9, { 1.2, 3.4 }); - REQUIRE(node_ref1 == node_ref2); - REQUIRE(node_ref1 != node_ref3); - REQUIRE(!osmium::location_equal()(node_ref1, node_ref2)); - REQUIRE(!osmium::location_equal()(node_ref2, node_ref3)); - REQUIRE(osmium::location_equal()(node_ref1, node_ref3)); -} + SECTION("equality") { + osmium::NodeRef node_ref1(7, { 1.2, 3.4 }); + osmium::NodeRef node_ref2(7, { 1.4, 3.1 }); + osmium::NodeRef node_ref3(9, { 1.2, 3.4 }); + REQUIRE(node_ref1 == node_ref2); + REQUIRE(node_ref1 != node_ref3); + REQUIRE(!osmium::location_equal()(node_ref1, node_ref2)); + REQUIRE(!osmium::location_equal()(node_ref2, node_ref3)); + REQUIRE(osmium::location_equal()(node_ref1, node_ref3)); + } -SECTION("set_location") { - osmium::NodeRef node_ref(7); - REQUIRE(!node_ref.location().valid()); - REQUIRE(node_ref.location() == osmium::Location()); - node_ref.set_location(osmium::Location(13.5, -7.2)); - REQUIRE(node_ref.location().lon() == 13.5); - REQUIRE(node_ref.location().valid()); -} + SECTION("set_location") { + osmium::NodeRef node_ref(7); + REQUIRE(!node_ref.location().valid()); + REQUIRE(node_ref.location() == osmium::Location()); + node_ref.set_location(osmium::Location(13.5, -7.2)); + REQUIRE(node_ref.location().lon() == 13.5); + REQUIRE(node_ref.location().valid()); + } -SECTION("ordering") { - osmium::NodeRef node_ref1(1, { 1.0, 3.0 }); - osmium::NodeRef node_ref2(2, { 1.4, 2.9 }); - osmium::NodeRef node_ref3(3, { 1.2, 3.0 }); - osmium::NodeRef node_ref4(4, { 1.2, 3.3 }); + SECTION("ordering") { + osmium::NodeRef node_ref1(1, { 1.0, 3.0 }); + osmium::NodeRef node_ref2(2, { 1.4, 2.9 }); + osmium::NodeRef node_ref3(3, { 1.2, 3.0 }); + osmium::NodeRef node_ref4(4, { 1.2, 3.3 }); - REQUIRE(node_ref1 < node_ref2); - REQUIRE(node_ref2 < node_ref3); - REQUIRE(node_ref1 < node_ref3); - REQUIRE(node_ref1 >= node_ref1); + REQUIRE(node_ref1 < node_ref2); + REQUIRE(node_ref2 < node_ref3); + REQUIRE(node_ref1 < node_ref3); + REQUIRE(node_ref1 >= node_ref1); - REQUIRE(osmium::location_less()(node_ref1, node_ref2)); - REQUIRE(!osmium::location_less()(node_ref2, node_ref3)); - REQUIRE(osmium::location_less()(node_ref1, node_ref3)); - REQUIRE(osmium::location_less()(node_ref3, node_ref4)); - REQUIRE(!osmium::location_less()(node_ref1, node_ref1)); -} + REQUIRE(osmium::location_less()(node_ref1, node_ref2)); + REQUIRE(!osmium::location_less()(node_ref2, node_ref3)); + REQUIRE(osmium::location_less()(node_ref1, node_ref3)); + REQUIRE(osmium::location_less()(node_ref3, node_ref4)); + REQUIRE(!osmium::location_less()(node_ref1, node_ref1)); + } } diff --git a/test/t/basic/test_object_comparisons.cpp b/test/t/basic/test_object_comparisons.cpp index ffffbccb3..2bfdcad90 100644 --- a/test/t/basic/test_object_comparisons.cpp +++ b/test/t/basic/test_object_comparisons.cpp @@ -6,142 +6,142 @@ TEST_CASE("Object_Comparisons") { -SECTION("order") { - osmium::memory::Buffer buffer(10 * 1000); + SECTION("order") { + osmium::memory::Buffer buffer(10 * 1000); - { - // add node 1 - osmium::builder::NodeBuilder node_builder(buffer); - node_builder.add_user("testuser"); - buffer.commit(); + { + // add node 1 + osmium::builder::NodeBuilder node_builder(buffer); + node_builder.add_user("testuser"); + buffer.commit(); + } + + { + // add node 2 + osmium::builder::NodeBuilder node_builder(buffer); + node_builder.add_user("testuser"); + buffer.commit(); + } + + auto it = buffer.begin(); + osmium::Node& node1 = static_cast(*it); + osmium::Node& node2 = static_cast(*(++it)); + + node1.set_id(10); + node1.set_version(1); + node2.set_id(15); + node2.set_version(2); + REQUIRE(true == (node1 < node2)); + REQUIRE(false == (node1 > node2)); + node1.set_id(20); + node1.set_version(1); + node2.set_id(20); + node2.set_version(2); + REQUIRE(true == (node1 < node2)); + REQUIRE(false == (node1 > node2)); + node1.set_id(-10); + node1.set_version(2); + node2.set_id(-15); + node2.set_version(1); + REQUIRE(true == (node1 < node2)); + REQUIRE(false == (node1 > node2)); } - { - // add node 2 - osmium::builder::NodeBuilder node_builder(buffer); - node_builder.add_user("testuser"); - buffer.commit(); + SECTION("order_types") { + osmium::memory::Buffer buffer(10 * 1000); + + { + // add node 1 + osmium::builder::NodeBuilder node_builder(buffer); + osmium::Node& node = node_builder.object(); + REQUIRE(osmium::item_type::node == node.type()); + + node.set_id(3); + node.set_version(3); + node_builder.add_user("testuser"); + + buffer.commit(); + } + + { + // add node 2 + osmium::builder::NodeBuilder node_builder(buffer); + osmium::Node& node = node_builder.object(); + REQUIRE(osmium::item_type::node == node.type()); + + node.set_id(3); + node.set_version(4); + node_builder.add_user("testuser"); + + buffer.commit(); + } + + { + // add node 3 + osmium::builder::NodeBuilder node_builder(buffer); + osmium::Node& node = node_builder.object(); + REQUIRE(osmium::item_type::node == node.type()); + + node.set_id(3); + node.set_version(4); + node_builder.add_user("testuser"); + + buffer.commit(); + } + + { + // add way + osmium::builder::WayBuilder way_builder(buffer); + osmium::Way& way = way_builder.object(); + REQUIRE(osmium::item_type::way == way.type()); + + way.set_id(2); + way.set_version(2); + way_builder.add_user("testuser"); + + buffer.commit(); + } + + { + // add relation + osmium::builder::RelationBuilder relation_builder(buffer); + osmium::Relation& relation = relation_builder.object(); + REQUIRE(osmium::item_type::relation == relation.type()); + + relation.set_id(1); + relation.set_version(1); + relation_builder.add_user("testuser"); + + buffer.commit(); + } + + auto it = buffer.begin(); + const osmium::Node& node1 = static_cast(*it); + const osmium::Node& node2 = static_cast(*(++it)); + const osmium::Node& node3 = static_cast(*(++it)); + const osmium::Way& way = static_cast(*(++it)); + const osmium::Relation& relation = static_cast(*(++it)); + + REQUIRE(true == (node1 < node2)); + REQUIRE(true == (node2 < way)); + REQUIRE(false == (node2 > way)); + REQUIRE(true == (way < relation)); + REQUIRE(true == (node1 < relation)); + + REQUIRE(true == osmium::object_order_type_id_version()(node1, node2)); + REQUIRE(true == osmium::object_order_type_id_reverse_version()(node2, node1)); + REQUIRE(true == osmium::object_order_type_id_version()(node1, way)); + REQUIRE(true == osmium::object_order_type_id_reverse_version()(node1, way)); + + REQUIRE(false == osmium::object_equal_type_id_version()(node1, node2)); + REQUIRE(true == osmium::object_equal_type_id_version()(node2, node3)); + + REQUIRE(true == osmium::object_equal_type_id()(node1, node2)); + REQUIRE(true == osmium::object_equal_type_id()(node2, node3)); + + REQUIRE(false == osmium::object_equal_type_id_version()(node1, way)); + REQUIRE(false == osmium::object_equal_type_id_version()(node1, relation)); + REQUIRE(false == osmium::object_equal_type_id()(node1, relation)); } - auto it = buffer.begin(); - osmium::Node& node1 = static_cast(*it); - osmium::Node& node2 = static_cast(*(++it)); - - node1.set_id(10); - node1.set_version(1); - node2.set_id(15); - node2.set_version(2); - REQUIRE(true == (node1 < node2)); - REQUIRE(false == (node1 > node2)); - node1.set_id(20); - node1.set_version(1); - node2.set_id(20); - node2.set_version(2); - REQUIRE(true == (node1 < node2)); - REQUIRE(false == (node1 > node2)); - node1.set_id(-10); - node1.set_version(2); - node2.set_id(-15); - node2.set_version(1); - REQUIRE(true == (node1 < node2)); - REQUIRE(false == (node1 > node2)); -} - -SECTION("order_types") { - osmium::memory::Buffer buffer(10 * 1000); - - { - // add node 1 - osmium::builder::NodeBuilder node_builder(buffer); - osmium::Node& node = node_builder.object(); - REQUIRE(osmium::item_type::node == node.type()); - - node.set_id(3); - node.set_version(3); - node_builder.add_user("testuser"); - - buffer.commit(); - } - - { - // add node 2 - osmium::builder::NodeBuilder node_builder(buffer); - osmium::Node& node = node_builder.object(); - REQUIRE(osmium::item_type::node == node.type()); - - node.set_id(3); - node.set_version(4); - node_builder.add_user("testuser"); - - buffer.commit(); - } - - { - // add node 3 - osmium::builder::NodeBuilder node_builder(buffer); - osmium::Node& node = node_builder.object(); - REQUIRE(osmium::item_type::node == node.type()); - - node.set_id(3); - node.set_version(4); - node_builder.add_user("testuser"); - - buffer.commit(); - } - - { - // add way - osmium::builder::WayBuilder way_builder(buffer); - osmium::Way& way = way_builder.object(); - REQUIRE(osmium::item_type::way == way.type()); - - way.set_id(2); - way.set_version(2); - way_builder.add_user("testuser"); - - buffer.commit(); - } - - { - // add relation - osmium::builder::RelationBuilder relation_builder(buffer); - osmium::Relation& relation = relation_builder.object(); - REQUIRE(osmium::item_type::relation == relation.type()); - - relation.set_id(1); - relation.set_version(1); - relation_builder.add_user("testuser"); - - buffer.commit(); - } - - auto it = buffer.begin(); - const osmium::Node& node1 = static_cast(*it); - const osmium::Node& node2 = static_cast(*(++it)); - const osmium::Node& node3 = static_cast(*(++it)); - const osmium::Way& way = static_cast(*(++it)); - const osmium::Relation& relation = static_cast(*(++it)); - - REQUIRE(true == (node1 < node2)); - REQUIRE(true == (node2 < way)); - REQUIRE(false == (node2 > way)); - REQUIRE(true == (way < relation)); - REQUIRE(true == (node1 < relation)); - - REQUIRE(true == osmium::object_order_type_id_version()(node1, node2)); - REQUIRE(true == osmium::object_order_type_id_reverse_version()(node2, node1)); - REQUIRE(true == osmium::object_order_type_id_version()(node1, way)); - REQUIRE(true == osmium::object_order_type_id_reverse_version()(node1, way)); - - REQUIRE(false == osmium::object_equal_type_id_version()(node1, node2)); - REQUIRE(true == osmium::object_equal_type_id_version()(node2, node3)); - - REQUIRE(true == osmium::object_equal_type_id()(node1, node2)); - REQUIRE(true == osmium::object_equal_type_id()(node2, node3)); - - REQUIRE(false == osmium::object_equal_type_id_version()(node1, way)); - REQUIRE(false == osmium::object_equal_type_id_version()(node1, relation)); - REQUIRE(false == osmium::object_equal_type_id()(node1, relation)); -} - } diff --git a/test/t/basic/test_timestamp.cpp b/test/t/basic/test_timestamp.cpp index 453b94b2e..6a04a4d09 100644 --- a/test/t/basic/test_timestamp.cpp +++ b/test/t/basic/test_timestamp.cpp @@ -6,40 +6,53 @@ TEST_CASE("Timestamp") { -SECTION("can be default initialized to invalid value") { - osmium::Timestamp t; - REQUIRE(0 == t); - REQUIRE("" == t.to_iso()); -} + SECTION("can be default initialized to invalid value") { + osmium::Timestamp t; + REQUIRE(0 == t); + REQUIRE("" == t.to_iso()); + } -SECTION("invalid value is zero") { - osmium::Timestamp t(static_cast(0)); - REQUIRE(0 == t); - REQUIRE("" == t.to_iso()); -} + SECTION("invalid value is zero") { + osmium::Timestamp t(static_cast(0)); + REQUIRE(0 == t); + REQUIRE("" == t.to_iso()); + } -SECTION("can be initialized from time_t") { - osmium::Timestamp t(static_cast(1)); - REQUIRE(1 == t); - REQUIRE("1970-01-01T00:00:01Z" == t.to_iso()); -} + SECTION("can be initialized from time_t") { + osmium::Timestamp t(static_cast(1)); + REQUIRE(1 == t); + REQUIRE("1970-01-01T00:00:01Z" == t.to_iso()); + } -SECTION("can be initialized from string") { - osmium::Timestamp t("2000-01-01T00:00:00Z"); - REQUIRE("2000-01-01T00:00:00Z" == t.to_iso()); -} + SECTION("can be initialized from string") { + osmium::Timestamp t("2000-01-01T00:00:00Z"); + REQUIRE("2000-01-01T00:00:00Z" == t.to_iso()); + } -SECTION("can be compared") { - osmium::Timestamp t1(10); - osmium::Timestamp t2(50); - REQUIRE(t1 < t2); -} + SECTION("can be implicitly cast to time_t") { + osmium::Timestamp t(4242); + time_t x = t; + REQUIRE(x == 4242); + } -SECTION("can be written to stream") { - std::stringstream ss; - osmium::Timestamp t(1); - ss << t; - REQUIRE("1970-01-01T00:00:01Z" == ss.str()); -} + SECTION("uint32_t can be initialized from Timestamp") { + osmium::Timestamp t(4242); + uint32_t x { t }; + + REQUIRE(x == 4242); + } + + SECTION("can be compared") { + osmium::Timestamp t1(10); + osmium::Timestamp t2(50); + REQUIRE(t1 < t2); + } + + SECTION("can be written to stream") { + std::stringstream ss; + osmium::Timestamp t(1); + ss << t; + REQUIRE("1970-01-01T00:00:01Z" == ss.str()); + } } diff --git a/test/t/buffer/test_buffer_node.cpp b/test/t/buffer/test_buffer_node.cpp index aabe6cbea..9bc8f701d 100644 --- a/test/t/buffer/test_buffer_node.cpp +++ b/test/t/buffer/test_buffer_node.cpp @@ -58,78 +58,78 @@ void check_node_2(osmium::Node& node) { TEST_CASE("Buffer_Node") { -SECTION("buffer_node") { - constexpr size_t buffer_size = 10000; - unsigned char data[buffer_size]; + SECTION("buffer_node") { + constexpr size_t buffer_size = 10000; + unsigned char data[buffer_size]; - osmium::memory::Buffer buffer(data, buffer_size, 0); - - { - // add node 1 - osmium::builder::NodeBuilder node_builder(buffer); - osmium::Node& node = node_builder.object(); - REQUIRE(osmium::item_type::node == node.type()); - - node.set_id(1); - node.set_version(3); - node.set_visible(true); - node.set_changeset(333); - node.set_uid(21); - node.set_timestamp(123); - node.set_location(osmium::Location(3.5, 4.7)); - - node_builder.add_user("testuser"); - - buffer.commit(); - } - - { - // add node 2 - osmium::builder::NodeBuilder node_builder(buffer); - osmium::Node& node = node_builder.object(); - REQUIRE(osmium::item_type::node == node.type()); - - node.set_id(2); - node.set_version(3); - node.set_visible(true); - node.set_changeset(333); - node.set_uid(21); - node.set_timestamp(123); - node.set_location(osmium::Location(3.5, 4.7)); - - node_builder.add_user("testuser"); + osmium::memory::Buffer buffer(data, buffer_size, 0); { - osmium::builder::TagListBuilder tag_builder(buffer, &node_builder); - tag_builder.add_tag("amenity", "bank"); - tag_builder.add_tag("name", "OSM Savings"); + // add node 1 + osmium::builder::NodeBuilder node_builder(buffer); + osmium::Node& node = node_builder.object(); + REQUIRE(osmium::item_type::node == node.type()); + + node.set_id(1); + node.set_version(3); + node.set_visible(true); + node.set_changeset(333); + node.set_uid(21); + node.set_timestamp(123); + node.set_location(osmium::Location(3.5, 4.7)); + + node_builder.add_user("testuser"); + + buffer.commit(); } - buffer.commit(); - } + { + // add node 2 + osmium::builder::NodeBuilder node_builder(buffer); + osmium::Node& node = node_builder.object(); + REQUIRE(osmium::item_type::node == node.type()); - REQUIRE(2 == std::distance(buffer.begin(), buffer.end())); - int item_no = 0; - for (osmium::memory::Item& item : buffer) { - REQUIRE(osmium::item_type::node == item.type()); + node.set_id(2); + node.set_version(3); + node.set_visible(true); + node.set_changeset(333); + node.set_uid(21); + node.set_timestamp(123); + node.set_location(osmium::Location(3.5, 4.7)); - osmium::Node& node = static_cast(item); + node_builder.add_user("testuser"); - switch (item_no) { - case 0: - check_node_1(node); - break; - case 1: - check_node_2(node); - break; - default: - break; + { + osmium::builder::TagListBuilder tag_builder(buffer, &node_builder); + tag_builder.add_tag("amenity", "bank"); + tag_builder.add_tag("name", "OSM Savings"); + } + + buffer.commit(); } - ++item_no; + REQUIRE(2 == std::distance(buffer.begin(), buffer.end())); + int item_no = 0; + for (osmium::memory::Item& item : buffer) { + REQUIRE(osmium::item_type::node == item.type()); + + osmium::Node& node = static_cast(item); + + switch (item_no) { + case 0: + check_node_1(node); + break; + case 1: + check_node_2(node); + break; + default: + break; + } + + ++item_no; + + } } } - -} diff --git a/test/t/geom/test_factory_with_projection.cpp b/test/t/geom/test_factory_with_projection.cpp index 9bc8c0681..42fc864bb 100644 --- a/test/t/geom/test_factory_with_projection.cpp +++ b/test/t/geom/test_factory_with_projection.cpp @@ -10,32 +10,32 @@ TEST_CASE("Projection") { -SECTION("point_mercator") { - osmium::geom::WKTFactory factory(2); + SECTION("point_mercator") { + osmium::geom::WKTFactory factory(2); - std::string wkt {factory.create_point(osmium::Location(3.2, 4.2))}; - REQUIRE(std::string{"POINT(356222.37 467961.14)"} == wkt); -} + 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 factory(osmium::geom::Projection(3857), 2); + SECTION("point_epsg_3857") { + osmium::geom::WKTFactory 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); -} + 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 wkb_factory(osmium::geom::Projection(3857), osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex); - osmium::geom::GEOSFactory geos_factory(osmium::geom::Projection(3857)); + SECTION("wkb_with_parameter") { + osmium::geom::WKBFactory wkb_factory(osmium::geom::Projection(3857), osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex); + osmium::geom::GEOSFactory geos_factory(osmium::geom::Projection(3857)); - std::string wkb = wkb_factory.create_point(osmium::Location(3.2, 4.2)); - std::unique_ptr geos_point = geos_factory.create_point(osmium::Location(3.2, 4.2)); - REQUIRE(geos_to_wkb(geos_point.get()) == wkb); -} + std::string wkb = wkb_factory.create_point(osmium::Location(3.2, 4.2)); + std::unique_ptr 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(); -} + SECTION("cleanup") { + // trying to make valgrind happy, but there is still a memory leak in proj library + pj_deallocate_grids(); + } } diff --git a/test/t/geom/test_mercator.cpp b/test/t/geom/test_mercator.cpp index a6ce2ee4a..cc16e55cf 100644 --- a/test/t/geom/test_mercator.cpp +++ b/test/t/geom/test_mercator.cpp @@ -4,34 +4,34 @@ TEST_CASE("Mercator") { -SECTION("mercator_projection") { - osmium::geom::MercatorProjection projection; - REQUIRE(3857 == projection.epsg()); - REQUIRE("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs" == projection.proj_string()); -} + SECTION("mercator_projection") { + osmium::geom::MercatorProjection projection; + REQUIRE(3857 == projection.epsg()); + REQUIRE("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs" == projection.proj_string()); + } -SECTION("low_level_mercator_functions") { - osmium::geom::Coordinates c1(17.839, -3.249); - osmium::geom::Coordinates r1 = osmium::geom::mercator_to_lonlat(osmium::geom::lonlat_to_mercator(c1)); - REQUIRE(r1.x == Approx(c1.x).epsilon(0.000001)); - REQUIRE(r1.y == Approx(c1.y).epsilon(0.000001)); + SECTION("low_level_mercator_functions") { + osmium::geom::Coordinates c1(17.839, -3.249); + osmium::geom::Coordinates r1 = osmium::geom::mercator_to_lonlat(osmium::geom::lonlat_to_mercator(c1)); + REQUIRE(r1.x == Approx(c1.x).epsilon(0.000001)); + REQUIRE(r1.y == Approx(c1.y).epsilon(0.000001)); - osmium::geom::Coordinates c2(-89.2, 15.915); - osmium::geom::Coordinates r2 = osmium::geom::mercator_to_lonlat(osmium::geom::lonlat_to_mercator(c2)); - REQUIRE(r2.x == Approx(c2.x).epsilon(0.000001)); - REQUIRE(r2.y == Approx(c2.y).epsilon(0.000001)); + osmium::geom::Coordinates c2(-89.2, 15.915); + osmium::geom::Coordinates r2 = osmium::geom::mercator_to_lonlat(osmium::geom::lonlat_to_mercator(c2)); + REQUIRE(r2.x == Approx(c2.x).epsilon(0.000001)); + REQUIRE(r2.y == Approx(c2.y).epsilon(0.000001)); - osmium::geom::Coordinates c3(180.0, 85.0); - osmium::geom::Coordinates r3 = osmium::geom::mercator_to_lonlat(osmium::geom::lonlat_to_mercator(c3)); - REQUIRE(r3.x == Approx(c3.x).epsilon(0.000001)); - REQUIRE(r3.y == Approx(c3.y).epsilon(0.000001)); -} + osmium::geom::Coordinates c3(180.0, 85.0); + osmium::geom::Coordinates r3 = osmium::geom::mercator_to_lonlat(osmium::geom::lonlat_to_mercator(c3)); + REQUIRE(r3.x == Approx(c3.x).epsilon(0.000001)); + REQUIRE(r3.y == Approx(c3.y).epsilon(0.000001)); + } -SECTION("mercator_bounds") { - osmium::Location mmax(180.0, osmium::geom::MERCATOR_MAX_LAT); - osmium::geom::Coordinates c = osmium::geom::lonlat_to_mercator(mmax); - REQUIRE(c.x == Approx(c.y).epsilon(0.001)); - REQUIRE(osmium::geom::detail::y_to_lat(osmium::geom::detail::lon_to_x(180.0)) == Approx(osmium::geom::MERCATOR_MAX_LAT).epsilon(0.0000001)); -} + SECTION("mercator_bounds") { + osmium::Location mmax(180.0, osmium::geom::MERCATOR_MAX_LAT); + osmium::geom::Coordinates c = osmium::geom::lonlat_to_mercator(mmax); + REQUIRE(c.x == Approx(c.y).epsilon(0.001)); + REQUIRE(osmium::geom::detail::y_to_lat(osmium::geom::detail::lon_to_x(180.0)) == Approx(osmium::geom::MERCATOR_MAX_LAT).epsilon(0.0000001)); + } } diff --git a/test/t/index/test_id_to_location.cpp b/test/t/index/test_id_to_location.cpp index fbb3f6a97..4aca238b6 100644 --- a/test/t/index/test_id_to_location.cpp +++ b/test/t/index/test_id_to_location.cpp @@ -58,113 +58,113 @@ void test_func_real(TIndex& index) { TEST_CASE("IdToLocation") { -SECTION("Dummy") { - typedef osmium::index::map::Dummy index_type; + SECTION("Dummy") { + typedef osmium::index::map::Dummy index_type; - index_type index1; + index_type index1; - REQUIRE(0 == index1.size()); - REQUIRE(0 == index1.used_memory()); + REQUIRE(0 == index1.size()); + REQUIRE(0 == index1.used_memory()); - test_func_all(index1); + test_func_all(index1); - REQUIRE(0 == index1.size()); - REQUIRE(0 == index1.used_memory()); -} + REQUIRE(0 == index1.size()); + REQUIRE(0 == index1.used_memory()); + } -SECTION("DenseMemArray") { - typedef osmium::index::map::DenseMemArray index_type; + SECTION("DenseMemArray") { + typedef osmium::index::map::DenseMemArray index_type; - index_type index1; - index1.reserve(1000); - test_func_all(index1); + index_type index1; + index1.reserve(1000); + test_func_all(index1); - index_type index2; - index2.reserve(1000); - test_func_real(index2); -} + index_type index2; + index2.reserve(1000); + test_func_real(index2); + } #ifdef __linux__ -SECTION("DenseMmapArray") { - typedef osmium::index::map::DenseMmapArray index_type; + SECTION("DenseMmapArray") { + typedef osmium::index::map::DenseMmapArray index_type; - index_type index1; - test_func_all(index1); + index_type index1; + test_func_all(index1); - index_type index2; - test_func_real(index2); -} + index_type index2; + test_func_real(index2); + } #else # pragma message("not running 'DenseMapMmap' test case on this machine") #endif -SECTION("DenseFileArray") { - typedef osmium::index::map::DenseFileArray index_type; + SECTION("DenseFileArray") { + typedef osmium::index::map::DenseFileArray index_type; - index_type index1; - test_func_all(index1); + index_type index1; + test_func_all(index1); - index_type index2; - test_func_real(index2); -} + index_type index2; + test_func_real(index2); + } #ifdef OSMIUM_WITH_SPARSEHASH -SECTION("SparseMemTable") { - typedef osmium::index::map::SparseMemTable index_type; + SECTION("SparseMemTable") { + typedef osmium::index::map::SparseMemTable index_type; - index_type index1; - test_func_all(index1); + index_type index1; + test_func_all(index1); - index_type index2; - test_func_real(index2); -} + index_type index2; + test_func_real(index2); + } #endif -SECTION("SparseMemMap") { - typedef osmium::index::map::SparseMemMap index_type; + SECTION("SparseMemMap") { + typedef osmium::index::map::SparseMemMap index_type; - index_type index1; - test_func_all(index1); + index_type index1; + test_func_all(index1); - index_type index2; - test_func_real(index2); -} - -SECTION("SparseMemArray") { - typedef osmium::index::map::SparseMemArray index_type; - - index_type index1; - - REQUIRE(0 == index1.size()); - REQUIRE(0 == index1.used_memory()); - - test_func_all(index1); - - REQUIRE(2 == index1.size()); - - index_type index2; - test_func_real(index2); -} - -SECTION("Dynamic map choice") { - typedef osmium::index::map::Map map_type; - const auto& map_factory = osmium::index::MapFactory::instance(); - - std::vector map_type_names = map_factory.map_types(); - REQUIRE(map_type_names.size() >= 5); - - for (const auto& map_type_name : map_type_names) { - std::unique_ptr index1 = map_factory.create_map(map_type_name); - index1->reserve(1000); - test_func_all(*index1); - - std::unique_ptr index2 = map_factory.create_map(map_type_name); - index2->reserve(1000); - test_func_real(*index2); + index_type index2; + test_func_real(index2); + } + + SECTION("SparseMemArray") { + typedef osmium::index::map::SparseMemArray index_type; + + index_type index1; + + REQUIRE(0 == index1.size()); + REQUIRE(0 == index1.used_memory()); + + test_func_all(index1); + + REQUIRE(2 == index1.size()); + + index_type index2; + test_func_real(index2); + } + + SECTION("Dynamic map choice") { + typedef osmium::index::map::Map map_type; + const auto& map_factory = osmium::index::MapFactory::instance(); + + std::vector map_type_names = map_factory.map_types(); + REQUIRE(map_type_names.size() >= 5); + + for (const auto& map_type_name : map_type_names) { + std::unique_ptr index1 = map_factory.create_map(map_type_name); + index1->reserve(1000); + test_func_all(*index1); + + std::unique_ptr index2 = map_factory.create_map(map_type_name); + index2->reserve(1000); + test_func_real(*index2); + } } -} } diff --git a/test/t/index/test_typed_mmap.cpp b/test/t/index/test_typed_mmap.cpp index df95dc267..bcc17bd2d 100644 --- a/test/t/index/test_typed_mmap.cpp +++ b/test/t/index/test_typed_mmap.cpp @@ -3,97 +3,74 @@ #include #if defined(_MSC_VER) || (defined(__GNUC__) && defined(_WIN32)) - #include "win_mkstemp.hpp" +#include "win_mkstemp.hpp" #endif TEST_CASE("TypedMmap") { -SECTION("Mmap") { - uint64_t* data = osmium::detail::typed_mmap::map(10); + SECTION("Mmap") { + uint64_t* data = osmium::detail::typed_mmap::map(10); - data[0] = 4ul; - data[3] = 9ul; - data[9] = 25ul; + data[0] = 4ul; + data[3] = 9ul; + data[9] = 25ul; - REQUIRE(4ul == data[0]); - REQUIRE(9ul == data[3]); - REQUIRE(25ul == data[9]); + REQUIRE(4ul == data[0]); + REQUIRE(9ul == data[3]); + REQUIRE(25ul == data[9]); - osmium::detail::typed_mmap::unmap(data, 10); -} - -SECTION("MmapSizeZero") { - REQUIRE_THROWS_AS(osmium::detail::typed_mmap::map(0), std::system_error); -} - -SECTION("MmapHugeSize") { - // this is a horrible hack to only run the test on 64bit machines. - if (sizeof(size_t) >= 8) { - REQUIRE_THROWS_AS(osmium::detail::typed_mmap::map(1ULL << (sizeof(size_t) * 6)), std::system_error); + osmium::detail::typed_mmap::unmap(data, 10); + } + + SECTION("MmapSizeZero") { + REQUIRE_THROWS_AS(osmium::detail::typed_mmap::map(0), std::system_error); + } + + SECTION("MmapHugeSize") { + // this is a horrible hack to only run the test on 64bit machines. + if (sizeof(size_t) >= 8) { + REQUIRE_THROWS_AS(osmium::detail::typed_mmap::map(1ULL << (sizeof(size_t) * 6)), std::system_error); + } } -} #ifdef __linux__ -SECTION("Remap") { - uint64_t* data = osmium::detail::typed_mmap::map(10); + SECTION("Remap") { + uint64_t* data = osmium::detail::typed_mmap::map(10); - data[0] = 4ul; - data[3] = 9ul; - data[9] = 25ul; + data[0] = 4ul; + data[3] = 9ul; + data[9] = 25ul; - uint64_t* new_data = osmium::detail::typed_mmap::remap(data, 10, 1000); + uint64_t* new_data = osmium::detail::typed_mmap::remap(data, 10, 1000); - REQUIRE(4ul == new_data[0]); - REQUIRE(9ul == new_data[3]); - REQUIRE(25ul == new_data[9]); -} + REQUIRE(4ul == new_data[0]); + REQUIRE(9ul == new_data[3]); + REQUIRE(25ul == new_data[9]); + } #else # pragma message("not running 'Remap' test case on this machine") #endif -SECTION("FileSize") { - const int size = 100; - char filename[] = "test_mmap_file_size_XXXXXX"; - const int fd = mkstemp(filename); - REQUIRE(fd > 0); - REQUIRE(0 == osmium::detail::typed_mmap::file_size(fd)); - REQUIRE(0 == ftruncate(fd, size * sizeof(uint64_t))); - REQUIRE(size == osmium::detail::typed_mmap::file_size(fd)); + SECTION("FileSize") { + const int size = 100; + char filename[] = "test_mmap_file_size_XXXXXX"; + const int fd = mkstemp(filename); + REQUIRE(fd > 0); + REQUIRE(0 == osmium::detail::typed_mmap::file_size(fd)); + REQUIRE(0 == ftruncate(fd, size * sizeof(uint64_t))); + REQUIRE(size == osmium::detail::typed_mmap::file_size(fd)); - osmium::detail::typed_mmap::grow_file(size / 2, fd); - REQUIRE(size == osmium::detail::typed_mmap::file_size(fd)); + osmium::detail::typed_mmap::grow_file(size / 2, fd); + REQUIRE(size == osmium::detail::typed_mmap::file_size(fd)); - osmium::detail::typed_mmap::grow_file(size, fd); - REQUIRE(size == osmium::detail::typed_mmap::file_size(fd)); + osmium::detail::typed_mmap::grow_file(size, fd); + REQUIRE(size == osmium::detail::typed_mmap::file_size(fd)); - osmium::detail::typed_mmap::grow_file(size * 2, fd); - REQUIRE((size * 2) == osmium::detail::typed_mmap::file_size(fd)); + osmium::detail::typed_mmap::grow_file(size * 2, fd); + REQUIRE((size * 2) == osmium::detail::typed_mmap::file_size(fd)); - REQUIRE(0 == close(fd)); - REQUIRE(0 == unlink(filename)); -} - -SECTION("GrowAndMap") { - const int size = 100; - char filename[] = "test_mmap_grow_and_map_XXXXXX"; - const int fd = mkstemp(filename); - REQUIRE(fd > 0); - - uint64_t* data = osmium::detail::typed_mmap::grow_and_map(size, fd); - REQUIRE(size == osmium::detail::typed_mmap::file_size(fd)); - - data[0] = 1ul; - data[1] = 8ul; - data[99] = 27ul; - - REQUIRE(1ul == data[0]); - REQUIRE(8ul == data[1]); - REQUIRE(27ul == data[99]); - - osmium::detail::typed_mmap::unmap(data, size); - - REQUIRE(0 == close(fd)); - REQUIRE(0 == unlink(filename)); -} + REQUIRE(0 == close(fd)); + REQUIRE(0 == unlink(filename)); + } } diff --git a/test/t/index/test_typed_mmap_grow.cpp b/test/t/index/test_typed_mmap_grow.cpp new file mode 100644 index 000000000..92ee0b40e --- /dev/null +++ b/test/t/index/test_typed_mmap_grow.cpp @@ -0,0 +1,34 @@ +#include "catch.hpp" + +#include + +#if defined(_MSC_VER) || (defined(__GNUC__) && defined(_WIN32)) +#include "win_mkstemp.hpp" +#endif + +TEST_CASE("TypedMmapGrow") { + + SECTION("GrowAndMap") { + const int size = 100; + char filename[] = "test_mmap_grow_and_map_XXXXXX"; + const int fd = mkstemp(filename); + REQUIRE(fd > 0); + + uint64_t* data = osmium::detail::typed_mmap::grow_and_map(size, fd); + REQUIRE(size == osmium::detail::typed_mmap::file_size(fd)); + + data[0] = 1ul; + data[1] = 8ul; + data[99] = 27ul; + + REQUIRE(1ul == data[0]); + REQUIRE(8ul == data[1]); + REQUIRE(27ul == data[99]); + + osmium::detail::typed_mmap::unmap(data, size); + + REQUIRE(0 == close(fd)); + REQUIRE(0 == unlink(filename)); + } + +} diff --git a/test/t/io/test_bzip2.cpp b/test/t/io/test_bzip2.cpp index e6342e11d..5cc30b427 100644 --- a/test/t/io/test_bzip2.cpp +++ b/test/t/io/test_bzip2.cpp @@ -9,25 +9,25 @@ TEST_CASE("Bzip2") { -SECTION("read_compressed_file") { - std::string input_file = with_data_dir("t/io/data_bzip2.txt.bz2"); + SECTION("read_compressed_file") { + std::string input_file = with_data_dir("t/io/data_bzip2.txt.bz2"); - int fd = ::open(input_file.c_str(), O_RDONLY); - REQUIRE(fd > 0); + int fd = ::open(input_file.c_str(), O_RDONLY); + REQUIRE(fd > 0); - size_t size = 0; - std::string all; - { - osmium::io::Bzip2Decompressor decomp(fd); - for (std::string data = decomp.read(); !data.empty(); data = decomp.read()) { - size += data.size(); - all += data; + size_t size = 0; + std::string all; + { + osmium::io::Bzip2Decompressor decomp(fd); + for (std::string data = decomp.read(); !data.empty(); data = decomp.read()) { + size += data.size(); + all += data; + } } + + REQUIRE(9 == size); + REQUIRE("TESTDATA\n" == all); } - REQUIRE(9 == size); - REQUIRE("TESTDATA\n" == all); -} - } diff --git a/test/t/io/test_file_formats.cpp b/test/t/io/test_file_formats.cpp index 03f95784c..e8785d6a4 100644 --- a/test/t/io/test_file_formats.cpp +++ b/test/t/io/test_file_formats.cpp @@ -6,246 +6,246 @@ TEST_CASE("FileFormats") { -SECTION("default_file_format") { - osmium::io::File f; - REQUIRE(osmium::io::file_format::unknown == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - REQUIRE_THROWS_AS(f.check(), std::runtime_error); -} + SECTION("default_file_format") { + osmium::io::File f; + REQUIRE(osmium::io::file_format::unknown == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + REQUIRE_THROWS_AS(f.check(), std::runtime_error); + } -SECTION("stdin_stdout_empty") { - osmium::io::File f {""}; - REQUIRE(osmium::io::file_format::unknown == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - REQUIRE_THROWS_AS(f.check(), std::runtime_error); -} + SECTION("stdin_stdout_empty") { + osmium::io::File f {""}; + REQUIRE(osmium::io::file_format::unknown == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + REQUIRE_THROWS_AS(f.check(), std::runtime_error); + } -SECTION("stdin_stdout_dash") { - osmium::io::File f {"-"}; - REQUIRE(osmium::io::file_format::unknown == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - REQUIRE_THROWS_AS(f.check(), std::runtime_error); -} + SECTION("stdin_stdout_dash") { + osmium::io::File f {"-"}; + REQUIRE(osmium::io::file_format::unknown == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + REQUIRE_THROWS_AS(f.check(), std::runtime_error); + } -SECTION("stdin_stdout_bz2") { - osmium::io::File f {"-", "osm.bz2"}; - REQUIRE("" == f.filename()); - REQUIRE(osmium::io::file_format::xml == f.format()); - REQUIRE(osmium::io::file_compression::bzip2 == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - f.check(); -} + SECTION("stdin_stdout_bz2") { + osmium::io::File f {"-", "osm.bz2"}; + REQUIRE("" == f.filename()); + REQUIRE(osmium::io::file_format::xml == f.format()); + REQUIRE(osmium::io::file_compression::bzip2 == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); + } -SECTION("detect_file_format_by_suffix_osm") { - osmium::io::File f {"test.osm"}; - REQUIRE(osmium::io::file_format::xml == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - f.check(); -} + SECTION("detect_file_format_by_suffix_osm") { + osmium::io::File f {"test.osm"}; + REQUIRE(osmium::io::file_format::xml == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); + } -SECTION("detect_file_format_by_suffix_pbf") { - osmium::io::File f {"test.pbf"}; - REQUIRE(osmium::io::file_format::pbf == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - f.check(); -} + SECTION("detect_file_format_by_suffix_pbf") { + osmium::io::File f {"test.pbf"}; + REQUIRE(osmium::io::file_format::pbf == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); + } -SECTION("detect_file_format_by_suffix_osm_pbf") { - osmium::io::File f {"test.osm.pbf"}; - REQUIRE(osmium::io::file_format::pbf == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - f.check(); -} + SECTION("detect_file_format_by_suffix_osm_pbf") { + osmium::io::File f {"test.osm.pbf"}; + REQUIRE(osmium::io::file_format::pbf == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); + } -SECTION("detect_file_format_by_suffix_opl") { - osmium::io::File f {"test.opl"}; - REQUIRE(osmium::io::file_format::opl == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - f.check(); -} + SECTION("detect_file_format_by_suffix_opl") { + osmium::io::File f {"test.opl"}; + REQUIRE(osmium::io::file_format::opl == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); + } -SECTION("detect_file_format_by_suffix_osm_opl") { - osmium::io::File f {"test.osm.opl"}; - REQUIRE(osmium::io::file_format::opl == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - f.check(); -} + SECTION("detect_file_format_by_suffix_osm_opl") { + osmium::io::File f {"test.osm.opl"}; + REQUIRE(osmium::io::file_format::opl == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); + } -SECTION("detect_file_format_by_suffix_osm_gz") { - osmium::io::File f {"test.osm.gz"}; - REQUIRE(osmium::io::file_format::xml == f.format()); - REQUIRE(osmium::io::file_compression::gzip == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - f.check(); -} + SECTION("detect_file_format_by_suffix_osm_gz") { + osmium::io::File f {"test.osm.gz"}; + REQUIRE(osmium::io::file_format::xml == f.format()); + REQUIRE(osmium::io::file_compression::gzip == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); + } -SECTION("detect_file_format_by_suffix_opl_bz2") { - osmium::io::File f {"test.osm.opl.bz2"}; - REQUIRE(osmium::io::file_format::opl == f.format()); - REQUIRE(osmium::io::file_compression::bzip2 == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - f.check(); -} + SECTION("detect_file_format_by_suffix_opl_bz2") { + osmium::io::File f {"test.osm.opl.bz2"}; + REQUIRE(osmium::io::file_format::opl == f.format()); + REQUIRE(osmium::io::file_compression::bzip2 == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); + } -SECTION("detect_file_format_by_suffix_osc_gz") { - osmium::io::File f {"test.osc.gz"}; - REQUIRE(osmium::io::file_format::xml == f.format()); - REQUIRE(osmium::io::file_compression::gzip == f.compression()); - REQUIRE(true == f.has_multiple_object_versions()); - f.check(); -} + SECTION("detect_file_format_by_suffix_osc_gz") { + osmium::io::File f {"test.osc.gz"}; + REQUIRE(osmium::io::file_format::xml == f.format()); + REQUIRE(osmium::io::file_compression::gzip == f.compression()); + REQUIRE(true == f.has_multiple_object_versions()); + f.check(); + } -SECTION("detect_file_format_by_suffix_opl_gz") { - osmium::io::File f {"test.osh.opl.gz"}; - REQUIRE(osmium::io::file_format::opl == f.format()); - REQUIRE(osmium::io::file_compression::gzip == f.compression()); - REQUIRE(true == f.has_multiple_object_versions()); - f.check(); -} + SECTION("detect_file_format_by_suffix_opl_gz") { + osmium::io::File f {"test.osh.opl.gz"}; + REQUIRE(osmium::io::file_format::opl == f.format()); + REQUIRE(osmium::io::file_compression::gzip == f.compression()); + REQUIRE(true == f.has_multiple_object_versions()); + f.check(); + } -SECTION("detect_file_format_by_suffix_osh_pbf") { - osmium::io::File f {"test.osh.pbf"}; - REQUIRE(osmium::io::file_format::pbf == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE(true == f.has_multiple_object_versions()); - f.check(); -} + SECTION("detect_file_format_by_suffix_osh_pbf") { + osmium::io::File f {"test.osh.pbf"}; + REQUIRE(osmium::io::file_format::pbf == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(true == f.has_multiple_object_versions()); + f.check(); + } -SECTION("override_file_format_by_suffix_osm") { - osmium::io::File f {"test", "osm"}; - REQUIRE(osmium::io::file_format::xml == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - f.check(); -} + SECTION("override_file_format_by_suffix_osm") { + osmium::io::File f {"test", "osm"}; + REQUIRE(osmium::io::file_format::xml == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); + } -SECTION("override_file_format_by_suffix_pbf") { - osmium::io::File f {"test", "pbf"}; - REQUIRE(osmium::io::file_format::pbf == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - f.check(); -} + SECTION("override_file_format_by_suffix_pbf") { + osmium::io::File f {"test", "pbf"}; + REQUIRE(osmium::io::file_format::pbf == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); + } -SECTION("override_file_format_by_suffix_osm_pbf") { - osmium::io::File f {"test", "osm.pbf"}; - REQUIRE(osmium::io::file_format::pbf == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - f.check(); -} + SECTION("override_file_format_by_suffix_osm_pbf") { + osmium::io::File f {"test", "osm.pbf"}; + REQUIRE(osmium::io::file_format::pbf == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); + } -SECTION("override_file_format_by_suffix_opl") { - osmium::io::File f {"test", "opl"}; - REQUIRE(osmium::io::file_format::opl == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - f.check(); -} + SECTION("override_file_format_by_suffix_opl") { + osmium::io::File f {"test", "opl"}; + REQUIRE(osmium::io::file_format::opl == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); + } -SECTION("override_file_format_by_suffix_osm_opl") { - osmium::io::File f {"test", "osm.opl"}; - REQUIRE(osmium::io::file_format::opl == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - f.check(); -} + SECTION("override_file_format_by_suffix_osm_opl") { + osmium::io::File f {"test", "osm.opl"}; + REQUIRE(osmium::io::file_format::opl == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); + } -SECTION("override_file_format_by_suffix_osm_gz") { - osmium::io::File f {"test", "osm.gz"}; - REQUIRE(osmium::io::file_format::xml == f.format()); - REQUIRE(osmium::io::file_compression::gzip == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - f.check(); -} + SECTION("override_file_format_by_suffix_osm_gz") { + osmium::io::File f {"test", "osm.gz"}; + REQUIRE(osmium::io::file_format::xml == f.format()); + REQUIRE(osmium::io::file_compression::gzip == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); + } -SECTION("override_file_format_by_suffix_osm_opl_bz2") { - osmium::io::File f {"test", "osm.opl.bz2"}; - REQUIRE(osmium::io::file_format::opl == f.format()); - REQUIRE(osmium::io::file_compression::bzip2 == f.compression()); - REQUIRE(false == f.has_multiple_object_versions()); - f.check(); -} + SECTION("override_file_format_by_suffix_osm_opl_bz2") { + osmium::io::File f {"test", "osm.opl.bz2"}; + REQUIRE(osmium::io::file_format::opl == f.format()); + REQUIRE(osmium::io::file_compression::bzip2 == f.compression()); + REQUIRE(false == f.has_multiple_object_versions()); + f.check(); + } -SECTION("override_file_format_by_suffix_osc_gz") { - osmium::io::File f {"test", "osc.gz"}; - REQUIRE(osmium::io::file_format::xml == f.format()); - REQUIRE(osmium::io::file_compression::gzip == f.compression()); - REQUIRE(true == f.has_multiple_object_versions()); - f.check(); -} + SECTION("override_file_format_by_suffix_osc_gz") { + osmium::io::File f {"test", "osc.gz"}; + REQUIRE(osmium::io::file_format::xml == f.format()); + REQUIRE(osmium::io::file_compression::gzip == f.compression()); + REQUIRE(true == f.has_multiple_object_versions()); + f.check(); + } -SECTION("override_file_format_by_suffix_osh_opl_gz") { - osmium::io::File f {"test", "osh.opl.gz"}; - REQUIRE(osmium::io::file_format::opl == f.format()); - REQUIRE(osmium::io::file_compression::gzip == f.compression()); - REQUIRE(true == f.has_multiple_object_versions()); - f.check(); -} + SECTION("override_file_format_by_suffix_osh_opl_gz") { + osmium::io::File f {"test", "osh.opl.gz"}; + REQUIRE(osmium::io::file_format::opl == f.format()); + REQUIRE(osmium::io::file_compression::gzip == f.compression()); + REQUIRE(true == f.has_multiple_object_versions()); + f.check(); + } -SECTION("override_file_format_by_suffix_osh_pbf") { - osmium::io::File f {"test", "osh.pbf"}; - REQUIRE(osmium::io::file_format::pbf == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE(true == f.has_multiple_object_versions()); - f.check(); -} + SECTION("override_file_format_by_suffix_osh_pbf") { + osmium::io::File f {"test", "osh.pbf"}; + REQUIRE(osmium::io::file_format::pbf == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(true == f.has_multiple_object_versions()); + f.check(); + } -SECTION("format_options_pbf_history") { - osmium::io::File f {"test", "pbf,history=true"}; - REQUIRE(osmium::io::file_format::pbf == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE(true == f.has_multiple_object_versions()); - f.check(); -} + SECTION("format_options_pbf_history") { + osmium::io::File f {"test", "pbf,history=true"}; + REQUIRE(osmium::io::file_format::pbf == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE(true == f.has_multiple_object_versions()); + f.check(); + } -SECTION("format_options_pbf_foo") { - osmium::io::File f {"test.osm", "pbf,foo=bar"}; - REQUIRE(osmium::io::file_format::pbf == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE("bar" == f.get("foo")); - f.check(); -} + SECTION("format_options_pbf_foo") { + osmium::io::File f {"test.osm", "pbf,foo=bar"}; + REQUIRE(osmium::io::file_format::pbf == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE("bar" == f.get("foo")); + f.check(); + } -SECTION("format_options_xml_abc_something") { - osmium::io::File f {"test.bla", "xml,abc,some=thing"}; - REQUIRE(osmium::io::file_format::xml == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE("true" == f.get("abc")); - REQUIRE("thing" == f.get("some")); - REQUIRE(2 == std::distance(f.begin(), f.end())); - f.check(); -} + SECTION("format_options_xml_abc_something") { + osmium::io::File f {"test.bla", "xml,abc,some=thing"}; + REQUIRE(osmium::io::file_format::xml == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE("true" == f.get("abc")); + REQUIRE("thing" == f.get("some")); + REQUIRE(2 == std::distance(f.begin(), f.end())); + f.check(); + } -SECTION("unknown_format_foo_bar") { - osmium::io::File f {"test.foo.bar"}; - REQUIRE(osmium::io::file_format::unknown == f.format()); - REQUIRE(osmium::io::file_compression::none == f.compression()); - REQUIRE_THROWS_AS(f.check(), std::runtime_error); -} + SECTION("unknown_format_foo_bar") { + osmium::io::File f {"test.foo.bar"}; + REQUIRE(osmium::io::file_format::unknown == f.format()); + REQUIRE(osmium::io::file_compression::none == f.compression()); + REQUIRE_THROWS_AS(f.check(), std::runtime_error); + } -SECTION("unknown_format_foo") { - osmium::io::File f {"test", "foo"}; - REQUIRE_THROWS_AS(f.check(), std::runtime_error); -} + SECTION("unknown_format_foo") { + osmium::io::File f {"test", "foo"}; + REQUIRE_THROWS_AS(f.check(), std::runtime_error); + } -SECTION("unknown_format_osm_foo") { - osmium::io::File f {"test", "osm.foo"}; - REQUIRE_THROWS_AS(f.check(), std::runtime_error); -} + SECTION("unknown_format_osm_foo") { + osmium::io::File f {"test", "osm.foo"}; + REQUIRE_THROWS_AS(f.check(), std::runtime_error); + } -SECTION("unknown_format_bla_equals_foo") { - osmium::io::File f {"test", "bla=foo"}; - REQUIRE_THROWS_AS(f.check(), std::runtime_error); -} + SECTION("unknown_format_bla_equals_foo") { + osmium::io::File f {"test", "bla=foo"}; + REQUIRE_THROWS_AS(f.check(), std::runtime_error); + } } diff --git a/test/t/tags/test_filter.cpp b/test/t/tags/test_filter.cpp index e65f63d3b..eefa5b076 100644 --- a/test/t/tags/test_filter.cpp +++ b/test/t/tags/test_filter.cpp @@ -25,192 +25,192 @@ void check_filter(const osmium::TagList& tag_list, const TFilter filter, const s TEST_CASE("Filter") { -SECTION("KeyFilter_matches_some_tags") { - osmium::tags::KeyFilter filter(false); - filter.add(true, "highway").add(true, "railway"); + SECTION("KeyFilter_matches_some_tags") { + osmium::tags::KeyFilter filter(false); + filter.add(true, "highway").add(true, "railway"); - osmium::memory::Buffer buffer(10240); - const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { - { "highway", "primary" }, // match - { "name", "Main Street" }, // no match - { "source", "GPS" } // no match - }); + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, // match + { "name", "Main Street" }, // no match + { "source", "GPS" } // no match + }); - std::vector results = { true, false, false }; + std::vector results = { true, false, false }; - check_filter(tag_list, filter, results); -} + check_filter(tag_list, filter, results); + } -SECTION("KeyFilter_iterator_filters_tags") { - osmium::tags::KeyFilter filter(false); - filter.add(true, "highway").add(true, "source"); + SECTION("KeyFilter_iterator_filters_tags") { + osmium::tags::KeyFilter filter(false); + filter.add(true, "highway").add(true, "source"); - osmium::memory::Buffer buffer(10240); - const osmium::TagList& tl = osmium::builder::build_tag_list(buffer, { - { "highway", "primary" }, // match - { "name", "Main Street" }, // no match - { "source", "GPS" } // no match - }); + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tl = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, // match + { "name", "Main Street" }, // no match + { "source", "GPS" } // no match + }); - osmium::tags::KeyFilter::iterator it(filter, tl.begin(), tl.end()); - const osmium::tags::KeyFilter::iterator end(filter, tl.end(), tl.end()); + osmium::tags::KeyFilter::iterator it(filter, tl.begin(), tl.end()); + const osmium::tags::KeyFilter::iterator end(filter, tl.end(), tl.end()); - REQUIRE(2 == std::distance(it, end)); + REQUIRE(2 == std::distance(it, end)); - REQUIRE(it != end); - REQUIRE(std::string("highway") == it->key()); - REQUIRE(std::string("primary") == it->value()); - ++it; - REQUIRE(std::string("source") == it->key()); - REQUIRE(std::string("GPS") == it->value()); - REQUIRE(++it == end); -} + REQUIRE(it != end); + REQUIRE(std::string("highway") == it->key()); + REQUIRE(std::string("primary") == it->value()); + ++it; + REQUIRE(std::string("source") == it->key()); + REQUIRE(std::string("GPS") == it->value()); + REQUIRE(++it == end); + } -SECTION("KeyValueFilter_matches_some_tags") { - osmium::tags::KeyValueFilter filter(false); + SECTION("KeyValueFilter_matches_some_tags") { + osmium::tags::KeyValueFilter filter(false); - filter.add(true, "highway", "residential").add(true, "highway", "primary").add(true, "railway"); + filter.add(true, "highway", "residential").add(true, "highway", "primary").add(true, "railway"); - osmium::memory::Buffer buffer(10240); - const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { - { "highway", "primary" }, - { "railway", "tram" }, - { "source", "GPS" } - }); + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "railway", "tram" }, + { "source", "GPS" } + }); - std::vector results = {true, true, false}; + std::vector results = {true, true, false}; - check_filter(tag_list, filter, results); -} + check_filter(tag_list, filter, results); + } -SECTION("KeyValueFilter_ordering_matters") { - osmium::tags::KeyValueFilter filter1(false); - filter1.add(true, "highway").add(false, "highway", "road"); + SECTION("KeyValueFilter_ordering_matters") { + osmium::tags::KeyValueFilter filter1(false); + filter1.add(true, "highway").add(false, "highway", "road"); - osmium::tags::KeyValueFilter filter2(false); - filter2.add(false, "highway", "road").add(true, "highway"); + osmium::tags::KeyValueFilter filter2(false); + filter2.add(false, "highway", "road").add(true, "highway"); - osmium::memory::Buffer buffer(10240); + osmium::memory::Buffer buffer(10240); - const osmium::TagList& tag_list1 = osmium::builder::build_tag_list(buffer, { - { "highway", "road" }, - { "name", "Main Street" } - }); + const osmium::TagList& tag_list1 = osmium::builder::build_tag_list(buffer, { + { "highway", "road" }, + { "name", "Main Street" } + }); - const osmium::TagList& tag_list2 = osmium::builder::build_tag_list(buffer, { - { "highway", "primary" }, - { "name", "Main Street" } - }); + const osmium::TagList& tag_list2 = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "name", "Main Street" } + }); - check_filter(tag_list1, filter1, {true, false}); - check_filter(tag_list1, filter2, {false, false}); - check_filter(tag_list2, filter2, {true, false}); -} + check_filter(tag_list1, filter1, {true, false}); + check_filter(tag_list1, filter2, {false, false}); + check_filter(tag_list2, filter2, {true, false}); + } -SECTION("KeyValueFilter_matches_against_taglist_with_any") { - osmium::tags::KeyValueFilter filter(false); + SECTION("KeyValueFilter_matches_against_taglist_with_any") { + osmium::tags::KeyValueFilter filter(false); - filter.add(true, "highway", "primary").add(true, "name"); + filter.add(true, "highway", "primary").add(true, "name"); - osmium::memory::Buffer buffer(10240); - const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { - { "highway", "primary" }, - { "railway", "tram" }, - { "source", "GPS" } - }); + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "railway", "tram" }, + { "source", "GPS" } + }); - REQUIRE( osmium::tags::match_any_of(tag_list, filter)); - REQUIRE(!osmium::tags::match_all_of(tag_list, filter)); - REQUIRE(!osmium::tags::match_none_of(tag_list, filter)); -} + REQUIRE( osmium::tags::match_any_of(tag_list, filter)); + REQUIRE(!osmium::tags::match_all_of(tag_list, filter)); + REQUIRE(!osmium::tags::match_none_of(tag_list, filter)); + } -SECTION("KeyValueFilter_matches_against_taglist_with_all") { - osmium::tags::KeyValueFilter filter(false); + SECTION("KeyValueFilter_matches_against_taglist_with_all") { + osmium::tags::KeyValueFilter filter(false); - filter.add(true, "highway", "primary").add(true, "name"); + filter.add(true, "highway", "primary").add(true, "name"); - osmium::memory::Buffer buffer(10240); - const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { - { "highway", "primary" }, - { "name", "Main Street" } - }); + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "name", "Main Street" } + }); - REQUIRE( osmium::tags::match_any_of(tag_list, filter)); - REQUIRE( osmium::tags::match_all_of(tag_list, filter)); - REQUIRE(!osmium::tags::match_none_of(tag_list, filter)); -} + REQUIRE( osmium::tags::match_any_of(tag_list, filter)); + REQUIRE( osmium::tags::match_all_of(tag_list, filter)); + REQUIRE(!osmium::tags::match_none_of(tag_list, filter)); + } -SECTION("KeyValueFilter_matches_against_taglist_with_none") { - osmium::tags::KeyValueFilter filter(false); + SECTION("KeyValueFilter_matches_against_taglist_with_none") { + osmium::tags::KeyValueFilter filter(false); - filter.add(true, "highway", "road").add(true, "source"); + filter.add(true, "highway", "road").add(true, "source"); - osmium::memory::Buffer buffer(10240); - const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { - { "highway", "primary" }, - { "name", "Main Street" } - }); + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "name", "Main Street" } + }); - REQUIRE(!osmium::tags::match_any_of(tag_list, filter)); - REQUIRE(!osmium::tags::match_all_of(tag_list, filter)); - REQUIRE( osmium::tags::match_none_of(tag_list, filter)); -} + REQUIRE(!osmium::tags::match_any_of(tag_list, filter)); + REQUIRE(!osmium::tags::match_all_of(tag_list, filter)); + REQUIRE( osmium::tags::match_none_of(tag_list, filter)); + } -SECTION("KeyValueFilter_matches_against_taglist_with_any_called_with_rvalue") { - osmium::memory::Buffer buffer(10240); - const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { - { "highway", "primary" }, - { "railway", "tram" }, - { "source", "GPS" } - }); + SECTION("KeyValueFilter_matches_against_taglist_with_any_called_with_rvalue") { + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "railway", "tram" }, + { "source", "GPS" } + }); - REQUIRE(osmium::tags::match_any_of(tag_list, - osmium::tags::KeyValueFilter().add(true, "highway", "primary").add(true, "name"))); -} + REQUIRE(osmium::tags::match_any_of(tag_list, + osmium::tags::KeyValueFilter().add(true, "highway", "primary").add(true, "name"))); + } -SECTION("RegexFilter_matches_some_tags") { - osmium::tags::RegexFilter filter(false); - filter.add(true, "highway", std::regex(".*_link")); + SECTION("RegexFilter_matches_some_tags") { + osmium::tags::RegexFilter filter(false); + filter.add(true, "highway", std::regex(".*_link")); - osmium::memory::Buffer buffer(10240); - const osmium::TagList& tag_list1 = osmium::builder::build_tag_list(buffer, { - { "highway", "primary_link" }, - { "source", "GPS" } - }); - const osmium::TagList& tag_list2 = osmium::builder::build_tag_list(buffer, { - { "highway", "primary" }, - { "source", "GPS" } - }); + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list1 = osmium::builder::build_tag_list(buffer, { + { "highway", "primary_link" }, + { "source", "GPS" } + }); + const osmium::TagList& tag_list2 = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "source", "GPS" } + }); - check_filter(tag_list1, filter, {true, false}); - check_filter(tag_list2, filter, {false, false}); -} + check_filter(tag_list1, filter, {true, false}); + check_filter(tag_list2, filter, {false, false}); + } -SECTION("RegexFilter_matches_some_tags_with_lvalue_regex") { - osmium::tags::RegexFilter filter(false); - std::regex r(".*straße"); - filter.add(true, "name", r); + SECTION("RegexFilter_matches_some_tags_with_lvalue_regex") { + osmium::tags::RegexFilter filter(false); + std::regex r(".*straße"); + filter.add(true, "name", r); - osmium::memory::Buffer buffer(10240); - const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { - { "highway", "primary" }, - { "name", "Hauptstraße" } - }); + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "name", "Hauptstraße" } + }); - check_filter(tag_list, filter, {false, true}); -} + check_filter(tag_list, filter, {false, true}); + } -SECTION("KeyPrefixFilter_matches_some_tags") { - osmium::tags::KeyPrefixFilter filter(false); - filter.add(true, "name:"); + SECTION("KeyPrefixFilter_matches_some_tags") { + osmium::tags::KeyPrefixFilter filter(false); + filter.add(true, "name:"); - osmium::memory::Buffer buffer(10240); - const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { - { "highway", "primary" }, - { "name:de", "Hauptstraße" } - }); + osmium::memory::Buffer buffer(10240); + const osmium::TagList& tag_list = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "name:de", "Hauptstraße" } + }); - check_filter(tag_list, filter, {false, true}); -} + check_filter(tag_list, filter, {false, true}); + } } diff --git a/test/t/tags/test_operators.cpp b/test/t/tags/test_operators.cpp index e2c22a405..33a53c2a2 100644 --- a/test/t/tags/test_operators.cpp +++ b/test/t/tags/test_operators.cpp @@ -8,54 +8,54 @@ TEST_CASE("Operators") { -SECTION("Equal") { - osmium::memory::Buffer buffer1(10240); - { - osmium::builder::TagListBuilder tl_builder(buffer1); - tl_builder.add_tag("highway", "primary"); - tl_builder.add_tag("name", "Main Street"); - tl_builder.add_tag("source", "GPS"); + SECTION("Equal") { + osmium::memory::Buffer buffer1(10240); + { + osmium::builder::TagListBuilder tl_builder(buffer1); + tl_builder.add_tag("highway", "primary"); + tl_builder.add_tag("name", "Main Street"); + tl_builder.add_tag("source", "GPS"); + } + buffer1.commit(); + + osmium::memory::Buffer buffer2(10240); + { + osmium::builder::TagListBuilder tl_builder(buffer2); + tl_builder.add_tag("highway", "primary"); + } + buffer2.commit(); + + const osmium::TagList& tl1 = buffer1.get(0); + const osmium::TagList& tl2 = buffer2.get(0); + + auto tagit1 = tl1.begin(); + auto tagit2 = tl2.begin(); + REQUIRE(*tagit1 == *tagit2); + ++tagit1; + REQUIRE(!(*tagit1 == *tagit2)); } - buffer1.commit(); - osmium::memory::Buffer buffer2(10240); - { - osmium::builder::TagListBuilder tl_builder(buffer2); - tl_builder.add_tag("highway", "primary"); + SECTION("Order") { + osmium::memory::Buffer buffer(10240); + { + osmium::builder::TagListBuilder tl_builder(buffer); + tl_builder.add_tag("highway", "residential"); + tl_builder.add_tag("highway", "primary"); + tl_builder.add_tag("name", "Main Street"); + tl_builder.add_tag("amenity", "post_box"); + } + buffer.commit(); + + const osmium::TagList& tl = buffer.get(0); + const osmium::Tag& t1 = *(tl.begin()); + const osmium::Tag& t2 = *(std::next(tl.begin(), 1)); + const osmium::Tag& t3 = *(std::next(tl.begin(), 2)); + const osmium::Tag& t4 = *(std::next(tl.begin(), 3)); + + REQUIRE(t2 < t1); + REQUIRE(t1 < t3); + REQUIRE(t2 < t3); + REQUIRE(t4 < t1); } - buffer2.commit(); - - const osmium::TagList& tl1 = buffer1.get(0); - const osmium::TagList& tl2 = buffer2.get(0); - - auto tagit1 = tl1.begin(); - auto tagit2 = tl2.begin(); - REQUIRE(*tagit1 == *tagit2); - ++tagit1; - REQUIRE(!(*tagit1 == *tagit2)); -} - -SECTION("Order") { - osmium::memory::Buffer buffer(10240); - { - osmium::builder::TagListBuilder tl_builder(buffer); - tl_builder.add_tag("highway", "residential"); - tl_builder.add_tag("highway", "primary"); - tl_builder.add_tag("name", "Main Street"); - tl_builder.add_tag("amenity", "post_box"); - } - buffer.commit(); - - const osmium::TagList& tl = buffer.get(0); - const osmium::Tag& t1 = *(tl.begin()); - const osmium::Tag& t2 = *(std::next(tl.begin(), 1)); - const osmium::Tag& t3 = *(std::next(tl.begin(), 2)); - const osmium::Tag& t4 = *(std::next(tl.begin(), 3)); - - REQUIRE(t2 < t1); - REQUIRE(t1 < t3); - REQUIRE(t2 < t3); - REQUIRE(t4 < t1); -} } diff --git a/test/t/tags/test_tag_list.cpp b/test/t/tags/test_tag_list.cpp index b25d8cac7..c2512d125 100644 --- a/test/t/tags/test_tag_list.cpp +++ b/test/t/tags/test_tag_list.cpp @@ -6,71 +6,71 @@ TEST_CASE("tag_list") { -SECTION("can_be_created_from_initializer_list") { - osmium::memory::Buffer buffer(10240); + SECTION("can_be_created_from_initializer_list") { + osmium::memory::Buffer buffer(10240); - const osmium::TagList& tl = osmium::builder::build_tag_list(buffer, { - { "highway", "primary" }, - { "name", "Main Street" }, - { "source", "GPS" } - }); + const osmium::TagList& tl = osmium::builder::build_tag_list(buffer, { + { "highway", "primary" }, + { "name", "Main Street" }, + { "source", "GPS" } + }); - REQUIRE(osmium::item_type::tag_list == tl.type()); - REQUIRE(3 == tl.size()); - REQUIRE(std::string("highway") == tl.begin()->key()); - REQUIRE(std::string("primary") == tl.begin()->value()); -} - -SECTION("can_be_created_from_map") { - osmium::memory::Buffer buffer(10240); - - const osmium::TagList& tl = osmium::builder::build_tag_list_from_map(buffer, std::map({ - { "highway", "primary" }, - { "name", "Main Street" } - })); - - REQUIRE(osmium::item_type::tag_list == tl.type()); - REQUIRE(2 == tl.size()); - - if (std::string("highway") == tl.begin()->key()) { + REQUIRE(osmium::item_type::tag_list == tl.type()); + REQUIRE(3 == tl.size()); + REQUIRE(std::string("highway") == tl.begin()->key()); REQUIRE(std::string("primary") == tl.begin()->value()); - REQUIRE(std::string("name") == std::next(tl.begin(), 1)->key()); - REQUIRE(std::string("Main Street") == std::next(tl.begin(), 1)->value()); - } else { - REQUIRE(std::string("highway") == std::next(tl.begin(), 1)->key()); - REQUIRE(std::string("primary") == std::next(tl.begin(), 1)->value()); - REQUIRE(std::string("name") == tl.begin()->key()); - REQUIRE(std::string("Main Street") == tl.begin()->value()); } -} -SECTION("can_be_created_with_callback") { - osmium::memory::Buffer buffer(10240); + SECTION("can_be_created_from_map") { + osmium::memory::Buffer buffer(10240); - const osmium::TagList& tl = osmium::builder::build_tag_list_from_func(buffer, [](osmium::builder::TagListBuilder& tlb) { - tlb.add_tag("highway", "primary"); - tlb.add_tag("bridge", "true"); - }); + const osmium::TagList& tl = osmium::builder::build_tag_list_from_map(buffer, std::map({ + { "highway", "primary" }, + { "name", "Main Street" } + })); - REQUIRE(osmium::item_type::tag_list == tl.type()); - REQUIRE(2 == tl.size()); - REQUIRE(std::string("bridge") == std::next(tl.begin(), 1)->key()); - REQUIRE(std::string("true") == std::next(tl.begin(), 1)->value()); -} + REQUIRE(osmium::item_type::tag_list == tl.type()); + REQUIRE(2 == tl.size()); -SECTION("returns_value_by_key") { - osmium::memory::Buffer buffer(10240); + if (std::string("highway") == tl.begin()->key()) { + REQUIRE(std::string("primary") == tl.begin()->value()); + REQUIRE(std::string("name") == std::next(tl.begin(), 1)->key()); + REQUIRE(std::string("Main Street") == std::next(tl.begin(), 1)->value()); + } else { + REQUIRE(std::string("highway") == std::next(tl.begin(), 1)->key()); + REQUIRE(std::string("primary") == std::next(tl.begin(), 1)->value()); + REQUIRE(std::string("name") == tl.begin()->key()); + REQUIRE(std::string("Main Street") == tl.begin()->value()); + } + } - const osmium::TagList& tl = osmium::builder::build_tag_list_from_func(buffer, [](osmium::builder::TagListBuilder& tlb) { - tlb.add_tag("highway", "primary"); - tlb.add_tag("bridge", "true"); - }); + SECTION("can_be_created_with_callback") { + osmium::memory::Buffer buffer(10240); - REQUIRE(std::string("primary") == tl.get_value_by_key("highway")); - REQUIRE(nullptr == tl.get_value_by_key("name")); - REQUIRE(std::string("foo") == tl.get_value_by_key("name", "foo")); + const osmium::TagList& tl = osmium::builder::build_tag_list_from_func(buffer, [](osmium::builder::TagListBuilder& tlb) { + tlb.add_tag("highway", "primary"); + tlb.add_tag("bridge", "true"); + }); - REQUIRE(std::string("true") == tl["bridge"]); -} + REQUIRE(osmium::item_type::tag_list == tl.type()); + REQUIRE(2 == tl.size()); + REQUIRE(std::string("bridge") == std::next(tl.begin(), 1)->key()); + REQUIRE(std::string("true") == std::next(tl.begin(), 1)->value()); + } + + SECTION("returns_value_by_key") { + osmium::memory::Buffer buffer(10240); + + const osmium::TagList& tl = osmium::builder::build_tag_list_from_func(buffer, [](osmium::builder::TagListBuilder& tlb) { + tlb.add_tag("highway", "primary"); + tlb.add_tag("bridge", "true"); + }); + + REQUIRE(std::string("primary") == tl.get_value_by_key("highway")); + REQUIRE(nullptr == tl.get_value_by_key("name")); + REQUIRE(std::string("foo") == tl.get_value_by_key("name", "foo")); + + REQUIRE(std::string("true") == tl["bridge"]); + } } diff --git a/test/t/thread/test_pool.cpp b/test/t/thread/test_pool.cpp index 4bbf9ee59..66bb3734a 100644 --- a/test/t/thread/test_pool.cpp +++ b/test/t/thread/test_pool.cpp @@ -36,7 +36,7 @@ TEST_CASE("thread") { SECTION("can send job to thread pool") { auto& pool = osmium::thread::Pool::instance(); result = 0; - auto future = pool.submit(test_job_ok{}); + auto future = pool.submit(test_job_ok {}); // wait a bit for the other thread to get a chance to run std::this_thread::sleep_for(std::chrono::milliseconds(1)); @@ -50,7 +50,7 @@ TEST_CASE("thread") { SECTION("can send job to thread pool") { auto& pool = osmium::thread::Pool::instance(); - auto future = pool.submit(test_job_with_result{}); + auto future = pool.submit(test_job_with_result {}); REQUIRE(future.get() == 42); } @@ -60,7 +60,7 @@ TEST_CASE("thread") { result = 0; bool got_exception = false; - auto future = pool.submit(test_job_throw{}); + auto future = pool.submit(test_job_throw {}); REQUIRE_THROWS_AS(future.get(), std::runtime_error); } diff --git a/test/t/util/test_double.cpp b/test/t/util/test_double.cpp index 79e8509b0..6cc87a03a 100644 --- a/test/t/util/test_double.cpp +++ b/test/t/util/test_double.cpp @@ -4,30 +4,30 @@ TEST_CASE("Double") { -SECTION("double2string") { - std::string s1; - osmium::util::double2string(s1, 1.123, 7); - REQUIRE(s1 == "1.123"); + SECTION("double2string") { + std::string s1; + osmium::util::double2string(s1, 1.123, 7); + REQUIRE(s1 == "1.123"); - std::string s2; - osmium::util::double2string(s2, 1.000, 7); - REQUIRE(s2 == "1"); + std::string s2; + osmium::util::double2string(s2, 1.000, 7); + REQUIRE(s2 == "1"); - std::string s3; - osmium::util::double2string(s3, 0.0, 7); - REQUIRE(s3 == "0"); + std::string s3; + osmium::util::double2string(s3, 0.0, 7); + REQUIRE(s3 == "0"); - std::string s4; - osmium::util::double2string(s4, 0.020, 7); - REQUIRE(s4 == "0.02"); + std::string s4; + osmium::util::double2string(s4, 0.020, 7); + REQUIRE(s4 == "0.02"); - std::string s5; - osmium::util::double2string(s5, -0.020, 7); - REQUIRE(s5 == "-0.02"); + std::string s5; + osmium::util::double2string(s5, -0.020, 7); + REQUIRE(s5 == "-0.02"); - std::string s6; - osmium::util::double2string(s6, -0.0, 7); - REQUIRE(s6 == "-0"); -} + std::string s6; + osmium::util::double2string(s6, -0.0, 7); + REQUIRE(s6 == "-0"); + } } diff --git a/test/t/util/test_options.cpp b/test/t/util/test_options.cpp index 203b9db48..969f20103 100644 --- a/test/t/util/test_options.cpp +++ b/test/t/util/test_options.cpp @@ -6,43 +6,43 @@ TEST_CASE("Options") { -SECTION("set_simple") { - osmium::util::Options o; - o.set("foo", "bar"); - REQUIRE("bar" == o.get("foo")); - REQUIRE("" == o.get("empty")); - REQUIRE("default" == o.get("empty", "default")); - REQUIRE(!o.is_true("foo")); - REQUIRE(!o.is_true("empty")); - REQUIRE(1 == o.size()); -} + SECTION("set_simple") { + osmium::util::Options o; + o.set("foo", "bar"); + REQUIRE("bar" == o.get("foo")); + REQUIRE("" == o.get("empty")); + REQUIRE("default" == o.get("empty", "default")); + REQUIRE(!o.is_true("foo")); + REQUIRE(!o.is_true("empty")); + REQUIRE(1 == o.size()); + } -SECTION("set_from_bool") { - osmium::util::Options o; - o.set("t", true); - o.set("f", false); - REQUIRE("true" == o.get("t")); - REQUIRE("false" == o.get("f")); - REQUIRE("" == o.get("empty")); - REQUIRE(o.is_true("t")); - REQUIRE(!o.is_true("f")); - REQUIRE(2 == o.size()); -} + SECTION("set_from_bool") { + osmium::util::Options o; + o.set("t", true); + o.set("f", false); + REQUIRE("true" == o.get("t")); + REQUIRE("false" == o.get("f")); + REQUIRE("" == o.get("empty")); + REQUIRE(o.is_true("t")); + REQUIRE(!o.is_true("f")); + REQUIRE(2 == o.size()); + } -SECTION("set_from_single_string_with_equals") { - osmium::util::Options o; - o.set("foo=bar"); - REQUIRE("bar" == o.get("foo")); - REQUIRE(1 == o.size()); -} + SECTION("set_from_single_string_with_equals") { + osmium::util::Options o; + o.set("foo=bar"); + REQUIRE("bar" == o.get("foo")); + REQUIRE(1 == o.size()); + } -SECTION("set_from_single_string_without_equals") { - osmium::util::Options o; - o.set("foo"); - REQUIRE("true" == o.get("foo")); - REQUIRE(o.is_true("foo")); - REQUIRE(1 == o.size()); -} + SECTION("set_from_single_string_without_equals") { + osmium::util::Options o; + o.set("foo"); + REQUIRE("true" == o.get("foo")); + REQUIRE(o.is_true("foo")); + REQUIRE(1 == o.size()); + } } diff --git a/test/t/util/test_string.cpp b/test/t/util/test_string.cpp index c7b75cf24..fa4978779 100644 --- a/test/t/util/test_string.cpp +++ b/test/t/util/test_string.cpp @@ -4,54 +4,54 @@ TEST_CASE("split_string") { -SECTION("split_string string") { - std::string str { "foo,baramba,baz" }; - std::vector result = {"foo", "baramba", "baz"}; + SECTION("split_string string") { + std::string str { "foo,baramba,baz" }; + std::vector result = {"foo", "baramba", "baz"}; - REQUIRE(result == osmium::split_string(str, ',')); -} + REQUIRE(result == osmium::split_string(str, ',')); + } -SECTION("split_string string without sep") { - std::string str { "foo" }; - std::vector result = {"foo"}; + SECTION("split_string string without sep") { + std::string str { "foo" }; + std::vector result = {"foo"}; - REQUIRE(result == osmium::split_string(str, ',')); -} + REQUIRE(result == osmium::split_string(str, ',')); + } -SECTION("split_string string with empty at end") { - std::string str { "foo,bar," }; - std::vector result = {"foo", "bar", ""}; + SECTION("split_string string with empty at end") { + std::string str { "foo,bar," }; + std::vector result = {"foo", "bar", ""}; - REQUIRE(result == osmium::split_string(str, ',')); -} + REQUIRE(result == osmium::split_string(str, ',')); + } -SECTION("split_string string with empty in middle") { - std::string str { "foo,,bar" }; - std::vector result = {"foo", "", "bar"}; + SECTION("split_string string with empty in middle") { + std::string str { "foo,,bar" }; + std::vector result = {"foo", "", "bar"}; - REQUIRE(result == osmium::split_string(str, ',')); -} + REQUIRE(result == osmium::split_string(str, ',')); + } -SECTION("split_string string with empty at start") { - std::string str { ",bar,baz" }; - std::vector result = {"", "bar", "baz"}; + SECTION("split_string string with empty at start") { + std::string str { ",bar,baz" }; + std::vector result = {"", "bar", "baz"}; - REQUIRE(result == osmium::split_string(str, ',')); -} + REQUIRE(result == osmium::split_string(str, ',')); + } -SECTION("split_string sep") { - std::string str { "," }; - std::vector result = {"", ""}; + SECTION("split_string sep") { + std::string str { "," }; + std::vector result = {"", ""}; - REQUIRE(result == osmium::split_string(str, ',')); -} + REQUIRE(result == osmium::split_string(str, ',')); + } -SECTION("split_string empty string") { - std::string str { "" }; - std::vector result; + SECTION("split_string empty string") { + std::string str { "" }; + std::vector result; - REQUIRE(result == osmium::split_string(str, ',')); -} + REQUIRE(result == osmium::split_string(str, ',')); + } } From a372ade7ce145f35f16989e59ce71bcc874975a8 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Tue, 17 Mar 2015 01:00:04 +0100 Subject: [PATCH 343/360] Mark suspicious transitions --- data_structures/hidden_markov_model.hpp | 4 ++++ routing_algorithms/map_matching.hpp | 9 +++++++-- util/matching_debug_info.hpp | 5 ++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/data_structures/hidden_markov_model.hpp b/data_structures/hidden_markov_model.hpp index 403f76608..cccaf7b5d 100644 --- a/data_structures/hidden_markov_model.hpp +++ b/data_structures/hidden_markov_model.hpp @@ -80,6 +80,7 @@ template struct HiddenMarkovModel std::vector>> parents; std::vector> path_lengths; std::vector> pruned; + std::vector> suspicious; std::vector breakage; const CandidateLists &candidates_list; @@ -95,6 +96,7 @@ template struct HiddenMarkovModel viterbi.emplace_back(l.size()); parents.emplace_back(l.size()); path_lengths.emplace_back(l.size()); + suspicious.emplace_back(l.size()); pruned.emplace_back(l.size()); } @@ -111,6 +113,7 @@ template struct HiddenMarkovModel std::fill(viterbi[t].begin(), viterbi[t].end(), osrm::matching::IMPOSSIBLE_LOG_PROB); std::fill(parents[t].begin(), parents[t].end(), std::make_pair(0u, 0u)); std::fill(path_lengths[t].begin(), path_lengths[t].end(), 0); + std::fill(suspicious[t].begin(), suspicious[t].end(), true); std::fill(pruned[t].begin(), pruned[t].end(), true); } std::fill(breakage.begin() + initial_timestamp, breakage.end(), true); @@ -129,6 +132,7 @@ template struct HiddenMarkovModel parents[initial_timestamp][s] = std::make_pair(initial_timestamp, s); pruned[initial_timestamp][s] = viterbi[initial_timestamp][s] < osrm::matching::MINIMAL_LOG_PROB; + suspicious[initial_timestamp][s] = false; breakage[initial_timestamp] = breakage[initial_timestamp] && pruned[initial_timestamp][s]; diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 75598ca2c..eb405a8e4 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -62,6 +62,9 @@ using SubMatchingList = std::vector; constexpr static const unsigned MAX_BROKEN_STATES = 6; constexpr static const unsigned MAX_BROKEN_TIME = 60; +constexpr static const unsigned MAX_DISTANCE_DELTA = 500; +constexpr static const unsigned SUSPICIOUS_DISTANCE_DELTA = 100; + constexpr static const double default_beta = 10.0; constexpr static const double default_sigma_z = 4.07; } @@ -168,6 +171,7 @@ class MapMatching final : public BasicRoutingInterface prune - if (d_t > 500) + if (d_t > osrm::matching::MAX_DISTANCE_DELTA) { continue; } @@ -232,6 +236,7 @@ class MapMatching final : public BasicRoutingInterface osrm::matching::SUSPICIOUS_DISTANCE_DELTA; model.breakage[t] = false; } } @@ -255,7 +260,7 @@ class MapMatching final : public BasicRoutingInterface> &viterbi, - const std::vector> &pruned) + const std::vector> &pruned, + const std::vector> &suspicious) { // json logger not enabled if (!logger) @@ -119,6 +120,8 @@ struct MatchingDebugInfo osrm::json::clamp_float(viterbi[t][s_prime]); osrm::json::get(*object, "states", t, s_prime, "pruned") = static_cast(pruned[t][s_prime]); + osrm::json::get(*object, "states", t, s_prime, "suspicious") = + static_cast(suspicious[t][s_prime]); } } } From f89f4bd20bc47214130cd2dc132dff911d80b1dc Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Mon, 23 Mar 2015 00:28:38 +0100 Subject: [PATCH 344/360] Add option to enable json logging --- CMakeLists.txt | 6 ++++++ util/json_logger.hpp | 15 ++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c1d771d03..9770a0227 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ if(WIN32 AND MSVC_VERSION LESS 1800) message(FATAL_ERROR "Building with Microsoft compiler needs Visual Studio 2013 or later (Express version works too)") endif() +option(ENABLE_JSON_LOGGING "Adds additional JSON debug logging to the response" OFF) option(WITH_TOOLS "Build OSRM tools" OFF) option(BUILD_TOOLS "Build OSRM tools" OFF) @@ -298,6 +299,11 @@ include_directories(${ZLIB_INCLUDE_DIRS}) target_link_libraries(osrm-extract ${ZLIB_LIBRARY}) target_link_libraries(osrm-routed ${ZLIB_LIBRARY}) +if (ENABLE_JSON_LOGGING) + message(STATUS "Enabling json logging") + add_definitions(-DENABLE_JSON_LOGGING) +endif() + if(WITH_TOOLS OR BUILD_TOOLS) message(STATUS "Activating OSRM internal tools") find_package(GDAL) diff --git a/util/json_logger.hpp b/util/json_logger.hpp index 03f8a171a..b7de7cbea 100644 --- a/util/json_logger.hpp +++ b/util/json_logger.hpp @@ -48,11 +48,20 @@ class Logger { static Logger logger; + bool return_logger = true; #ifdef NDEBUG - return nullptr; -#else - return &logger; + return_logger = false; #endif +#ifdef ENABLE_JSON_LOGGING + return_logger = true; +#endif + + if (return_logger) + { + return &logger; + } + + return nullptr; } void initialize(const std::string& name) From 7ee877616568f153b9a3030249251fd17f5084bc Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 27 Mar 2015 01:25:22 +0100 Subject: [PATCH 345/360] Remove second stage classifier: obsolete with trace splitting --- plugins/match.hpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/plugins/match.hpp b/plugins/match.hpp index 93282d406..9f6486b1a 100644 --- a/plugins/match.hpp +++ b/plugins/match.hpp @@ -89,12 +89,6 @@ template class MapMatchingPlugin : public BasePlugin const auto label_with_confidence = classifier.classify(distance_feature); - // "second stage classifier": if we need to remove points there is something fishy - if (removed_points > 0) - { - return std::make_pair(ClassifierT::ClassLabel::NEGATIVE, 1.0); - } - return label_with_confidence; } From 3248977e024db3fcf7c3c370833844c98b31159b Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Tue, 31 Mar 2015 10:15:12 +0200 Subject: [PATCH 346/360] Update classifier parameters --- plugins/match.hpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/plugins/match.hpp b/plugins/match.hpp index 9f6486b1a..a866947b4 100644 --- a/plugins/match.hpp +++ b/plugins/match.hpp @@ -61,13 +61,12 @@ template class MapMatchingPlugin : public BasePlugin public: MapMatchingPlugin(DataFacadeT *facade, const int max_locations_map_matching) : descriptor_string("match"), facade(facade), - max_locations_map_matching(max_locations_map_matching) + max_locations_map_matching(max_locations_map_matching), // the values where derived from fitting a laplace distribution // to the values of manually classified traces - , - classifier(LaplaceDistribution(0.0057154021891018675, 0.020294704891166186), - LaplaceDistribution(0.11467696742821254, 0.49918444000368756), - 0.7977883096366508) // valid apriori probability + classifier(LaplaceDistribution(0.005986, 0.016646), + LaplaceDistribution(0.054385, 0.458432), + 0.696774) // valid apriori probability { search_engine_ptr = std::make_shared>(facade); } From 727e284ed0fa8684a14a4d36c0a330905a343c4b Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sat, 4 Apr 2015 17:48:19 +0200 Subject: [PATCH 347/360] Reduce map beta, as it fits better to the intended sample rate --- routing_algorithms/map_matching.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index eb405a8e4..604103097 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -65,7 +65,7 @@ constexpr static const unsigned MAX_BROKEN_TIME = 60; constexpr static const unsigned MAX_DISTANCE_DELTA = 500; constexpr static const unsigned SUSPICIOUS_DISTANCE_DELTA = 100; -constexpr static const double default_beta = 10.0; +constexpr static const double default_beta = 5.0; constexpr static const double default_sigma_z = 4.07; } } From f2cdb978678739be3ef73eed7aae6607c2947b62 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Mon, 6 Apr 2015 13:51:07 +0200 Subject: [PATCH 348/360] Change max distance delta to 200m --- routing_algorithms/map_matching.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp index 604103097..737494b64 100644 --- a/routing_algorithms/map_matching.hpp +++ b/routing_algorithms/map_matching.hpp @@ -62,7 +62,7 @@ using SubMatchingList = std::vector; constexpr static const unsigned MAX_BROKEN_STATES = 6; constexpr static const unsigned MAX_BROKEN_TIME = 60; -constexpr static const unsigned MAX_DISTANCE_DELTA = 500; +constexpr static const unsigned MAX_DISTANCE_DELTA = 200; constexpr static const unsigned SUSPICIOUS_DISTANCE_DELTA = 100; constexpr static const double default_beta = 5.0; From c03aec364cf4fe0314e663ea8414db24d32f6e1d Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 16 Apr 2015 11:25:43 +0200 Subject: [PATCH 349/360] add comparison tool for graph classes --- CMakeLists.txt | 2 + data_structures/dynamic_graph.hpp | 60 ++++----- data_structures/static_graph.hpp | 6 +- tools/graph_compare.cpp | 199 ++++++++++++++++++++++++++++++ 4 files changed, 233 insertions(+), 34 deletions(-) create mode 100644 tools/graph_compare.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9770a0227..503171a59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -332,6 +332,8 @@ if(WITH_TOOLS OR BUILD_TOOLS) target_link_libraries(osrm-check-hsgr ${Boost_LIBRARIES}) add_executable(osrm-springclean tools/springclean.cpp $ $ $ $) target_link_libraries(osrm-springclean ${Boost_LIBRARIES}) + add_executable(osrm-graph-compare tools/graph_compare.cpp $ $ $ $ $ $ $) + target_link_libraries(osrm-graph-compare ${Boost_LIBRARIES} ${TBB_LIBRARIES}) install(TARGETS osrm-cli DESTINATION bin) install(TARGETS osrm-io-benchmark DESTINATION bin) diff --git a/data_structures/dynamic_graph.hpp b/data_structures/dynamic_graph.hpp index 3a8f520c6..b39c7f2d7 100644 --- a/data_structures/dynamic_graph.hpp +++ b/data_structures/dynamic_graph.hpp @@ -76,8 +76,8 @@ template class DynamicGraph // Constructs an empty graph with a given number of nodes. explicit DynamicGraph(NodeIterator nodes) : number_of_nodes(nodes), number_of_edges(0) { - node_list.reserve(number_of_nodes); - node_list.resize(number_of_nodes); + node_array.reserve(number_of_nodes); + node_array.resize(number_of_nodes); edge_list.reserve(number_of_nodes * 1.1); edge_list.resize(number_of_nodes); @@ -87,29 +87,29 @@ template class DynamicGraph { number_of_nodes = nodes; number_of_edges = static_cast(graph.size()); - node_list.reserve(number_of_nodes + 1); - node_list.resize(number_of_nodes + 1); + // node_array.reserve(number_of_nodes + 1); + node_array.resize(number_of_nodes + 1); EdgeIterator edge = 0; EdgeIterator position = 0; for (const auto node : osrm::irange(0u, number_of_nodes)) { - EdgeIterator lastEdge = edge; + EdgeIterator last_edge = edge; while (edge < number_of_edges && graph[edge].source == node) { ++edge; } - node_list[node].firstEdge = position; - node_list[node].edges = edge - lastEdge; - position += node_list[node].edges; + node_array[node].first_edge = position; + node_array[node].edges = edge - last_edge; + position += node_array[node].edges; } - node_list.back().firstEdge = position; + node_array.back().first_edge = position; edge_list.reserve(static_cast(edge_list.size() * 1.1)); edge_list.resize(position); edge = 0; for (const auto node : osrm::irange(0u, number_of_nodes)) { - for (const auto i : osrm::irange(node_list[node].firstEdge, - node_list[node].firstEdge + node_list[node].edges)) + for (const auto i : osrm::irange(node_array[node].first_edge, + node_array[node].first_edge + node_array[node].edges)) { edge_list[i].target = graph[edge].target; edge_list[i].data = graph[edge].data; @@ -124,7 +124,7 @@ template class DynamicGraph unsigned GetNumberOfEdges() const { return number_of_edges; } - unsigned GetOutDegree(const NodeIterator n) const { return node_list[n].edges; } + unsigned GetOutDegree(const NodeIterator n) const { return node_array[n].edges; } unsigned GetDirectedOutDegree(const NodeIterator n) const { @@ -149,12 +149,12 @@ template class DynamicGraph EdgeIterator BeginEdges(const NodeIterator n) const { - return EdgeIterator(node_list[n].firstEdge); + return EdgeIterator(node_array[n].first_edge); } EdgeIterator EndEdges(const NodeIterator n) const { - return EdgeIterator(node_list[n].firstEdge + node_list[n].edges); + return EdgeIterator(node_array[n].first_edge + node_array[n].edges); } EdgeRange GetAdjacentEdgeRange(const NodeIterator node) const @@ -164,7 +164,7 @@ template class DynamicGraph NodeIterator InsertNode() { - node_list.emplace_back(node_list.back()); + node_array.emplace_back(node_array.back()); number_of_nodes += 1; return number_of_nodes; @@ -173,14 +173,14 @@ template class DynamicGraph // adds an edge. Invalidates edge iterators for the source node EdgeIterator InsertEdge(const NodeIterator from, const NodeIterator to, const EdgeDataT &data) { - Node &node = node_list[from]; - EdgeIterator newFirstEdge = node.edges + node.firstEdge; + Node &node = node_array[from]; + EdgeIterator newFirstEdge = node.edges + node.first_edge; if (newFirstEdge >= edge_list.size() || !isDummy(newFirstEdge)) { - if (node.firstEdge != 0 && isDummy(node.firstEdge - 1)) + if (node.first_edge != 0 && isDummy(node.first_edge - 1)) { - node.firstEdge--; - edge_list[node.firstEdge] = edge_list[node.firstEdge + node.edges]; + node.first_edge--; + edge_list[node.first_edge] = edge_list[node.first_edge + node.edges]; } else { @@ -195,32 +195,32 @@ template class DynamicGraph edge_list.resize(edge_list.size() + newSize); for (const auto i : osrm::irange(0u, node.edges)) { - edge_list[newFirstEdge + i] = edge_list[node.firstEdge + i]; - makeDummy(node.firstEdge + i); + edge_list[newFirstEdge + i] = edge_list[node.first_edge + i]; + makeDummy(node.first_edge + i); } for (const auto i : osrm::irange(node.edges + 1, newSize)) { makeDummy(newFirstEdge + i); } - node.firstEdge = newFirstEdge; + node.first_edge = newFirstEdge; } } - Edge &edge = edge_list[node.firstEdge + node.edges]; + Edge &edge = edge_list[node.first_edge + node.edges]; edge.target = to; edge.data = data; ++number_of_edges; ++node.edges; - return EdgeIterator(node.firstEdge + node.edges); + return EdgeIterator(node.first_edge + node.edges); } // removes an edge. Invalidates edge iterators for the source node void DeleteEdge(const NodeIterator source, const EdgeIterator e) { - Node &node = node_list[source]; + Node &node = node_array[source]; --number_of_edges; --node.edges; BOOST_ASSERT(std::numeric_limits::max() != node.edges); - const unsigned last = node.firstEdge + node.edges; + const unsigned last = node.first_edge + node.edges; BOOST_ASSERT(std::numeric_limits::max() != last); // swap with last edge edge_list[e] = edge_list[last]; @@ -245,7 +245,7 @@ template class DynamicGraph } number_of_edges -= deleted; - node_list[source].edges -= deleted; + node_array[source].edges -= deleted; return deleted; } @@ -277,7 +277,7 @@ template class DynamicGraph struct Node { // index of the first edge - EdgeIterator firstEdge; + EdgeIterator first_edge; // amount of edges unsigned edges; }; @@ -291,7 +291,7 @@ template class DynamicGraph NodeIterator number_of_nodes; std::atomic_uint number_of_edges; - std::vector node_list; + std::vector node_array; DeallocatingVector edge_list; }; diff --git a/data_structures/static_graph.hpp b/data_structures/static_graph.hpp index 2a5f6481e..d4fcdf7a5 100644 --- a/data_structures/static_graph.hpp +++ b/data_structures/static_graph.hpp @@ -91,7 +91,6 @@ template class StaticGraph StaticGraph(const int nodes, std::vector &graph) { - tbb::parallel_sort(graph.begin(), graph.end()); number_of_nodes = nodes; number_of_edges = static_cast(graph.size()); node_array.resize(number_of_nodes + 1); @@ -112,11 +111,10 @@ template class StaticGraph for (const auto node : osrm::irange(0u, number_of_nodes)) { EdgeIterator e = node_array[node + 1].first_edge; - for (EdgeIterator i = node_array[node].first_edge; i != e; ++i) + for (const auto i : osrm::irange(node_array[node].first_edge, e)) { edge_array[i].target = graph[edge].target; edge_array[i].data = graph[edge].data; - BOOST_ASSERT(edge_array[i].data.distance > 0); edge++; } } @@ -143,7 +141,7 @@ template class StaticGraph return NodeIterator(edge_array[e].target); } - inline EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_array[e].data; } + EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_array[e].data; } const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return edge_array[e].data; } diff --git a/tools/graph_compare.cpp b/tools/graph_compare.cpp new file mode 100644 index 000000000..2bc7f0b6e --- /dev/null +++ b/tools/graph_compare.cpp @@ -0,0 +1,199 @@ +#include "../data_structures/dynamic_graph.hpp" +#include "../data_structures/import_edge.hpp" +#include "../data_structures/query_node.hpp" +#include "../data_structures/restriction.hpp" +#include "../data_structures/static_graph.hpp" +#include "../util/fingerprint.hpp" +#include "../util/graph_loader.hpp" +#include "../util/integer_range.hpp" +#include "../util/make_unique.hpp" +#include "../util/osrm_exception.hpp" +#include "../util/simple_logger.hpp" + +#include "../typedefs.h" + +#include +#include + +struct TarjanEdgeData +{ + TarjanEdgeData() : distance(INVALID_EDGE_WEIGHT), name_id(INVALID_NAMEID) {} + TarjanEdgeData(unsigned distance, unsigned name_id) : distance(distance), name_id(name_id) {} + unsigned distance; + unsigned name_id; +}; + +using StaticTestGraph = StaticGraph; +using DynamicTestGraph = StaticGraph; +using StaticEdge = StaticTestGraph::InputEdge; +using DynamicEdge = DynamicTestGraph::InputEdge; + +int main(int argc, char *argv[]) +{ + std::vector coordinate_list; + std::vector restriction_list; + std::vector bollard_node_list; + std::vector traffic_lights_list; + + LogPolicy::GetInstance().Unmute(); + try + { + // enable logging + if (argc < 3) + { + SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0] + << " "; + return -1; + } + + SimpleLogger().Write() << "Using restrictions from file: " << argv[2]; + std::ifstream restriction_ifstream(argv[2], std::ios::binary); + const FingerPrint fingerprint_orig; + FingerPrint fingerprint_loaded; + restriction_ifstream.read(reinterpret_cast(&fingerprint_loaded), + sizeof(FingerPrint)); + + // check fingerprint and warn if necessary + if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig)) + { + SimpleLogger().Write(logWARNING) << argv[2] << " was prepared with a different build. " + "Reprocess to get rid of this warning."; + } + + if (!restriction_ifstream.good()) + { + throw osrm::exception("Could not access files"); + } + uint32_t usable_restrictions = 0; + restriction_ifstream.read(reinterpret_cast(&usable_restrictions), sizeof(uint32_t)); + restriction_list.resize(usable_restrictions); + + // load restrictions + if (usable_restrictions > 0) + { + restriction_ifstream.read(reinterpret_cast(&restriction_list[0]), + usable_restrictions * sizeof(TurnRestriction)); + } + restriction_ifstream.close(); + + std::ifstream input_stream(argv[1], std::ifstream::in | std::ifstream::binary); + if (!input_stream.is_open()) + { + throw osrm::exception("Cannot open osrm file"); + } + + // load graph data + std::vector edge_list; + const NodeID number_of_nodes = + readBinaryOSRMGraphFromStream(input_stream, edge_list, bollard_node_list, + traffic_lights_list, &coordinate_list, restriction_list); + input_stream.close(); + + BOOST_ASSERT_MSG(restriction_list.size() == usable_restrictions, + "size of restriction_list changed"); + + SimpleLogger().Write() << restriction_list.size() << " restrictions, " + << bollard_node_list.size() << " bollard nodes, " + << traffic_lights_list.size() << " traffic lights"; + + traffic_lights_list.clear(); + traffic_lights_list.shrink_to_fit(); + + // Building an node-based graph + std::vector static_graph_edge_list; + std::vector dynamic_graph_edge_list; + for (const auto &input_edge : edge_list) + { + if (input_edge.source == input_edge.target) + { + continue; + } + + if (input_edge.forward) + { + static_graph_edge_list.emplace_back(input_edge.source, input_edge.target, + (std::max)(input_edge.weight, 1), + input_edge.name_id); + dynamic_graph_edge_list.emplace_back(input_edge.source, input_edge.target, + (std::max)(input_edge.weight, 1), + input_edge.name_id); + } + if (input_edge.backward) + { + dynamic_graph_edge_list.emplace_back(input_edge.target, input_edge.source, + (std::max)(input_edge.weight, 1), + input_edge.name_id); + static_graph_edge_list.emplace_back(input_edge.target, input_edge.source, + (std::max)(input_edge.weight, 1), + input_edge.name_id); + } + } + edge_list.clear(); + edge_list.shrink_to_fit(); + BOOST_ASSERT_MSG(0 == edge_list.size() && 0 == edge_list.capacity(), + "input edge vector not properly deallocated"); + + tbb::parallel_sort(static_graph_edge_list.begin(), static_graph_edge_list.end()); + tbb::parallel_sort(dynamic_graph_edge_list.begin(), dynamic_graph_edge_list.end()); + + auto static_graph = + osrm::make_unique(number_of_nodes, static_graph_edge_list); + auto dynamic_graph = + osrm::make_unique(number_of_nodes, dynamic_graph_edge_list); + + SimpleLogger().Write() << "Starting static/dynamic graph comparison"; + + BOOST_ASSERT(static_graph->GetNumberOfNodes() == dynamic_graph->GetNumberOfNodes()); + BOOST_ASSERT(static_graph->GetNumberOfEdges() == dynamic_graph->GetNumberOfEdges()); + for (const auto node : osrm::irange(0u, static_graph->GetNumberOfNodes())) + { + const auto static_range = static_graph->GetAdjacentEdgeRange(node); + const auto dynamic_range = dynamic_graph->GetAdjacentEdgeRange(node); + SimpleLogger().Write() << "checking node " << node << "/" + << static_graph->GetNumberOfNodes(); + + BOOST_ASSERT(static_range.size() == dynamic_range.size()); + const auto static_begin = static_graph->BeginEdges(node); + const auto dynamic_begin = dynamic_graph->BeginEdges(node); + + // check raw interface + for (int i = 0; i < static_range.size(); ++i) + { + const auto static_target = static_graph->GetTarget(static_begin + i); + const auto dynamic_target = dynamic_graph->GetTarget(dynamic_begin + i); + BOOST_ASSERT(static_target == dynamic_target); + + const auto static_data = static_graph->GetEdgeData(static_begin + i); + const auto dynamic_data = dynamic_graph->GetEdgeData(dynamic_begin + i); + + BOOST_ASSERT(static_data.distance == dynamic_data.distance); + BOOST_ASSERT(static_data.name_id == dynamic_data.name_id); + } + + // check range interface + std::vector static_target_ids, dynamic_target_ids; + std::vector static_edge_data, dynamic_edge_data; + for (const auto static_id : static_range) + { + static_target_ids.push_back(static_graph->GetTarget(static_id)); + static_edge_data.push_back(static_graph->GetEdgeData(static_id)); + } + for (const auto dynamic_id : dynamic_range) + { + dynamic_target_ids.push_back(dynamic_graph->GetTarget(dynamic_id)); + dynamic_edge_data.push_back(dynamic_graph->GetEdgeData(dynamic_id)); + } + BOOST_ASSERT(static_target_ids.size() == dynamic_target_ids.size()); + BOOST_ASSERT(std::equal(std::begin(static_target_ids), std::end(static_target_ids), + std::begin(dynamic_target_ids))); + } + + SimpleLogger().Write() << "Graph comparison finished successfully"; + } + catch (const std::exception &e) + { + SimpleLogger().Write(logWARNING) << "[exception] " << e.what(); + } + + return 0; +} From 0eb210606736f13fd00d92c789b63eb48d9c9e96 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 16 Apr 2015 14:30:52 +0200 Subject: [PATCH 350/360] reorder includes, add tuple include --- data_structures/dynamic_graph.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/data_structures/dynamic_graph.hpp b/data_structures/dynamic_graph.hpp index b39c7f2d7..31aac5b58 100644 --- a/data_structures/dynamic_graph.hpp +++ b/data_structures/dynamic_graph.hpp @@ -36,9 +36,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include -#include #include +#include +#include +#include template class DynamicGraph { From c7bd96ea8b6350066dc196e0c7be1f48b8ef7882 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 16 Apr 2015 14:31:13 +0200 Subject: [PATCH 351/360] fix unintended signed/unsigned comparison --- tools/graph_compare.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/graph_compare.cpp b/tools/graph_compare.cpp index 2bc7f0b6e..8adc06e78 100644 --- a/tools/graph_compare.cpp +++ b/tools/graph_compare.cpp @@ -157,7 +157,7 @@ int main(int argc, char *argv[]) const auto dynamic_begin = dynamic_graph->BeginEdges(node); // check raw interface - for (int i = 0; i < static_range.size(); ++i) + for (const auto i : osrm::irange(0u, static_range.size())) { const auto static_target = static_graph->GetTarget(static_begin + i); const auto dynamic_target = dynamic_graph->GetTarget(dynamic_begin + i); From 4a0a0bac1d04b1764a4cb94f421614ac2000925c Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 16 Apr 2015 14:38:42 +0200 Subject: [PATCH 352/360] clear right edge list after graph instantiation --- tools/components.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/components.cpp b/tools/components.cpp index 85cfd88bd..2168cc5d6 100644 --- a/tools/components.cpp +++ b/tools/components.cpp @@ -173,8 +173,8 @@ int main(int argc, char *argv[]) tbb::parallel_sort(graph_edge_list.begin(), graph_edge_list.end()); auto graph = std::make_shared(number_of_nodes, graph_edge_list); - edge_list.clear(); - edge_list.shrink_to_fit(); + graph_edge_list.clear(); + graph_edge_list.shrink_to_fit(); SimpleLogger().Write() << "Starting SCC graph traversal"; From 59bceee258672c110fdd5d276c553022f99b23e9 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 16 Apr 2015 16:08:10 +0200 Subject: [PATCH 353/360] make sure GetNumberOfNodes() is only called once --- algorithms/tiny_components.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/algorithms/tiny_components.hpp b/algorithms/tiny_components.hpp index f3ca3c412..8eb61a912 100644 --- a/algorithms/tiny_components.hpp +++ b/algorithms/tiny_components.hpp @@ -95,18 +95,18 @@ template class TarjanSCC void run() { TIMER_START(SCC_RUN); + const NodeID max_node_id = m_node_based_graph->GetNumberOfNodes(); + // The following is a hack to distinguish between stuff that happens // before the recursive call and stuff that happens after std::stack recursion_stack; // true = stuff before, false = stuff after call std::stack tarjan_stack; - std::vector tarjan_node_list(m_node_based_graph->GetNumberOfNodes()); + std::vector tarjan_node_list(max_node_id); unsigned component_index = 0, size_of_current_component = 0; unsigned index = 0; - const NodeID last_node = m_node_based_graph->GetNumberOfNodes(); - std::vector processing_node_before_recursion(m_node_based_graph->GetNumberOfNodes(), - true); - for (const NodeID node : osrm::irange(0u, last_node)) + std::vector processing_node_before_recursion(max_node_id, true); + for (const NodeID node : osrm::irange(0u, max_node_id)) { if (SPECIAL_NODEID == components_index[node]) { From 0d432f6377533adb6c43cca7edda9cb636e2e50a Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 16 Apr 2015 16:11:06 +0200 Subject: [PATCH 354/360] fix comparison to recognize small components in a static graph --- tools/components.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tools/components.cpp b/tools/components.cpp index 2168cc5d6..565fb2f48 100644 --- a/tools/components.cpp +++ b/tools/components.cpp @@ -27,8 +27,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../typedefs.h" #include "../algorithms/tiny_components.hpp" -#include "../data_structures/static_graph.hpp" #include "../data_structures/coordinate_calculation.hpp" +#include "../data_structures/dynamic_graph.hpp" +#include "../data_structures/static_graph.hpp" #include "../util/fingerprint.hpp" #include "../util/graph_loader.hpp" #include "../util/make_unique.hpp" @@ -63,8 +64,8 @@ struct TarjanEdgeData unsigned name_id; }; -using TarjanGraph = StaticGraph; -using TarjanEdge = TarjanGraph::InputEdge; +using TarjanDynamicGraph = StaticGraph; +using TarjanEdge = TarjanDynamicGraph::InputEdge; void DeleteFileIfExists(const std::string &file_name) { @@ -148,6 +149,7 @@ int main(int argc, char *argv[]) // Building an node-based graph std::vector graph_edge_list; +// DeallocatingVector graph_edge_list; for (const auto &input_edge : edge_list) { if (input_edge.source == input_edge.target) @@ -172,15 +174,16 @@ int main(int argc, char *argv[]) "input edge vector not properly deallocated"); tbb::parallel_sort(graph_edge_list.begin(), graph_edge_list.end()); - auto graph = std::make_shared(number_of_nodes, graph_edge_list); + const auto graph = std::make_shared(number_of_nodes, graph_edge_list); graph_edge_list.clear(); graph_edge_list.shrink_to_fit(); SimpleLogger().Write() << "Starting SCC graph traversal"; RestrictionMap restriction_map(restriction_list); - auto tarjan = - osrm::make_unique>(graph, restriction_map, bollard_node_list); + auto tarjan = osrm::make_unique>(graph, + restriction_map, + bollard_node_list); tarjan->run(); SimpleLogger().Write() << "identified: " << tarjan->get_number_of_components() << " many components"; @@ -233,9 +236,9 @@ int main(int argc, char *argv[]) percentage.printIncrement(); for (const auto current_edge : graph->GetAdjacentEdgeRange(source)) { - const TarjanGraph::NodeIterator target = graph->GetTarget(current_edge); + const TarjanDynamicGraph::NodeIterator target = graph->GetTarget(current_edge); - if (source < target || graph->EndEdges(target) == graph->FindEdge(target, source)) + if (source < target || graph->EndEdges(target) >= graph->FindEdge(target, source)) { total_network_length += 100 * coordinate_calculation::euclidean_distance( From aff590a44d9250ebeb4da04fc320d837206172b5 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 16 Apr 2015 16:12:08 +0200 Subject: [PATCH 355/360] make implementation of FindEdge consistent among graph implementations, introduce FindSmallestEdge() function to return the edge with smallest weight if there are multiple, fixes #1427 --- data_structures/dynamic_graph.hpp | 19 +++++++++++++++++++ data_structures/static_graph.hpp | 13 +++++++++++++ 2 files changed, 32 insertions(+) diff --git a/data_structures/dynamic_graph.hpp b/data_structures/dynamic_graph.hpp index 31aac5b58..021a3bc37 100644 --- a/data_structures/dynamic_graph.hpp +++ b/data_structures/dynamic_graph.hpp @@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "deallocating_vector.hpp" #include "../util/integer_range.hpp" +#include "../typedefs.h" #include @@ -264,6 +265,24 @@ template class DynamicGraph return EndEdges(from); } + // searches for a specific edge + EdgeIterator FindSmallestEdge(const NodeIterator from, const NodeIterator to) const + { + EdgeIterator smallest_edge = SPECIAL_EDGEID; + EdgeWeight smallest_weight = INVALID_EDGE_WEIGHT; + for (auto edge : GetAdjacentEdgeRange(from)) + { + const NodeID target = GetTarget(edge); + const EdgeWeight weight = GetEdgeData(edge).distance; + if (target == to && weight < smallest_weight) + { + smallest_edge = edge; + smallest_weight = weight; + } + } + return smallest_edge; + } + protected: bool isDummy(const EdgeIterator edge) const { diff --git a/data_structures/static_graph.hpp b/data_structures/static_graph.hpp index d4fcdf7a5..09ba2c436 100644 --- a/data_structures/static_graph.hpp +++ b/data_structures/static_graph.hpp @@ -157,6 +157,19 @@ template class StaticGraph // searches for a specific edge EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const + { + for (const auto i : osrm::irange(BeginEdges(from), EndEdges(from))) + { + if (to == edge_array[i].target) + { + return i; + } + } + return EndEdges(from); + } + + // searches for a specific edge + EdgeIterator FindSmallestEdge(const NodeIterator from, const NodeIterator to) const { EdgeIterator smallest_edge = SPECIAL_EDGEID; EdgeWeight smallest_weight = INVALID_EDGE_WEIGHT; From f2cd68e3ec999d3a095e604147f268aa950c274b Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 17 Apr 2015 00:20:37 +0200 Subject: [PATCH 356/360] Return SPECIAL_EDGEID if no edge was found --- data_structures/dynamic_graph.hpp | 2 +- data_structures/static_graph.hpp | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/data_structures/dynamic_graph.hpp b/data_structures/dynamic_graph.hpp index 021a3bc37..e6773b3d1 100644 --- a/data_structures/dynamic_graph.hpp +++ b/data_structures/dynamic_graph.hpp @@ -262,7 +262,7 @@ template class DynamicGraph return i; } } - return EndEdges(from); + return SPECIAL_EDGEID; } // searches for a specific edge diff --git a/data_structures/static_graph.hpp b/data_structures/static_graph.hpp index 09ba2c436..7434b56de 100644 --- a/data_structures/static_graph.hpp +++ b/data_structures/static_graph.hpp @@ -35,8 +35,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -#include - #include #include #include @@ -165,7 +163,7 @@ template class StaticGraph return i; } } - return EndEdges(from); + return SPECIAL_EDGEID; } // searches for a specific edge From 52592b84fd611623afb0aa17209dde1273947d05 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 17 Apr 2015 00:22:51 +0200 Subject: [PATCH 357/360] Add functions to find reverse edge to DynamicGraph --- data_structures/dynamic_graph.hpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/data_structures/dynamic_graph.hpp b/data_structures/dynamic_graph.hpp index e6773b3d1..43e6c3aca 100644 --- a/data_structures/dynamic_graph.hpp +++ b/data_structures/dynamic_graph.hpp @@ -283,6 +283,27 @@ template class DynamicGraph return smallest_edge; } + EdgeIterator FindEdgeInEitherDirection(const NodeIterator from, const NodeIterator to) const + { + EdgeIterator tmp = FindEdge(from, to); + return (SPECIAL_NODEID != tmp ? tmp : FindEdge(to, from)); + } + + EdgeIterator + FindEdgeIndicateIfReverse(const NodeIterator from, const NodeIterator to, bool &result) const + { + EdgeIterator current_iterator = FindEdge(from, to); + if (SPECIAL_NODEID == current_iterator) + { + current_iterator = FindEdge(to, from); + if (SPECIAL_NODEID != current_iterator) + { + result = true; + } + } + return current_iterator; + } + protected: bool isDummy(const EdgeIterator edge) const { From 04b5833e98950e10738551af5f264c6277470165 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 17 Apr 2015 00:23:58 +0200 Subject: [PATCH 358/360] Adapt EdgeBasedGraphFactory to new FindEdge behaviour --- contractor/edge_based_graph_factory.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/contractor/edge_based_graph_factory.cpp b/contractor/edge_based_graph_factory.cpp index c4dc81a5b..268bb9f8d 100644 --- a/contractor/edge_based_graph_factory.cpp +++ b/contractor/edge_based_graph_factory.cpp @@ -93,15 +93,8 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, // find reverse edge id and const EdgeID edge_id_2 = m_node_based_graph->FindEdge(node_v, node_u); - -#ifndef NDEBUG - if (edge_id_2 == m_node_based_graph->EndEdges(node_v)) - { - SimpleLogger().Write(logWARNING) << "Did not find edge (" << node_v << "," << node_u << ")"; - } -#endif BOOST_ASSERT(edge_id_2 != SPECIAL_EDGEID); - BOOST_ASSERT(edge_id_2 < m_node_based_graph->EndEdges(node_v)); + const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(edge_id_2); if (forward_data.edgeBasedNodeID == SPECIAL_NODEID && @@ -315,7 +308,6 @@ void EdgeBasedGraphFactory::CompressGeometry() BOOST_ASSERT(node_u != node_v); const EdgeID forward_e1 = m_node_based_graph->FindEdge(node_u, node_v); - BOOST_ASSERT(m_node_based_graph->EndEdges(node_u) != forward_e1); BOOST_ASSERT(SPECIAL_EDGEID != forward_e1); BOOST_ASSERT(node_v == m_node_based_graph->GetTarget(forward_e1)); const EdgeID reverse_e1 = m_node_based_graph->FindEdge(node_w, node_v); @@ -325,9 +317,7 @@ void EdgeBasedGraphFactory::CompressGeometry() const EdgeData &fwd_edge_data1 = m_node_based_graph->GetEdgeData(forward_e1); const EdgeData &rev_edge_data1 = m_node_based_graph->GetEdgeData(reverse_e1); - if ((m_node_based_graph->FindEdge(node_u, node_w) != - m_node_based_graph->EndEdges(node_u)) || - (m_node_based_graph->FindEdge(node_w, node_u) != m_node_based_graph->EndEdges(node_w))) + if (m_node_based_graph->FindEdgeInEitherDirection(node_u, node_w) != SPECIAL_EDGEID) { continue; } From 94d7fd911289078e3bd01c128781441e37278f39 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 17 Apr 2015 00:25:01 +0200 Subject: [PATCH 359/360] Adapt osrm-components to new FindEdge interface --- tools/components.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/components.cpp b/tools/components.cpp index 565fb2f48..7ac64f8d9 100644 --- a/tools/components.cpp +++ b/tools/components.cpp @@ -64,8 +64,8 @@ struct TarjanEdgeData unsigned name_id; }; -using TarjanDynamicGraph = StaticGraph; -using TarjanEdge = TarjanDynamicGraph::InputEdge; +using TarjanGraph = StaticGraph; +using TarjanEdge = TarjanGraph::InputEdge; void DeleteFileIfExists(const std::string &file_name) { @@ -174,14 +174,14 @@ int main(int argc, char *argv[]) "input edge vector not properly deallocated"); tbb::parallel_sort(graph_edge_list.begin(), graph_edge_list.end()); - const auto graph = std::make_shared(number_of_nodes, graph_edge_list); + const auto graph = std::make_shared(number_of_nodes, graph_edge_list); graph_edge_list.clear(); graph_edge_list.shrink_to_fit(); SimpleLogger().Write() << "Starting SCC graph traversal"; RestrictionMap restriction_map(restriction_list); - auto tarjan = osrm::make_unique>(graph, + auto tarjan = osrm::make_unique>(graph, restriction_map, bollard_node_list); tarjan->run(); @@ -236,9 +236,9 @@ int main(int argc, char *argv[]) percentage.printIncrement(); for (const auto current_edge : graph->GetAdjacentEdgeRange(source)) { - const TarjanDynamicGraph::NodeIterator target = graph->GetTarget(current_edge); + const TarjanGraph::NodeIterator target = graph->GetTarget(current_edge); - if (source < target || graph->EndEdges(target) >= graph->FindEdge(target, source)) + if (source < target || SPECIAL_EDGEID == graph->FindEdge(target, source)) { total_network_length += 100 * coordinate_calculation::euclidean_distance( From 6d43d9f2b6336b9eae572ccf0b778308bc9225ab Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 17 Apr 2015 00:38:09 +0200 Subject: [PATCH 360/360] Add unit test for dynamic graph Also simplify the unit tests. --- unit_tests/data_structures/dynamic_graph.cpp | 96 ++++++++++++++++++++ unit_tests/data_structures/static_graph.cpp | 61 ++++--------- 2 files changed, 115 insertions(+), 42 deletions(-) create mode 100644 unit_tests/data_structures/dynamic_graph.cpp diff --git a/unit_tests/data_structures/dynamic_graph.cpp b/unit_tests/data_structures/dynamic_graph.cpp new file mode 100644 index 000000000..27dc7dc68 --- /dev/null +++ b/unit_tests/data_structures/dynamic_graph.cpp @@ -0,0 +1,96 @@ +/* + +Copyright (c) 2014, Project OSRM contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "../../data_structures/dynamic_graph.hpp" +#include "../../util/make_unique.hpp" +#include "../../typedefs.h" + +#include +#include +#include + +#include +#include + +BOOST_AUTO_TEST_SUITE(dynamic_graph) + +struct TestData +{ + EdgeID id; +}; + +typedef DynamicGraph TestDynamicGraph; +typedef TestDynamicGraph::InputEdge TestInputEdge; + +BOOST_AUTO_TEST_CASE(find_test) +{ + /* + * (0) -1-> (1) + * ^ ^ + * 2 5 + * | | + * (3) -3-> (4) + * <-4- + */ + std::vector input_edges = { + TestInputEdge{0, 1, TestData{1}}, + TestInputEdge{3, 0, TestData{2}}, + TestInputEdge{3, 4, TestData{3}}, + TestInputEdge{4, 3, TestData{4}}, + TestInputEdge{3, 0, TestData{5}} + }; + TestDynamicGraph simple_graph(5, input_edges); + + auto eit = simple_graph.FindEdge(0, 1); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1); + + eit = simple_graph.FindEdge(1, 0); + BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID); + + eit = simple_graph.FindEdgeInEitherDirection(1, 0); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1); + + bool reverse = false; + eit = simple_graph.FindEdgeIndicateIfReverse(1, 0, reverse); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1); + BOOST_CHECK(reverse); + + eit = simple_graph.FindEdge(3, 1); + BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID); + eit = simple_graph.FindEdge(0, 4); + BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID); + + eit = simple_graph.FindEdge(3, 4); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 3); + eit = simple_graph.FindEdgeInEitherDirection(3, 4); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 3); + + eit = simple_graph.FindEdge(3, 0); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 2); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/unit_tests/data_structures/static_graph.cpp b/unit_tests/data_structures/static_graph.cpp index 4b68b254d..ed303b791 100644 --- a/unit_tests/data_structures/static_graph.cpp +++ b/unit_tests/data_structures/static_graph.cpp @@ -40,15 +40,6 @@ BOOST_AUTO_TEST_SUITE(static_graph) struct TestData { EdgeID id; - bool shortcut; - unsigned distance; -}; - -struct TestEdge -{ - unsigned source; - unsigned target; - unsigned distance; }; typedef StaticGraph TestStaticGraph; @@ -58,7 +49,7 @@ typedef TestStaticGraph::InputEdge TestInputEdge; constexpr unsigned TEST_NUM_NODES = 100; constexpr unsigned TEST_NUM_EDGES = 500; -// Choosen by a fair W20 dice roll (this value is completely arbitrary) +// Chosen by a fair W20 dice roll (this value is completely arbitrary) constexpr unsigned RANDOM_SEED = 15; template struct RandomArrayEntryFixture @@ -94,8 +85,7 @@ template struct RandomArrayEntryFixture for (unsigned i = 0; i < NUM_EDGES; i++) { edges.emplace_back( - TestEdgeArrayEntry{static_cast(node_udist(g)), - TestData{i, false, static_cast(lengths_udist(g))}}); + TestEdgeArrayEntry{static_cast(node_udist(g)), TestData{i}}); } for (unsigned i = 0; i < NUM_NODES; i++) @@ -128,49 +118,37 @@ BOOST_FIXTURE_TEST_CASE(array_test, TestRandomArrayEntryFixture) } } -TestStaticGraph GraphFromEdgeList(const std::vector &edges) -{ - std::vector input_edges; - unsigned i = 0; - unsigned num_nodes = 0; - for (const auto &e : edges) - { - input_edges.push_back(TestInputEdge{e.source, e.target, TestData{i++, false, e.distance}}); - - num_nodes = std::max(num_nodes, std::max(e.source, e.target)); - } - - return TestStaticGraph(num_nodes, input_edges); -} - BOOST_AUTO_TEST_CASE(find_test) { /* * (0) -1-> (1) * ^ ^ - * 2 1 + * 2 5 * | | - * (3) -4-> (4) - * <-3- + * (3) -3-> (4) + * <-4- */ - TestStaticGraph simple_graph = GraphFromEdgeList({TestEdge{0, 1, 1}, - TestEdge{3, 0, 2}, - TestEdge{3, 4, 4}, - TestEdge{4, 3, 3}, - TestEdge{3, 0, 1}}); + std::vector input_edges = { + TestInputEdge{0, 1, TestData{1}}, + TestInputEdge{3, 0, TestData{2}}, + TestInputEdge{3, 4, TestData{3}}, + TestInputEdge{4, 3, TestData{4}}, + TestInputEdge{3, 0, TestData{5}} + }; + TestStaticGraph simple_graph(5, input_edges); auto eit = simple_graph.FindEdge(0, 1); - BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 0); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1); eit = simple_graph.FindEdge(1, 0); BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID); eit = simple_graph.FindEdgeInEitherDirection(1, 0); - BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 0); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1); bool reverse = false; eit = simple_graph.FindEdgeIndicateIfReverse(1, 0, reverse); - BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 0); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1); BOOST_CHECK(reverse); eit = simple_graph.FindEdge(3, 1); @@ -179,13 +157,12 @@ BOOST_AUTO_TEST_CASE(find_test) BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID); eit = simple_graph.FindEdge(3, 4); - BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 2); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 3); eit = simple_graph.FindEdgeInEitherDirection(3, 4); - // I think this is wrong behaviour! Should be 3. - BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 2); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 3); eit = simple_graph.FindEdge(3, 0); - BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 4); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 2); } BOOST_AUTO_TEST_SUITE_END()