Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLev Dragunov <l.dragunov@corp.mail.ru>2015-04-22 12:29:46 +0300
committerAlex Zolotarev <alex@maps.me>2015-09-23 02:47:23 +0300
commit5ac42bd3a1e5eaafdcb29e66bd569583a2210f45 (patch)
treeca5ca6e74352ade81ad479954c9cb31151bdfade /3party/osrm
parent6f79d3b0a62bb5d555145d4dec9efceac11ddb6b (diff)
New OSRM v4.6 c2fc47d
Diffstat (limited to '3party/osrm')
-rw-r--r--3party/osrm/osrm-backend/.clang-format53
-rw-r--r--3party/osrm/osrm-backend/.gitignore93
-rw-r--r--3party/osrm/osrm-backend/.gitmodules0
-rw-r--r--3party/osrm/osrm-backend/.travis.yml54
-rw-r--r--3party/osrm/osrm-backend/Algorithms/StronglyConnectedComponents.h459
-rw-r--r--3party/osrm/osrm-backend/Benchmarks/StaticRTreeBench.cpp130
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/CMakeLists.txt253
-rw-r--r--3party/osrm/osrm-backend/DataStructures/Coordinate.cpp465
-rw-r--r--3party/osrm/osrm-backend/DataStructures/EdgeBasedNode.h106
-rw-r--r--3party/osrm/osrm-backend/DataStructures/EdgeBasedNodeData.h123
-rw-r--r--3party/osrm/osrm-backend/DataStructures/InputReaderFactory.h123
-rw-r--r--3party/osrm/osrm-backend/DataStructures/PhantomNodes.h181
-rw-r--r--3party/osrm/osrm-backend/Descriptors/DescriptionFactory.cpp126
-rw-r--r--3party/osrm/osrm-backend/Descriptors/DescriptionFactory.h218
-rw-r--r--3party/osrm/osrm-backend/Descriptors/GPXDescriptor.h101
-rw-r--r--3party/osrm/osrm-backend/Docs/webclient.txt3
-rw-r--r--3party/osrm/osrm-backend/Extractor/BaseParser.cpp140
-rw-r--r--3party/osrm/osrm-backend/Extractor/BaseParser.h67
-rw-r--r--3party/osrm/osrm-backend/Extractor/ExtractionHelperFunctions.h90
-rw-r--r--3party/osrm/osrm-backend/Extractor/Extractor.cpp305
-rw-r--r--3party/osrm/osrm-backend/Extractor/Extractor.h36
-rw-r--r--3party/osrm/osrm-backend/Extractor/ExtractorCallbacks.cpp184
-rw-r--r--3party/osrm/osrm-backend/Extractor/ExtractorStructs.h114
-rw-r--r--3party/osrm/osrm-backend/Extractor/PBFParser.cpp665
-rw-r--r--3party/osrm/osrm-backend/Extractor/PBFParser.h103
-rw-r--r--3party/osrm/osrm-backend/Extractor/ScriptingEnvironment.cpp121
-rw-r--r--3party/osrm/osrm-backend/Extractor/XMLParser.cpp354
-rw-r--r--3party/osrm/osrm-backend/Extractor/XMLParser.h54
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/Gemfile2
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/Gemfile.lock0
-rw-r--r--3party/osrm/osrm-backend/Include/osrm/Coordinate.h113
-rw-r--r--3party/osrm/osrm-backend/Include/osrm/Reply.h74
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/LICENCE.TXT2
-rw-r--r--3party/osrm/osrm-backend/Library/OSRM_impl.cpp169
-rw-r--r--3party/osrm/osrm-backend/Plugins/MapsMePlugin.h192
-rw-r--r--3party/osrm/osrm-backend/Plugins/ViaRoutePlugin.h176
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/README.md0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/Rakefile5
-rw-r--r--3party/osrm/osrm-backend/RoutingAlgorithms/BasicRoutingInterface.h347
-rw-r--r--3party/osrm/osrm-backend/RoutingAlgorithms/NToMManyToManyRouting.h265
-rw-r--r--3party/osrm/osrm-backend/Server/APIGrammar.h74
-rw-r--r--3party/osrm/osrm-backend/Server/RequestHandler.cpp142
-rw-r--r--3party/osrm/osrm-backend/Server/RequestParser.cpp310
-rw-r--r--3party/osrm/osrm-backend/Tools/components.cpp130
-rw-r--r--3party/osrm/osrm-backend/UnitTests/datastructure_tests.cpp7
-rw-r--r--3party/osrm/osrm-backend/Util/GraphLoader.h429
-rw-r--r--3party/osrm/osrm-backend/Util/TimingUtil.h39
-rw-r--r--3party/osrm/osrm-backend/Util/TrigonometryTables.h790
-rwxr-xr-x3party/osrm/osrm-backend/algorithms/bayes_classifier.hpp117
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/algorithms/bfs_components.hpp (renamed from 3party/osrm/osrm-backend/Algorithms/BFSComponentExplorer.h)93
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/algorithms/crc32_processor.hpp (renamed from 3party/osrm/osrm-backend/Algorithms/IteratorBasedCRC32.h)15
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/algorithms/douglas_peucker.cpp (renamed from 3party/osrm/osrm-backend/Algorithms/DouglasPeucker.cpp)102
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/algorithms/douglas_peucker.hpp (renamed from 3party/osrm/osrm-backend/Algorithms/DouglasPeucker.h)41
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/algorithms/object_encoder.hpp (renamed from 3party/osrm/osrm-backend/Algorithms/ObjectToBase64.h)23
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/algorithms/polyline_compressor.cpp (renamed from 3party/osrm/osrm-backend/Algorithms/PolylineCompressor.cpp)74
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/algorithms/polyline_compressor.hpp (renamed from 3party/osrm/osrm-backend/Algorithms/PolylineCompressor.h)12
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/algorithms/polyline_formatter.cpp (renamed from 3party/osrm/osrm-backend/Util/Azimuth.h)63
-rwxr-xr-x3party/osrm/osrm-backend/algorithms/polyline_formatter.hpp45
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/algorithms/route_name_extraction.hpp (renamed from 3party/osrm/osrm-backend/Algorithms/ExtractRouteNames.h)65
-rwxr-xr-x3party/osrm/osrm-backend/algorithms/tiny_components.hpp239
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/appveyor.yml10
-rwxr-xr-x3party/osrm/osrm-backend/benchmarks/static_rtree.cpp184
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/cmake/CPackDebianConfig.cmake0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/cmake/CheckCXXCompilerFlag.cmake0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/cmake/FindDebArch.cmake0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/cmake/FindLua52.cmake1
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/cmake/FindLuaJIT.cmake0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/cmake/FindLuabind.cmake0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/cmake/FindOSMPBF.cmake2
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/cmake/FindSTXXL.cmake0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/cmake/FindTBB.cmake2
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/cmake/FingerPrint-Config.cmake10
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/cmake/GetGitRevisionDescription.cmake0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/cmake/GetGitRevisionDescription.cmake.in2
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/cmake/check_luabind.cmake0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/cmake/cmake_options_script.py0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/cmake/pkgconfig.in0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/cmake/postinst.in0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/config/cucumber.yml0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/contractor/contractor.hpp (renamed from 3party/osrm/osrm-backend/Contractor/Contractor.h)225
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/contractor/edge_based_graph_factory.cpp (renamed from 3party/osrm/osrm-backend/Contractor/EdgeBasedGraphFactory.cpp)406
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/contractor/edge_based_graph_factory.hpp (renamed from 3party/osrm/osrm-backend/Contractor/EdgeBasedGraphFactory.h)39
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/contractor/geometry_compressor.cpp (renamed from 3party/osrm/osrm-backend/Contractor/GeometryCompressor.cpp)42
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/contractor/geometry_compressor.hpp (renamed from 3party/osrm/osrm-backend/Contractor/GeometryCompressor.h)10
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/contractor/processing_chain.cpp (renamed from 3party/osrm/osrm-backend/Contractor/Prepare.cpp)121
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/contractor/processing_chain.hpp (renamed from 3party/osrm/osrm-backend/Contractor/Prepare.h)49
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/binary_heap.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/BinaryHeap.h)58
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/concurrent_queue.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/ConcurrentQueue.h)22
-rwxr-xr-x3party/osrm/osrm-backend/data_structures/coordinate.cpp87
-rwxr-xr-x3party/osrm/osrm-backend/data_structures/coordinate_calculation.cpp268
-rwxr-xr-x3party/osrm/osrm-backend/data_structures/coordinate_calculation.hpp82
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/deallocating_vector.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/DeallocatingVector.h)75
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/dynamic_graph.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/DynamicGraph.h)142
-rwxr-xr-x3party/osrm/osrm-backend/data_structures/edge_based_node.hpp109
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/external_memory_node.cpp (renamed from 3party/osrm/osrm-backend/DataStructures/ImportNode.cpp)40
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/external_memory_node.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/ImportNode.h)30
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/fixed_point_number.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/FixedPointNumber.h)8
-rwxr-xr-x3party/osrm/osrm-backend/data_structures/hidden_markov_model.hpp158
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/hilbert_value.cpp (renamed from 3party/osrm/osrm-backend/DataStructures/HilbertValue.cpp)6
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/hilbert_value.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/HilbertValue.h)8
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/import_edge.cpp (renamed from 3party/osrm/osrm-backend/DataStructures/ImportEdge.cpp)14
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/import_edge.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/ImportEdge.h)14
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/internal_route_result.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/RawRouteData.h)30
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/lru_cache.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/LRUCache.h)10
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/node_based_graph.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/NodeBasedGraph.h)102
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/node_id.hpp (renamed from 3party/osrm/osrm-backend/extractor.cpp)27
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/original_edge_data.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/OriginalEdgeData.h)17
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/percent.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/Percent.h)12
-rwxr-xr-x3party/osrm/osrm-backend/data_structures/phantom_node.cpp106
-rwxr-xr-x3party/osrm/osrm-backend/data_structures/phantom_node.hpp152
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/query_edge.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/QueryEdge.h)18
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/query_node.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/QueryNode.h)38
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/range_table.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/RangeTable.h)114
-rwxr-xr-x3party/osrm/osrm-backend/data_structures/rectangle.hpp211
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/restriction.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/Restriction.h)86
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/restriction_map.cpp (renamed from 3party/osrm/osrm-backend/DataStructures/RestrictionMap.cpp)98
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/restriction_map.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/RestrictionMap.h)105
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/route_parameters.cpp (renamed from 3party/osrm/osrm-backend/DataStructures/RouteParameters.cpp)32
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/search_engine.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/SearchEngine.h)28
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/search_engine_data.cpp (renamed from 3party/osrm/osrm-backend/DataStructures/SearchEngineData.cpp)42
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/search_engine_data.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/SearchEngineData.h)26
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/segment_information.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/SegmentInformation.h)14
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/shared_memory_factory.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/SharedMemoryFactory.h)77
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/shared_memory_vector_wrapper.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/SharedMemoryVectorWrapper.h)12
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/static_graph.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/StaticGraph.h)44
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/static_kdtree.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/StaticKDTree.h)12
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/static_rtree.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/StaticRTree.h)832
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/travel_mode.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/TravelMode.h)12
-rwxr-xr-x3party/osrm/osrm-backend/data_structures/tribool.hpp40
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/turn_instructions.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/TurnInstructions.h)35
-rwxr-xr-x3party/osrm/osrm-backend/data_structures/upper_bound.hpp77
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/xor_fast_hash.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/XORFastHash.h)20
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/data_structures/xor_fast_hash_storage.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/XORFastHashStorage.h)40
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/datastore.cpp68
-rwxr-xr-x3party/osrm/osrm-backend/descriptors/description_factory.cpp244
-rwxr-xr-x3party/osrm/osrm-backend/descriptors/description_factory.hpp96
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/descriptors/descriptor_base.hpp (renamed from 3party/osrm/osrm-backend/Descriptors/BaseDescriptor.h)46
-rwxr-xr-x3party/osrm/osrm-backend/descriptors/gpx_descriptor.hpp94
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/descriptors/json_descriptor.hpp (renamed from 3party/osrm/osrm-backend/Descriptors/JSONDescriptor.h)177
-rwxr-xr-x3party/osrm/osrm-backend/extract.cpp83
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/extractor/extraction_containers.cpp (renamed from 3party/osrm/osrm-backend/Extractor/ExtractionContainers.cpp)211
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/extractor/extraction_containers.hpp (renamed from 3party/osrm/osrm-backend/Extractor/ExtractionContainers.h)33
-rwxr-xr-x3party/osrm/osrm-backend/extractor/extraction_helper_functions.hpp119
-rwxr-xr-x3party/osrm/osrm-backend/extractor/extraction_node.hpp38
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/extractor/extraction_way.hpp (renamed from 3party/osrm/osrm-backend/Extractor/ExtractionWay.h)67
-rwxr-xr-x3party/osrm/osrm-backend/extractor/extractor.cpp239
-rwxr-xr-x3party/osrm/osrm-backend/extractor/extractor.hpp37
-rwxr-xr-x3party/osrm/osrm-backend/extractor/extractor_callbacks.cpp211
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/extractor/extractor_callbacks.hpp (renamed from 3party/osrm/osrm-backend/Extractor/ExtractorCallbacks.h)23
-rwxr-xr-x3party/osrm/osrm-backend/extractor/extractor_options.cpp174
-rwxr-xr-x3party/osrm/osrm-backend/extractor/extractor_options.hpp63
-rwxr-xr-x3party/osrm/osrm-backend/extractor/first_and_last_segment_of_way.hpp88
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/extractor/internal_extractor_edge.hpp (renamed from 3party/osrm/osrm-backend/Extractor/InternalExtractorEdge.h)46
-rwxr-xr-x3party/osrm/osrm-backend/extractor/restriction_parser.cpp233
-rwxr-xr-x3party/osrm/osrm-backend/extractor/restriction_parser.hpp62
-rwxr-xr-x3party/osrm/osrm-backend/extractor/scripting_environment.cpp151
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/extractor/scripting_environment.hpp (renamed from 3party/osrm/osrm-backend/Extractor/ScriptingEnvironment.h)19
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/access.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/access_node.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/area.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/barrier.feature0
-rwxr-xr-x3party/osrm/osrm-backend/features/bicycle/bridge.feature47
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/cycleway.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/destination.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/ferry.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/maxspeed.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/mode.feature252
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/names.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/oneway.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/pushing.feature10
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/ref.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/restrictions.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/roundabout.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/stop_area.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/surface.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/train.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/turn_penalty.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/bicycle/way.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/car/access.feature2
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/car/barrier.feature1
-rwxr-xr-x3party/osrm/osrm-backend/features/car/bridge.feature47
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/car/destination.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/car/ferry.feature25
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/car/link.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/car/maxspeed.feature64
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/car/names.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/car/oneway.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/car/permissive.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/car/restrictions.feature1
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/car/roundabout.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/car/shuttle_train.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/car/speed.feature28
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/car/surface.feature95
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/car/way.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/foot/access.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/foot/access_node.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/foot/area.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/foot/barrier.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/foot/ferry.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/foot/maxspeed.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/foot/names.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/foot/oneway.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/foot/ref.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/foot/restrictions.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/foot/roundabout.feature4
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/foot/surface.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/foot/way.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/locate/locate.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/nearest/pick.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/nearest/projection.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/options/extract/files.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/options/extract/help.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/options/extract/invalid.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/options/extract/version.feature2
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/options/prepare/files.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/options/prepare/help.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/options/prepare/invalid.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/options/prepare/version.feature2
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/options/routed/files.feature2
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/options/routed/help.feature18
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/options/routed/invalid.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/options/routed/version.feature2
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/step_definitions/data.rb0
-rwxr-xr-x3party/osrm/osrm-backend/features/step_definitions/distance_matrix.rb56
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/step_definitions/locate.rb0
-rwxr-xr-x3party/osrm/osrm-backend/features/step_definitions/matching.rb96
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/step_definitions/nearest.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/step_definitions/options.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/step_definitions/requests.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/step_definitions/routability.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/step_definitions/routing.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/step_definitions/timestamp.rb2
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/stress/launch.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/config.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/cucumber.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/data.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/env.rb18
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/exceptions.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/file.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/fuzzy.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/hash.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/hooks.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/launch.rb3
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/locate.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/log.rb2
-rwxr-xr-x3party/osrm/osrm-backend/features/support/match.rb26
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/nearest.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/osm_parser.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/osmlib.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/route.rb5
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/run.rb8
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/support/shortcuts.rb0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/bad.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/basic.feature2
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/bearing.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/bearing_param.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/bugs.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/compression.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/datastore.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/distance.feature50
-rwxr-xr-x3party/osrm/osrm-backend/features/testbot/distance_matrix.feature102
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/duration.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/example.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/fastest.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/ferry.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/fixed.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/geometry.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/graph.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/impedance.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/load.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/loop.feature14
-rwxr-xr-x3party/osrm/osrm-backend/features/testbot/matching.feature55
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/maxspeed.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/mode.feature2
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/oneway.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/opposite.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/origin.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/overlap.feature6
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/penalty.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/planetary.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/projection.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/protobuffer.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/roundabout.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/routes.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/snap.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/speed.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/status.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/time.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/turns.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/utf.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/uturn.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/testbot/via.feature0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/features/timestamp/timestamp.feature0
-rwxr-xr-x3party/osrm/osrm-backend/include/osrm/coordinate.hpp71
-rwxr-xr-x3party/osrm/osrm-backend/include/osrm/json_container.hpp96
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/include/osrm/libosrm_config.hpp (renamed from 3party/osrm/osrm-backend/Util/MachineInfo.h)41
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/include/osrm/route_parameters.hpp (renamed from 3party/osrm/osrm-backend/Include/osrm/RouteParameters.h)24
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/include/osrm/server_paths.hpp (renamed from 3party/osrm/osrm-backend/Include/osrm/ServerPaths.h)4
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/library/osrm.hpp (renamed from 3party/osrm/osrm-backend/Library/OSRM.h)21
-rwxr-xr-x3party/osrm/osrm-backend/library/osrm_impl.cpp181
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/library/osrm_impl.hpp (renamed from 3party/osrm/osrm-backend/Library/OSRM_impl.h)23
-rw-r--r--3party/osrm/osrm-backend/mapsme/converter.cpp388
-rw-r--r--3party/osrm/osrm-backend/mapsme/converter.hpp13
-rw-r--r--3party/osrm/osrm-backend/mapsme/main.cpp29
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/plugins/distance_table.hpp (renamed from 3party/osrm/osrm-backend/Plugins/DistanceTablePlugin.h)99
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/plugins/hello_world.hpp (renamed from 3party/osrm/osrm-backend/Plugins/HelloWorldPlugin.h)42
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/plugins/locate.hpp (renamed from 3party/osrm/osrm-backend/Plugins/LocatePlugin.h)35
-rwxr-xr-x3party/osrm/osrm-backend/plugins/match.hpp314
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/plugins/nearest.hpp (renamed from 3party/osrm/osrm-backend/Plugins/NearestPlugin.h)59
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/plugins/plugin_base.hpp (renamed from 3party/osrm/osrm-backend/Plugins/BasePlugin.h)32
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/plugins/timestamp.hpp (renamed from 3party/osrm/osrm-backend/Plugins/TimestampPlugin.h)18
-rwxr-xr-x3party/osrm/osrm-backend/plugins/viaroute.hpp192
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/prepare.cpp10
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/profile.lua258
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/profiles/bicycle.lua254
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/profiles/car.lua258
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/profiles/examples/postgis.lua10
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/profiles/foot.lua114
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/profiles/lib/access.lua6
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/profiles/lib/maxspeed.lua0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/profiles/testbot.lua63
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/profiles/turnbot.lua2
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/routed.cpp45
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/routing_algorithms/alternative_path.hpp (renamed from 3party/osrm/osrm-backend/RoutingAlgorithms/AlternativePathRouting.h)243
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/routing_algorithms/many_to_many.hpp (renamed from 3party/osrm/osrm-backend/RoutingAlgorithms/ManyToManyRouting.h)39
-rwxr-xr-x3party/osrm/osrm-backend/routing_algorithms/map_matching.hpp344
-rwxr-xr-x3party/osrm/osrm-backend/routing_algorithms/routing_base.hpp494
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/routing_algorithms/shortest_path.hpp (renamed from 3party/osrm/osrm-backend/RoutingAlgorithms/ShortestPathRouting.h)126
-rwxr-xr-x3party/osrm/osrm-backend/server/api_grammar.hpp101
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/server/connection.cpp (renamed from 3party/osrm/osrm-backend/Server/Connection.cpp)93
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/server/connection.hpp (renamed from 3party/osrm/osrm-backend/Server/Connection.h)50
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/server/data_structures/datafacade_base.hpp (renamed from 3party/osrm/osrm-backend/Server/DataStructures/BaseDataFacade.h)64
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/server/data_structures/internal_datafacade.hpp (renamed from 3party/osrm/osrm-backend/Server/DataStructures/InternalDataFacade.h)182
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/server/data_structures/shared_barriers.hpp (renamed from 3party/osrm/osrm-backend/Server/DataStructures/SharedBarriers.h)8
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/server/data_structures/shared_datafacade.hpp (renamed from 3party/osrm/osrm-backend/Server/DataStructures/SharedDataFacade.h)175
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/server/data_structures/shared_datatype.hpp (renamed from 3party/osrm/osrm-backend/Server/DataStructures/SharedDataType.h)168
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/server/http/compression_type.hpp (renamed from 3party/osrm/osrm-backend/Server/Http/CompressionType.h)21
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/server/http/header.hpp (renamed from 3party/osrm/osrm-backend/Include/osrm/Header.h)19
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/server/http/reply.cpp (renamed from 3party/osrm/osrm-backend/Server/Http/Reply.cpp)68
-rwxr-xr-x3party/osrm/osrm-backend/server/http/reply.hpp65
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/server/http/request.hpp (renamed from 3party/osrm/osrm-backend/Server/Http/Request.h)10
-rwxr-xr-x3party/osrm/osrm-backend/server/request_handler.cpp175
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/server/request_handler.hpp (renamed from 3party/osrm/osrm-backend/Server/RequestHandler.h)14
-rwxr-xr-x3party/osrm/osrm-backend/server/request_parser.cpp323
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/server/request_parser.hpp (renamed from 3party/osrm/osrm-backend/Server/RequestParser.h)94
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/server/server.hpp (renamed from 3party/osrm/osrm-backend/Server/Server.h)24
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/taginfo.json0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/test/.gitignore0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/test/.stxxl0
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/.gitignore2
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/.travis.yml51
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/.ycm_extra_conf.py48
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/CHANGELOG.md31
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/CMakeLists.txt333
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/CONTRIBUTING.md132
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/LICENSE.txt23
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/README.md104
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/appveyor.yml77
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/benchmarks/CMakeLists.txt48
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/benchmarks/README.md41
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/benchmarks/download_data.sh12
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/benchmarks/osmium_benchmark_count.cpp54
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/benchmarks/osmium_benchmark_count_tag.cpp55
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/benchmarks/osmium_benchmark_index_map.cpp41
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/benchmarks/osmium_benchmark_static_vs_dynamic_index.cpp136
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/benchmarks/run_benchmark_count.sh22
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/benchmarks/run_benchmark_count_tag.sh22
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/benchmarks/run_benchmark_index_map.sh27
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/benchmarks/run_benchmark_static_vs_dynamic_index.sh21
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/benchmarks/run_benchmarks.sh15
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/benchmarks/setup.sh34
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/cmake/FindGem.cmake153
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/cmake/FindOSMPBF.cmake50
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/cmake/FindOsmium.cmake340
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/cmake/README3
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/cmake/build.bat15
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/cmake/iwyu.sh43
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/doc/CMakeLists.txt35
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/doc/Doxyfile.in2313
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/doc/README.md8
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/doc/doc.txt26
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/doc/header.html56
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/doc/osmium.css22
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/examples/CMakeLists.txt115
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_area_test.cpp138
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_convert.cpp112
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_count.cpp57
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_create_node_cache.cpp58
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_debug.cpp52
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_index.cpp237
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_read.cpp32
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_serdump.cpp209
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_toogr.cpp246
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_toogr2.cpp333
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_toogr2_exp.cpp307
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_use_node_cache.cpp71
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/boost_unicode_iterator.hpp776
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/mmap_for_windows.hpp103
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/assembler.hpp783
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/detail/node_ref_segment.hpp262
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/detail/proto_ring.hpp274
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/detail/segment_list.hpp216
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/multipolygon_collector.hpp212
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/problem_reporter.hpp149
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/problem_reporter_exception.hpp96
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/problem_reporter_ogr.hpp223
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/problem_reporter_stream.hpp96
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/builder/builder.hpp223
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/builder/builder_helper.hpp103
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/builder/osm_object_builder.hpp284
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/diff_handler.hpp67
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/diff_iterator.hpp129
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/diff_visitor.hpp104
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/dynamic_handler.hpp195
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/experimental/flex_reader.hpp129
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/coordinates.hpp97
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/factory.hpp328
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/geojson.hpp154
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/geos.hpp230
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/haversine.hpp94
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/mercator_projection.hpp109
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/ogr.hpp206
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/projection.hpp167
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/relations.hpp57
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/util.hpp75
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/wkb.hpp277
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/wkt.hpp150
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler.hpp101
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/chain.hpp128
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/disk_store.hpp111
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/dump.hpp294
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/node_locations_for_ways.hpp180
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/object_relations.hpp106
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/create_map_with_fd.hpp73
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/mmap_vector_anon.hpp78
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/mmap_vector_base.hpp184
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/mmap_vector_file.hpp85
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/tmpfile.hpp62
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/typed_mmap.hpp229
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/vector_map.hpp238
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/vector_multimap.hpp152
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/index.hpp100
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map.hpp254
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/all.hpp46
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/dense_file_array.hpp67
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/dense_mem_array.hpp57
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/dense_mmap_array.hpp60
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/dummy.hpp88
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_file_array.hpp67
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_mem_array.hpp60
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_mem_map.hpp115
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_mem_table.hpp146
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_mmap_array.hpp60
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap.hpp127
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/all.hpp41
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/hybrid.hpp200
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/sparse_file_array.hpp54
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/sparse_mem_array.hpp58
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/sparse_mem_multimap.hpp151
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/sparse_mmap_array.hpp58
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/node_locations_map.hpp70
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/any_compression.hpp48
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/any_input.hpp51
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/any_output.hpp52
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/bzip2_compression.hpp289
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/compression.hpp281
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/input_format.hpp158
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/opl_output_format.hpp317
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/output_format.hpp156
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf.hpp98
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf_input_format.hpp262
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf_output_format.hpp972
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf_parser.hpp455
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf_stringtable.hpp218
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/read_thread.hpp106
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/read_write.hpp160
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/write_thread.hpp86
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/xml_input_format.hpp738
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/xml_output_format.hpp484
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/zlib.hpp113
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/error.hpp58
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/file.hpp344
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/file_compression.hpp72
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/file_format.hpp78
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/gzip_compression.hpp246
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/header.hpp122
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/input_iterator.hpp140
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/opl_output.hpp39
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/output_iterator.hpp124
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/overwrite.hpp52
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/pbf_input.hpp49
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/pbf_output.hpp49
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/reader.hpp312
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/reader_iterator.hpp51
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/writer.hpp145
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/xml_input.hpp48
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/xml_output.hpp47
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/memory/buffer.hpp535
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/memory/collection.hpp154
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/memory/item.hpp178
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/memory/item_iterator.hpp234
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/object_pointer_collection.hpp112
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm.hpp48
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/area.hpp214
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/box.hpp250
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/changeset.hpp335
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/diff_object.hpp156
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/entity.hpp79
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/entity_bits.hpp105
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/item_type.hpp173
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/location.hpp285
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/node.hpp76
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/node_ref.hpp173
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/node_ref_list.hpp184
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/object.hpp437
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/object_comparisons.hpp110
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/relation.hpp189
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/segment.hpp105
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/tag.hpp140
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/timestamp.hpp175
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/types.hpp83
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/undirected_segment.hpp100
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/way.hpp117
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/relations/collector.hpp544
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/relations/detail/member_meta.hpp158
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/relations/detail/relation_meta.hpp136
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/tags/filter.hpp162
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/tags/regex_filter.hpp58
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/tags/taglist.hpp67
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/thread/function_wrapper.hpp111
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/thread/pool.hpp180
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/thread/queue.hpp181
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/thread/sorted_queue.hpp159
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/thread/util.hpp87
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/cast.hpp103
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/compatibility.hpp47
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/config.hpp72
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/double.hpp93
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/options.hpp155
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/string.hpp68
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/verbose_output.hpp139
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/include/osmium/visitor.hpp255
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/osmium.imp11
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/CMakeLists.txt165
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/README13
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/.gitignore1
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/CMakeLists.txt118
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/README.md10
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/include/check_basics_handler.hpp92
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/include/check_wkt_handler.hpp86
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/include/common.hpp22
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/include/testdata-testcases.hpp10
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/multipolygon.qgs880
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/run-testdata-multipolygon.cmake46
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testcases/test-100.cpp41
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testcases/test-101.cpp43
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testcases/test-110.cpp58
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testdata-multipolygon.cpp291
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testdata-overview.cpp197
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testdata-testcases.cpp27
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testdata-xml.cpp462
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/include/catch.hpp9003
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/include/catch_orig.hpp8997
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/include/utils.hpp18
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/include/win_mkstemp.hpp42
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/area/test_area_id.cpp25
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/area/test_node_ref_segment.cpp115
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/helper.hpp97
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_box.cpp91
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_changeset.cpp57
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_entity_bits.cpp31
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_location.cpp154
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_node.cpp117
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_node_ref.cpp57
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_object_comparisons.cpp147
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_relation.cpp60
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_timestamp.cpp58
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_way.cpp82
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/buffer/test_buffer_node.cpp135
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/buffer/test_buffer_purge.cpp186
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/helper.hpp15
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_factory_with_projection.cpp41
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_geojson.cpp236
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_geos.cpp198
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_geos_wkb.cpp156
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_mercator.cpp37
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_ogr.cpp185
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_projection.cpp131
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_wkb.cpp133
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_wkt.cpp198
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/index/test_id_to_location.cpp170
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/index/test_typed_mmap.cpp76
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/index/test_typed_mmap_grow.cpp34
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data.osm4
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data.osm.bz2bin0 -> 200 bytes
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data.osm.gzbin0 -> 187 bytes
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data_bzip2.txt1
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data_bzip2.txt.bz2bin0 -> 45 bytes
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/io/test_bzip2.cpp33
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/io/test_file_formats.cpp251
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/io/test_output_iterator.cpp37
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/io/test_reader.cpp117
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/tags/test_filter.cpp216
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/tags/test_operators.cpp61
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/tags/test_tag_list.cpp76
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/thread/test_pool.cpp69
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/util/test_cast_with_assert.cpp89
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/util/test_double.cpp33
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/util/test_options.cpp48
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/t/util/test_string.cpp57
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/test_main.cpp2
-rwxr-xr-x3party/osrm/osrm-backend/third_party/libosmium/test/valgrind.supp47
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/.gitignore3
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/.travis.yml22
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/Jamroot75
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/LICENSE25
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/README.md67
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/appveyor.yml27
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/common.gypi143
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/optional.hpp69
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/third_party/variant/recursive_wrapper.hpp (renamed from 3party/osrm/osrm-backend/ThirdParty/variant/recursive_wrapper.hpp)7
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/scripts/linux.sh59
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/scripts/osx.sh20
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/test/bench_variant.cpp204
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/test/binary_visitor_test.cpp136
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/test/boost_variant_hello_world.cpp19
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/test/catch.hpp8683
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/test/optional_unit.cpp82
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/test/recursive_wrapper_test.cpp132
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/test/reference_wrapper_test.cpp74
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/test/unique_ptr_test.cpp128
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/test/unit.cpp314
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/test/variant_hello_world.cpp22
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/variant.gyp21
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/third_party/variant/variant.hpp (renamed from 3party/osrm/osrm-backend/ThirdParty/variant/variant.hpp)314
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/variant_io.hpp39
-rwxr-xr-x3party/osrm/osrm-backend/third_party/variant/vcbuild.bat8
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/tools/.gitignore (renamed from 3party/osrm/osrm-backend/Tools/.gitignore)0
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/tools/check-hsgr.cpp (renamed from 3party/osrm/osrm-backend/Tools/check-hsgr.cpp)32
-rwxr-xr-x3party/osrm/osrm-backend/tools/components.cpp293
-rwxr-xr-x3party/osrm/osrm-backend/tools/graph_compare.cpp199
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/tools/io-benchmark.cpp (renamed from 3party/osrm/osrm-backend/Tools/io-benchmark.cpp)56
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/tools/simpleclient.cpp (renamed from 3party/osrm/osrm-backend/Tools/simpleclient.cpp)90
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/tools/springclean.cpp (renamed from 3party/osrm/osrm-backend/Tools/springclean.cpp)14
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/tools/unlock_all_mutexes.cpp (renamed from 3party/osrm/osrm-backend/Tools/unlock_all_mutexes.cpp)8
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/typedefs.h1
-rwxr-xr-x3party/osrm/osrm-backend/unit_tests/algorithm_tests.cpp34
-rwxr-xr-x3party/osrm/osrm-backend/unit_tests/algorithms/douglas_peucker.cpp105
-rwxr-xr-x3party/osrm/osrm-backend/unit_tests/algorithms/duration_parsing.cpp64
-rwxr-xr-x3party/osrm/osrm-backend/unit_tests/algorithms/string_util.cpp75
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/unit_tests/data_structures/binary_heap.cpp (renamed from 3party/osrm/osrm-backend/UnitTests/DataStructures/BinaryHeapTest.cpp)29
-rwxr-xr-x3party/osrm/osrm-backend/unit_tests/data_structures/coordinate.cpp50
-rwxr-xr-x3party/osrm/osrm-backend/unit_tests/data_structures/dynamic_graph.cpp96
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/unit_tests/data_structures/range_table.cpp (renamed from 3party/osrm/osrm-backend/UnitTests/DataStructures/RangeTableTest.cpp)34
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/unit_tests/data_structures/static_graph.cpp (renamed from 3party/osrm/osrm-backend/UnitTests/DataStructures/StaticGraphTest.cpp)90
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/unit_tests/data_structures/static_rtree.cpp (renamed from 3party/osrm/osrm-backend/UnitTests/DataStructures/StaticRTreeTest.cpp)157
-rwxr-xr-x3party/osrm/osrm-backend/unit_tests/datastructure_tests.cpp34
-rwxr-xr-x3party/osrm/osrm-backend/util/bearing.cpp65
-rwxr-xr-x3party/osrm/osrm-backend/util/bearing.hpp38
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/boost_filesystem_2_fix.hpp (renamed from 3party/osrm/osrm-backend/Util/BoostFileSystemFix.h)18
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/cast.hpp (renamed from 3party/osrm/osrm-backend/Util/cast.hpp)17
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/compute_angle.cpp (renamed from 3party/osrm/osrm-backend/Util/compute_angle.cpp)25
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/compute_angle.hpp (renamed from 3party/osrm/osrm-backend/Util/compute_angle.hpp)13
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/container.hpp (renamed from 3party/osrm/osrm-backend/Util/container.hpp)60
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/datastore_options.hpp (renamed from 3party/osrm/osrm-backend/Util/DataStoreOptions.h)62
-rwxr-xr-x3party/osrm/osrm-backend/util/fingerprint.cpp29
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/fingerprint.hpp (renamed from 3party/osrm/osrm-backend/Util/FingerPrint.h)5
-rwxr-xr-x3party/osrm/osrm-backend/util/fingerprint_impl.hpp103
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/fingerprint_impl.hpp.in (renamed from 3party/osrm/osrm-backend/Util/FingerPrint.cpp.in)16
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/floating_point.hpp (renamed from 3party/osrm/osrm-backend/Util/floating_point.hpp)2
-rwxr-xr-x3party/osrm/osrm-backend/util/git_sha.cpp31
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/git_sha.cpp.in (renamed from 3party/osrm/osrm-backend/Util/GitDescription.cpp.in)4
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/git_sha.hpp (renamed from 3party/osrm/osrm-backend/Util/GitDescription.h)8
-rwxr-xr-x3party/osrm/osrm-backend/util/graph_loader.hpp539
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/ini_file.hpp (renamed from 3party/osrm/osrm-backend/Util/IniFileUtil.h)26
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/integer_range.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/Range.h)31
-rwxr-xr-x3party/osrm/osrm-backend/util/iso_8601_duration_parser.hpp102
-rwxr-xr-x3party/osrm/osrm-backend/util/iterator_range.hpp71
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/json_logger.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/HashTable.h)78
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/json_renderer.hpp (renamed from 3party/osrm/osrm-backend/DataStructures/JSONContainer.h)81
-rwxr-xr-x3party/osrm/osrm-backend/util/json_util.hpp103
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/lua_util.hpp (renamed from 3party/osrm/osrm-backend/Util/LuaUtil.h)8
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/make_unique.hpp (renamed from 3party/osrm/osrm-backend/Util/make_unique.hpp)44
-rwxr-xr-x3party/osrm/osrm-backend/util/matching_debug_info.hpp155
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/mercator.cpp (renamed from 3party/osrm/osrm-backend/Util/MercatorUtil.h)15
-rwxr-xr-x3party/osrm/osrm-backend/util/mercator.hpp38
-rwxr-xr-x3party/osrm/osrm-backend/util/osrm_exception.cpp43
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/osrm_exception.hpp (renamed from 3party/osrm/osrm-backend/Util/OSRMException.h)25
-rwxr-xr-x3party/osrm/osrm-backend/util/range_algorithms.hpp49
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/routed_options.hpp (renamed from 3party/osrm/osrm-backend/Util/ProgramOptions.h)99
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/simple_logger.cpp (renamed from 3party/osrm/osrm-backend/Util/simple_logger.cpp)62
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/simple_logger.hpp (renamed from 3party/osrm/osrm-backend/Util/simple_logger.hpp)6
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/std_hash.hpp (renamed from 3party/osrm/osrm-backend/Util/StdHashExtensions.h)29
-rwxr-xr-x[-rw-r--r--]3party/osrm/osrm-backend/util/string_util.hpp (renamed from 3party/osrm/osrm-backend/Util/StringUtil.h)85
-rwxr-xr-x3party/osrm/osrm-backend/util/timing_util.hpp90
-rwxr-xr-x3party/osrm/osrm-backend/util/trigonometry_table.hpp448
-rwxr-xr-x3party/osrm/osrm-backend/util/xml_renderer.hpp142
697 files changed, 81026 insertions, 12801 deletions
diff --git a/3party/osrm/osrm-backend/.clang-format b/3party/osrm/osrm-backend/.clang-format
deleted file mode 100644
index 47429976bc..0000000000
--- a/3party/osrm/osrm-backend/.clang-format
+++ /dev/null
@@ -1,53 +0,0 @@
----
-Language: Cpp
-# BasedOnStyle: LLVM
-AccessModifierOffset: -2
-ConstructorInitializerIndentWidth: 4
-AlignEscapedNewlinesLeft: false
-AlignTrailingComments: true
-AllowAllParametersOfDeclarationOnNextLine: true
-AllowShortIfStatementsOnASingleLine: false
-AllowShortLoopsOnASingleLine: false
-AllowShortFunctionsOnASingleLine: true
-AlwaysBreakTemplateDeclarations: false
-AlwaysBreakBeforeMultilineStrings: false
-BreakBeforeBinaryOperators: false
-BreakBeforeTernaryOperators: true
-BreakConstructorInitializersBeforeComma: false
-BinPackParameters: false
-ColumnLimit: 100
-ConstructorInitializerAllOnOneLineOrOnePerLine: false
-DerivePointerBinding: false
-ExperimentalAutoDetectBinPacking: false
-IndentCaseLabels: false
-MaxEmptyLinesToKeep: 1
-KeepEmptyLinesAtTheStartOfBlocks: true
-NamespaceIndentation: None
-ObjCSpaceAfterProperty: false
-ObjCSpaceBeforeProtocolList: true
-PenaltyBreakBeforeFirstCallParameter: 19
-PenaltyBreakComment: 300
-PenaltyBreakString: 1000
-PenaltyBreakFirstLessLess: 120
-PenaltyExcessCharacter: 1000
-PenaltyReturnTypeOnItsOwnLine: 60
-PointerBindsToType: false
-SpacesBeforeTrailingComments: 1
-Cpp11BracedListStyle: true
-Standard: Cpp11
-IndentWidth: 4
-TabWidth: 8
-UseTab: Never
-BreakBeforeBraces: Allman
-IndentFunctionDeclarationAfterType: false
-SpacesInParentheses: false
-SpacesInAngles: false
-SpaceInEmptyParentheses: false
-SpacesInCStyleCastParentheses: false
-SpacesInContainerLiterals: true
-SpaceBeforeAssignmentOperators: true
-ContinuationIndentWidth: 4
-CommentPragmas: '^ IWYU pragma:'
-ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
-SpaceBeforeParens: ControlStatements
-...
diff --git a/3party/osrm/osrm-backend/.gitignore b/3party/osrm/osrm-backend/.gitignore
deleted file mode 100644
index 5e8c12d8bc..0000000000
--- a/3party/osrm/osrm-backend/.gitignore
+++ /dev/null
@@ -1,93 +0,0 @@
-# Compiled source #
-###################
-*.com
-*.class
-*.dll
-*.exe
-*.o
-*.so
-
-# Packages #
-############
-# it's better to unpack these files and commit the raw source
-# git has its own built in compression methods
-*.7z
-*.dmg
-*.gz
-*.iso
-*.jar
-*.rar
-*.tar
-*.zip
-
-# Logs and databases #
-######################
-*.log
-*.sql
-*.sqlite
-
-# OS generated files #
-######################
-.DS_Store
-ehthumbs.db
-Icon?
-Thumbs.db
-
-# build related files #
-#######################
-/build/
-/Util/FingerPrint.cpp
-/Util/GitDescription.cpp
-
-# Eclipse related files #
-#########################
-.setting*
-.scb
-.cproject
-.project
-
-# stxxl related files #
-#######################
-.stxxl
-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 #
-####################################
-/win/*.user
-/win/*.ncb
-/win/*.suo
-/win/Debug/
-/win/Release/
-/win/bin/
-/win/bin-debug/
-/osrm-extract
-/osrm-io-benchmark
-/osrm-components
-/osrm-routed
-/osrm-datastore
-/osrm-prepare
-/osrm-unlock-all
-/osrm-cli
-/osrm-check-hsgr
-/nohup.out
-
-# Sandbox folder #
-###################
-/sandbox/
-
-/test/profile.lua
-
-# Deprecated config file #
-##########################
-/server.ini
diff --git a/3party/osrm/osrm-backend/.gitmodules b/3party/osrm/osrm-backend/.gitmodules
deleted file mode 100644
index e69de29bb2..0000000000
--- a/3party/osrm/osrm-backend/.gitmodules
+++ /dev/null
diff --git a/3party/osrm/osrm-backend/.travis.yml b/3party/osrm/osrm-backend/.travis.yml
deleted file mode 100644
index 8817e38747..0000000000
--- a/3party/osrm/osrm-backend/.travis.yml
+++ /dev/null
@@ -1,54 +0,0 @@
-language: cpp
-compiler:
- - gcc
-# - clang
-# Make sure CMake is installed
-install:
- - sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
- - sudo add-apt-repository -y ppa:boost-latest/ppa
- - sudo apt-get update >/dev/null
- - sudo apt-get -q install libprotoc-dev libprotobuf7 libprotobuf-dev libosmpbf-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.7
- - sudo apt-get install libboost1.54-all-dev
- #luabind
- - curl https://gist.githubusercontent.com/DennisOSRM/f2eb7b948e6fe1ae319e/raw/install-luabind.sh | sudo bash
- #osmosis
- - curl -s https://gist.githubusercontent.com/DennisOSRM/803a64a9178ec375069f/raw/ | sudo bash
-before_script:
- - rvm use 1.9.3
- - gem install bundler
- - bundle install
- - mkdir build
- - cd build
- - cmake .. $CMAKEOPTIONS
-script:
- - make -j 2
- - cd ..
- - cucumber -p verify
-after_script:
-# - cd ..
-# - cucumber -p verify
-branches:
- only:
- - master
- - develop
-cache:
-- bundler
-- apt
-env:
- - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-4.7" OSRM_PORT=5000 OSRM_TIMEOUT=60
- - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++-4.7" OSRM_PORT=5010 OSRM_TIMEOUT=60
-notifications:
- irc:
- channels:
- - irc.oftc.net#osrm
- on_success: change
- on_failure: always
- use_notice: true
- skip_join: false
-
- recipients:
- - dennis@mapbox.com
- email:
- on_success: change
- on_failure: always
diff --git a/3party/osrm/osrm-backend/Algorithms/StronglyConnectedComponents.h b/3party/osrm/osrm-backend/Algorithms/StronglyConnectedComponents.h
deleted file mode 100644
index 681f78fa3b..0000000000
--- a/3party/osrm/osrm-backend/Algorithms/StronglyConnectedComponents.h
+++ /dev/null
@@ -1,459 +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 STRONGLYCONNECTEDCOMPONENTS_H_
-#define STRONGLYCONNECTEDCOMPONENTS_H_
-
-#include "../typedefs.h"
-#include "../DataStructures/DeallocatingVector.h"
-#include "../DataStructures/DynamicGraph.h"
-#include "../DataStructures/ImportEdge.h"
-#include "../DataStructures/QueryNode.h"
-#include "../DataStructures/Percent.h"
-#include "../DataStructures/Range.h"
-#include "../DataStructures/Restriction.h"
-#include "../DataStructures/TurnInstructions.h"
-
-#include "../Util/OSRMException.h"
-#include "../Util/simple_logger.hpp"
-#include "../Util/StdHashExtensions.h"
-#include "../Util/TimingUtil.h"
-
-#include <osrm/Coordinate.h>
-
-#include <boost/assert.hpp>
-#include <boost/filesystem.hpp>
-
-#include <tbb/parallel_sort.h>
-
-#ifdef __APPLE__
-#include <gdal.h>
-#include <ogrsf_frmts.h>
-#else
-#include <gdal/gdal.h>
-#include <gdal/ogrsf_frmts.h>
-#endif
-
-#include <cstdint>
-
-#include <memory>
-#include <stack>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-class TarjanSCC
-{
- private:
- struct TarjanNode
- {
- TarjanNode() : index(SPECIAL_NODEID), low_link(SPECIAL_NODEID), on_stack(false) {}
- unsigned index;
- unsigned low_link;
- bool on_stack;
- };
-
- 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;
- unsigned name_id;
- };
-
- struct TarjanStackFrame
- {
- explicit TarjanStackFrame(NodeID v, NodeID parent) : v(v), parent(parent) {}
- NodeID v;
- NodeID parent;
- };
-
- using TarjanDynamicGraph = DynamicGraph<TarjanEdgeData>;
- using TarjanEdge = TarjanDynamicGraph::InputEdge;
- using RestrictionSource = std::pair<NodeID, NodeID>;
- using RestrictionTarget = std::pair<NodeID, bool>;
- using EmanatingRestrictionsVector = std::vector<RestrictionTarget>;
- using RestrictionMap = std::unordered_map<RestrictionSource, unsigned>;
-
- std::vector<NodeInfo> m_coordinate_list;
- std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
- std::shared_ptr<TarjanDynamicGraph> m_node_based_graph;
- std::unordered_set<NodeID> barrier_node_list;
- std::unordered_set<NodeID> traffic_light_list;
- unsigned m_restriction_counter;
- RestrictionMap m_restriction_map;
-
- public:
- TarjanSCC(int number_of_nodes,
- std::vector<NodeBasedEdge> &input_edges,
- std::vector<NodeID> &bn,
- std::vector<NodeID> &tl,
- std::vector<TurnRestriction> &irs,
- std::vector<NodeInfo> &nI)
- : m_coordinate_list(nI), m_restriction_counter(irs.size())
- {
- TIMER_START(SCC_LOAD);
- for (const TurnRestriction &restriction : irs)
- {
- std::pair<NodeID, NodeID> restriction_source = {restriction.fromNode,
- restriction.viaNode};
- unsigned index = 0;
- const auto restriction_iterator = m_restriction_map.find(restriction_source);
- if (restriction_iterator == 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_iterator->second;
- // Map already contains an is_only_*-restriction
- if (m_restriction_bucket_list.at(index).begin()->second)
- {
- continue;
- }
- else if (restriction.flags.isOnly)
- {
- // We are going to insert an is_only_*-restriction. There can be only one.
- m_restriction_bucket_list.at(index).clear();
- }
- }
-
- m_restriction_bucket_list.at(index)
- .emplace_back(restriction.toNode, restriction.flags.isOnly);
- }
-
- barrier_node_list.insert(bn.begin(), bn.end());
- traffic_light_list.insert(tl.begin(), tl.end());
-
- DeallocatingVector<TarjanEdge> edge_list;
- for (const NodeBasedEdge &input_edge : input_edges)
- {
- if (input_edge.source == input_edge.target)
- {
- continue;
- }
-
- if (input_edge.forward)
- {
- 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)
- {
- edge_list.emplace_back(input_edge.target,
- input_edge.source,
- (std::max)((int)input_edge.weight, 1),
- input_edge.name_id);
- }
- }
- input_edges.clear();
- input_edges.shrink_to_fit();
- BOOST_ASSERT_MSG(0 == input_edges.size() && 0 == input_edges.capacity(),
- "input edge vector not properly deallocated");
-
- tbb::parallel_sort(edge_list.begin(), edge_list.end());
- m_node_based_graph = std::make_shared<TarjanDynamicGraph>(number_of_nodes, edge_list);
- TIMER_STOP(SCC_LOAD);
- SimpleLogger().Write() << "Loading data into SCC took " << TIMER_MSEC(SCC_LOAD)/1000. << "s";
- }
-
- ~TarjanSCC() { m_node_based_graph.reset(); }
-
- void Run()
- {
- TIMER_START(SCC_RUN_SETUP);
- // remove files from previous run if exist
- DeleteFileIfExists("component.dbf");
- DeleteFileIfExists("component.shx");
- DeleteFileIfExists("component.shp");
-
- Percent p(m_node_based_graph->GetNumberOfNodes());
-
- OGRRegisterAll();
-
- const char *pszDriverName = "ESRI Shapefile";
- OGRSFDriver *poDriver =
- OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(pszDriverName);
- if (nullptr == poDriver)
- {
- throw OSRMException("ESRI Shapefile driver not available");
- }
- OGRDataSource *poDS = poDriver->CreateDataSource("component.shp", nullptr);
-
- if (nullptr == poDS)
- {
- throw OSRMException("Creation of output file failed");
- }
-
- OGRSpatialReference *poSRS = new OGRSpatialReference();
- poSRS->importFromEPSG(4326);
-
- OGRLayer *poLayer = poDS->CreateLayer("component", poSRS, wkbLineString, nullptr);
-
- if (nullptr == poLayer)
- {
- throw OSRMException("Layer creation failed.");
- }
- TIMER_STOP(SCC_RUN_SETUP);
- SimpleLogger().Write() << "shapefile setup took " << TIMER_MSEC(SCC_RUN_SETUP)/1000. << "s";
-
- TIMER_START(SCC_RUN);
- // The following is a hack to distinguish between stuff that happens
- // before the recursive call and stuff that happens after
- std::stack<TarjanStackFrame> recursion_stack;
- // true = stuff before, false = stuff after call
- std::stack<NodeID> tarjan_stack;
- std::vector<unsigned> components_index(m_node_based_graph->GetNumberOfNodes(),
- SPECIAL_NODEID);
- std::vector<NodeID> component_size_vector;
- std::vector<TarjanNode> tarjan_node_list(m_node_based_graph->GetNumberOfNodes());
- unsigned component_index = 0, size_of_current_component = 0;
- int index = 0;
- const NodeID last_node = m_node_based_graph->GetNumberOfNodes();
- std::vector<bool> 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])
- {
- recursion_stack.emplace(TarjanStackFrame(node, node));
- }
-
- while (!recursion_stack.empty())
- {
- TarjanStackFrame currentFrame = recursion_stack.top();
- const NodeID v = currentFrame.v;
- recursion_stack.pop();
- const bool before_recursion = processing_node_before_recursion[v];
-
- if (before_recursion && tarjan_node_list[v].index != UINT_MAX)
- {
- continue;
- }
-
- if (before_recursion)
- {
- // Mark frame to handle tail of recursion
- recursion_stack.emplace(currentFrame);
- processing_node_before_recursion[v] = false;
-
- // Mark essential information for SCC
- tarjan_node_list[v].index = index;
- tarjan_node_list[v].low_link = index;
- tarjan_stack.push(v);
- tarjan_node_list[v].on_stack = true;
- ++index;
-
- // Traverse outgoing edges
- for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(v))
- {
- const TarjanDynamicGraph::NodeIterator vprime =
- m_node_based_graph->GetTarget(current_edge);
- if (SPECIAL_NODEID == tarjan_node_list[vprime].index)
- {
- recursion_stack.emplace(TarjanStackFrame(vprime, v));
- }
- else
- {
- if (tarjan_node_list[vprime].on_stack &&
- tarjan_node_list[vprime].index < tarjan_node_list[v].low_link)
- {
- tarjan_node_list[v].low_link = tarjan_node_list[vprime].index;
- }
- }
- }
- }
- else
- {
- processing_node_before_recursion[v] = true;
- tarjan_node_list[currentFrame.parent].low_link =
- std::min(tarjan_node_list[currentFrame.parent].low_link,
- tarjan_node_list[v].low_link);
- // after recursion, lets do cycle checking
- // Check if we found a cycle. This is the bottom part of the recursion
- if (tarjan_node_list[v].low_link == tarjan_node_list[v].index)
- {
- NodeID vprime;
- do
- {
- vprime = tarjan_stack.top();
- tarjan_stack.pop();
- tarjan_node_list[vprime].on_stack = false;
- components_index[vprime] = component_index;
- ++size_of_current_component;
- } while (v != vprime);
-
- component_size_vector.emplace_back(size_of_current_component);
-
- if (size_of_current_component > 1000)
- {
- SimpleLogger().Write() << "large component [" << component_index
- << "]=" << size_of_current_component;
- }
-
- ++component_index;
- size_of_current_component = 0;
- }
- }
- }
- }
-
- TIMER_STOP(SCC_RUN);
- SimpleLogger().Write() << "SCC run took: " << TIMER_MSEC(SCC_RUN)/1000. << "s";
- SimpleLogger().Write() << "identified: " << component_size_vector.size()
- << " many components, marking small components";
-
- TIMER_START(SCC_OUTPUT);
-
- const unsigned size_one_counter = std::count_if(component_size_vector.begin(),
- component_size_vector.end(),
- [](unsigned value)
- {
- return 1 == value;
- });
-
- SimpleLogger().Write() << "identified " << size_one_counter << " SCCs of size 1";
-
- uint64_t total_network_distance = 0;
- p.reinit(m_node_based_graph->GetNumberOfNodes());
- // const NodeID last_u_node = m_node_based_graph->GetNumberOfNodes();
- for (const NodeID source : osrm::irange(0u, last_node))
- {
- p.printIncrement();
- for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(source))
- {
- const TarjanDynamicGraph::NodeIterator target =
- m_node_based_graph->GetTarget(current_edge);
-
- if (source < target ||
- m_node_based_graph->EndEdges(target) ==
- m_node_based_graph->FindEdge(target, source))
- {
- total_network_distance +=
- 100 * FixedPointCoordinate::ApproximateEuclideanDistance(
- m_coordinate_list[source].lat,
- m_coordinate_list[source].lon,
- m_coordinate_list[target].lat,
- m_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(component_size_vector[components_index[source]],
- component_size_vector[components_index[target]]);
-
- // edges that end on bollard nodes may actually be in two distinct components
- if (size_of_containing_component < 10)
- {
- OGRLineString lineString;
- lineString.addPoint(m_coordinate_list[source].lon / COORDINATE_PRECISION,
- m_coordinate_list[source].lat / COORDINATE_PRECISION);
- lineString.addPoint(m_coordinate_list[target].lon / COORDINATE_PRECISION,
- m_coordinate_list[target].lat / COORDINATE_PRECISION);
-
- OGRFeature *poFeature = OGRFeature::CreateFeature(poLayer->GetLayerDefn());
-
- poFeature->SetGeometry(&lineString);
- if (OGRERR_NONE != poLayer->CreateFeature(poFeature))
- {
- throw OSRMException("Failed to create feature in shapefile.");
- }
- OGRFeature::DestroyFeature(poFeature);
- }
- }
- }
- }
- OGRDataSource::DestroyDataSource(poDS);
- component_size_vector.clear();
- component_size_vector.shrink_to_fit();
- BOOST_ASSERT_MSG(0 == component_size_vector.size() && 0 == component_size_vector.capacity(),
- "component_size_vector not properly deallocated");
-
- components_index.clear();
- components_index.shrink_to_fit();
- BOOST_ASSERT_MSG(0 == components_index.size() && 0 == components_index.capacity(),
- "components_index not properly deallocated");
- TIMER_STOP(SCC_OUTPUT);
- SimpleLogger().Write() << "generating output took: " << TIMER_MSEC(SCC_OUTPUT)/1000. << "s";
-
- SimpleLogger().Write() << "total network distance: "
- << (uint64_t)total_network_distance / 100 / 1000. << " km";
- }
-
- private:
- unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const
- {
- std::pair<NodeID, NodeID> restriction_source = {u, v};
- const auto restriction_iterator = m_restriction_map.find(restriction_source);
- if (restriction_iterator != m_restriction_map.end())
- {
- const unsigned index = restriction_iterator->second;
- for (const RestrictionSource &restriction_target : m_restriction_bucket_list.at(index))
- {
- if (restriction_target.second)
- {
- return restriction_target.first;
- }
- }
- }
- return SPECIAL_NODEID;
- }
-
- bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const
- {
- // only add an edge if turn is not a U-turn except it is the end of dead-end street.
- std::pair<NodeID, NodeID> restriction_source = {u, v};
- const auto restriction_iterator = m_restriction_map.find(restriction_source);
- if (restriction_iterator != m_restriction_map.end())
- {
- const unsigned index = restriction_iterator->second;
- for (const RestrictionTarget &restriction_target : m_restriction_bucket_list.at(index))
- {
- if (w == restriction_target.first)
- {
- return true;
- }
- }
- }
- return false;
- }
-
- void DeleteFileIfExists(const std::string &file_name) const
- {
- if (boost::filesystem::exists(file_name))
- {
- boost::filesystem::remove(file_name);
- }
- }
-};
-
-#endif /* STRONGLYCONNECTEDCOMPONENTS_H_ */
diff --git a/3party/osrm/osrm-backend/Benchmarks/StaticRTreeBench.cpp b/3party/osrm/osrm-backend/Benchmarks/StaticRTreeBench.cpp
deleted file mode 100644
index b0b34fb6e0..0000000000
--- a/3party/osrm/osrm-backend/Benchmarks/StaticRTreeBench.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-#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 <osrm/Coordinate.h>
-
-#include <random>
-
-// Choosen by a fair W20 dice roll (this value is completely arbitrary)
-constexpr unsigned RANDOM_SEED = 13;
-constexpr int32_t WORLD_MIN_LAT = -90 * COORDINATE_PRECISION;
-constexpr int32_t WORLD_MAX_LAT = 90 * COORDINATE_PRECISION;
-constexpr int32_t WORLD_MIN_LON = -180 * COORDINATE_PRECISION;
-constexpr int32_t WORLD_MAX_LON = 180 * COORDINATE_PRECISION;
-
-using RTreeLeaf = EdgeBasedNode;
-using FixedPointCoordinateListPtr = std::shared_ptr<std::vector<FixedPointCoordinate>>;
-using BenchStaticRTree = StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, false>::vector, false>;
-
-FixedPointCoordinateListPtr LoadCoordinates(const boost::filesystem::path &nodes_file)
-{
- boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary);
-
- NodeInfo current_node;
- unsigned number_of_coordinates = 0;
- nodes_input_stream.read((char *)&number_of_coordinates, sizeof(unsigned));
- auto coords = std::make_shared<std::vector<FixedPointCoordinate>>(number_of_coordinates);
- for (unsigned i = 0; i < number_of_coordinates; ++i)
- {
- nodes_input_stream.read((char *)&current_node, sizeof(NodeInfo));
- coords->at(i) = FixedPointCoordinate(current_node.lat, current_node.lon);
- BOOST_ASSERT((std::abs(coords->at(i).lat) >> 30) == 0);
- BOOST_ASSERT((std::abs(coords->at(i).lon) >> 30) == 0);
- }
- nodes_input_stream.close();
- return coords;
-}
-
-void Benchmark(BenchStaticRTree &rtree, unsigned num_queries)
-{
- std::mt19937 mt_rand(RANDOM_SEED);
- std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT);
- std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON);
- std::vector<FixedPointCoordinate> queries;
- for (unsigned i = 0; i < num_queries; i++)
- {
- queries.emplace_back(FixedPointCoordinate(lat_udist(mt_rand), lon_udist(mt_rand)));
- }
-
- const unsigned num_results = 5;
- std::cout << "#### IncrementalFindPhantomNodeForCoordinate : " << num_results
- << " phantom nodes"
- << "\n";
-
- TIMER_START(query_phantom);
- std::vector<PhantomNode> resulting_phantom_node_vector;
- for (const auto &q : queries)
- {
- resulting_phantom_node_vector.clear();
- rtree.IncrementalFindPhantomNodeForCoordinate(
- q, resulting_phantom_node_vector, 3, num_results);
- resulting_phantom_node_vector.clear();
- rtree.IncrementalFindPhantomNodeForCoordinate(
- q, resulting_phantom_node_vector, 17, num_results);
- }
- TIMER_STOP(query_phantom);
-
- std::cout << "Took " << TIMER_MSEC(query_phantom) << " msec for " << num_queries << " queries."
- << "\n";
- std::cout << TIMER_MSEC(query_phantom) / ((double)num_queries) << " msec/query."
- << "\n";
-
- std::cout << "#### LocateClosestEndPointForCoordinate"
- << "\n";
-
- TIMER_START(query_endpoint);
- FixedPointCoordinate result;
- for (const auto &q : queries)
- {
- rtree.LocateClosestEndPointForCoordinate(q, result, 3);
- }
- TIMER_STOP(query_endpoint);
-
- std::cout << "Took " << TIMER_MSEC(query_endpoint) << " msec for " << num_queries << " queries."
- << "\n";
- std::cout << TIMER_MSEC(query_endpoint) / ((double)num_queries) << " msec/query."
- << "\n";
-
- std::cout << "#### FindPhantomNodeForCoordinate"
- << "\n";
-
- TIMER_START(query_phantomnode);
- for (const auto &q : queries)
- {
- PhantomNode phantom;
- rtree.FindPhantomNodeForCoordinate(q, phantom, 3);
- }
- TIMER_STOP(query_phantomnode);
-
- std::cout << "Took " << TIMER_MSEC(query_phantomnode) << " msec for " << num_queries
- << " queries."
- << "\n";
- std::cout << TIMER_MSEC(query_phantomnode) / ((double)num_queries) << " msec/query."
- << "\n";
-}
-
-int main(int argc, char **argv)
-{
- if (argc < 4)
- {
- std::cout << "./rtree-bench file.ramIndex file.fileIndx file.nodes"
- << "\n";
- return 1;
- }
-
- const char *ramPath = argv[1];
- const char *filePath = argv[2];
- const char *nodesPath = argv[3];
-
- auto coords = LoadCoordinates(nodesPath);
-
- BenchStaticRTree rtree(ramPath, filePath, coords);
-
- Benchmark(rtree, 10000);
-
- return 0;
-}
diff --git a/3party/osrm/osrm-backend/CMakeLists.txt b/3party/osrm/osrm-backend/CMakeLists.txt
index 49af1e6f77..503171a599 100644..100755
--- a/3party/osrm/osrm-backend/CMakeLists.txt
+++ b/3party/osrm/osrm-backend/CMakeLists.txt
@@ -1,22 +1,17 @@
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.")
endif()
-project(OSRM)
+project(OSRM C CXX)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include(CheckCXXCompilerFlag)
include(FindPackageHandleStandardArgs)
-set(OMIM_STORAGE_PATH "../../../storage/")
-set(OMIM_DEBUG_PATH "${CMAKE_SOURCE_DIR}/../../../../omim-build-debug/out/debug")
-set(OMIM_RELEASE_PATH "${CMAKE_SOURCE_DIR}/../../../../omim-build-release/out/release")
-set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
-
-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)
@@ -28,76 +23,89 @@ 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(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)
-include_directories(${CMAKE_SOURCE_DIR}/Include/)
-include_directories(${CMAKE_SOURCE_DIR}/../../jansson/src/)
+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_target(FingerPrintConfigure ALL
${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FingerPrint-Config.cmake
- COMMENT "Configuring FingerPrint.cpp"
+ COMMENT "Configuring revision fingerprint"
VERBATIM)
-set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread)
+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/GitDescription.cpp.in
- ${CMAKE_SOURCE_DIR}/Util/GitDescription.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 ExtractorGlobH Extractor/*.h)
-file(GLOB ImporterGlob DataStructures/Import*.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)
-
-set(ExtractorSources extractor.cpp ${ExtractorGlob} ${ExtractorGlobH})
-add_executable(osrm-extract ${ExtractorSources} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER>)
-
-file(GLOB PrepareGlobH Contractor/*.h DataStructures/*.h)
-file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp DataStructures/RestrictionMap.cpp Util/compute_angle.cpp)
-set(PrepareSources prepare.cpp ${PrepareGlob} ${PrepareGlobH})
-add_executable(osrm-prepare ${PrepareSources} $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER>)
-
-file(GLOB ServerGlob Server/*.cpp)
-file(GLOB RoutingAlgs RoutingAlgorithms/*.h)
-file(GLOB DescriptorGlob Descriptors/*.cpp)
-file(GLOB DatastructureGlob DataStructures/SearchEngineData.cpp DataStructures/RouteParameters.cpp)
-list(REMOVE_ITEM DatastructureGlob DataStructures/Coordinate.cpp)
-file(GLOB CoordinateGlob DataStructures/Coordinate.cpp)
-file(GLOB AlgorithmGlob Algorithms/*.cpp)
-file(GLOB HttpGlob Server/Http/*.cpp)
-file(GLOB LibOSRMGlob Library/*.cpp)
-
-file(GLOB MapsMeSources mapsme/*.cpp)
-file(GLOB MapsMeHeaders mapsme/*.h)
-file(GLOB MapsMeGenerator "${OMIM_STORAGE_PATH}/country.cpp" "${OMIM_STORAGE_PATH}/country_decl.cpp" "${OMIM_STORAGE_PATH}/country_info.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(ANGLE OBJECT util/compute_angle.cpp)
+
+set(ExtractorSources extract.cpp ${ExtractorGlob})
+add_executable(osrm-extract ${ExtractorSources} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
+
+add_library(RESTRICTION OBJECT data_structures/restriction_map.cpp)
+
+file(GLOB PrepareGlob contractor/*.cpp data_structures/hilbert_value.cpp {RestrictionMapGlob})
+set(PrepareSources prepare.cpp ${PrepareGlob})
+add_executable(osrm-prepare ${PrepareSources} $<TARGET_OBJECTS:ANGLE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
+
+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)
+file(GLOB DataStructureTestsGlob unit_tests/data_structures/*.cpp data_structures/hilbert_value.cpp)
+file(GLOB AlgorithmTestsGlob unit_tests/algorithms/*.cpp)
set(
OSRMSources
${LibOSRMGlob}
${DescriptorGlob}
${DatastructureGlob}
- ${CoordinateGlob}
${AlgorithmGlob}
${HttpGlob}
- ${MapsMeGenerator}
)
+
add_library(COORDINATE OBJECT ${CoordinateGlob})
-add_library(FINGERPRINT OBJECT Util/FingerPrint.cpp)
-add_library(GITDESCRIPTION OBJECT Util/GitDescription.cpp)
-add_library(OSRM ${OSRMSources} $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER>)
+add_library(GITDESCRIPTION OBJECT util/git_sha.cpp)
+add_library(OSRM ${OSRMSources} $<TARGET_OBJECTS:ANGLE> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
+
+add_library(FINGERPRINT OBJECT util/fingerprint.cpp)
add_dependencies(FINGERPRINT FingerPrintConfigure)
+add_dependencies(OSRM FingerPrintConfigure)
+set_target_properties(FINGERPRINT PROPERTIES LINKER_LANGUAGE CXX)
-add_executable(osrm-routed routed.cpp ${ServerGlob} ${RoutingAlgs})
-add_executable(osrm-datastore datastore.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER>)
-add_executable(osrm-mapsme ${MapsMeSources} ${MapsMeHeaders} "${CMAKE_SOURCE_DIR}/../../succinct/rs_bit_vector.cpp" $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:COORDINATE>)
+add_executable(osrm-routed routed.cpp ${ServerGlob} $<TARGET_OBJECTS:EXCEPTION>)
+add_executable(osrm-datastore datastore.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
+# Unit tests
+add_executable(datastructure-tests EXCLUDE_FROM_ALL unit_tests/datastructure_tests.cpp ${DataStructureTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
+add_executable(algorithm-tests EXCLUDE_FROM_ALL unit_tests/algorithm_tests.cpp ${AlgorithmTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION>)
+
+# Benchmarks
+add_executable(rtree-bench EXCLUDE_FROM_ALL benchmarks/static_rtree.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
# Check the release mode
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
@@ -105,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")
@@ -115,48 +123,68 @@ 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
+ 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 (HAS_LTO_FLAG)
+ endif()
+endif()
+
+if(NOT WIN32)
+ add_definitions(-DBOOST_TEST_DYN_LINK)
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)
+ set(COLOR_FLAG "")
+ endif()
# using GCC
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -fPIC")
- if (WIN32) # using mingw
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -fPIC ${COLOR_FLAG}")
+ 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_OMP_LIB gomp)
+ 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)
add_definitions(-DNOMINMAX) # avoid min and max macros that can break compilation
add_definitions(-D_USE_MATH_DEFINES) # define M_PI
add_definitions(-D_WIN32_WINNT=0x0501)
+ add_definitions(-DXML_STATIC)
+ find_library(ws2_32_LIBRARY_PATH ws2_32)
+ target_link_libraries(osrm-extract wsock32 ws2_32)
endif()
# Activate C++11
-if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
- ADD_DEFINITIONS(-std=c++11)
+if(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ")
endif()
# Configuring other platform dependencies
@@ -191,35 +219,20 @@ include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(OSRM ${Boost_LIBRARIES})
target_link_libraries(osrm-extract ${Boost_LIBRARIES})
target_link_libraries(osrm-prepare ${Boost_LIBRARIES})
-target_link_libraries(osrm-routed ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM
- debug "${OMIM_DEBUG_PATH}/libcoding.a"
- "${OMIM_DEBUG_PATH}/libbase.a"
- "${OMIM_DEBUG_PATH}/libgeometry.a"
- "${OMIM_DEBUG_PATH}/libindexer.a"
- "${OMIM_DEBUG_PATH}/libjansson.a"
- general "${OMIM_RELEASE_PATH}/libcoding.a"
- "${OMIM_RELEASE_PATH}/libgeometry.a"
- "${OMIM_RELEASE_PATH}/libindexer.a"
- "${OMIM_RELEASE_PATH}/libjansson.a"
- "${OMIM_RELEASE_PATH}/libbase.a")
+target_link_libraries(osrm-routed ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
target_link_libraries(osrm-datastore ${Boost_LIBRARIES})
-
-target_link_libraries(osrm-mapsme ${Boost_LIBRARIES} OSRM
- debug "${OMIM_DEBUG_PATH}/libcoding.a"
- "${OMIM_DEBUG_PATH}/libbase.a"
- "${OMIM_DEBUG_PATH}/librouting.a"
- "${OMIM_DEBUG_PATH}/libgeometry.a"
- "${OMIM_DEBUG_PATH}/libindexer.a"
- general "${OMIM_RELEASE_PATH}/libcoding.a"
- "${OMIM_RELEASE_PATH}/libbase.a"
- "${OMIM_RELEASE_PATH}/librouting.a"
- "${OMIM_RELEASE_PATH}/libgeometry.a"
- "${OMIM_RELEASE_PATH}/libindexer.a")
+target_link_libraries(datastructure-tests ${Boost_LIBRARIES})
+target_link_libraries(algorithm-tests ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
+target_link_libraries(rtree-bench ${Boost_LIBRARIES})
find_package(Threads REQUIRED)
-target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT} ${OPTIONAL_OMP_LIB})
+target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(osrm-datastore ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries(osrm-prepare ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(OSRM ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries(datastructure-tests ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries(algorithm-tests ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries(rtree-bench ${CMAKE_THREAD_LIBS_INIT})
find_package(TBB REQUIRED)
if(WIN32 AND CMAKE_BUILD_TYPE MATCHES Debug)
@@ -229,6 +242,9 @@ target_link_libraries(osrm-datastore ${TBB_LIBRARIES})
target_link_libraries(osrm-extract ${TBB_LIBRARIES})
target_link_libraries(osrm-prepare ${TBB_LIBRARIES})
target_link_libraries(osrm-routed ${TBB_LIBRARIES})
+target_link_libraries(datastructure-tests ${TBB_LIBRARIES})
+target_link_libraries(algorithm-tests ${TBB_LIBRARIES})
+target_link_libraries(rtree-bench ${TBB_LIBRARIES})
include_directories(${TBB_INCLUDE_DIR})
find_package( Luabind REQUIRED )
@@ -238,7 +254,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()
@@ -247,17 +263,24 @@ else()
endif()
include_directories(${LUA_INCLUDE_DIR})
-find_package(LibXml2 REQUIRED)
-include_directories(${LIBXML2_INCLUDE_DIR})
-target_link_libraries(osrm-extract ${LIBXML2_LIBRARIES})
+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})
-find_package( OSMPBF REQUIRED )
+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}")
+endif()
+
+find_package(OSMPBF REQUIRED)
include_directories(${OSMPBF_INCLUDE_DIR})
target_link_libraries(osrm-extract ${OSMPBF_LIBRARY})
target_link_libraries(osrm-prepare ${OSMPBF_LIBRARY})
@@ -276,32 +299,51 @@ 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)
if(GDAL_FOUND)
- add_executable(osrm-components Tools/components.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER>)
+ add_executable(osrm-components tools/components.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
target_link_libraries(osrm-components ${TBB_LIBRARIES})
include_directories(${GDAL_INCLUDE_DIR})
target_link_libraries(
osrm-components
${GDAL_LIBRARIES} ${Boost_LIBRARIES})
+ install(TARGETS osrm-components DESTINATION bin)
else()
message(FATAL_ERROR "libgdal and/or development headers not found")
endif()
- add_executable(osrm-cli Tools/simpleclient.cpp $<TARGET_OBJECTS:LOGGER>)
+ add_executable(osrm-cli tools/simpleclient.cpp $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:COORDINATE>)
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 $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER>)
+ add_executable(osrm-io-benchmark tools/io-benchmark.cpp $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER>)
target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES})
- add_executable(osrm-unlock-all Tools/unlock_all_mutexes.cpp $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER>)
+ add_executable(osrm-unlock-all tools/unlock_all_mutexes.cpp $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION>)
target_link_libraries(osrm-unlock-all ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
if(UNIX AND NOT APPLE)
target_link_libraries(osrm-unlock-all rt)
endif()
+ add_executable(osrm-check-hsgr tools/check-hsgr.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:LOGGER>)
+ target_link_libraries(osrm-check-hsgr ${Boost_LIBRARIES})
+ add_executable(osrm-springclean tools/springclean.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:EXCEPTION>)
+ target_link_libraries(osrm-springclean ${Boost_LIBRARIES})
+ add_executable(osrm-graph-compare tools/graph_compare.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
+ target_link_libraries(osrm-graph-compare ${Boost_LIBRARIES} ${TBB_LIBRARIES})
+
+ install(TARGETS osrm-cli DESTINATION bin)
+ install(TARGETS osrm-io-benchmark DESTINATION bin)
+ install(TARGETS osrm-unlock-all DESTINATION bin)
+ install(TARGETS osrm-check-hsgr DESTINATION bin)
+ install(TARGETS osrm-springclean DESTINATION bin)
endif()
-file(GLOB InstallGlob Include/osrm/*.h 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
# (i.e., from /usr/local/bin/) the linker can find library dependencies. For
@@ -312,6 +354,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)
@@ -320,13 +363,13 @@ 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)
+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)
diff --git a/3party/osrm/osrm-backend/DataStructures/Coordinate.cpp b/3party/osrm/osrm-backend/DataStructures/Coordinate.cpp
deleted file mode 100644
index fee8c9648f..0000000000
--- a/3party/osrm/osrm-backend/DataStructures/Coordinate.cpp
+++ /dev/null
@@ -1,465 +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 <osrm/Coordinate.h>
-
-#include "../Util/MercatorUtil.h"
-#include "../Util/StringUtil.h"
-
-#include <boost/assert.hpp>
-
-#include <iostream>
-#include <limits>
-
-
-FixedPointCoordinate::FixedPointCoordinate()
- : lat(std::numeric_limits<int>::min()), lon(std::numeric_limits<int>::min())
-{
-}
-
-FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon)
-{
-}
-
-void FixedPointCoordinate::Reset()
-{
- lat = std::numeric_limits<int>::min();
- lon = std::numeric_limits<int>::min();
-}
-bool FixedPointCoordinate::isSet() const
-{
- return (std::numeric_limits<int>::min() != lat) && (std::numeric_limits<int>::min() != lon);
-}
-bool FixedPointCoordinate::isValid() 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<int>::min());
- BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
- BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
- BOOST_ASSERT(lon2 != std::numeric_limits<int>::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<int>::min());
- BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
- BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
- BOOST_ASSERT(lon2 != std::numeric_limits<int>::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<float>(lat2y(point.lat / COORDINATE_PRECISION));
- const float y_value = point.lon / COORDINATE_PRECISION;
- float a = static_cast<float>(lat2y(source_coordinate.lat / COORDINATE_PRECISION));
- float b = source_coordinate.lon / COORDINATE_PRECISION;
- float c = static_cast<float>(lat2y(target_coordinate.lat / COORDINATE_PRECISION));
- float d = target_coordinate.lon / COORDINATE_PRECISION;
- float p, q;
- if (std::abs(a - c) > std::numeric_limits<float>::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<float>::epsilon() &&
- std::abs(a) < std::numeric_limits<float>::epsilon())
- {
- ratio = (q - b) / (d - b);
- }
- else
- {
- if (std::abs(c) < std::numeric_limits<float>::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<float>::epsilon())
- {
- ratio = 0.f;
- }
- else if (std::abs(ratio - 1.f) <= std::numeric_limits<float>::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<int>(y2lat(p) * COORDINATE_PRECISION);
- nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
- }
-
- BOOST_ASSERT(nearest_location.isValid());
- 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.isValid());
-
- // 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<double>::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<double>::epsilon())
- {
- ratio = 0.f;
- }
- else if (std::abs(ratio - 1.f) <= std::numeric_limits<double>::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<int>(y2lat(p) * COORDINATE_PRECISION);
- nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
- }
- BOOST_ASSERT(nearest_location.isValid());
-
- 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<float>(M_PI) / 180.f);
-}
-
-float FixedPointCoordinate::RadianToDegree(const float radian)
-{
- return radian * (180.f * static_cast<float>(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<float>(lat2y(input_point.lat / COORDINATE_PRECISION));
- const float y = input_point.lon / COORDINATE_PRECISION;
- const float a = static_cast<float>(lat2y(segment_source.lat / COORDINATE_PRECISION));
- const float b = segment_source.lon / COORDINATE_PRECISION;
- const float c = static_cast<float>(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<int>(q * COORDINATE_PRECISION);
- dy = input_point.lat - static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
- }
-
- // return an approximation in the plane
- return static_cast<int>(sqrt(dx * dx + dy * dy));
-}
diff --git a/3party/osrm/osrm-backend/DataStructures/EdgeBasedNode.h b/3party/osrm/osrm-backend/DataStructures/EdgeBasedNode.h
deleted file mode 100644
index 869ed5bdc9..0000000000
--- a/3party/osrm/osrm-backend/DataStructures/EdgeBasedNode.h
+++ /dev/null
@@ -1,106 +0,0 @@
-#ifndef EDGE_BASED_NODE_H
-#define EDGE_BASED_NODE_H
-
-#include "../DataStructures/TravelMode.h"
-#include "../typedefs.h"
-
-#include "../Include/osrm/Coordinate.h"
-
-#include <boost/assert.hpp>
-
-#include <limits>
-
-struct EdgeBasedNode
-{
-
- EdgeBasedNode() :
- forward_way_id(-1),
- reverse_way_id(-1),
- 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),
- fwd_segment_position( std::numeric_limits<unsigned short>::max() ),
- is_in_tiny_cc(false),
- forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
- backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
- { }
-
- explicit EdgeBasedNode(
- unsigned forward_way_id,
- unsigned reverse_way_id,
- 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 short fwd_segment_position,
- bool belongs_to_tiny_component,
- TravelMode forward_travel_mode,
- TravelMode backward_travel_mode
- ) :
- forward_way_id(forward_way_id),
- reverse_way_id(reverse_way_id),
- 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),
- fwd_segment_position(fwd_segment_position),
- is_in_tiny_cc(belongs_to_tiny_component),
- 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)
- {
- FixedPointCoordinate centroid;
- //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;
- }
-
- unsigned forward_way_id;
- unsigned reverse_way_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
- unsigned packed_geometry_id; // if set, then the edge represents a packed geometry
- unsigned short fwd_segment_position; // segment id in a compressed geometry
- bool is_in_tiny_cc;
- TravelMode forward_travel_mode : 4;
- TravelMode backward_travel_mode : 4;
-};
-
-#endif //EDGE_BASED_NODE_H
diff --git a/3party/osrm/osrm-backend/DataStructures/EdgeBasedNodeData.h b/3party/osrm/osrm-backend/DataStructures/EdgeBasedNodeData.h
deleted file mode 100644
index dbcadfe01b..0000000000
--- a/3party/osrm/osrm-backend/DataStructures/EdgeBasedNodeData.h
+++ /dev/null
@@ -1,123 +0,0 @@
-#pragma once
-
-#include <stdint.h>
-#include <vector>
-#include <fstream>
-
-
-namespace osrm
-{
-
-struct NodeData
-{
-#pragma pack (push, 1)
- struct SegmentInfo
- {
- uint64_t wayId;
- double lat1, lon1, lat2, lon2;
-
- SegmentInfo()
- : wayId(-1), lat1(-10000), lon1(-10000), lat2(-10000), lon2(-10000)
- {
- }
-
- SegmentInfo(uint64_t wayId, double lat1, double lon1, double lat2, double lon2)
- : wayId(wayId), lat1(lat1), lon1(lon1), lat2(lat2), lon2(lon2)
- {
- }
-
- bool operator != (SegmentInfo const & other) const
- {
- return wayId != other.wayId || lat1 != other.lat1 || lon1 != other.lon1 ||
- lat2 != other.lat2 || lon2 != other.lon2;
- }
- };
-#pragma pack (pop)
-
- typedef std::vector<SegmentInfo> SegmentInfoVectorT;
- SegmentInfoVectorT m_segments;
-
- NodeData()
- {
- }
-
- NodeData(SegmentInfoVectorT & vec)
- {
- m_segments.swap(vec);
- }
-
- bool operator == (NodeData const & other) const
- {
- if (m_segments.size() != other.m_segments.size())
- return false;
-
- for (uint32_t i = 0; i < m_segments.size(); ++i)
- if (m_segments[i] != other.m_segments[i])
- return false;
-
- return true;
- }
-
- bool operator != (NodeData const & other) const
- {
- return !(*this == other);
- }
-
- void AddSegment(uint64_t wayId, double lat1, double lon1, double lat2, double lon2)
- {
- m_segments.emplace_back(wayId, lat1, lon1, lat2, lon2);
- }
-
- void SetSegments(SegmentInfoVectorT & segments)
- {
- m_segments.swap(segments);
- }
-};
-
-
-typedef std::vector<NodeData> NodeDataVectorT;
-
-inline bool SaveNodeDataToFile(std::string const & filename, NodeDataVectorT const & data)
-{
- std::ofstream stream;
- stream.open(filename);
- if (!stream.is_open())
- return false;
-
- uint32_t count = data.size();
- stream.write((char*)&count, sizeof(count));
- for (auto d : data)
- {
- uint32_t pc = d.m_segments.size();
- stream.write((char*)&pc, sizeof(pc));
- stream.write((char*)d.m_segments.data(), sizeof(NodeData::SegmentInfo) * pc);
- }
- stream.close();
- return true;
-}
-
-inline bool LoadNodeDataFromFile(std::string const & filename, NodeDataVectorT & data)
-{
- std::ifstream stream;
- stream.open(filename);
- if (!stream.is_open())
- return false;
-
- uint32_t count = 0;
- stream.read((char*)&count, sizeof(count));
- for (uint32_t i = 0; i < count; ++i)
- {
- uint32_t pc;
- stream.read((char*)&pc, sizeof(pc));
- NodeData::SegmentInfoVectorT segments;
- segments.resize(pc);
- stream.read((char*)segments.data(), sizeof(NodeData::SegmentInfo) * pc);
-
- data.emplace_back(segments);
- }
- stream.close();
-
- return true;
-}
-
-}
diff --git a/3party/osrm/osrm-backend/DataStructures/InputReaderFactory.h b/3party/osrm/osrm-backend/DataStructures/InputReaderFactory.h
deleted file mode 100644
index 3f6aa3c63b..0000000000
--- a/3party/osrm/osrm-backend/DataStructures/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 <boost/assert.hpp>
-
-#include <bzlib.h>
-#include <libxml/xmlreader.h>
-
-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
diff --git a/3party/osrm/osrm-backend/DataStructures/PhantomNodes.h b/3party/osrm/osrm-backend/DataStructures/PhantomNodes.h
deleted file mode 100644
index 88028a67be..0000000000
--- a/3party/osrm/osrm-backend/DataStructures/PhantomNodes.h
+++ /dev/null
@@ -1,181 +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 PHANTOM_NODES_H
-#define PHANTOM_NODES_H
-
-#include "../Include/osrm/Coordinate.h"
-#include "../DataStructures/TravelMode.h"
-#include "../Util/simple_logger.hpp"
-#include "../typedefs.h"
-
-#include <vector>
-
-struct 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, 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),
- location(location),
- fwd_segment_position(fwd_segment_position),
- forward_travel_mode(forward_travel_mode),
- backward_travel_mode(backward_travel_mode)
- { }
-
- PhantomNode() :
- forward_node_id(SPECIAL_NODEID),
- reverse_node_id(SPECIAL_NODEID),
- name_id(std::numeric_limits<unsigned>::max()),
- forward_weight(INVALID_EDGE_WEIGHT),
- reverse_weight(INVALID_EDGE_WEIGHT),
- forward_offset(0),
- reverse_offset(0),
- packed_geometry_id(SPECIAL_EDGEID),
- fwd_segment_position(0),
- forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
- backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
- { }
-
- 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;
- FixedPointCoordinate location;
- unsigned short fwd_segment_position;
- TravelMode forward_travel_mode : 4;
- TravelMode backward_travel_mode : 4;
-
- int GetForwardWeightPlusOffset() const
- {
- if (SPECIAL_NODEID == forward_node_id)
- {
- return 0;
- }
- const int result = (forward_offset + forward_weight);
- return result;
- }
-
- int GetReverseWeightPlusOffset() const
- {
- if (SPECIAL_NODEID == reverse_node_id)
- {
- return 0;
- }
- const int result = (reverse_offset + reverse_weight);
- return result;
- }
-
- bool isBidirected() const
- {
- return (forward_node_id != SPECIAL_NODEID) &&
- (reverse_node_id != SPECIAL_NODEID);
- }
-
- bool IsCompressed() const
- {
- return (forward_offset != 0) || (reverse_offset != 0);
- }
-
- bool isValid(const unsigned numberOfNodes) const
- {
- return
- location.isValid() &&
- (
- (forward_node_id < numberOfNodes) ||
- (reverse_node_id < numberOfNodes)
- ) &&
- (
- (forward_weight != INVALID_EDGE_WEIGHT) ||
- (reverse_weight != INVALID_EDGE_WEIGHT)
- ) &&
- (name_id != std::numeric_limits<unsigned>::max()
- );
- }
-
- bool isValid() const
- {
- return location.isValid() &&
- (name_id != std::numeric_limits<unsigned>::max());
- }
-
- bool operator==(const PhantomNode & other) const
- {
- return location == other.location;
- }
-};
-
-using PhantomNodeArray = std::vector<std::vector<PhantomNode>>;
-
-struct PhantomNodeLists
-{
- std::vector<PhantomNode> source_phantom_list;
- std::vector<PhantomNode> target_phantom_list;
-};
-
-struct PhantomNodes
-{
- PhantomNode source_phantom;
- PhantomNode target_phantom;
-};
-
-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)
-{
- 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 << ", " <<
- "pos: " << pn.fwd_segment_position << ", " <<
- "loc: " << pn.location;
- return out;
-}
-
-#endif // PHANTOM_NODES_H
diff --git a/3party/osrm/osrm-backend/Descriptors/DescriptionFactory.cpp b/3party/osrm/osrm-backend/Descriptors/DescriptionFactory.cpp
deleted file mode 100644
index 715bf69037..0000000000
--- a/3party/osrm/osrm-backend/Descriptors/DescriptionFactory.cpp
+++ /dev/null
@@ -1,126 +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 "DescriptionFactory.h"
-
-#include <osrm/Coordinate.h>
-
-#include "../typedefs.h"
-#include "../Algorithms/PolylineCompressor.h"
-#include "../DataStructures/PhantomNodes.h"
-#include "../DataStructures/RawRouteData.h"
-#include "../DataStructures/SegmentInformation.h"
-#include "../DataStructures/TurnInstructions.h"
-
-DescriptionFactory::DescriptionFactory() : entireLength(0) { via_indices.push_back(0); }
-
-std::vector<unsigned> const &DescriptionFactory::GetViaIndices() const { return via_indices; }
-
-void DescriptionFactory::SetStartSegment(const PhantomNode &source, const bool traversed_in_reverse)
-{
- start_phantom = source;
- const EdgeWeight segment_duration =
- (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));
- BOOST_ASSERT(path_description.back().duration == segment_duration);
-}
-
-void DescriptionFactory::SetEndSegment(const PhantomNode &target,
- const bool traversed_in_reverse,
- const bool is_via_location)
-{
- target_phantom = target;
- const EdgeWeight segment_duration =
- (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,
- is_via_location ? TurnInstruction::ReachViaLocation
- : TurnInstruction::NoTurn,
- true,
- true,
- travel_mode);
- BOOST_ASSERT(path_description.back().duration == segment_duration);
-}
-
-void DescriptionFactory::AppendSegment(const FixedPointCoordinate &coordinate,
- const PathData &path_point)
-{
- // if the start location is on top of a node, the first movement might be zero-length,
- // in which case we dont' add a new description, but instead update the existing one
- if ((1 == path_description.size()) && (path_description.front().location == coordinate))
- {
- if (path_point.segment_duration > 0)
- {
- path_description.front().name_id = path_point.name_id;
- path_description.front().travel_mode = path_point.travel_mode;
- }
- return;
- }
-
- // make sure mode changes are announced, even when there otherwise is no turn
- const TurnInstruction turn = [&]() -> TurnInstruction
- {
- if (TurnInstruction::NoTurn == path_point.turn_instruction &&
- path_description.front().travel_mode != path_point.travel_mode &&
- path_point.segment_duration > 0)
- {
- return TurnInstruction::GoStraight;
- }
- 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);
-}
-
-JSON::Value DescriptionFactory::AppendGeometryString(const bool return_encoded)
-{
- if (return_encoded)
- {
- return polyline_compressor.printEncodedString(path_description);
- }
- return polyline_compressor.printUnencodedString(path_description);
-}
-
-void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time)
-{
- summary.source_name_id = start_phantom.name_id;
- summary.target_name_id = target_phantom.name_id;
- summary.BuildDurationAndLengthStrings(distance, time);
-}
diff --git a/3party/osrm/osrm-backend/Descriptors/DescriptionFactory.h b/3party/osrm/osrm-backend/Descriptors/DescriptionFactory.h
deleted file mode 100644
index ac4c70234f..0000000000
--- a/3party/osrm/osrm-backend/Descriptors/DescriptionFactory.h
+++ /dev/null
@@ -1,218 +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 DESCRIPTIONFACTORY_H_
-#define DESCRIPTIONFACTORY_H_
-
-#include "../Algorithms/DouglasPeucker.h"
-#include "../Algorithms/PolylineCompressor.h"
-#include "../DataStructures/PhantomNodes.h"
-#include "../DataStructures/SegmentInformation.h"
-#include "../DataStructures/TurnInstructions.h"
-#include "../typedefs.h"
-
-#include <osrm/Coordinate.h>
-
-#include <limits>
-#include <vector>
-
-struct PathData;
-/* This class is fed with all way segments in consecutive order
- * and produces the description plus the encoded polyline */
-
-class DescriptionFactory
-{
- DouglasPeucker polyline_generalizer;
- PolylineCompressor polyline_compressor;
- PhantomNode start_phantom, target_phantom;
-
- double DegreeToRadian(const double degree) const;
- double RadianToDegree(const double degree) const;
-
- std::vector<unsigned> via_indices;
-
- public:
- struct RouteSummary
- {
- unsigned distance;
- EdgeWeight duration;
- unsigned source_name_id;
- unsigned target_name_id;
- RouteSummary() : distance(0), duration(0), source_name_id(0), target_name_id(0) {}
-
- void BuildDurationAndLengthStrings(const double raw_distance, const unsigned raw_duration)
- {
- // compute distance/duration for route summary
- distance = static_cast<unsigned>(round(raw_distance));
- duration = static_cast<unsigned>(round(raw_duration / 10.));
- }
- } summary;
-
- double entireLength;
-
- // I know, declaring this public is considered bad. I'm lazy
- std::vector<SegmentInformation> path_description;
- DescriptionFactory();
- void AppendSegment(const FixedPointCoordinate &coordinate, const PathData &data);
- void BuildRouteSummary(const double distance, const unsigned time);
- void SetStartSegment(const PhantomNode &start_phantom, const bool traversed_in_reverse);
- void SetEndSegment(const PhantomNode &start_phantom,
- const bool traversed_in_reverse,
- const bool is_via_location = false);
- JSON::Value AppendGeometryString(const bool return_encoded);
- std::vector<unsigned> const &GetViaIndices() const;
-
- template <class DataFacadeT> 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)
- {
- entireLength += 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<double>::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<double>::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, 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<unsigned>(angle * 10);
- }
- }
- via_indices.push_back(necessary_pieces + 1);
- BOOST_ASSERT(via_indices.size() >= 2);
- // BOOST_ASSERT(0 != necessary_pieces || path_description.empty());
- return;
- }
-};
-
-#endif /* DESCRIPTIONFACTORY_H_ */
diff --git a/3party/osrm/osrm-backend/Descriptors/GPXDescriptor.h b/3party/osrm/osrm-backend/Descriptors/GPXDescriptor.h
deleted file mode 100644
index 6f76b3bc87..0000000000
--- a/3party/osrm/osrm-backend/Descriptors/GPXDescriptor.h
+++ /dev/null
@@ -1,101 +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 GPX_DESCRIPTOR_H
-#define GPX_DESCRIPTOR_H
-
-#include "BaseDescriptor.h"
-
-template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<DataFacadeT>
-{
- private:
- DescriptorConfig config;
- FixedPointCoordinate current;
- DataFacadeT *facade;
-
- void AddRoutePoint(const FixedPointCoordinate &coordinate, std::vector<char> &output)
- {
- const std::string route_point_head = "<rtept lat=\"";
- const std::string route_point_middle = " lon=\"";
- const std::string route_point_tail = "\"></rtept>";
-
- std::string tmp;
-
- FixedPointCoordinate::convertInternalLatLonToString(coordinate.lat, tmp);
- output.insert(output.end(), route_point_head.begin(), route_point_head.end());
- output.insert(output.end(), tmp.begin(), tmp.end());
- output.push_back('\"');
-
- FixedPointCoordinate::convertInternalLatLonToString(coordinate.lon, tmp);
- output.insert(output.end(), route_point_middle.begin(), route_point_middle.end());
- output.insert(output.end(), tmp.begin(), tmp.end());
- output.insert(output.end(), route_point_tail.begin(), route_point_tail.end());
- }
-
- public:
- explicit GPXDescriptor(DataFacadeT *facade) : facade(facade) {}
-
- void SetConfig(const DescriptorConfig &c) final { config = c; }
-
- // TODO: reorder parameters
- void Run(const RawRouteData &raw_route, http::Reply &reply) final
- {
- std::string header("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
- "<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
- "xmlns=\"http://www.topografix.com/GPX/1/1\" "
- "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
- "xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
- "\">"
- "<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
- " OpenStreetMap contributors (ODbL)</license></copyright>"
- "</metadata>"
- "<rte>");
- reply.content.insert(reply.content.end(), header.begin(), header.end());
- const bool found_route = (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT) &&
- (!raw_route.unpacked_path_segments.front().empty());
- if (found_route)
- {
- AddRoutePoint(raw_route.segment_end_coordinates.front().source_phantom.location,
- reply.content);
-
- for (const std::vector<PathData> &path_data_vector : raw_route.unpacked_path_segments)
- {
- for (const PathData &path_data : path_data_vector)
- {
- const FixedPointCoordinate current_coordinate =
- facade->GetCoordinateOfNode(path_data.node);
- AddRoutePoint(current_coordinate, reply.content);
- }
- }
- AddRoutePoint(raw_route.segment_end_coordinates.back().target_phantom.location,
- reply.content);
- }
- std::string footer("</rte></gpx>");
- reply.content.insert(reply.content.end(), footer.begin(), footer.end());
- }
-};
-#endif // GPX_DESCRIPTOR_H
diff --git a/3party/osrm/osrm-backend/Docs/webclient.txt b/3party/osrm/osrm-backend/Docs/webclient.txt
deleted file mode 100644
index 55fcd15b8e..0000000000
--- a/3party/osrm/osrm-backend/Docs/webclient.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-The javascript based web client is a seperate project available at
-
-https://github.com/DennisSchiefer/Project-OSRM-Web \ No newline at end of file
diff --git a/3party/osrm/osrm-backend/Extractor/BaseParser.cpp b/3party/osrm/osrm-backend/Extractor/BaseParser.cpp
deleted file mode 100644
index 20c864556b..0000000000
--- a/3party/osrm/osrm-backend/Extractor/BaseParser.cpp
+++ /dev/null
@@ -1,140 +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 "BaseParser.h"
-#include "ExtractionWay.h"
-#include "ScriptingEnvironment.h"
-
-#include "../DataStructures/ImportNode.h"
-#include "../Util/LuaUtil.h"
-#include "../Util/OSRMException.h"
-#include "../Util/simple_logger.hpp"
-
-#include <boost/algorithm/string.hpp>
-#include <boost/algorithm/string/regex.hpp>
-#include <boost/ref.hpp>
-#include <boost/regex.hpp>
-
-BaseParser::BaseParser(ExtractorCallbacks *extractor_callbacks,
- ScriptingEnvironment &scripting_environment)
- : extractor_callbacks(extractor_callbacks),
- lua_state(scripting_environment.getLuaState()),
- scripting_environment(scripting_environment), use_turn_restrictions(true)
-{
- ReadUseRestrictionsSetting();
- ReadRestrictionExceptions();
-}
-
-void BaseParser::ReadUseRestrictionsSetting()
-{
- if (0 != luaL_dostring(lua_state, "return use_turn_restrictions\n"))
- {
- use_turn_restrictions = false;
- }
- else if (lua_isboolean(lua_state, -1))
- {
- use_turn_restrictions = lua_toboolean(lua_state, -1);
- }
-
- if (use_turn_restrictions)
- {
- SimpleLogger().Write() << "Using turn restrictions";
- }
- else
- {
- SimpleLogger().Write() << "Ignoring turn restrictions";
- }
-}
-
-void BaseParser::ReadRestrictionExceptions()
-{
- if (lua_function_exists(lua_state, "get_exceptions"))
- {
- // get list of turn restriction exceptions
- luabind::call_function<void>(
- lua_state, "get_exceptions", boost::ref(restriction_exceptions));
- const unsigned exception_count = restriction_exceptions.size();
- SimpleLogger().Write() << "Found " << exception_count
- << " exceptions to turn restrictions:";
- for (const std::string &str : restriction_exceptions)
- {
- SimpleLogger().Write() << " " << str;
- }
- }
- else
- {
- SimpleLogger().Write() << "Found no exceptions to turn restrictions";
- }
-}
-
-void BaseParser::report_errors(lua_State *lua_state, const int status) const
-{
- if (0 != status)
- {
- std::cerr << "-- " << lua_tostring(lua_state, -1) << std::endl;
- lua_pop(lua_state, 1); // remove error message
- }
-}
-
-void BaseParser::ParseNodeInLua(ImportNode &node, lua_State *local_lua_state)
-{
- luabind::call_function<void>(local_lua_state, "node_function", boost::ref(node));
-}
-
-void BaseParser::ParseWayInLua(ExtractionWay &way, lua_State *local_lua_state)
-{
- luabind::call_function<void>(local_lua_state, "way_function", boost::ref(way));
-}
-
-bool BaseParser::ShouldIgnoreRestriction(const std::string &except_tag_string) const
-{
- // should this restriction be ignored? yes if there's an overlap between:
- // a) the list of modes in the except tag of the restriction
- // (except_tag_string), eg: except=bus;bicycle
- // b) the lua profile defines a hierachy of modes,
- // eg: [access, vehicle, bicycle]
-
- if (except_tag_string.empty())
- {
- return false;
- }
-
- // Be warned, this is quadratic work here, but we assume that
- // only a few exceptions are actually defined.
- std::vector<std::string> exceptions;
- boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*"));
- for (std::string &current_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;
-}
diff --git a/3party/osrm/osrm-backend/Extractor/BaseParser.h b/3party/osrm/osrm-backend/Extractor/BaseParser.h
deleted file mode 100644
index b18da34311..0000000000
--- a/3party/osrm/osrm-backend/Extractor/BaseParser.h
+++ /dev/null
@@ -1,67 +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 BASEPARSER_H_
-#define BASEPARSER_H_
-
-#include <string>
-#include <vector>
-
-struct lua_State;
-class ExtractorCallbacks;
-class ScriptingEnvironment;
-struct ExtractionWay;
-struct ImportNode;
-
-class BaseParser
-{
- public:
- BaseParser() = delete;
- BaseParser(const BaseParser &) = delete;
- BaseParser(ExtractorCallbacks *extractor_callbacks,
- ScriptingEnvironment &scripting_environment);
- virtual ~BaseParser() {}
- virtual bool ReadHeader() = 0;
- virtual bool Parse() = 0;
-
- virtual void ParseNodeInLua(ImportNode &node, lua_State *lua_state);
- virtual void ParseWayInLua(ExtractionWay &way, lua_State *lua_state);
- virtual void report_errors(lua_State *lua_state, const int status) const;
-
- protected:
- virtual void ReadUseRestrictionsSetting();
- virtual void ReadRestrictionExceptions();
- virtual bool ShouldIgnoreRestriction(const std::string &except_tag_string) const;
-
- ExtractorCallbacks *extractor_callbacks;
- lua_State *lua_state;
- ScriptingEnvironment &scripting_environment;
- std::vector<std::string> restriction_exceptions;
- bool use_turn_restrictions;
-};
-
-#endif /* BASEPARSER_H_ */
diff --git a/3party/osrm/osrm-backend/Extractor/ExtractionHelperFunctions.h b/3party/osrm/osrm-backend/Extractor/ExtractionHelperFunctions.h
deleted file mode 100644
index b053338fd0..0000000000
--- a/3party/osrm/osrm-backend/Extractor/ExtractionHelperFunctions.h
+++ /dev/null
@@ -1,90 +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 EXTRACTION_HELPER_FUNCTIONS_H
-#define EXTRACTION_HELPER_FUNCTIONS_H
-
-#include "../Util/cast.hpp"
-
-#include <boost/algorithm/string.hpp>
-#include <boost/algorithm/string_regex.hpp>
-#include <boost/spirit/include/qi.hpp>
-#include <boost/regex.hpp>
-
-#include <limits>
-
-namespace qi = boost::spirit::qi;
-
-// TODO: Move into LUA
-
-inline bool durationIsValid(const std::string &s)
-{
- 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<std::string> result;
- boost::algorithm::split_regex(result, s, boost::regex(":"));
- const bool matched = regex_match(s, e);
- return matched;
-}
-
-inline 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<std::string> result;
- boost::algorithm::split_regex(result, s, boost::regex(":"));
- const bool matched = regex_match(s, e);
- if (matched)
- {
- 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);
- }
- return std::numeric_limits<unsigned>::max();
-}
-
-#endif // EXTRACTION_HELPER_FUNCTIONS_H_
diff --git a/3party/osrm/osrm-backend/Extractor/Extractor.cpp b/3party/osrm/osrm-backend/Extractor/Extractor.cpp
deleted file mode 100644
index c9c870bf15..0000000000
--- a/3party/osrm/osrm-backend/Extractor/Extractor.cpp
+++ /dev/null
@@ -1,305 +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 "Extractor.h"
-
-#include "ExtractorCallbacks.h"
-#include "ExtractionContainers.h"
-#include "PBFParser.h"
-#include "ScriptingEnvironment.h"
-#include "XMLParser.h"
-
-#include "../Util/GitDescription.h"
-#include "../Util/IniFileUtil.h"
-#include "../Util/OSRMException.h"
-#include "../Util/simple_logger.hpp"
-#include "../Util/TimingUtil.h"
-#include "../typedefs.h"
-
-#include <boost/program_options.hpp>
-
-#include <tbb/task_scheduler_init.h>
-
-#include <cstdlib>
-
-#include <chrono>
-#include <fstream>
-#include <iostream>
-#include <thread>
-#include <unordered_map>
-
-Extractor::Extractor() : requested_num_threads(0), file_has_pbf_format(false)
-{
-}
-
-Extractor::~Extractor() {}
-
-bool Extractor::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<boost::filesystem::path>(&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
- boost::program_options::options_description config_options("Configuration");
- config_options.add_options()("profile,p",
- boost::program_options::value<boost::filesystem::path>(
- &profile_path)->default_value("profile.lua"),
- "Path to LUA routing profile")(
- "threads,t",
- boost::program_options::value<unsigned int>(&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
- std::string string_input_path;
- boost::program_options::options_description hidden_options("Hidden options");
- hidden_options.add_options()(
- "input,i",
- boost::program_options::value<std::string>(&string_input_path),
- "Input file in .osm, .osm.bz2 or .osm.pbf format");
-
- // positional option
- boost::program_options::positional_options_description positional_options;
- positional_options.add("input", 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]) + " <input.osm/.osm.bz2/.osm.pbf> [options]");
- 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);
-
- // parse config file
- if (boost::filesystem::is_regular_file(config_file_path))
- {
- SimpleLogger().Write() << "Reading options from: " << config_file_path.string();
- std::string ini_file_contents = ReadIniFileAndLowerContents(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 false;
- }
-
- input_path = boost::filesystem::path(string_input_path);
-
- return true;
-}
-
-void Extractor::GenerateOutputFilesNames()
-{
- output_file_name = input_path.string();
- restriction_file_name = input_path.string();
- std::string::size_type pos = output_file_name.find(".osm.bz2");
- if (pos == std::string::npos)
- {
- pos = output_file_name.find(".osm.pbf");
- if (pos != std::string::npos)
- {
- file_has_pbf_format = true;
- }
- else
- {
- pos = output_file_name.find(".osm.xml");
- }
- }
- if (pos == std::string::npos)
- {
- pos = output_file_name.find(".pbf");
- if (pos != std::string::npos)
- {
- file_has_pbf_format = true;
- }
- }
- if (pos == std::string::npos)
- {
- pos = output_file_name.find(".osm");
- if (pos == std::string::npos)
- {
- output_file_name.append(".osrm");
- restriction_file_name.append(".osrm.restrictions");
- }
- else
- {
- output_file_name.replace(pos, 5, ".osrm");
- restriction_file_name.replace(pos, 5, ".osrm.restrictions");
- }
- }
- else
- {
- output_file_name.replace(pos, 8, ".osrm");
- restriction_file_name.replace(pos, 8, ".osrm.restrictions");
- }
-}
-
-int Extractor::Run(int argc, char *argv[])
-{
- try
- {
- LogPolicy::GetInstance().Unmute();
-
- TIMER_START(extracting);
-
- if (!ParseArguments(argc, argv))
- return 0;
-
- if (1 > requested_num_threads)
- {
- SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
- return 1;
- }
-
- if (!boost::filesystem::is_regular_file(input_path))
- {
- SimpleLogger().Write(logWARNING) << "Input file " << input_path.string()
- << " not found!";
- return 1;
- }
-
- if (!boost::filesystem::is_regular_file(profile_path))
- {
- SimpleLogger().Write(logWARNING) << "Profile " << profile_path.string()
- << " not found!";
- return 1;
- }
-
- const unsigned recommended_num_threads = tbb::task_scheduler_init::default_num_threads();
-
- SimpleLogger().Write() << "Input file: " << input_path.filename().string();
- SimpleLogger().Write() << "Profile: " << profile_path.filename().string();
- SimpleLogger().Write() << "Threads: " << requested_num_threads;
- if (recommended_num_threads != requested_num_threads)
- {
- SimpleLogger().Write(logWARNING) << "The recommended number of threads is "
- << recommended_num_threads
- << "! This setting may have performance side-effects.";
- }
-
- tbb::task_scheduler_init init(requested_num_threads);
-
- /*** Setup Scripting Environment ***/
- ScriptingEnvironment scripting_environment(profile_path.string().c_str());
-
- GenerateOutputFilesNames();
-
- std::unordered_map<std::string, NodeID> string_map;
- ExtractionContainers extraction_containers;
-
- string_map[""] = 0;
- auto extractor_callbacks = new ExtractorCallbacks(extraction_containers, string_map);
- BaseParser *parser;
- if (file_has_pbf_format)
- {
- parser = new PBFParser(input_path.string().c_str(),
- extractor_callbacks,
- scripting_environment,
- requested_num_threads);
- }
- else
- {
- parser = new XMLParser(input_path.string().c_str(),
- extractor_callbacks,
- scripting_environment);
- }
-
- if (!parser->ReadHeader())
- {
- throw OSRMException("Parser not initialized!");
- }
-
- SimpleLogger().Write() << "Parsing in progress..";
- TIMER_START(parsing);
-
- parser->Parse();
- delete parser;
- delete extractor_callbacks;
-
- TIMER_STOP(parsing);
- SimpleLogger().Write() << "Parsing finished after " << TIMER_SEC(parsing) << " seconds";
-
- if (extraction_containers.all_edges_list.empty())
- {
- SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
- return 1;
- }
-
- extraction_containers.PrepareData(output_file_name, restriction_file_name);
-
- TIMER_STOP(extracting);
- SimpleLogger().Write() << "extraction finished after " << TIMER_SEC(extracting) << "s";
- SimpleLogger().Write() << "To prepare the data for routing, run: "
- << "./osrm-prepare " << output_file_name << std::endl;
- }
- catch (boost::program_options::too_many_positional_options_error &)
- {
- SimpleLogger().Write(logWARNING) << "Only one input file can be specified";
- return 1;
- }
- catch (std::exception &e)
- {
- SimpleLogger().Write(logWARNING) << e.what();
- return 1;
- }
- return 0;
-}
diff --git a/3party/osrm/osrm-backend/Extractor/Extractor.h b/3party/osrm/osrm-backend/Extractor/Extractor.h
deleted file mode 100644
index 70c943a06a..0000000000
--- a/3party/osrm/osrm-backend/Extractor/Extractor.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef EXTRACTOR_H_
-#define EXTRACTOR_H_
-
-#include <boost/filesystem.hpp>
-
-#include <string>
-
-class ExtractorCallbacks;
-
-/** \brief Class of 'extract' utility. */
-class Extractor
-{
- protected:
- unsigned requested_num_threads;
- boost::filesystem::path config_file_path;
- boost::filesystem::path input_path;
- boost::filesystem::path profile_path;
-
- std::string output_file_name;
- std::string restriction_file_name;
- bool file_has_pbf_format;
-
- /** \brief Parses "extractor's" command line arguments */
- bool ParseArguments(int argc, char *argv[]);
-
- /** \brief Parses config file, if present in options */
- void GenerateOutputFilesNames();
-
- public:
- explicit Extractor();
- Extractor(const Extractor &) = delete;
- virtual ~Extractor();
-
- int Run(int argc, char *argv[]);
-};
-#endif /* EXTRACTOR_H_ */
diff --git a/3party/osrm/osrm-backend/Extractor/ExtractorCallbacks.cpp b/3party/osrm/osrm-backend/Extractor/ExtractorCallbacks.cpp
deleted file mode 100644
index d607d41da0..0000000000
--- a/3party/osrm/osrm-backend/Extractor/ExtractorCallbacks.cpp
+++ /dev/null
@@ -1,184 +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 "ExtractorCallbacks.h"
-#include "ExtractionContainers.h"
-#include "ExtractionWay.h"
-
-#include "../DataStructures/Restriction.h"
-#include "../DataStructures/ImportNode.h"
-#include "../Util/simple_logger.hpp"
-
-#include <osrm/Coordinate.h>
-
-#include <limits>
-#include <string>
-#include <vector>
-
-ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers,
- std::unordered_map<std::string, NodeID> &string_map)
- : string_map(string_map), external_memory(extraction_containers)
-{
-}
-
-/** warning: caller needs to take care of synchronization! */
-void ExtractorCallbacks::ProcessNode(const ExternalMemoryNode &n)
-{
- if (n.lat <= 85 * COORDINATE_PRECISION && n.lat >= -85 * COORDINATE_PRECISION)
- {
- external_memory.all_nodes_list.push_back(n);
- }
-}
-
-bool ExtractorCallbacks::ProcessRestriction(const InputRestrictionContainer &restriction)
-{
- external_memory.restrictions_list.push_back(restriction);
- return true;
-}
-
-/** warning: caller needs to take care of synchronization! */
-void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way)
-{
- if (((0 >= parsed_way.forward_speed) ||
- (TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode)) &&
- ((0 >= parsed_way.backward_speed) ||
- (TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode)) &&
- (0 >= parsed_way.duration))
- { // Only true if the way is specified by the speed profile
- return;
- }
-
- if (parsed_way.path.size() <= 1)
- { // safe-guard against broken data
- return;
- }
-
- if (std::numeric_limits<unsigned>::max() == parsed_way.id)
- {
- SimpleLogger().Write(logDEBUG) << "found bogus way with id: " << parsed_way.id
- << " of size " << parsed_way.path.size();
- return;
- }
-
- if (0 < parsed_way.duration)
- {
- // TODO: iterate all way segments and set duration corresponding to the length of each
- // segment
- parsed_way.forward_speed = parsed_way.duration / (parsed_way.path.size() - 1);
- parsed_way.backward_speed = parsed_way.duration / (parsed_way.path.size() - 1);
- }
-
- if (std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.forward_speed))
- {
- SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << parsed_way.id;
- return;
- }
-
- // Get the unique identifier for the street name
- const auto &string_map_iterator = string_map.find(parsed_way.name);
- if (string_map.end() == string_map_iterator)
- {
- parsed_way.nameID = external_memory.name_list.size();
- external_memory.name_list.push_back(parsed_way.name);
- string_map.insert(std::make_pair(parsed_way.name, parsed_way.nameID));
- }
- else
- {
- parsed_way.nameID = string_map_iterator->second;
- }
-
- if (TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode)
- {
- std::reverse(parsed_way.path.begin(), parsed_way.path.end());
- parsed_way.forward_travel_mode = parsed_way.backward_travel_mode;
- parsed_way.backward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
- }
-
- const bool split_edge =
- (parsed_way.forward_speed>0) && (TRAVEL_MODE_INACCESSIBLE != parsed_way.forward_travel_mode) &&
- (parsed_way.backward_speed>0) && (TRAVEL_MODE_INACCESSIBLE != parsed_way.backward_travel_mode) &&
- ((parsed_way.forward_speed != parsed_way.backward_speed) ||
- (parsed_way.forward_travel_mode != parsed_way.backward_travel_mode));
-
- BOOST_ASSERT(parsed_way.forward_travel_mode>0);
- for (unsigned n = 0; n < (parsed_way.path.size() - 1); ++n)
- {
- external_memory.all_edges_list.push_back(InternalExtractorEdge(
- parsed_way.id,
- parsed_way.path[n],
- parsed_way.path[n + 1],
- ((split_edge || TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode) ? ExtractionWay::oneway
- : ExtractionWay::bidirectional),
- parsed_way.forward_speed,
- parsed_way.nameID,
- parsed_way.roundabout,
- parsed_way.ignoreInGrid,
- (0 < parsed_way.duration),
- parsed_way.isAccessRestricted,
- parsed_way.forward_travel_mode,
- split_edge));
- external_memory.used_node_id_list.push_back(parsed_way.path[n]);
- }
- external_memory.used_node_id_list.push_back(parsed_way.path.back());
-
- // The following information is needed to identify start and end segments of restrictions
- external_memory.way_start_end_id_list.push_back(
- WayIDStartAndEndEdge(parsed_way.id,
- parsed_way.path[0],
- parsed_way.path[1],
- parsed_way.path[parsed_way.path.size() - 2],
- parsed_way.path.back()));
-
- if (split_edge)
- { // Only true if the way should be split
- BOOST_ASSERT(parsed_way.backward_travel_mode>0);
- std::reverse(parsed_way.path.begin(), parsed_way.path.end());
-
- for (std::vector<NodeID>::size_type n = 0; n < parsed_way.path.size() - 1; ++n)
- {
- external_memory.all_edges_list.push_back(
- InternalExtractorEdge(parsed_way.id,
- parsed_way.path[n],
- parsed_way.path[n + 1],
- ExtractionWay::oneway,
- parsed_way.backward_speed,
- parsed_way.nameID,
- parsed_way.roundabout,
- parsed_way.ignoreInGrid,
- (0 < parsed_way.duration),
- parsed_way.isAccessRestricted,
- parsed_way.backward_travel_mode,
- split_edge));
- }
- external_memory.way_start_end_id_list.push_back(
- WayIDStartAndEndEdge(parsed_way.id,
- parsed_way.path[0],
- parsed_way.path[1],
- parsed_way.path[parsed_way.path.size() - 2],
- parsed_way.path.back()));
- }
-}
diff --git a/3party/osrm/osrm-backend/Extractor/ExtractorStructs.h b/3party/osrm/osrm-backend/Extractor/ExtractorStructs.h
deleted file mode 100644
index a3c6f3eaf5..0000000000
--- a/3party/osrm/osrm-backend/Extractor/ExtractorStructs.h
+++ /dev/null
@@ -1,114 +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 EXTRACTORSTRUCTS_H_
-#define EXTRACTORSTRUCTS_H_
-
-#include "../DataStructures/HashTable.h"
-#include "../DataStructures/ImportNode.h"
-#include "../typedefs.h"
-
-#include <limits>
-#include <string>
-
-struct ExtractorRelation
-{
- ExtractorRelation() : type(unknown) {}
- enum
- { unknown = 0,
- ferry,
- turnRestriction } type;
- HashTable<std::string, std::string> keyVals;
-};
-
-struct WayIDStartAndEndEdge
-{
- unsigned wayID;
- NodeID firstStart;
- NodeID firstTarget;
- NodeID lastStart;
- NodeID lastTarget;
- WayIDStartAndEndEdge()
- : wayID(std::numeric_limits<unsigned>::max()), firstStart(std::numeric_limits<unsigned>::max()), firstTarget(std::numeric_limits<unsigned>::max()), lastStart(std::numeric_limits<unsigned>::max()),
- lastTarget(std::numeric_limits<unsigned>::max())
- {
- }
-
- explicit WayIDStartAndEndEdge(unsigned w, NodeID fs, NodeID ft, NodeID ls, NodeID lt)
- : wayID(w), firstStart(fs), firstTarget(ft), lastStart(ls), lastTarget(lt)
- {
- }
-
- static WayIDStartAndEndEdge min_value()
- {
- return WayIDStartAndEndEdge((std::numeric_limits<unsigned>::min)(),
- (std::numeric_limits<unsigned>::min)(),
- (std::numeric_limits<unsigned>::min)(),
- (std::numeric_limits<unsigned>::min)(),
- (std::numeric_limits<unsigned>::min)());
- }
- static WayIDStartAndEndEdge max_value()
- {
- return WayIDStartAndEndEdge((std::numeric_limits<unsigned>::max)(),
- (std::numeric_limits<unsigned>::max)(),
- (std::numeric_limits<unsigned>::max)(),
- (std::numeric_limits<unsigned>::max)(),
- (std::numeric_limits<unsigned>::max)());
- }
-};
-
-struct CmpWayByID
-{
- using value_type = WayIDStartAndEndEdge;
- bool operator()(const WayIDStartAndEndEdge &a, const WayIDStartAndEndEdge &b) const
- {
- return a.wayID < b.wayID;
- }
- value_type max_value() { return WayIDStartAndEndEdge::max_value(); }
- value_type min_value() { return WayIDStartAndEndEdge::min_value(); }
-};
-
-struct Cmp
-{
- using value_type = NodeID;
- bool operator()(const NodeID left, const NodeID right) const { return left < right; }
- value_type max_value() { return 0xffffffff; }
- value_type min_value() { return 0x0; }
-};
-
-struct CmpNodeByID
-{
- using value_type = ExternalMemoryNode;
- bool operator()(const ExternalMemoryNode &left, const ExternalMemoryNode &right) const
- {
- return left.node_id < right.node_id;
- }
- value_type max_value() { return ExternalMemoryNode::max_value(); }
- value_type min_value() { return ExternalMemoryNode::min_value(); }
-};
-
-#endif /* EXTRACTORSTRUCTS_H_ */
diff --git a/3party/osrm/osrm-backend/Extractor/PBFParser.cpp b/3party/osrm/osrm-backend/Extractor/PBFParser.cpp
deleted file mode 100644
index fd489533f1..0000000000
--- a/3party/osrm/osrm-backend/Extractor/PBFParser.cpp
+++ /dev/null
@@ -1,665 +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 "PBFParser.h"
-
-#include "ExtractionWay.h"
-#include "ExtractorCallbacks.h"
-#include "ScriptingEnvironment.h"
-
-#include "../DataStructures/HashTable.h"
-#include "../DataStructures/ImportNode.h"
-#include "../DataStructures/Restriction.h"
-#include "../Util/MachineInfo.h"
-#include "../Util/OSRMException.h"
-#include "../Util/simple_logger.hpp"
-#include "../typedefs.h"
-
-#include <boost/assert.hpp>
-
-#include <tbb/parallel_for.h>
-#include <tbb/task_scheduler_init.h>
-
-#include <osrm/Coordinate.h>
-
-#include <zlib.h>
-
-#include <functional>
-#include <iostream>
-#include <limits>
-#include <thread>
-
-PBFParser::PBFParser(const char *fileName,
- ExtractorCallbacks *extractor_callbacks,
- ScriptingEnvironment &scripting_environment,
- unsigned num_threads)
- : BaseParser(extractor_callbacks, scripting_environment)
-{
- if (0 == num_threads)
- {
- num_parser_threads = tbb::task_scheduler_init::default_num_threads();
- }
- else
- {
- num_parser_threads = num_threads;
- }
-
- GOOGLE_PROTOBUF_VERIFY_VERSION;
- // TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
- // NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
-
- // Max 2500 items in queue, hardcoded.
- thread_data_queue = std::make_shared<ConcurrentQueue<ParserThreadData *>>(2500);
- input.open(fileName, std::ios::in | std::ios::binary);
-
- if (!input)
- {
- throw OSRMException("pbf file not found.");
- }
-
- block_count = 0;
- group_count = 0;
-}
-
-PBFParser::~PBFParser()
-{
- if (input.is_open())
- {
- input.close();
- }
-
- // Clean up any leftover ThreadData objects in the queue
- ParserThreadData *thread_data;
- while (thread_data_queue->try_pop(thread_data))
- {
- delete thread_data;
- }
- google::protobuf::ShutdownProtobufLibrary();
-
- SimpleLogger().Write(logDEBUG) << "parsed " << block_count << " blocks from pbf with "
- << group_count << " groups";
-}
-
-inline bool PBFParser::ReadHeader()
-{
- ParserThreadData init_data;
- /** read Header */
- if (!readPBFBlobHeader(input, &init_data))
- {
- return false;
- }
-
- if (readBlob(input, &init_data))
- {
- if (!init_data.PBFHeaderBlock.ParseFromArray(&(init_data.charBuffer[0]),
- static_cast<int>(init_data.charBuffer.size())))
- {
- std::cerr << "[error] Header not parseable!" << std::endl;
- return false;
- }
-
- const auto feature_size = init_data.PBFHeaderBlock.required_features_size();
- for (int i = 0; i < feature_size; ++i)
- {
- const std::string &feature = init_data.PBFHeaderBlock.required_features(i);
- bool supported = false;
- if ("OsmSchema-V0.6" == feature)
- {
- supported = true;
- }
- else if ("DenseNodes" == feature)
- {
- supported = true;
- }
-
- if (!supported)
- {
- std::cerr << "[error] required feature not supported: " << feature.data()
- << std::endl;
- return false;
- }
- }
- }
- else
- {
- std::cerr << "[error] blob not loaded!" << std::endl;
- }
- return true;
-}
-
-inline void PBFParser::ReadData()
-{
- bool keep_running = true;
- do
- {
- ParserThreadData *thread_data = new ParserThreadData();
- keep_running = readNextBlock(input, thread_data);
-
- if (keep_running)
- {
- thread_data_queue->push(thread_data);
- }
- else
- {
- // No more data to read, parse stops when nullptr encountered
- thread_data_queue->push(nullptr);
- delete thread_data;
- }
- } while (keep_running);
-}
-
-inline void PBFParser::ParseData()
-{
- tbb::task_scheduler_init init(num_parser_threads);
-
- while (true)
- {
- ParserThreadData *thread_data;
- thread_data_queue->wait_and_pop(thread_data);
- if (nullptr == thread_data)
- {
- thread_data_queue->push(nullptr); // Signal end of data for other threads
- break;
- }
-
- loadBlock(thread_data);
-
- int group_size = thread_data->PBFprimitiveBlock.primitivegroup_size();
- for (int i = 0; i < group_size; ++i)
- {
- thread_data->currentGroupID = i;
- loadGroup(thread_data);
-
- if (thread_data->entityTypeIndicator == TypeNode)
- {
- parseNode(thread_data);
- }
- if (thread_data->entityTypeIndicator == TypeWay)
- {
- parseWay(thread_data);
- }
- if (thread_data->entityTypeIndicator == TypeRelation)
- {
- parseRelation(thread_data);
- }
- if (thread_data->entityTypeIndicator == TypeDenseNode)
- {
- parseDenseNode(thread_data);
- }
- }
-
- delete thread_data;
- thread_data = nullptr;
- }
-}
-
-inline bool PBFParser::Parse()
-{
- // Start the read and parse threads
- std::thread read_thread(std::bind(&PBFParser::ReadData, this));
-
- // Open several parse threads that are synchronized before call to
- std::thread parse_thread(std::bind(&PBFParser::ParseData, this));
-
- // Wait for the threads to finish
- read_thread.join();
- parse_thread.join();
-
- return true;
-}
-
-inline void PBFParser::parseDenseNode(ParserThreadData *thread_data)
-{
- const OSMPBF::DenseNodes &dense =
- thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).dense();
- int denseTagIndex = 0;
- int64_t m_lastDenseID = 0;
- int64_t m_lastDenseLatitude = 0;
- int64_t m_lastDenseLongitude = 0;
-
- const int number_of_nodes = dense.id_size();
- std::vector<ImportNode> extracted_nodes_vector(number_of_nodes);
- for (int i = 0; i < number_of_nodes; ++i)
- {
- m_lastDenseID += dense.id(i);
- m_lastDenseLatitude += dense.lat(i);
- m_lastDenseLongitude += dense.lon(i);
- extracted_nodes_vector[i].node_id = static_cast<NodeID>(m_lastDenseID);
- extracted_nodes_vector[i].lat = static_cast<int>(
- COORDINATE_PRECISION *
- ((double)m_lastDenseLatitude * thread_data->PBFprimitiveBlock.granularity() +
- thread_data->PBFprimitiveBlock.lat_offset()) /
- NANO);
- extracted_nodes_vector[i].lon = static_cast<int>(
- COORDINATE_PRECISION *
- ((double)m_lastDenseLongitude * thread_data->PBFprimitiveBlock.granularity() +
- thread_data->PBFprimitiveBlock.lon_offset()) /
- NANO);
- while (denseTagIndex < dense.keys_vals_size())
- {
- const int tagValue = dense.keys_vals(denseTagIndex);
- if (0 == tagValue)
- {
- ++denseTagIndex;
- break;
- }
- const int keyValue = dense.keys_vals(denseTagIndex + 1);
- const std::string &key = thread_data->PBFprimitiveBlock.stringtable().s(tagValue);
- const std::string &value = thread_data->PBFprimitiveBlock.stringtable().s(keyValue);
- extracted_nodes_vector[i].keyVals.Add(std::move(key), std::move(value));
- denseTagIndex += 2;
- }
- }
-
- tbb::parallel_for(tbb::blocked_range<size_t>(0, extracted_nodes_vector.size()),
- [this, &extracted_nodes_vector](const tbb::blocked_range<size_t> &range)
- {
- lua_State *lua_state = this->scripting_environment.getLuaState();
- for (size_t i = range.begin(); i != range.end(); ++i)
- {
- ImportNode &import_node = extracted_nodes_vector[i];
- ParseNodeInLua(import_node, lua_state);
- }
- });
-
- for (const ImportNode &import_node : extracted_nodes_vector)
- {
- extractor_callbacks->ProcessNode(import_node);
- }
-}
-
-inline void PBFParser::parseNode(ParserThreadData *)
-{
- throw OSRMException("Parsing of simple nodes not supported. PBF should use dense nodes");
-}
-
-inline void PBFParser::parseRelation(ParserThreadData *thread_data)
-{
- // TODO: leave early, if relation is not a restriction
- // TODO: reuse rawRestriction container
- if (!use_turn_restrictions)
- {
- return;
- }
- const OSMPBF::PrimitiveGroup &group =
- thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID);
-
- for (int i = 0, relation_size = group.relations_size(); i < relation_size; ++i)
- {
- std::string except_tag_string;
- const OSMPBF::Relation &inputRelation =
- thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).relations(i);
- bool is_restriction = false;
- bool is_only_restriction = false;
- for (int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k)
- {
- const std::string &key =
- thread_data->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k));
- const std::string &val =
- thread_data->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k));
- if ("type" == key)
- {
- if ("restriction" == val)
- {
- is_restriction = true;
- }
- else
- {
- break;
- }
- }
- if (("restriction" == key) && (val.find("only_") == 0))
- {
- is_only_restriction = true;
- }
- if ("except" == key)
- {
- except_tag_string = val;
- }
- }
-
- if (is_restriction && ShouldIgnoreRestriction(except_tag_string))
- {
- continue;
- }
-
- if (is_restriction)
- {
- int64_t last_ref = 0;
- InputRestrictionContainer current_restriction_container(is_only_restriction);
- for (int rolesIndex = 0, last_role = inputRelation.roles_sid_size();
- rolesIndex < last_role;
- ++rolesIndex)
- {
- const std::string &role = thread_data->PBFprimitiveBlock.stringtable().s(
- inputRelation.roles_sid(rolesIndex));
- last_ref += inputRelation.memids(rolesIndex);
-
- if (!("from" == role || "to" == role || "via" == role))
- {
- continue;
- }
-
- switch (inputRelation.types(rolesIndex))
- {
- case 0: // node
- if ("from" == role || "to" == role)
- { // Only via should be a node
- continue;
- }
- BOOST_ASSERT("via" == role);
- if (std::numeric_limits<unsigned>::max() !=
- current_restriction_container.viaNode)
- {
- current_restriction_container.viaNode =
- std::numeric_limits<unsigned>::max();
- }
- BOOST_ASSERT(std::numeric_limits<unsigned>::max() ==
- current_restriction_container.viaNode);
- current_restriction_container.restriction.viaNode =
- static_cast<NodeID>(last_ref);
- break;
- case 1: // way
- BOOST_ASSERT("from" == role || "to" == role || "via" == role);
- if ("from" == role)
- {
- current_restriction_container.fromWay = static_cast<EdgeID>(last_ref);
- }
- if ("to" == role)
- {
- current_restriction_container.toWay = static_cast<EdgeID>(last_ref);
- }
- if ("via" == role)
- {
- BOOST_ASSERT(current_restriction_container.restriction.toNode ==
- std::numeric_limits<unsigned>::max());
- current_restriction_container.viaNode = static_cast<NodeID>(last_ref);
- }
- break;
- case 2: // relation, not used. relations relating to relations are evil.
- continue;
- BOOST_ASSERT(false);
- break;
-
- default: // should not happen
- BOOST_ASSERT(false);
- break;
- }
- }
- if (!extractor_callbacks->ProcessRestriction(current_restriction_container))
- {
- std::cerr << "[PBFParser] relation not parsed" << std::endl;
- }
- }
- }
-}
-
-inline void PBFParser::parseWay(ParserThreadData *thread_data)
-{
- const int number_of_ways =
- thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).ways_size();
- std::vector<ExtractionWay> parsed_way_vector(number_of_ways);
- for (int i = 0; i < number_of_ways; ++i)
- {
- const OSMPBF::Way &input_way =
- thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).ways(i);
- parsed_way_vector[i].id = static_cast<EdgeID>(input_way.id());
- unsigned node_id_in_path = 0;
- const auto number_of_referenced_nodes = input_way.refs_size();
- for (auto j = 0; j < number_of_referenced_nodes; ++j)
- {
- node_id_in_path += static_cast<NodeID>(input_way.refs(j));
- parsed_way_vector[i].path.push_back(node_id_in_path);
- }
- BOOST_ASSERT(input_way.keys_size() == input_way.vals_size());
- const auto number_of_keys = input_way.keys_size();
- for (auto j = 0; j < number_of_keys; ++j)
- {
- const std::string &key =
- thread_data->PBFprimitiveBlock.stringtable().s(input_way.keys(j));
- const std::string &val =
- thread_data->PBFprimitiveBlock.stringtable().s(input_way.vals(j));
- parsed_way_vector[i].keyVals.Add(std::move(key), std::move(val));
- }
- }
-
- // TODO: investigate if schedule guided will be handled by tbb automatically
- tbb::parallel_for(tbb::blocked_range<size_t>(0, parsed_way_vector.size()),
- [this, &parsed_way_vector](const tbb::blocked_range<size_t> &range)
- {
- lua_State *lua_state = this->scripting_environment.getLuaState();
- for (size_t i = range.begin(); i != range.end(); i++)
- {
- ExtractionWay &extraction_way = parsed_way_vector[i];
- if (2 <= extraction_way.path.size())
- {
- ParseWayInLua(extraction_way, lua_state);
- }
- }
- });
-
- for (ExtractionWay &extraction_way : parsed_way_vector)
- {
- if (2 <= extraction_way.path.size())
- {
- extractor_callbacks->ProcessWay(extraction_way);
- }
- }
-}
-
-inline void PBFParser::loadGroup(ParserThreadData *thread_data)
-{
-#ifndef NDEBUG
- ++group_count;
-#endif
-
- const OSMPBF::PrimitiveGroup &group =
- thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID);
- thread_data->entityTypeIndicator = TypeDummy;
- if (0 != group.nodes_size())
- {
- thread_data->entityTypeIndicator = TypeNode;
- }
- if (0 != group.ways_size())
- {
- thread_data->entityTypeIndicator = TypeWay;
- }
- if (0 != group.relations_size())
- {
- thread_data->entityTypeIndicator = TypeRelation;
- }
- if (group.has_dense())
- {
- thread_data->entityTypeIndicator = TypeDenseNode;
- BOOST_ASSERT(0 != group.dense().id_size());
- }
- BOOST_ASSERT(thread_data->entityTypeIndicator != TypeDummy);
-}
-
-inline void PBFParser::loadBlock(ParserThreadData *thread_data)
-{
- ++block_count;
- thread_data->currentGroupID = 0;
- thread_data->currentEntityID = 0;
-}
-
-inline bool PBFParser::readPBFBlobHeader(std::fstream &stream, ParserThreadData *thread_data)
-{
- int size(0);
- stream.read((char *)&size, sizeof(int));
- size = SwapEndian(size);
- if (stream.eof())
- {
- return false;
- }
- if (size > MAX_BLOB_HEADER_SIZE || size < 0)
- {
- return false;
- }
- char *data = new char[size];
- stream.read(data, size * sizeof(data[0]));
-
- bool dataSuccessfullyParsed = (thread_data->PBFBlobHeader).ParseFromArray(data, size);
- delete[] data;
- return dataSuccessfullyParsed;
-}
-
-inline bool PBFParser::unpackZLIB(ParserThreadData *thread_data)
-{
- auto raw_size = thread_data->PBFBlob.raw_size();
- char *unpacked_data_array = new char[raw_size];
- z_stream compressed_data_stream;
- compressed_data_stream.next_in = (unsigned char *)thread_data->PBFBlob.zlib_data().data();
- compressed_data_stream.avail_in = thread_data->PBFBlob.zlib_data().size();
- compressed_data_stream.next_out = (unsigned char *)unpacked_data_array;
- compressed_data_stream.avail_out = raw_size;
- compressed_data_stream.zalloc = Z_NULL;
- compressed_data_stream.zfree = Z_NULL;
- compressed_data_stream.opaque = Z_NULL;
- int return_code = inflateInit(&compressed_data_stream);
- if (return_code != Z_OK)
- {
- std::cerr << "[error] failed to init zlib stream" << std::endl;
- delete[] unpacked_data_array;
- return false;
- }
-
- return_code = inflate(&compressed_data_stream, Z_FINISH);
- if (return_code != Z_STREAM_END)
- {
- std::cerr << "[error] failed to inflate zlib stream" << std::endl;
- std::cerr << "[error] Error type: " << return_code << std::endl;
- delete[] unpacked_data_array;
- return false;
- }
-
- return_code = inflateEnd(&compressed_data_stream);
- if (return_code != Z_OK)
- {
- std::cerr << "[error] failed to deinit zlib stream" << std::endl;
- delete[] unpacked_data_array;
- return false;
- }
-
- thread_data->charBuffer.clear();
- thread_data->charBuffer.resize(raw_size);
- std::copy(unpacked_data_array, unpacked_data_array + raw_size, thread_data->charBuffer.begin());
- delete[] unpacked_data_array;
- return true;
-}
-
-inline bool PBFParser::unpackLZMA(ParserThreadData *) { return false; }
-
-inline bool PBFParser::readBlob(std::fstream &stream, ParserThreadData *thread_data)
-{
- if (stream.eof())
- {
- return false;
- }
-
- const int size = thread_data->PBFBlobHeader.datasize();
- if (size < 0 || size > MAX_BLOB_SIZE)
- {
- std::cerr << "[error] invalid Blob size:" << size << std::endl;
- return false;
- }
-
- char *data = new char[size];
- stream.read(data, sizeof(data[0]) * size);
-
- if (!thread_data->PBFBlob.ParseFromArray(data, size))
- {
- std::cerr << "[error] failed to parse blob" << std::endl;
- delete[] data;
- return false;
- }
-
- if (thread_data->PBFBlob.has_raw())
- {
- const std::string &data = thread_data->PBFBlob.raw();
- thread_data->charBuffer.clear();
- thread_data->charBuffer.resize(data.size());
- std::copy(data.begin(), data.end(), thread_data->charBuffer.begin());
- }
- else if (thread_data->PBFBlob.has_zlib_data())
- {
- if (!unpackZLIB(thread_data))
- {
- std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl;
- delete[] data;
- return false;
- }
- }
- else if (thread_data->PBFBlob.has_lzma_data())
- {
- if (!unpackLZMA(thread_data))
- {
- std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl;
- }
- delete[] data;
- return false;
- }
- else
- {
- std::cerr << "[error] Blob contains no data" << std::endl;
- delete[] data;
- return false;
- }
- delete[] data;
- return true;
-}
-
-bool PBFParser::readNextBlock(std::fstream &stream, ParserThreadData *thread_data)
-{
- if (stream.eof())
- {
- return false;
- }
-
- if (!readPBFBlobHeader(stream, thread_data))
- {
- return false;
- }
-
- if (thread_data->PBFBlobHeader.type() != "OSMData")
- {
- return false;
- }
-
- if (!readBlob(stream, thread_data))
- {
- return false;
- }
-
- if (!thread_data->PBFprimitiveBlock.ParseFromArray(&(thread_data->charBuffer[0]),
- thread_data->charBuffer.size()))
- {
- std::cerr << "failed to parse PrimitiveBlock" << std::endl;
- return false;
- }
- return true;
-}
diff --git a/3party/osrm/osrm-backend/Extractor/PBFParser.h b/3party/osrm/osrm-backend/Extractor/PBFParser.h
deleted file mode 100644
index c65a29d406..0000000000
--- a/3party/osrm/osrm-backend/Extractor/PBFParser.h
+++ /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.
-
-*/
-
-#ifndef PBFPARSER_H_
-#define PBFPARSER_H_
-
-#include "BaseParser.h"
-#include "../DataStructures/ConcurrentQueue.h"
-
-#include <osmpbf/fileformat.pb.h>
-#include <osmpbf/osmformat.pb.h>
-
-#include <fstream>
-#include <memory>
-
-class PBFParser : public BaseParser
-{
-
- enum EntityType
- { TypeDummy = 0,
- TypeNode = 1,
- TypeWay = 2,
- TypeRelation = 4,
- TypeDenseNode = 8 };
-
- struct ParserThreadData
- {
- int currentGroupID;
- int currentEntityID;
- EntityType entityTypeIndicator;
-
- OSMPBF::BlobHeader PBFBlobHeader;
- OSMPBF::Blob PBFBlob;
-
- OSMPBF::HeaderBlock PBFHeaderBlock;
- OSMPBF::PrimitiveBlock PBFprimitiveBlock;
-
- std::vector<char> charBuffer;
- };
-
- public:
- PBFParser(const char *file_name,
- ExtractorCallbacks *extractor_callbacks,
- ScriptingEnvironment &scripting_environment,
- unsigned num_parser_threads = 0);
- virtual ~PBFParser();
-
- inline bool ReadHeader();
- inline bool Parse();
-
- private:
- inline void ReadData();
- inline void ParseData();
- inline void parseDenseNode(ParserThreadData *thread_data);
- inline void parseNode(ParserThreadData *thread_data);
- inline void parseRelation(ParserThreadData *thread_data);
- inline void parseWay(ParserThreadData *thread_data);
-
- inline void loadGroup(ParserThreadData *thread_data);
- inline void loadBlock(ParserThreadData *thread_data);
- inline bool readPBFBlobHeader(std::fstream &stream, ParserThreadData *thread_data);
- inline bool unpackZLIB(ParserThreadData *thread_data);
- inline bool unpackLZMA(ParserThreadData *thread_data);
- inline bool readBlob(std::fstream &stream, ParserThreadData *thread_data);
- inline bool readNextBlock(std::fstream &stream, ParserThreadData *thread_data);
-
- static const int NANO = 1000 * 1000 * 1000;
- static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
- static const int MAX_BLOB_SIZE = 32 * 1024 * 1024;
-
- unsigned group_count;
- unsigned block_count;
-
- std::fstream input; // the input stream to parse
- std::shared_ptr<ConcurrentQueue<ParserThreadData *>> thread_data_queue;
- unsigned num_parser_threads;
-};
-
-#endif /* PBFPARSER_H_ */
diff --git a/3party/osrm/osrm-backend/Extractor/ScriptingEnvironment.cpp b/3party/osrm/osrm-backend/Extractor/ScriptingEnvironment.cpp
deleted file mode 100644
index 3ecb0c4664..0000000000
--- a/3party/osrm/osrm-backend/Extractor/ScriptingEnvironment.cpp
+++ /dev/null
@@ -1,121 +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 "ScriptingEnvironment.h"
-
-#include "ExtractionHelperFunctions.h"
-#include "ExtractionWay.h"
-#include "../DataStructures/ImportNode.h"
-#include "../Util/LuaUtil.h"
-#include "../Util/OSRMException.h"
-#include "../Util/simple_logger.hpp"
-#include "../typedefs.h"
-
-#include <sstream>
-
-ScriptingEnvironment::ScriptingEnvironment() {}
-ScriptingEnvironment::ScriptingEnvironment(const char *file_name)
-: file_name(file_name)
-{
- SimpleLogger().Write() << "Using script " << file_name;
-}
-
-void ScriptingEnvironment::initLuaState(lua_State* lua_state)
-{
- luabind::open(lua_state);
- // open utility libraries string library;
- luaL_openlibs(lua_state);
-
- luaAddScriptFolderToLoadPath(lua_state, file_name.c_str());
-
- // Add our function to the state's global scope
- luabind::module(lua_state)[
- luabind::def("print", LUA_print<std::string>),
- luabind::def("durationIsValid", durationIsValid),
- luabind::def("parseDuration", parseDuration),
-
- luabind::class_<HashTable<std::string, std::string>>("keyVals")
- .def("Add", &HashTable<std::string, std::string>::Add)
- .def("Find", &HashTable<std::string, std::string>::Find)
- .def("Holds", &HashTable<std::string, std::string>::Holds),
-
- luabind::class_<ImportNode>("Node")
- // .def(luabind::constructor<>())
- .def_readwrite("lat", &ImportNode::lat)
- .def_readwrite("lon", &ImportNode::lon)
- .def_readonly("id", &ImportNode::node_id)
- .def_readwrite("bollard", &ImportNode::bollard)
- .def_readwrite("traffic_light", &ImportNode::trafficLight)
- .def_readwrite("tags", &ImportNode::keyVals),
-
- luabind::class_<ExtractionWay>("Way")
- // .def(luabind::constructor<>())
- .def_readonly("id", &ExtractionWay::id)
- .def_readwrite("name", &ExtractionWay::name)
- .def_readwrite("forward_speed", &ExtractionWay::forward_speed)
- .def_readwrite("backward_speed", &ExtractionWay::backward_speed)
- .def_readwrite("duration", &ExtractionWay::duration)
- .def_readwrite("access", &ExtractionWay::access)
- .def_readwrite("roundabout", &ExtractionWay::roundabout)
- .def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted)
- .def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
- .def_readwrite("tags", &ExtractionWay::keyVals)
- .property("direction", &ExtractionWay::get_direction, &ExtractionWay::set_direction)
- .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_<std::vector<std::string>>("vector")
- .def("Add", static_cast<void (std::vector<std::string>::*)(const std::string &)>(&std::vector<std::string>::push_back))
- ];
-
- if (0 != luaL_dofile(lua_state, file_name.c_str()))
- {
- luabind::object error_msg(luabind::from_stack(lua_state, -1));
- std::ostringstream error_stream;
- error_stream << error_msg;
- throw OSRMException("ERROR occured in profile script:\n" + error_stream.str());
- }
-}
-
-lua_State *ScriptingEnvironment::getLuaState()
-{
- bool initialized = false;
- auto& ref = script_contexts.local(initialized);
- if (!initialized)
- {
- std::shared_ptr<lua_State> state(luaL_newstate(), lua_close);
- ref = state;
- initLuaState(ref.get());
- }
-
- return ref.get();
-}
diff --git a/3party/osrm/osrm-backend/Extractor/XMLParser.cpp b/3party/osrm/osrm-backend/Extractor/XMLParser.cpp
deleted file mode 100644
index a984c76b72..0000000000
--- a/3party/osrm/osrm-backend/Extractor/XMLParser.cpp
+++ /dev/null
@@ -1,354 +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 "XMLParser.h"
-
-#include "ExtractionWay.h"
-#include "ExtractorCallbacks.h"
-
-#include "../DataStructures/HashTable.h"
-#include "../DataStructures/ImportNode.h"
-#include "../DataStructures/InputReaderFactory.h"
-#include "../DataStructures/Restriction.h"
-#include "../Util/cast.hpp"
-#include "../Util/simple_logger.hpp"
-#include "../Util/StringUtil.h"
-#include "../typedefs.h"
-
-#include <osrm/Coordinate.h>
-
-XMLParser::XMLParser(const char *filename,
- ExtractorCallbacks *extractor_callbacks,
- ScriptingEnvironment &scripting_environment)
- : BaseParser(extractor_callbacks, scripting_environment)
-{
- inputReader = inputReaderFactory(filename);
-}
-
-bool XMLParser::ReadHeader() { return xmlTextReaderRead(inputReader) == 1; }
-bool XMLParser::Parse()
-{
- while (xmlTextReaderRead(inputReader) == 1)
- {
- const int type = xmlTextReaderNodeType(inputReader);
-
- // 1 is Element
- if (type != 1)
- {
- continue;
- }
-
- xmlChar *currentName = xmlTextReaderName(inputReader);
- if (currentName == nullptr)
- {
- continue;
- }
-
- if (xmlStrEqual(currentName, (const xmlChar *)"node") == 1)
- {
- ImportNode current_node = ReadXMLNode();
- ParseNodeInLua(current_node, lua_state);
- extractor_callbacks->ProcessNode(current_node);
- }
-
- if (xmlStrEqual(currentName, (const xmlChar *)"way") == 1)
- {
- ExtractionWay way = ReadXMLWay();
- ParseWayInLua(way, lua_state);
- extractor_callbacks->ProcessWay(way);
- }
- if (use_turn_restrictions && xmlStrEqual(currentName, (const xmlChar *)"relation") == 1)
- {
- InputRestrictionContainer current_restriction = ReadXMLRestriction();
- if ((UINT_MAX != current_restriction.fromWay) &&
- !extractor_callbacks->ProcessRestriction(current_restriction))
- {
- std::cerr << "[XMLParser] restriction not parsed" << std::endl;
- }
- }
- xmlFree(currentName);
- }
- return true;
-}
-
-InputRestrictionContainer XMLParser::ReadXMLRestriction()
-{
-
- InputRestrictionContainer restriction;
-
- if (xmlTextReaderIsEmptyElement(inputReader) == 1)
- {
- return restriction;
- }
-
- std::string except_tag_string;
- const int depth = xmlTextReaderDepth(inputReader);
- while (xmlTextReaderRead(inputReader) == 1)
- {
- const int child_type = xmlTextReaderNodeType(inputReader);
- if (child_type != 1 && child_type != 15)
- {
- continue;
- }
- const int child_depth = xmlTextReaderDepth(inputReader);
- xmlChar *child_name = xmlTextReaderName(inputReader);
- if (child_name == nullptr)
- {
- continue;
- }
- if (depth == child_depth && child_type == 15 &&
- xmlStrEqual(child_name, (const xmlChar *)"relation") == 1)
- {
- xmlFree(child_name);
- break;
- }
- if (child_type != 1)
- {
- xmlFree(child_name);
- continue;
- }
-
- if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
- {
- xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
- xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
- if (key != nullptr && value != nullptr)
- {
- if (xmlStrEqual(key, (const xmlChar *)"restriction") &&
- StringStartsWith((const char *)value, "only_"))
- {
- restriction.restriction.flags.isOnly = true;
- }
- if (xmlStrEqual(key, (const xmlChar *)"except"))
- {
- except_tag_string = (const char *)value;
- }
- }
-
- if (key != nullptr)
- {
- xmlFree(key);
- }
- if (value != nullptr)
- {
- xmlFree(value);
- }
- }
- else if (xmlStrEqual(child_name, (const xmlChar *)"member") == 1)
- {
- xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
- if (ref != nullptr)
- {
- xmlChar *role = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"role");
- xmlChar *type = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"type");
-
- if (xmlStrEqual(role, (const xmlChar *)"to") &&
- xmlStrEqual(type, (const xmlChar *)"way"))
- {
- restriction.toWay = cast::string_to_uint((const char *)ref);
- }
- if (xmlStrEqual(role, (const xmlChar *)"from") &&
- xmlStrEqual(type, (const xmlChar *)"way"))
- {
- restriction.fromWay = cast::string_to_uint((const char *)ref);
- }
- if (xmlStrEqual(role, (const xmlChar *)"via") &&
- xmlStrEqual(type, (const xmlChar *)"node"))
- {
- restriction.restriction.viaNode = cast::string_to_uint((const char *)ref);
- }
-
- if (nullptr != type)
- {
- xmlFree(type);
- }
- if (nullptr != role)
- {
- xmlFree(role);
- }
- if (nullptr != ref)
- {
- xmlFree(ref);
- }
- }
- }
- xmlFree(child_name);
- }
-
- if (ShouldIgnoreRestriction(except_tag_string))
- {
- restriction.fromWay = UINT_MAX; // workaround to ignore the restriction
- }
- return restriction;
-}
-
-ExtractionWay XMLParser::ReadXMLWay()
-{
- ExtractionWay way;
- if (xmlTextReaderIsEmptyElement(inputReader) == 1)
- {
- return way;
- }
- const int depth = xmlTextReaderDepth(inputReader);
- while (xmlTextReaderRead(inputReader) == 1)
- {
- const int child_type = xmlTextReaderNodeType(inputReader);
- if (child_type != 1 && child_type != 15)
- {
- continue;
- }
- const int child_depth = xmlTextReaderDepth(inputReader);
- xmlChar *child_name = xmlTextReaderName(inputReader);
- if (child_name == nullptr)
- {
- continue;
- }
-
- if (depth == child_depth && child_type == 15 &&
- xmlStrEqual(child_name, (const xmlChar *)"way") == 1)
- {
- xmlChar *way_id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
- way.id = cast::string_to_uint((char *)way_id);
- xmlFree(way_id);
- xmlFree(child_name);
- break;
- }
- if (child_type != 1)
- {
- xmlFree(child_name);
- continue;
- }
-
- if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
- {
- xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
- xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
-
- if (key != nullptr && value != nullptr)
- {
- way.keyVals.Add(std::string((char *)key), std::string((char *)value));
- }
- if (key != nullptr)
- {
- xmlFree(key);
- }
- if (value != nullptr)
- {
- xmlFree(value);
- }
- }
- else if (xmlStrEqual(child_name, (const xmlChar *)"nd") == 1)
- {
- xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
- if (ref != nullptr)
- {
- way.path.push_back(cast::string_to_uint((const char *)ref));
- xmlFree(ref);
- }
- }
- xmlFree(child_name);
- }
- return way;
-}
-
-ImportNode XMLParser::ReadXMLNode()
-{
- ImportNode node;
-
- xmlChar *attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lat");
- if (attribute != nullptr)
- {
- node.lat = static_cast<int>(COORDINATE_PRECISION * cast::string_to_double((const char *)attribute));
- xmlFree(attribute);
- }
- attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lon");
- if (attribute != nullptr)
- {
- node.lon = static_cast<int>(COORDINATE_PRECISION * cast::string_to_double((const char *)attribute));
- xmlFree(attribute);
- }
- attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
- if (attribute != nullptr)
- {
- node.node_id = cast::string_to_uint((const char *)attribute);
- xmlFree(attribute);
- }
-
- if (xmlTextReaderIsEmptyElement(inputReader) == 1)
- {
- return node;
- }
- const int depth = xmlTextReaderDepth(inputReader);
- while (xmlTextReaderRead(inputReader) == 1)
- {
- const int child_type = xmlTextReaderNodeType(inputReader);
- // 1 = Element, 15 = EndElement
- if (child_type != 1 && child_type != 15)
- {
- continue;
- }
- const int child_depth = xmlTextReaderDepth(inputReader);
- xmlChar *child_name = xmlTextReaderName(inputReader);
- if (child_name == nullptr)
- {
- continue;
- }
-
- if (depth == child_depth && child_type == 15 &&
- xmlStrEqual(child_name, (const xmlChar *)"node") == 1)
- {
- xmlFree(child_name);
- break;
- }
- if (child_type != 1)
- {
- xmlFree(child_name);
- continue;
- }
-
- if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
- {
- xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
- xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
- if (key != nullptr && value != nullptr)
- {
- node.keyVals.Add(std::string((char *)(key)), std::string((char *)(value)));
- }
- if (key != nullptr)
- {
- xmlFree(key);
- }
- if (value != nullptr)
- {
- xmlFree(value);
- }
- }
-
- xmlFree(child_name);
- }
- return node;
-}
diff --git a/3party/osrm/osrm-backend/Extractor/XMLParser.h b/3party/osrm/osrm-backend/Extractor/XMLParser.h
deleted file mode 100644
index 178747ae71..0000000000
--- a/3party/osrm/osrm-backend/Extractor/XMLParser.h
+++ /dev/null
@@ -1,54 +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 XMLPARSER_H_
-#define XMLPARSER_H_
-
-#include "BaseParser.h"
-#include "../DataStructures/Restriction.h"
-
-#include <libxml/xmlreader.h>
-
-class ExtractorCallbacks;
-
-class XMLParser : public BaseParser
-{
- public:
- XMLParser(const char *filename,
- ExtractorCallbacks *extractor_callbacks,
- ScriptingEnvironment &scripting_environment);
- bool ReadHeader();
- bool Parse();
-
- private:
- InputRestrictionContainer ReadXMLRestriction();
- ExtractionWay ReadXMLWay();
- ImportNode ReadXMLNode();
- xmlTextReaderPtr inputReader;
-};
-
-#endif /* XMLPARSER_H_ */
diff --git a/3party/osrm/osrm-backend/Gemfile b/3party/osrm/osrm-backend/Gemfile
index 114808e497..31d044bd62 100644..100755
--- a/3party/osrm/osrm-backend/Gemfile
+++ b/3party/osrm/osrm-backend/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/3party/osrm/osrm-backend/Gemfile.lock b/3party/osrm/osrm-backend/Gemfile.lock
index ac056a0a22..ac056a0a22 100644..100755
--- a/3party/osrm/osrm-backend/Gemfile.lock
+++ b/3party/osrm/osrm-backend/Gemfile.lock
diff --git a/3party/osrm/osrm-backend/Include/osrm/Coordinate.h b/3party/osrm/osrm-backend/Include/osrm/Coordinate.h
deleted file mode 100644
index 5b8102d283..0000000000
--- a/3party/osrm/osrm-backend/Include/osrm/Coordinate.h
+++ /dev/null
@@ -1,113 +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 FIXED_POINT_COORDINATE_H_
-#define FIXED_POINT_COORDINATE_H_
-
-#include <iosfwd> //for std::ostream
-#include <string>
-#include <type_traits>
-
-#include "../../../../../std/msvc_cpp11_workarounds.hpp"
-
-CONSTEXPR_VALUE float COORDINATE_PRECISION = 1000000.f;
-
-struct FixedPointCoordinate
-{
- int lat;
- int lon;
-
- FixedPointCoordinate();
- FixedPointCoordinate(int lat, int lon);
-
- template<class T>
- FixedPointCoordinate(const T &coordinate) : lat(coordinate.lat), lon(coordinate.lon)
- {
- static_assert(std::is_same<decltype(lat), decltype(coordinate.lat)>::value, "coordinate types incompatible");
- static_assert(std::is_same<decltype(lon), decltype(coordinate.lon)>::value, "coordinate types incompatible");
- }
-
- void Reset();
- bool isSet() const;
- bool isValid() 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)
-{
- coordinate.Output(out_stream);
- return out_stream;
-}
-
-#endif /* FIXED_POINT_COORDINATE_H_ */
diff --git a/3party/osrm/osrm-backend/Include/osrm/Reply.h b/3party/osrm/osrm-backend/Include/osrm/Reply.h
deleted file mode 100644
index a2ee1f4863..0000000000
--- a/3party/osrm/osrm-backend/Include/osrm/Reply.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 REPLY_H
-#define REPLY_H
-
-#include "Header.h"
-
-#include <boost/asio.hpp>
-
-#include <vector>
-
-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
-{
- public:
- enum status_type
- { ok = 200,
- badRequest = 400,
- internalServerError = 500 } status;
-
- std::vector<Header> headers;
- std::vector<boost::asio::const_buffer> ToBuffers();
- std::vector<boost::asio::const_buffer> HeaderstoBuffers();
- std::vector<char> content;
- static Reply StockReply(status_type status);
- void SetSize(const unsigned size);
- void SetUncompressedSize();
-
- Reply();
-
- private:
- std::string ToString(Reply::status_type status);
- boost::asio::const_buffer ToBuffer(Reply::status_type status);
-};
-}
-
-#endif // REPLY_H
diff --git a/3party/osrm/osrm-backend/LICENCE.TXT b/3party/osrm/osrm-backend/LICENCE.TXT
index 28fe97b353..c77e5cd1b2 100644..100755
--- a/3party/osrm/osrm-backend/LICENCE.TXT
+++ b/3party/osrm/osrm-backend/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/3party/osrm/osrm-backend/Library/OSRM_impl.cpp b/3party/osrm/osrm-backend/Library/OSRM_impl.cpp
deleted file mode 100644
index 4d194c065d..0000000000
--- a/3party/osrm/osrm-backend/Library/OSRM_impl.cpp
+++ /dev/null
@@ -1,169 +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.
-
-*/
-
-namespace boost { namespace interprocess { class named_mutex; } }
-
-#include "OSRM_impl.h"
-#include "OSRM.h"
-
-#include <osrm/Reply.h>
-#include <osrm/RouteParameters.h>
-#include <osrm/ServerPaths.h>
-
-#include "../Plugins/BasePlugin.h"
-#include "../Plugins/DistanceTablePlugin.h"
-#include "../Plugins/HelloWorldPlugin.h"
-#include "../Plugins/LocatePlugin.h"
-#include "../Plugins/NearestPlugin.h"
-#include "../Plugins/TimestampPlugin.h"
-#include "../Plugins/ViaRoutePlugin.h"
-#include "../Plugins/MapsMePlugin.h"
-#include "../Server/DataStructures/BaseDataFacade.h"
-#include "../Server/DataStructures/InternalDataFacade.h"
-#include "../Server/DataStructures/SharedBarriers.h"
-#include "../Server/DataStructures/SharedDataFacade.h"
-#include "../Util/make_unique.hpp"
-#include "../Util/ProgramOptions.h"
-#include "../Util/simple_logger.hpp"
-
-#include <boost/assert.hpp>
-#include <boost/interprocess/sync/named_condition.hpp>
-#include <boost/interprocess/sync/scoped_lock.hpp>
-
-#include <algorithm>
-#include <fstream>
-#include <utility>
-#include <vector>
-
-OSRM_impl::OSRM_impl(ServerPaths server_paths, const bool use_shared_memory)
-{
- if (use_shared_memory)
- {
- barrier = osrm::make_unique<SharedBarriers>();
- query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>();
- }
- else
- {
- // populate base path
- populate_base_path(server_paths);
- query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(server_paths);
- }
-
- // The following plugins handle all requests.
- RegisterPlugin(new DistanceTablePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
- RegisterPlugin(new HelloWorldPlugin());
- RegisterPlugin(new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
- RegisterPlugin(new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
- RegisterPlugin(new TimestampPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
- RegisterPlugin(new ViaRoutePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
- RegisterPlugin(new MapsMePlugin<BaseDataFacade<QueryEdge::EdgeData>>(
- query_data_facade, server_paths["borders"].string(), server_paths["enodesdata"].string()));
-}
-
-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);
-}
-
-void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
-{
- 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
- boost::interprocess::scoped_lock<boost::interprocess::named_mutex> pending_lock(
- barrier->pending_update_mutex);
-
- // lock query
- boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
- barrier->query_mutex);
-
- // unlock update pending
- pending_lock.unlock();
-
- // increment query count
- ++(barrier->number_of_queries);
-
- (static_cast<SharedDataFacade<QueryEdge::EdgeData> *>(query_data_facade))
- ->CheckAndReloadFacade();
- }
-
- iter->second->HandleRequest(route_parameters, reply);
- if (barrier)
- {
- // lock query
- boost::interprocess::scoped_lock<boost::interprocess::named_mutex> 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();
- }
- }
- }
- else
- {
- reply = http::Reply::StockReply(http::Reply::badRequest);
- }
-}
-
-// proxy code for compilation firewall
-
-OSRM::OSRM(ServerPaths paths, const bool use_shared_memory)
- : OSRM_pimpl_(osrm::make_unique<OSRM_impl>(paths, use_shared_memory))
-{
-}
-
-OSRM::~OSRM() { OSRM_pimpl_.reset(); }
-
-void OSRM::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
-{
- OSRM_pimpl_->RunQuery(route_parameters, reply);
-}
diff --git a/3party/osrm/osrm-backend/Plugins/MapsMePlugin.h b/3party/osrm/osrm-backend/Plugins/MapsMePlugin.h
deleted file mode 100644
index 78ac4a6f2d..0000000000
--- a/3party/osrm/osrm-backend/Plugins/MapsMePlugin.h
+++ /dev/null
@@ -1,192 +0,0 @@
-#pragma once
-
-#include "BasePlugin.h"
-
-#include "../Algorithms/ObjectToBase64.h"
-#include "../DataStructures/EdgeBasedNodeData.h"
-#include "../DataStructures/JSONContainer.h"
-#include "../DataStructures/QueryEdge.h"
-#include "../DataStructures/SearchEngine.h"
-#include "../Descriptors/BaseDescriptor.h"
-#include "../Util/make_unique.hpp"
-#include "../Util/StringUtil.h"
-#include "../Util/TimingUtil.h"
-
-#include <algorithm>
-#include <memory>
-#include <unordered_map>
-#include <string>
-#include <vector>
-
-#include "../../../../base/string_utils.hpp"
-#include "../../../../coding/file_container.hpp"
-#include "../../../../coding/read_write_utils.hpp"
-#include "../../../../defines.hpp"
-#include "../../../../geometry/region2d.hpp"
-#include "../../../../indexer/geometry_serialization.hpp"
-#include "../../../../indexer/mercator.hpp"
-#include "../../../../storage/country_decl.hpp"
-#include "../../../../storage/country_polygon.hpp"
-
-template <class DataFacadeT> class MapsMePlugin final : public BasePlugin
-{
- class GetByPoint
- {
- m2::PointD const &m_pt;
- std::vector<std::vector<m2::RegionD>> const &m_regions;
-
- public:
- size_t m_res;
-
- GetByPoint(std::vector<std::vector<m2::RegionD>> const &regions, m2::PointD const &pt)
- : m_pt(pt), m_regions(regions), m_res(-1)
- {
- }
-
- /// @param[in] id Index in m_countries.
- /// @return false If point is in country.
- bool operator()(size_t id)
- {
- auto it =
- find_if(m_regions[id].begin(), m_regions[id].end(), [&](m2::RegionD const &region)
- { return region.Contains(m_pt);});
- if (it == m_regions[id].end())
- return true;
- m_res = id;
- return false;
- }
- };
-
- public:
- explicit MapsMePlugin(DataFacadeT *facade, std::string const &baseDir, std::string const & nodeDataFile)
- : m_descriptorString("mapsme"), m_facade(facade),
- m_reader(baseDir + '/' + PACKED_POLYGONS_FILE)
- {
- if (!osrm::LoadNodeDataFromFile(nodeDataFile, m_nodeData))
- {
- SimpleLogger().Write(logDEBUG) << "Can't load node data";
- return;
- }
- ReaderSource<ModelReaderPtr> src(m_reader.GetReader(PACKED_POLYGONS_INFO_TAG));
- rw::Read(src, m_countries);
- m_regions.resize(m_countries.size());
- for (size_t i = 0; i < m_countries.size(); ++i)
- {
- // load regions from file
- ReaderSource<ModelReaderPtr> src(m_reader.GetReader(strings::to_string(i)));
-
- uint32_t const count = ReadVarUint<uint32_t>(src);
- for (size_t j = 0; j < count; ++j)
- {
- vector<m2::PointD> points;
- serial::LoadOuterPath(src, serial::CodingParams(), points);
-
- m_regions[i].emplace_back(move(m2::RegionD(points.begin(), points.end())));
- }
- }
- m_searchEngine = osrm::make_unique<SearchEngine<DataFacadeT>>(facade);
- }
-
- template <class ToDo> void ForEachCountry(m2::PointD const &pt, ToDo &toDo) const
- {
- for (size_t i = 0; i < m_countries.size(); ++i)
- if (m_countries[i].m_rect.IsPointInside(pt))
- if (!toDo(i))
- return;
- }
-
- virtual ~MapsMePlugin() {}
-
- const std::string GetDescriptor() const final { return m_descriptorString; }
-
- void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
- {
- // check number of parameters
- if (2 > route_parameters.coordinates.size())
- {
- reply = http::Reply::StockReply(http::Reply::badRequest);
- return;
- }
-
- RawRouteData raw_route;
- raw_route.check_sum = m_facade->GetCheckSum();
-
- if (std::any_of(begin(route_parameters.coordinates), end(route_parameters.coordinates),
- [&](FixedPointCoordinate coordinate)
- {
- return !coordinate.isValid();
- }))
- {
- reply = http::Reply::StockReply(http::Reply::badRequest);
- return;
- }
-
- for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
- {
- raw_route.raw_via_node_coordinates.emplace_back(coordinate);
- }
-
- std::vector<PhantomNode> phantom_node_vector(raw_route.raw_via_node_coordinates.size());
- const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
-
- for (unsigned i = 0; i < raw_route.raw_via_node_coordinates.size(); ++i)
- {
- m_facade->FindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
- phantom_node_vector[i],
- route_parameters.zoom_level);
- }
-
- PhantomNodes current_phantom_node_pair;
- for (unsigned i = 0; i < phantom_node_vector.size() - 1; ++i)
- {
- current_phantom_node_pair.source_phantom = phantom_node_vector[i];
- current_phantom_node_pair.target_phantom = phantom_node_vector[i + 1];
- raw_route.segment_end_coordinates.emplace_back(current_phantom_node_pair);
- }
-
- m_searchEngine->alternative_path(raw_route.segment_end_coordinates.front(), raw_route);
-
- if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
- {
- SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
- }
- reply.status = http::Reply::ok;
-
- // Get mwm names
- set<string> usedMwms;
-
- for (auto i : osrm::irange<std::size_t>(0, raw_route.unpacked_path_segments.size()))
- {
- size_t const n = raw_route.unpacked_path_segments[i].size();
- for (size_t j = 0; j < n; ++j)
- {
- PathData const &path_data = raw_route.unpacked_path_segments[i][j];
- auto const & data = m_nodeData[path_data.node];
- if (data.m_segments.empty())
- continue;
- auto const & seg = data.m_segments.front();
- m2::PointD pt = MercatorBounds::FromLatLon(seg.lat1, seg.lon1);
- GetByPoint doGet(m_regions, pt);
- ForEachCountry(pt, doGet);
-
- if (doGet.m_res != -1)
- usedMwms.insert(m_countries[doGet.m_res].m_name);
- }
- }
-
- JSON::Object json_object;
- JSON::Array json_array;
- json_array.values.insert(json_array.values.begin(), usedMwms.begin(), usedMwms.end());
- json_object.values["used_mwms"] = json_array;
- JSON::render(reply.content, json_object);
- }
-
- private:
- std::unique_ptr<SearchEngine<DataFacadeT>> m_searchEngine;
- std::vector<storage::CountryDef> m_countries;
- std::vector<std::vector<m2::RegionD>> m_regions;
- std::string m_descriptorString;
- DataFacadeT * m_facade;
- FilesContainerR m_reader;
- osrm::NodeDataVectorT m_nodeData;
-};
diff --git a/3party/osrm/osrm-backend/Plugins/ViaRoutePlugin.h b/3party/osrm/osrm-backend/Plugins/ViaRoutePlugin.h
deleted file mode 100644
index 7bd4b70ecd..0000000000
--- a/3party/osrm/osrm-backend/Plugins/ViaRoutePlugin.h
+++ /dev/null
@@ -1,176 +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 VIA_ROUTE_PLUGIN_H
-#define VIA_ROUTE_PLUGIN_H
-
-#include "BasePlugin.h"
-
-#include "../Algorithms/ObjectToBase64.h"
-#include "../DataStructures/QueryEdge.h"
-#include "../DataStructures/SearchEngine.h"
-#include "../Descriptors/BaseDescriptor.h"
-#include "../Descriptors/GPXDescriptor.h"
-#include "../Descriptors/JSONDescriptor.h"
-#include "../Util/make_unique.hpp"
-#include "../Util/simple_logger.hpp"
-#include "../Util/StringUtil.h"
-#include "../Util/TimingUtil.h"
-
-#include <cstdlib>
-
-#include <algorithm>
-#include <memory>
-#include <unordered_map>
-#include <string>
-#include <vector>
-
-template <class DataFacadeT> class ViaRoutePlugin final : public BasePlugin
-{
- private:
- std::unordered_map<std::string, unsigned> descriptor_table;
- std::unique_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
-
- public:
- explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade)
- {
- search_engine_ptr = osrm::make_unique<SearchEngine<DataFacadeT>>(facade);
-
- descriptor_table.emplace("json", 0);
- descriptor_table.emplace("gpx", 1);
- // descriptor_table.emplace("geojson", 2);
- }
-
- virtual ~ViaRoutePlugin() {}
-
- const std::string GetDescriptor() const final { return descriptor_string; }
-
- void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
- {
- // check number of parameters
- if (2 > route_parameters.coordinates.size() ||
- std::any_of(begin(route_parameters.coordinates),
- end(route_parameters.coordinates),
- [&](FixedPointCoordinate coordinate)
- {
- return !coordinate.isValid();
- }))
- {
- reply = http::Reply::StockReply(http::Reply::badRequest);
- return;
- }
-
- RawRouteData raw_route;
- raw_route.check_sum = facade->GetCheckSum();
- for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
- {
- raw_route.raw_via_node_coordinates.emplace_back(coordinate);
- }
-
- std::vector<PhantomNode> phantom_node_vector(raw_route.raw_via_node_coordinates.size());
- const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
-
- for (unsigned i = 0; i < raw_route.raw_via_node_coordinates.size(); ++i)
- {
- if (checksum_OK && i < route_parameters.hints.size() &&
- !route_parameters.hints[i].empty())
- {
- ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], phantom_node_vector[i]);
- if (phantom_node_vector[i].isValid(facade->GetNumberOfNodes()))
- {
- continue;
- }
- }
- facade->FindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
- phantom_node_vector[i],
- route_parameters.zoom_level);
- }
-
- PhantomNodes current_phantom_node_pair;
- for (unsigned i = 0; i < phantom_node_vector.size() - 1; ++i)
- {
- current_phantom_node_pair.source_phantom = phantom_node_vector[i];
- current_phantom_node_pair.target_phantom = phantom_node_vector[i + 1];
- raw_route.segment_end_coordinates.emplace_back(current_phantom_node_pair);
- }
-
- const bool is_alternate_requested = route_parameters.alternate_route;
- const bool is_only_one_segment = (1 == raw_route.segment_end_coordinates.size());
- if (is_alternate_requested && is_only_one_segment)
- {
- search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
- raw_route);
- }
- else
- {
- search_engine_ptr->shortest_path(
- raw_route.segment_end_coordinates, route_parameters.uturns, raw_route);
- }
-
- if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
- {
- SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
- }
- reply.status = http::Reply::ok;
-
- 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<BaseDescriptor<DataFacadeT>> descriptor;
- switch (descriptor_type)
- {
- // case 0:
- // descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>();
- // break;
- case 1:
- descriptor = std::make_shared<GPXDescriptor<DataFacadeT>>(facade);
- break;
- // case 2:
- // descriptor = std::make_shared<GEOJSONDescriptor<DataFacadeT>>();
- // break;
- default:
- descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>(facade);
- break;
- }
-
- descriptor->SetConfig(descriptor_config);
- descriptor->Run(raw_route, reply);
- }
-
- private:
- std::string descriptor_string;
- DataFacadeT *facade;
-};
-
-#endif // VIA_ROUTE_PLUGIN_H
diff --git a/3party/osrm/osrm-backend/README.md b/3party/osrm/osrm-backend/README.md
index 624cc1da77..624cc1da77 100644..100755
--- a/3party/osrm/osrm-backend/README.md
+++ b/3party/osrm/osrm-backend/README.md
diff --git a/3party/osrm/osrm-backend/Rakefile b/3party/osrm/osrm-backend/Rakefile
index 562823b8ae..1c848bb07d 100644..100755
--- a/3party/osrm/osrm-backend/Rakefile
+++ b/3party/osrm/osrm-backend/Rakefile
@@ -158,7 +158,7 @@ task :down do
Process.kill 'TERM', pid
else
puts "Already down."
- end
+ end
end
desc "Kill all osrm-extract, osrm-prepare and osrm-routed processes."
@@ -168,7 +168,7 @@ task :kill do
each_process('osrm-extract') { |pid,state| Process.kill 'KILL', pid }
wait_for_shutdown 'osrm-routed'
wait_for_shutdown 'osrm-prepare'
- wait_for_shutdown 'osrm-extract'
+ wait_for_shutdown 'osrm-extract'
end
desc "Get PIDs of all osrm-extract, osrm-prepare and osrm-routed processes."
@@ -187,3 +187,4 @@ desc "Remove test cache files."
task :sweep do
system "rm test/cache/*"
end
+
diff --git a/3party/osrm/osrm-backend/RoutingAlgorithms/BasicRoutingInterface.h b/3party/osrm/osrm-backend/RoutingAlgorithms/BasicRoutingInterface.h
deleted file mode 100644
index f5e7225a21..0000000000
--- a/3party/osrm/osrm-backend/RoutingAlgorithms/BasicRoutingInterface.h
+++ /dev/null
@@ -1,347 +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 BASIC_ROUTING_INTERFACE_H
-#define BASIC_ROUTING_INTERFACE_H
-
-#include "../DataStructures/RawRouteData.h"
-#include "../DataStructures/SearchEngineData.h"
-#include "../DataStructures/TurnInstructions.h"
-// #include "../Util/simple_logger.hpp.h"
-
-#include <boost/assert.hpp>
-
-#include <stack>
-
-SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap;
-SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap;
-SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap2;
-SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap2;
-SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap3;
-SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap3;
-
-template <class DataFacadeT> class BasicRoutingInterface
-{
- private:
- typedef typename DataFacadeT::EdgeData EdgeData;
-
- protected:
- DataFacadeT *facade;
-
- public:
- BasicRoutingInterface() = delete;
- BasicRoutingInterface(const BasicRoutingInterface &) = delete;
- explicit BasicRoutingInterface(DataFacadeT *facade) : facade(facade) {}
- virtual ~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
- {
- const NodeID node = forward_heap.DeleteMin();
- 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;
-
- if (reverse_heap.WasInserted(node))
- {
- const int new_distance = reverse_heap.GetKey(node) + distance;
- if (new_distance < *upper_bound)
- {
- if (new_distance >= 0)
- {
- *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;
- }
- }
- }
-
- if (distance + min_edge_offset > *upper_bound)
- {
- // SimpleLogger().Write() << "min_edge_offset: " << min_edge_offset;
- forward_heap.DeleteAll();
- return;
- }
-
- // Stalling
- for (const auto edge : facade->GetAdjacentEdgeRange(node))
- {
- const EdgeData &data = facade->GetEdgeData(edge, node);
- const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
- if (reverse_flag)
- {
- const NodeID to = facade->GetTarget(edge);
- const int edge_weight = data.distance;
-
- BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
-
- if (forward_heap.WasInserted(to))
- {
- if (forward_heap.GetKey(to) + edge_weight < distance)
- {
- return;
- }
- }
- }
- }
-
- for (const auto edge : facade->GetAdjacentEdgeRange(node))
- {
- const EdgeData &data = facade->GetEdgeData(edge, node);
- bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
- if (forward_directionFlag)
- {
-
- const NodeID to = facade->GetTarget(edge);
- const int edge_weight = data.distance;
-
- BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
- const int to_distance = distance + edge_weight;
-
- // New Node discovered -> Add to Heap + Node Info Storage
- if (!forward_heap.WasInserted(to))
- {
- forward_heap.Insert(to, to_distance, node);
- }
- // Found a shorter Path -> Update distance
- else if (to_distance < forward_heap.GetKey(to))
- {
- // new parent
- forward_heap.GetData(to).parent = node;
- forward_heap.DecreaseKey(to, to_distance);
- }
- }
- }
- }
-
- inline void UnpackPath(const std::vector<NodeID> &packed_path,
- const PhantomNodes &phantom_node_pair,
- std::vector<PathData> &unpacked_path) const
- {
-// const bool start_traversed_in_reverse =
-// (packed_path.front() != phantom_node_pair.source_phantom.forward_node_id);
-// const bool target_traversed_in_reverse =
-// (packed_path.back() != phantom_node_pair.target_phantom.forward_node_id);
-
- const unsigned packed_path_size = static_cast<unsigned>(packed_path.size());
- std::stack<std::pair<NodeID, NodeID>> recursion_stack;
-
- // We have to push the path in reverse order onto the stack because it's LIFO.
- for (unsigned i = packed_path_size - 1; i > 0; --i)
- {
- recursion_stack.emplace(packed_path[i - 1], packed_path[i]);
- }
-
- unpacked_path.emplace_back(packed_path[0], INVALID_EDGE_WEIGHT, TurnInstruction::NoTurn, INVALID_EDGE_WEIGHT, TRAVEL_MODE_INACCESSIBLE);
- std::pair<NodeID, NodeID> edge;
- while (!recursion_stack.empty())
- {
- /*
- Graphical representation of variables:
-
- edge.first edge.second
- *------------------>*
- edge_id
- */
- edge = recursion_stack.top();
- recursion_stack.pop();
-
- // facade->FindEdge does not suffice here in case of shortcuts.
- // The above explanation unclear? Think!
- EdgeID smaller_edge_id = SPECIAL_EDGEID;
- NodeID smaller_node_id = SPECIAL_NODEID;
- int edge_weight = std::numeric_limits<EdgeWeight>::max();
- for (const auto edge_id : facade->GetAdjacentEdgeRange(edge.first))
- {
- auto const & edgeData = facade->GetEdgeData(edge_id, edge.first);
- const int weight = edgeData.distance;
- if ((facade->GetTarget(edge_id) == edge.second) && (weight < edge_weight) &&
- edgeData.forward)
- {
- smaller_edge_id = edge_id;
- smaller_node_id = edge.first;
- edge_weight = weight;
- }
- }
-
- /*
- Graphical representation of variables:
-
- edge.first edge.second
- *<------------------*
- edge_id
- */
- if (SPECIAL_EDGEID == smaller_edge_id)
- {
- for (const auto edge_id : facade->GetAdjacentEdgeRange(edge.second))
- {
- auto const & edgeData = facade->GetEdgeData(edge_id, edge.second);
- const int weight = edgeData.distance;
- if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) &&
- edgeData.backward)
- {
- smaller_edge_id = edge_id;
- smaller_node_id = edge.second;
- edge_weight = weight;
- }
- }
- }
- BOOST_ASSERT_MSG(edge_weight != INVALID_EDGE_WEIGHT, "edge id invalid");
-
- const EdgeData &ed = facade->GetEdgeData(smaller_edge_id, smaller_node_id);
- if (ed.shortcut)
- { // unpack
- const NodeID middle_node_id = ed.id;
- // again, we need to this in reversed order
- recursion_stack.emplace(middle_node_id, edge.second);
- recursion_stack.emplace(edge.first, middle_node_id);
- }
- else
- {
- const TravelMode travel_mode = facade->GetTravelModeForEdgeID(ed.id);
- unpacked_path.emplace_back(edge.second,
- INVALID_EDGE_WEIGHT,
- TurnInstruction::NoTurn,
- ed.distance,
- travel_mode);
- }
- }
-
- // there is no equivalent to a node-based node in an edge-expanded graph.
- // two equivalent routes may start (or end) at different node-based edges
- // as they are added with the offset how much "distance" on the edge
- // has already been traversed. Depending on offset one needs to remove
- // the last node.
- if (unpacked_path.size() > 1)
- {
- const std::size_t last_index = unpacked_path.size() - 1;
- const std::size_t second_to_last_index = last_index - 1;
-
- // looks like a trivially true check but tests for underflow
- BOOST_ASSERT(last_index > second_to_last_index);
-
- if (unpacked_path[last_index].node == unpacked_path[second_to_last_index].node)
- {
- unpacked_path.pop_back();
- }
- BOOST_ASSERT(!unpacked_path.empty());
- }
- }
-
- inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> &unpacked_path) const
- {
- std::stack<std::pair<NodeID, NodeID>> recursion_stack;
- recursion_stack.emplace(s, t);
-
- std::pair<NodeID, NodeID> edge;
- while (!recursion_stack.empty())
- {
- edge = recursion_stack.top();
- recursion_stack.pop();
-
- EdgeID smaller_edge_id = SPECIAL_EDGEID;
- NodeID smaller_node_id = SPECIAL_NODEID;
- int edge_weight = std::numeric_limits<EdgeWeight>::max();
- for (const auto edge_id : facade->GetAdjacentEdgeRange(edge.first))
- {
- auto const & edgeData = facade->GetEdgeData(edge_id, edge.first);
- const int weight = edgeData.distance;
- if ((facade->GetTarget(edge_id) == edge.second) && (weight < edge_weight) &&
- edgeData.forward)
- {
- smaller_edge_id = edge_id;
- smaller_node_id = edge.first;
- edge_weight = weight;
- }
- }
-
- if (SPECIAL_EDGEID == smaller_edge_id)
- {
- for (const auto edge_id : facade->GetAdjacentEdgeRange(edge.second))
- {
- auto const & edgeData = facade->GetEdgeData(edge_id, edge.second);
- const int weight = edgeData.distance;
- if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) &&
- edgeData.backward)
- {
- smaller_edge_id = edge_id;
- smaller_node_id = edge.second;
- edge_weight = weight;
- }
- }
- }
- BOOST_ASSERT_MSG(edge_weight != std::numeric_limits<EdgeWeight>::max(), "edge weight invalid");
-
- const EdgeData &ed = facade->GetEdgeData(smaller_edge_id, smaller_node_id);
- if (ed.shortcut)
- { // unpack
- const NodeID middle_node_id = ed.id;
- // again, we need to this in reversed order
- recursion_stack.emplace(middle_node_id, edge.second);
- recursion_stack.emplace(edge.first, middle_node_id);
- }
- else
- {
- BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut");
- unpacked_path.emplace_back(edge.first);
- }
- }
- 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<NodeID> &packed_path) const
- {
- RetrievePackedPathFromSingleHeap(forward_heap, middle_node_id, packed_path);
- std::reverse(packed_path.begin(), packed_path.end());
- packed_path.emplace_back(middle_node_id);
- RetrievePackedPathFromSingleHeap(reverse_heap, middle_node_id, packed_path);
- }
-
- inline void RetrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap,
- const NodeID middle_node_id,
- std::vector<NodeID> &packed_path) const
- {
- NodeID current_node_id = middle_node_id;
- while (current_node_id != search_heap.GetData(current_node_id).parent)
- {
- current_node_id = search_heap.GetData(current_node_id).parent;
- packed_path.emplace_back(current_node_id);
- }
- }
-};
-
-#endif // BASIC_ROUTING_INTERFACE_H
diff --git a/3party/osrm/osrm-backend/RoutingAlgorithms/NToMManyToManyRouting.h b/3party/osrm/osrm-backend/RoutingAlgorithms/NToMManyToManyRouting.h
deleted file mode 100644
index 32521790e9..0000000000
--- a/3party/osrm/osrm-backend/RoutingAlgorithms/NToMManyToManyRouting.h
+++ /dev/null
@@ -1,265 +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 NMMANY_TO_MANY_ROUTING_H
-#define NMMANY_TO_MANY_ROUTING_H
-
-#include "BasicRoutingInterface.h"
-#include "../DataStructures/SearchEngineData.h"
-#include "../typedefs.h"
-
-#include <boost/assert.hpp>
-
-#include <limits>
-#include <memory>
-#include <unordered_map>
-#include <vector>
-
-template <class DataFacadeT> class NMManyToManyRouting final : public BasicRoutingInterface<DataFacadeT>
-{
- using super = BasicRoutingInterface<DataFacadeT>;
- using QueryHeap = SearchEngineData::QueryHeap;
- SearchEngineData &engine_working_data;
-
- struct NodeBucket
- {
- unsigned target_id; // essentially a row in the distance matrix
- EdgeWeight distance;
- NodeBucket(const unsigned target_id, const EdgeWeight distance)
- : target_id(target_id), distance(distance)
- {
- }
- };
- using SearchSpaceWithBuckets = std::unordered_map<NodeID, std::vector<NodeBucket>>;
-
- public:
- NMManyToManyRouting(DataFacadeT *facade, SearchEngineData &engine_working_data)
- : super(facade), engine_working_data(engine_working_data)
- {
- }
-
- std::shared_ptr<std::vector<EdgeWeight>> operator()(const PhantomNodeArray &phantom_sources_nodes_array,
- const PhantomNodeArray &phantom_targets_nodes_array) const
- {
- const unsigned number_of_sources = static_cast<unsigned>(phantom_sources_nodes_array.size());
- const unsigned number_of_targets = static_cast<unsigned>(phantom_targets_nodes_array.size());
- std::shared_ptr<std::vector<EdgeWeight>> result_table =
- std::make_shared<std::vector<EdgeWeight>>(number_of_sources * number_of_targets,
- std::numeric_limits<EdgeWeight>::max());
-
- engine_working_data.InitializeOrClearFirstThreadLocalStorage(
- super::facade->GetNumberOfNodes());
-
- QueryHeap &query_heap = *(engine_working_data.forwardHeap);
-
- SearchSpaceWithBuckets search_space_with_buckets;
-
- unsigned target_id = 0;
- for (const std::vector<PhantomNode> &phantom_node_vector : phantom_targets_nodes_array)
- {
- query_heap.Clear();
- // insert target(s) at distance 0
-
- for (const PhantomNode &phantom_node : phantom_node_vector)
- {
- if (SPECIAL_NODEID != phantom_node.forward_node_id)
- {
- query_heap.Insert(phantom_node.forward_node_id,
- phantom_node.GetForwardWeightPlusOffset(),
- phantom_node.forward_node_id);
- }
- if (SPECIAL_NODEID != phantom_node.reverse_node_id)
- {
- query_heap.Insert(phantom_node.reverse_node_id,
- phantom_node.GetReverseWeightPlusOffset(),
- phantom_node.reverse_node_id);
- }
- }
-
- // explore search space
- while (!query_heap.Empty())
- {
- BackwardRoutingStep(target_id, query_heap, search_space_with_buckets);
- }
-
- ++target_id;
- }
-
- // for each source do forward search
- unsigned source_id = 0;
- for (const std::vector<PhantomNode> &phantom_node_vector : phantom_sources_nodes_array)
- {
- query_heap.Clear();
- for (const PhantomNode &phantom_node : phantom_node_vector)
- {
- // insert sources at distance 0
- if (SPECIAL_NODEID != phantom_node.forward_node_id)
- {
- query_heap.Insert(phantom_node.forward_node_id,
- -phantom_node.GetForwardWeightPlusOffset(),
- phantom_node.forward_node_id);
- }
- if (SPECIAL_NODEID != phantom_node.reverse_node_id)
- {
- query_heap.Insert(phantom_node.reverse_node_id,
- -phantom_node.GetReverseWeightPlusOffset(),
- phantom_node.reverse_node_id);
- }
- }
-
- // explore search space
- while (!query_heap.Empty())
- {
- ForwardRoutingStep(source_id,
- number_of_targets,
- query_heap,
- search_space_with_buckets,
- result_table);
-
- }
-
- ++source_id;
- }
- //BOOST_ASSERT(source_id == target_id);
- return result_table;
- }
-
- void ForwardRoutingStep(const unsigned source_id,
- const unsigned number_of_locations,
- QueryHeap &query_heap,
- const SearchSpaceWithBuckets &search_space_with_buckets,
- std::shared_ptr<std::vector<EdgeWeight>> result_table) const
- {
- const NodeID node = query_heap.DeleteMin();
- const int source_distance = query_heap.GetKey(node);
-
- // check if each encountered node has an entry
- const auto bucket_iterator = search_space_with_buckets.find(node);
- // iterate bucket if there exists one
- if (bucket_iterator != search_space_with_buckets.end())
- {
- const std::vector<NodeBucket> &bucket_list = bucket_iterator->second;
- for (const NodeBucket &current_bucket : bucket_list)
- {
- // get target id from bucket entry
- const unsigned target_id = current_bucket.target_id;
- const int target_distance = current_bucket.distance;
- const EdgeWeight current_distance =
- (*result_table)[source_id * number_of_locations + target_id];
- // check if new distance is better
- const EdgeWeight new_distance = source_distance + target_distance;
- if (new_distance >= 0 && new_distance < current_distance)
- {
- (*result_table)[source_id * number_of_locations + target_id] =
- (source_distance + target_distance);
- }
- }
- }
- if (StallAtNode<true>(node, source_distance, query_heap))
- {
- return;
- }
- RelaxOutgoingEdges<true>(node, source_distance, query_heap);
- }
-
- void BackwardRoutingStep(const unsigned target_id,
- QueryHeap &query_heap,
- SearchSpaceWithBuckets &search_space_with_buckets) const
- {
- const NodeID node = query_heap.DeleteMin();
- const int target_distance = query_heap.GetKey(node);
-
- // store settled nodes in search space bucket
- search_space_with_buckets[node].emplace_back(target_id, target_distance);
-
- if (StallAtNode<false>(node, target_distance, query_heap))
- {
- return;
- }
-
- RelaxOutgoingEdges<false>(node, target_distance, query_heap);
- }
-
- template <bool forward_direction>
- inline void
- RelaxOutgoingEdges(const NodeID node, const EdgeWeight distance, QueryHeap &query_heap) const
- {
- for (auto edge : super::facade->GetAdjacentEdgeRange(node))
- {
- const auto &data = super::facade->GetEdgeData(edge, node);
- const bool direction_flag = (forward_direction ? data.forward : data.backward);
- if (direction_flag)
- {
- const NodeID to = super::facade->GetTarget(edge);
- const int edge_weight = data.distance;
-
- BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
- const int to_distance = distance + edge_weight;
-
- // New Node discovered -> Add to Heap + Node Info Storage
- if (!query_heap.WasInserted(to))
- {
- query_heap.Insert(to, to_distance, node);
- }
- // Found a shorter Path -> Update distance
- else if (to_distance < query_heap.GetKey(to))
- {
- // new parent
- query_heap.GetData(to).parent = node;
- query_heap.DecreaseKey(to, to_distance);
- }
- }
- }
- }
-
- // Stalling
- template <bool forward_direction>
- inline bool StallAtNode(const NodeID node, const EdgeWeight distance, QueryHeap &query_heap)
- const
- {
- for (auto edge : super::facade->GetAdjacentEdgeRange(node))
- {
- const auto &data = super::facade->GetEdgeData(edge, node);
- const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
- if (reverse_flag)
- {
- const NodeID to = super::facade->GetTarget(edge);
- const int edge_weight = data.distance;
- BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
- if (query_heap.WasInserted(to))
- {
- if (query_heap.GetKey(to) + edge_weight < distance)
- {
- return true;
- }
- }
- }
- }
- return false;
- }
-};
-#endif
diff --git a/3party/osrm/osrm-backend/Server/APIGrammar.h b/3party/osrm/osrm-backend/Server/APIGrammar.h
deleted file mode 100644
index 83a5cd03b3..0000000000
--- a/3party/osrm/osrm-backend/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 <boost/bind.hpp>
-#include <boost/spirit/include/qi.hpp>
-#include <boost/spirit/include/qi_action.hpp>
-
-namespace qi = boost::spirit::qi;
-
-template <typename Iterator, class HandlerT>
-struct APIGrammar : qi::grammar<Iterator>
-{
- 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<Iterator> api_call, query;
- qi::rule<Iterator, std::string()> 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/3party/osrm/osrm-backend/Server/RequestHandler.cpp b/3party/osrm/osrm-backend/Server/RequestHandler.cpp
deleted file mode 100644
index b358d8d2da..0000000000
--- a/3party/osrm/osrm-backend/Server/RequestHandler.cpp
+++ /dev/null
@@ -1,142 +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 "RequestHandler.h"
-
-#include "APIGrammar.h"
-#include "Http/Request.h"
-
-#include "../DataStructures/JSONContainer.h"
-#include "../Library/OSRM.h"
-#include "../Util/simple_logger.hpp"
-#include "../Util/StringUtil.h"
-#include "../typedefs.h"
-
-#include <osrm/Reply.h>
-#include <osrm/RouteParameters.h>
-
-#include <ctime>
-
-#include <algorithm>
-#include <iostream>
-
-RequestHandler::RequestHandler() : routing_machine(nullptr) {}
-
-void RequestHandler::handle_request(const http::Request &req, http::Reply &reply)
-{
- // parse command
- try
- {
- std::string request;
- URIDecode(req.uri, request);
-
- // 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;
-
- time_t ltime;
- struct tm *time_stamp;
-
- ltime = time(nullptr);
- time_stamp = localtime(&ltime);
-
- // 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;
-
- RouteParameters route_parameters;
- APIGrammarParser api_parser(&route_parameters);
-
- auto iter = request.begin();
- const bool result = boost::spirit::qi::parse(iter, request.end(), api_parser);
-
- // 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);
- json_result.values["status_message"] = message;
- JSON::render(reply.content, json_result);
- return;
- }
-
- // parsing done, lets call the right plugin to handle the request
- BOOST_ASSERT_MSG(routing_machine != nullptr, "pointer not init'ed");
-
- 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());
- }
- routing_machine->RunQuery(route_parameters, reply);
- if (!route_parameters.jsonp_parameter.empty())
- { // append brace to jsonp response
- reply.content.push_back(')');
- }
-
- // set headers
- reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size()));
- if ("gpx" == route_parameters.output_format)
- { // gpx file
- 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
- reply.headers.emplace_back("Content-Type", "application/json; charset=UTF-8");
- reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.json\"");
- }
- else
- { // jsonp
- reply.headers.emplace_back("Content-Type", "text/javascript; charset=UTF-8");
- reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.js\"");
- }
- }
- catch (const std::exception &e)
- {
- reply = http::Reply::StockReply(http::Reply::internalServerError);
- SimpleLogger().Write(logWARNING) << "[server error] code: " << e.what()
- << ", uri: " << req.uri;
- return;
- }
-}
-
-void RequestHandler::RegisterRoutingMachine(OSRM *osrm) { routing_machine = osrm; }
diff --git a/3party/osrm/osrm-backend/Server/RequestParser.cpp b/3party/osrm/osrm-backend/Server/RequestParser.cpp
deleted file mode 100644
index 6e9cddf5ee..0000000000
--- a/3party/osrm/osrm-backend/Server/RequestParser.cpp
+++ /dev/null
@@ -1,310 +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 "RequestParser.h"
-
-#include "Http/Request.h"
-
-namespace http
-{
-
-RequestParser::RequestParser() : state_(method_start), header({"", ""}) {}
-
-void RequestParser::Reset() { state_ = method_start; }
-
-boost::tuple<boost::tribool, char *>
-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)
- {
- return boost::make_tuple(result, begin);
- }
- }
- boost::tribool result = boost::indeterminate;
- return boost::make_tuple(result, begin);
-}
-
-boost::tribool
-RequestParser::consume(Request &req, char input, http::CompressionType *compression_type)
-{
- switch (state_)
- {
- case method_start:
- if (!isChar(input) || isCTL(input) || isTSpecial(input))
- {
- return false;
- }
- state_ = method;
- return boost::indeterminate;
- case method:
- if (input == ' ')
- {
- state_ = uri;
- return boost::indeterminate;
- }
- if (!isChar(input) || isCTL(input) || isTSpecial(input))
- {
- return false;
- }
- return boost::indeterminate;
- case uri_start:
- if (isCTL(input))
- {
- return false;
- }
- state_ = uri;
- req.uri.push_back(input);
- return boost::indeterminate;
- case uri:
- if (input == ' ')
- {
- state_ = http_version_h;
- return boost::indeterminate;
- }
- if (isCTL(input))
- {
- return false;
- }
- req.uri.push_back(input);
- return boost::indeterminate;
- case http_version_h:
- if (input == 'H')
- {
- state_ = http_version_t_1;
- return boost::indeterminate;
- }
- return false;
- case http_version_t_1:
- if (input == 'T')
- {
- state_ = http_version_t_2;
- return boost::indeterminate;
- }
- return false;
- case http_version_t_2:
- if (input == 'T')
- {
- state_ = http_version_p;
- return boost::indeterminate;
- }
- return false;
- case http_version_p:
- if (input == 'P')
- {
- state_ = http_version_slash;
- return boost::indeterminate;
- }
- return false;
- case http_version_slash:
- if (input == '/')
- {
- state_ = http_version_major_start;
- return boost::indeterminate;
- }
- return false;
- case http_version_major_start:
- if (isDigit(input))
- {
- state_ = http_version_major;
- return boost::indeterminate;
- }
- return false;
- case http_version_major:
- if (input == '.')
- {
- state_ = http_version_minor_start;
- return boost::indeterminate;
- }
- if (isDigit(input))
- {
- return boost::indeterminate;
- }
- return false;
- case http_version_minor_start:
- if (isDigit(input))
- {
- state_ = http_version_minor;
- return boost::indeterminate;
- }
- return false;
- case http_version_minor:
- if (input == '\r')
- {
- state_ = expecting_newline_1;
- return boost::indeterminate;
- }
- if (isDigit(input))
- {
- return boost::indeterminate;
- }
- return false;
- case expecting_newline_1:
- if (input == '\n')
- {
- state_ = header_line_start;
- return boost::indeterminate;
- }
- return false;
- case header_line_start:
- if (header.name == "Accept-Encoding")
- {
- /* giving gzip precedence over deflate */
- if (header.value.find("deflate") != std::string::npos)
- {
- *compression_type = deflateRFC1951;
- }
- if (header.value.find("gzip") != std::string::npos)
- {
- *compression_type = gzipRFC1952;
- }
- }
-
- if ("Referer" == header.name)
- {
- req.referrer = header.value;
- }
-
- if ("User-Agent" == header.name)
- {
- req.agent = header.value;
- }
-
- if (input == '\r')
- {
- state_ = expecting_newline_3;
- return boost::indeterminate;
- }
- if (!isChar(input) || isCTL(input) || isTSpecial(input))
- {
- return false;
- }
- state_ = header_name;
- header.Clear();
- header.name.push_back(input);
- return boost::indeterminate;
- case header_lws:
- if (input == '\r')
- {
- state_ = expecting_newline_2;
- return boost::indeterminate;
- }
- if (input == ' ' || input == '\t')
- {
- return boost::indeterminate;
- }
- if (isCTL(input))
- {
- return false;
- }
- state_ = header_value;
- return boost::indeterminate;
- case header_name:
- if (input == ':')
- {
- state_ = space_before_header_value;
- return boost::indeterminate;
- }
- if (!isChar(input) || isCTL(input) || isTSpecial(input))
- {
- return false;
- }
- header.name.push_back(input);
- return boost::indeterminate;
- case space_before_header_value:
- if (input == ' ')
- {
- state_ = header_value;
- return boost::indeterminate;
- }
- return false;
- case header_value:
- if (input == '\r')
- {
- state_ = expecting_newline_2;
- return boost::indeterminate;
- }
- if (isCTL(input))
- {
- return false;
- }
- header.value.push_back(input);
- return boost::indeterminate;
- case expecting_newline_2:
- if (input == '\n')
- {
- state_ = header_line_start;
- return boost::indeterminate;
- }
- return false;
- default: // expecting_newline_3:
- return (input == '\n');
- // default:
- // return false;
- }
-}
-
-inline bool RequestParser::isChar(int character) { return character >= 0 && character <= 127; }
-
-inline bool RequestParser::isCTL(int character)
-{
- return (character >= 0 && character <= 31) || (character == 127);
-}
-
-inline bool RequestParser::isTSpecial(int character)
-{
- switch (character)
- {
- case '(':
- case ')':
- case '<':
- case '>':
- case '@':
- case ',':
- case ';':
- case ':':
- case '\\':
- case '"':
- case '/':
- case '[':
- case ']':
- case '?':
- case '=':
- case '{':
- case '}':
- case ' ':
- case '\t':
- return true;
- default:
- return false;
- }
-}
-
-inline bool RequestParser::isDigit(int character) { return character >= '0' && character <= '9'; }
-}
diff --git a/3party/osrm/osrm-backend/Tools/components.cpp b/3party/osrm/osrm-backend/Tools/components.cpp
deleted file mode 100644
index b60077bd0d..0000000000
--- a/3party/osrm/osrm-backend/Tools/components.cpp
+++ /dev/null
@@ -1,130 +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 "../typedefs.h"
-#include "../Algorithms/StronglyConnectedComponents.h"
-#include "../Util/GraphLoader.h"
-#include "../Util/OSRMException.h"
-#include "../Util/simple_logger.hpp"
-#include "../Util/FingerPrint.h"
-
-#include <fstream>
-#include <memory>
-#include <string>
-#include <vector>
-
-std::vector<NodeInfo> coordinate_list;
-std::vector<TurnRestriction> restrictions_vector;
-std::vector<NodeID> bollard_ID_list;
-std::vector<NodeID> trafficlight_ID_list;
-
-int main(int argc, char *argv[])
-{
- LogPolicy::GetInstance().Unmute();
- try
- {
- // enable logging
- if (argc < 3)
- {
- SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0]
- << " <osrm> <osrm.restrictions>";
- 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((char *)&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 OSRMException("Could not access <osrm-restrictions> files");
- }
- uint32_t usable_restrictions = 0;
- restriction_ifstream.read((char *)&usable_restrictions, sizeof(uint32_t));
- restrictions_vector.resize(usable_restrictions);
-
- // load restrictions
- if (usable_restrictions > 0)
- {
- restriction_ifstream.read((char *)&(restrictions_vector[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 OSRMException("Cannot open osrm file");
- }
-
- // load graph data
- std::vector<ImportEdge> edge_list;
- const NodeID number_of_nodes = readBinaryOSRMGraphFromStream(input_stream,
- edge_list,
- bollard_ID_list,
- trafficlight_ID_list,
- &coordinate_list,
- restrictions_vector);
- input_stream.close();
-
- BOOST_ASSERT_MSG(restrictions_vector.size() == usable_restrictions,
- "size of restrictions_vector changed");
-
- SimpleLogger().Write() << restrictions_vector.size() << " restrictions, "
- << bollard_ID_list.size() << " bollard nodes, "
- << trafficlight_ID_list.size() << " traffic lights";
-
- // Building an edge-expanded graph from node-based input an turn
- // restrictions
- SimpleLogger().Write() << "Starting SCC graph traversal";
- std::shared_ptr<TarjanSCC> tarjan = std::make_shared<TarjanSCC>(number_of_nodes,
- edge_list,
- bollard_ID_list,
- trafficlight_ID_list,
- restrictions_vector,
- coordinate_list);
- edge_list.clear();
- edge_list.shrink_to_fit();
-
- tarjan->Run();
- SimpleLogger().Write() << "finished component analysis";
- }
- catch (const std::exception &e)
- {
- SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
- }
- return 0;
-}
diff --git a/3party/osrm/osrm-backend/UnitTests/datastructure_tests.cpp b/3party/osrm/osrm-backend/UnitTests/datastructure_tests.cpp
deleted file mode 100644
index d451a91c7a..0000000000
--- a/3party/osrm/osrm-backend/UnitTests/datastructure_tests.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-#define BOOST_TEST_MODULE datastructure tests
-
-#include <boost/test/unit_test.hpp>
-
-/*
- * This file will contain an automatically generated main function.
- */
diff --git a/3party/osrm/osrm-backend/Util/GraphLoader.h b/3party/osrm/osrm-backend/Util/GraphLoader.h
deleted file mode 100644
index f1a43af1c4..0000000000
--- a/3party/osrm/osrm-backend/Util/GraphLoader.h
+++ /dev/null
@@ -1,429 +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 GRAPHLOADER_H
-#define GRAPHLOADER_H
-
-#include "OSRMException.h"
-#include "../DataStructures/ImportNode.h"
-#include "../DataStructures/ImportEdge.h"
-#include "../DataStructures/QueryNode.h"
-#include "../DataStructures/Restriction.h"
-#include "../Util/simple_logger.hpp"
-#include "../Util/FingerPrint.h"
-#include "../typedefs.h"
-
-#include <boost/assert.hpp>
-#include <boost/filesystem.hpp>
-#include <boost/filesystem/fstream.hpp>
-
-#include <cmath>
-
-#include <algorithm>
-#include <fstream>
-#include <iostream>
-#include <iomanip>
-#include <unordered_map>
-#include <vector>
-
-template <typename EdgeT>
-NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream,
- std::vector<EdgeT> &edge_list,
- std::vector<NodeID> &barrier_node_list,
- std::vector<NodeID> &traffic_light_node_list,
- std::vector<NodeInfo> *int_to_ext_node_id_map,
- std::vector<TurnRestriction> &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.";
- }
-
- NodeID n, source, target;
- EdgeID m;
- short dir; // direction (0 = open, 1 = forward, 2+ = open)
- std::unordered_map<NodeID, NodeID> ext_to_int_id_map;
- 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 *)&current_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.bollard)
- {
- barrier_node_list.emplace_back(i);
- }
- if (current_node.trafficLight)
- {
- traffic_light_node_list.emplace_back(i);
- }
- }
-
- // tighten vector sizes
- barrier_node_list.shrink_to_fit();
- traffic_light_node_list.shrink_to_fit();
- input_stream.read((char *)&m, sizeof(unsigned));
- SimpleLogger().Write() << " and " << m << " edges ";
- for (TurnRestriction &current_restriction : restriction_list)
- {
- auto internal_id_iter = ext_to_int_id_map.find(current_restriction.fromNode);
- if (internal_id_iter == ext_to_int_id_map.end())
- {
- SimpleLogger().Write(logDEBUG) << "Unmapped from Node of restriction";
- continue;
- }
- current_restriction.fromNode = internal_id_iter->second;
-
- internal_id_iter = ext_to_int_id_map.find(current_restriction.viaNode);
- if (internal_id_iter == ext_to_int_id_map.end())
- {
- SimpleLogger().Write(logDEBUG) << "Unmapped via node of restriction";
- continue;
- }
- current_restriction.viaNode = internal_id_iter->second;
-
- internal_id_iter = ext_to_int_id_map.find(current_restriction.toNode);
- if (internal_id_iter == ext_to_int_id_map.end())
- {
- SimpleLogger().Write(logDEBUG) << "Unmapped to node of restriction";
- continue;
- }
- current_restriction.toNode = internal_id_iter->second;
- }
-
- edge_list.reserve(m);
- EdgeWeight weight;
- NodeID nameID;
- int length;
- bool is_roundabout, ignore_in_grid, is_access_restricted, is_split;
- TravelMode travel_mode;
- unsigned way_id;
-
- for (EdgeID i = 0; i < m; ++i)
- {
- input_stream.read((char *)&way_id, sizeof(unsigned));
- 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 != UINT_MAX && target != UINT_MAX, "nonexisting source or target");
-
- if (source > target)
- {
- std::swap(source, target);
- std::swap(forward, backward);
- }
-
- edge_list.emplace_back(way_id,
- source,
- target,
- nameID,
- weight,
- forward,
- backward,
- is_roundabout,
- ignore_in_grid,
- is_access_restricted,
- travel_mode,
- is_split);
- }
-
- std::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].backward != edge_list[i].backward);
- const bool edge_flags_are_superset_2 =
- (edge_list[i].forward && edge_list[i].backward) &&
- (edge_list[i - 1].backward != 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 = UINT_MAX;
- }
- 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 = UINT_MAX;
- }
- 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 = UINT_MAX;
- }
- }
- }
- }
- const auto new_end_iter = std::remove_if(edge_list.begin(),
- edge_list.end(),
- [](const EdgeT &edge)
- { return edge.source == SPECIAL_NODEID; });
- ext_to_int_id_map.clear();
- 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 <typename EdgeT, typename CoordinateT>
-NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream,
- std::vector<EdgeT> &edge_list,
- std::vector<CoordinateT> & coordinate_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.";
- }
-
- NodeID n, source, target;
- EdgeID m;
- short dir; // direction (0 = open, 1 = forward, 2+ = open)
- std::unordered_map<NodeID, NodeID> ext_to_int_id_map;
-
- 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 *)&current_node, sizeof(ExternalMemoryNode));
- coordinate_list.emplace_back(current_node.lat, current_node.lon);
- ext_to_int_id_map.emplace(current_node.node_id, i);
- }
-
- input_stream.read((char *)&m, sizeof(unsigned));
- SimpleLogger().Write() << " and " << m << " edges ";
-
- edge_list.reserve(m);
- EdgeWeight weight;
- NodeID nameID;
- int length;
- unsigned way_id;
- bool is_roundabout, ignore_in_grid, is_access_restricted, is_split;
- TravelMode travel_mode;
-
- for (EdgeID i = 0; i < m; ++i)
- {
- input_stream.read((char *)&way_id, sizeof(unsigned));
- 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");
-
- // 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 != UINT_MAX && target != UINT_MAX, "nonexisting source or target");
-
- if (source > target)
- {
- std::swap(source, target);
- }
-
- edge_list.emplace_back(source,
- target);
- }
-
- std::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))
- {
- edge_list[i].distance = std::min(edge_list[i - 1].distance, edge_list[i].distance);
- edge_list[i - 1].source = UINT_MAX;
- }
- }
- const auto new_end_iter = std::remove_if(edge_list.begin(),
- edge_list.end(),
- [](const EdgeT &edge)
- { return edge.source == SPECIAL_NODEID; });
- ext_to_int_id_map.clear();
- edge_list.erase(new_end_iter, edge_list.end()); // remove excess candidates.
- edge_list.shrink_to_fit();
- SimpleLogger().Write() << "Graph loaded ok and has " << n << " nodes and " << edge_list.size() << " edges";
- return n;
-}
-
-
-template <typename NodeT, typename EdgeT>
-unsigned readHSGRFromStream(const boost::filesystem::path &hsgr_file,
- std::vector<NodeT> &node_list,
- std::vector<EdgeT> &edge_list,
- unsigned *check_sum)
-{
- if (!boost::filesystem::exists(hsgr_file))
- {
- throw OSRMException("hsgr file does not exist");
- }
- if (0 == boost::filesystem::file_size(hsgr_file))
- {
- throw OSRMException("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 // GRAPHLOADER_H
diff --git a/3party/osrm/osrm-backend/Util/TimingUtil.h b/3party/osrm/osrm-backend/Util/TimingUtil.h
deleted file mode 100644
index c1505cebfe..0000000000
--- a/3party/osrm/osrm-backend/Util/TimingUtil.h
+++ /dev/null
@@ -1,39 +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 TIMINGUTIL_H
-#define TIMINGUTIL_H
-
-#include <chrono>
-
-#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_MSEC(_X) std::chrono::duration_cast<std::chrono::milliseconds>(_X##_stop - _X##_start).count()
-#define TIMER_SEC(_X) (0.001*std::chrono::duration_cast<std::chrono::milliseconds>(_X##_stop - _X##_start).count())
-#define TIMER_MIN(_X) std::chrono::duration_cast<std::chrono::minutes>(_X##_stop - _X##_start).count()
-
-#endif // TIMINGUTIL_H
diff --git a/3party/osrm/osrm-backend/Util/TrigonometryTables.h b/3party/osrm/osrm-backend/Util/TrigonometryTables.h
deleted file mode 100644
index 64076a23c3..0000000000
--- a/3party/osrm/osrm-backend/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 <cmath>
-
-#include <limits>
-
-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;
-
-double atan2_lookup(double y, double x)
-{
- if (std::abs(x) < std::numeric_limits<double>::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/3party/osrm/osrm-backend/algorithms/bayes_classifier.hpp b/3party/osrm/osrm-backend/algorithms/bayes_classifier.hpp
new file mode 100755
index 0000000000..3358144c75
--- /dev/null
+++ b/3party/osrm/osrm-backend/algorithms/bayes_classifier.hpp
@@ -0,0 +1,117 @@
+/*
+
+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 BAYES_CLASSIFIER_HPP
+#define BAYES_CLASSIFIER_HPP
+
+#include <cmath>
+
+#include <vector>
+
+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 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));
+ }
+
+ 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 density_function(const double val) const
+ {
+ const double x = std::abs(val - location);
+ return 1.0 / (2. * scale) * std::exp(-x / scale);
+ }
+
+ double location;
+ double scale;
+};
+
+template <typename PositiveDistributionT, typename NegativeDistributionT, typename ValueT>
+class BayesClassifier
+{
+ public:
+ enum class ClassLabel : unsigned
+ {
+ NEGATIVE,
+ POSITIVE
+ };
+ using ClassificationT = std::pair<ClassLabel, double>;
+
+ 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.
+ ClassificationT classify(const ValueT &v) const
+ {
+ 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)
+ {
+ 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/3party/osrm/osrm-backend/Algorithms/BFSComponentExplorer.h b/3party/osrm/osrm-backend/algorithms/bfs_components.hpp
index daab82a14f..b3f5364015 100644..100755
--- a/3party/osrm/osrm-backend/Algorithms/BFSComponentExplorer.h
+++ b/3party/osrm/osrm-backend/algorithms/bfs_components.hpp
@@ -1,8 +1,35 @@
-#ifndef BFS_COMPONENT_EXPLORER_H_
-#define BFS_COMPONENT_EXPLORER_H_
+/*
+
+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 BFS_COMPONENTS_HPP_
+#define BFS_COMPONENTS_HPP_
#include "../typedefs.h"
-#include "../DataStructures/RestrictionMap.h"
+#include "../data_structures/restriction_map.hpp"
#include <queue>
#include <unordered_set>
@@ -68,8 +95,8 @@ template <typename GraphT> class BFSComponentExplorer
* Explores the current component that starts at node using BFS.
*/
unsigned ExploreComponent(std::queue<std::pair<NodeID, NodeID>> &bfs_queue,
- NodeID node,
- unsigned current_component)
+ NodeID node,
+ unsigned current_component)
{
/*
Graphical representation of variables:
@@ -91,42 +118,42 @@ template <typename GraphT> class BFSComponentExplorer
std::pair<NodeID, NodeID> 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;
- const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
- if (!is_barrier_node)
+ if (m_barrier_nodes.find(v) != m_barrier_nodes.end())
+ {
+ continue;
+ }
+ const NodeID to_node_of_only_restriction =
+ m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
+
+ for (auto e2 : m_graph.GetAdjacentEdgeRange(v))
{
- const NodeID to_node_of_only_restriction =
- m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
+ const NodeID w = m_graph.GetTarget(e2);
- for (auto e2 : m_graph.GetAdjacentEdgeRange(v))
+ if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
+ w != to_node_of_only_restriction)
{
- const NodeID w = m_graph.GetTarget(e2);
-
- if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
- w != to_node_of_only_restriction)
- {
- // At an only_-restriction but not at the right turn
- continue;
- }
+ // At an only_-restriction but not at the right turn
+ continue;
+ }
- if (u != w)
+ if (u != w)
+ {
+ // 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))
{
- // 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))
+ // only add an edge if turn is not prohibited
+ if (std::numeric_limits<unsigned>::max() == m_component_index_list[w])
{
- // only add an edge if turn is not prohibited
- if (std::numeric_limits<unsigned>::max() == m_component_index_list[w])
- {
- // insert next (node, parent) only if w has
- // not yet been explored
- // mark node as read
- m_component_index_list[w] = current_component;
- bfs_queue.emplace(w, v);
- }
+ // insert next (node, parent) only if w has
+ // not yet been explored
+ // mark node as read
+ m_component_index_list[w] = current_component;
+ bfs_queue.emplace(w, v);
}
}
}
@@ -144,4 +171,4 @@ template <typename GraphT> class BFSComponentExplorer
const std::unordered_set<NodeID> &m_barrier_nodes;
};
-#endif // BFS_COMPONENT_EXPLORER_H_
+#endif // BFS_COMPONENTS_HPP_
diff --git a/3party/osrm/osrm-backend/Algorithms/IteratorBasedCRC32.h b/3party/osrm/osrm-backend/algorithms/crc32_processor.hpp
index a68514dceb..a31b4ad23a 100644..100755
--- a/3party/osrm/osrm-backend/Algorithms/IteratorBasedCRC32.h
+++ b/3party/osrm/osrm-backend/algorithms/crc32_processor.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -49,7 +49,7 @@ class IteratorbasedCRC32
while (iter != end)
{
using value_type = typename std::iterator_traits<Iterator>::value_type;
- char *data = (char *)(&(*iter));
+ const char *data = reinterpret_cast<const char *>(&(*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);
@@ -96,7 +96,7 @@ class IteratorbasedCRC32
++p;
}
- str = (char *)p;
+ str = reinterpret_cast<char *>(p);
while (r--)
{
__asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
@@ -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
{
@@ -131,8 +131,7 @@ class IteratorbasedCRC32
struct RangebasedCRC32
{
- template<typename Iteratable>
- unsigned operator()(const Iteratable &iterable)
+ template <typename Iteratable> unsigned operator()(const Iteratable &iterable)
{
return crc32(std::begin(iterable), std::end(iterable));
}
diff --git a/3party/osrm/osrm-backend/Algorithms/DouglasPeucker.cpp b/3party/osrm/osrm-backend/algorithms/douglas_peucker.cpp
index 6444f13575..fa7d7826b8 100644..100755
--- a/3party/osrm/osrm-backend/Algorithms/DouglasPeucker.cpp
+++ b/3party/osrm/osrm-backend/algorithms/douglas_peucker.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,20 +25,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "DouglasPeucker.h"
+#include "douglas_peucker.hpp"
-#include "../DataStructures/Range.h"
-#include "../DataStructures/SegmentInformation.h"
-
-#include <osrm/Coordinate.h>
+#include "../data_structures/segment_information.hpp"
#include <boost/assert.hpp>
+#include <osrm/coordinate.hpp>
#include <cmath>
-
#include <algorithm>
+#include <iterator>
-namespace {
+namespace
+{
struct CoordinatePairCalculator
{
CoordinatePairCalculator() = delete;
@@ -64,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<int>(std::min(dist1, dist2));
@@ -82,61 +81,40 @@ struct CoordinatePairCalculator
};
}
-DouglasPeucker::DouglasPeucker()
- : douglas_peucker_thresholds({512440, // z0
- 256720, // z1
- 122560, // z2
- 56780, // z3
- 28800, // z4
- 14400, // z5
- 7200, // z6
- 3200, // z7
- 2400, // z8
- 1000, // z9
- 600, // z10
- 120, // z11
- 60, // z12
- 45, // z13
- 36, // z14
- 20, // z15
- 8, // z16
- 6, // z17
- 4 // z18
- })
+void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level)
{
+ Run(std::begin(input_geometry), std::end(input_geometry), zoom_level);
}
-void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level)
+void DouglasPeucker::Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level)
{
- // check if input data is invalid
- BOOST_ASSERT_MSG(!input_geometry.empty(), "geometry invalid");
-
- if (input_geometry.size() < 2)
+ const auto size = std::distance(begin, end);
+ if (size < 2)
{
return;
}
- input_geometry.front().necessary = true;
- input_geometry.back().necessary = true;
+ begin->necessary = true;
+ std::prev(end)->necessary = true;
{
- BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level");
- unsigned left_border = 0;
- unsigned right_border = 1;
+ BOOST_ASSERT_MSG(zoom_level < DOUGLAS_PEUCKER_THRESHOLDS.size(), "unsupported zoom level");
+ RandomAccessIt left_border = begin;
+ RandomAccessIt right_border = std::next(begin);
// Sweep over array and identify those ranges that need to be checked
do
{
// traverse list until new border element found
- if (input_geometry[right_border].necessary)
+ if (right_border->necessary)
{
// sanity checks
- BOOST_ASSERT(input_geometry[left_border].necessary);
- BOOST_ASSERT(input_geometry[right_border].necessary);
+ BOOST_ASSERT(left_border->necessary);
+ BOOST_ASSERT(right_border->necessary);
recursion_stack.emplace(left_border, right_border);
left_border = right_border;
}
++right_border;
- } while (right_border < input_geometry.size());
+ } while (right_border != end);
}
// mark locations as 'necessary' by divide-and-conquer
@@ -146,40 +124,40 @@ void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const
const GeometryRange pair = recursion_stack.top();
recursion_stack.pop();
// sanity checks
- BOOST_ASSERT_MSG(input_geometry[pair.first].necessary, "left border mus be necessary");
- BOOST_ASSERT_MSG(input_geometry[pair.second].necessary, "right border must be necessary");
- BOOST_ASSERT_MSG(pair.second < input_geometry.size(), "right border outside of geometry");
- BOOST_ASSERT_MSG(pair.first < pair.second, "left border on the wrong side");
+ BOOST_ASSERT_MSG(pair.first->necessary, "left border must be necessary");
+ BOOST_ASSERT_MSG(pair.second->necessary, "right border must be necessary");
+ BOOST_ASSERT_MSG(std::distance(pair.second, end) > 0, "right border outside of geometry");
+ BOOST_ASSERT_MSG(std::distance(pair.first, pair.second) >= 0,
+ "left border on the wrong side");
int max_int_distance = 0;
- unsigned farthest_entry_index = pair.second;
- const CoordinatePairCalculator dist_calc(input_geometry[pair.first].location,
- input_geometry[pair.second].location);
+ auto farthest_entry_it = pair.second;
+ const CoordinatePairCalculator dist_calc(pair.first->location, pair.second->location);
// sweep over range to find the maximum
- for (const auto i : osrm::irange(pair.first + 1, pair.second))
+ for (auto it = std::next(pair.first); it != pair.second; ++it)
{
- const int distance = dist_calc(input_geometry[i].location);
+ const int distance = dist_calc(it->location);
// found new feasible maximum?
- if (distance > max_int_distance && distance > douglas_peucker_thresholds[zoom_level])
+ if (distance > max_int_distance && distance > DOUGLAS_PEUCKER_THRESHOLDS[zoom_level])
{
- farthest_entry_index = i;
+ farthest_entry_it = it;
max_int_distance = distance;
}
}
// check if maximum violates a zoom level dependent threshold
- if (max_int_distance > douglas_peucker_thresholds[zoom_level])
+ if (max_int_distance > DOUGLAS_PEUCKER_THRESHOLDS[zoom_level])
{
// mark idx as necessary
- input_geometry[farthest_entry_index].necessary = true;
- if (1 < (farthest_entry_index - pair.first))
+ farthest_entry_it->necessary = true;
+ if (1 < std::distance(pair.first, farthest_entry_it))
{
- recursion_stack.emplace(pair.first, farthest_entry_index);
+ recursion_stack.emplace(pair.first, farthest_entry_it);
}
- if (1 < (pair.second - farthest_entry_index))
+ if (1 < std::distance(farthest_entry_it, pair.second))
{
- recursion_stack.emplace(farthest_entry_index, pair.second);
+ recursion_stack.emplace(farthest_entry_it, pair.second);
}
}
}
diff --git a/3party/osrm/osrm-backend/Algorithms/DouglasPeucker.h b/3party/osrm/osrm-backend/algorithms/douglas_peucker.hpp
index 60fc377b10..da02982f3d 100644..100755
--- a/3party/osrm/osrm-backend/Algorithms/DouglasPeucker.h
+++ b/3party/osrm/osrm-backend/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,
@@ -25,9 +25,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef DOUGLASPEUCKER_H_
-#define DOUGLASPEUCKER_H_
+#ifndef DOUGLAS_PEUCKER_HPP_
+#define DOUGLAS_PEUCKER_HPP_
+#include "../data_structures/segment_information.hpp"
+
+#include <array>
#include <stack>
#include <utility>
#include <vector>
@@ -39,20 +42,40 @@ 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<int, 19> DOUGLAS_PEUCKER_THRESHOLDS{{
+ 512440, // z0
+ 256720, // z1
+ 122560, // z2
+ 56780, // z3
+ 28800, // z4
+ 14400, // z5
+ 7200, // z6
+ 3200, // z7
+ 2400, // z8
+ 1000, // z9
+ 600, // z10
+ 120, // z11
+ 60, // z12
+ 45, // z13
+ 36, // z14
+ 20, // z15
+ 8, // z16
+ 6, // z17
+ 4 // z18
+}};
class DouglasPeucker
{
- private:
- std::vector<int> douglas_peucker_thresholds;
+ public:
+ using RandomAccessIt = std::vector<SegmentInformation>::iterator;
- using GeometryRange = std::pair<unsigned, unsigned>;
+ using GeometryRange = std::pair<RandomAccessIt, RandomAccessIt>;
// Stack to simulate the recursion
std::stack<GeometryRange> recursion_stack;
public:
- DouglasPeucker();
+ void Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level);
void Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level);
};
-#endif /* DOUGLASPEUCKER_H_ */
+#endif /* DOUGLAS_PEUCKER_HPP_ */
diff --git a/3party/osrm/osrm-backend/Algorithms/ObjectToBase64.h b/3party/osrm/osrm-backend/algorithms/object_encoder.hpp
index 6930b9c2c1..e880496a2d 100644..100755
--- a/3party/osrm/osrm-backend/Algorithms/ObjectToBase64.h
+++ b/3party/osrm/osrm-backend/algorithms/object_encoder.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,10 +25,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef OBJECT_TO_BASE64_H_
-#define OBJECT_TO_BASE64_H_
+#ifndef OBJECT_ENCODER_HPP
+#define OBJECT_ENCODER_HPP
-#include "../Util/StringUtil.h"
+#include "../util/string_util.hpp"
#include <boost/assert.hpp>
#include <boost/archive/iterators/base64_from_binary.hpp>
@@ -49,10 +49,9 @@ struct ObjectEncoder
8,
6>;
- template <class ObjectT>
- static void EncodeToBase64(const ObjectT &object, std::string &encoded)
+ template <class ObjectT> 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<const char *>(&object);
std::vector<unsigned char> data(sizeof(object));
std::copy(char_ptr_to_object, char_ptr_to_object + sizeof(ObjectT), data.begin());
@@ -71,8 +70,7 @@ struct ObjectEncoder
replaceAll(encoded, "/", "_");
}
- template <class ObjectT>
- static void DecodeFromBase64(const std::string &input, ObjectT &object)
+ template <class ObjectT> static void DecodeFromBase64(const std::string &input, ObjectT &object)
{
try
{
@@ -81,9 +79,8 @@ struct ObjectEncoder
replaceAll(encoded, "-", "+");
replaceAll(encoded, "_", "/");
- std::copy(binary_t(encoded.begin()),
- binary_t(encoded.begin() + encoded.length() - 1),
- (char *)&object);
+ std::copy(binary_t(encoded.begin()), binary_t(encoded.begin() + encoded.length() - 1),
+ reinterpret_cast<char *>(&object));
}
catch (...)
{
@@ -91,4 +88,4 @@ struct ObjectEncoder
}
};
-#endif /* OBJECT_TO_BASE64_H_ */
+#endif /* OBJECT_ENCODER_HPP */
diff --git a/3party/osrm/osrm-backend/Algorithms/PolylineCompressor.cpp b/3party/osrm/osrm-backend/algorithms/polyline_compressor.cpp
index bae40052b3..d5fd5828bb 100644..100755
--- a/3party/osrm/osrm-backend/Algorithms/PolylineCompressor.cpp
+++ b/3party/osrm/osrm-backend/algorithms/polyline_compressor.cpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,16 +25,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "PolylineCompressor.h"
-#include "../DataStructures/SegmentInformation.h"
+#include "polyline_compressor.hpp"
+#include "../data_structures/segment_information.hpp"
-#include <osrm/Coordinate.h>
+#include <osrm/coordinate.hpp>
-void PolylineCompressor::encodeVectorSignedNumber(std::vector<int> &numbers,
- std::string &output) const
+std::string PolylineCompressor::encode_vector(std::vector<int> &numbers) const
{
- const unsigned end = static_cast<unsigned>(numbers.size());
- for (unsigned i = 0; i < end; ++i)
+ std::string output;
+ const auto end = numbers.size();
+ for (std::size_t i = 0; i < end; ++i)
{
numbers[i] <<= 1;
if (numbers[i] < 0)
@@ -44,69 +44,47 @@ void PolylineCompressor::encodeVectorSignedNumber(std::vector<int> &numbers,
}
for (const int number : numbers)
{
- encodeNumber(number, output);
+ output += encode_number(number);
}
+ return output;
}
-void PolylineCompressor::encodeNumber(int number_to_encode, std::string &output) const
+std::string PolylineCompressor::encode_number(int number_to_encode) const
{
+ std::string output;
while (number_to_encode >= 0x20)
{
const int next_value = (0x20 | (number_to_encode & 0x1f)) + 63;
output += static_cast<char>(next_value);
- if (92 == next_value)
- {
- output += static_cast<char>(next_value);
- }
number_to_encode >>= 5;
}
number_to_encode += 63;
output += static_cast<char>(number_to_encode);
- if (92 == number_to_encode)
- {
- output += static_cast<char>(number_to_encode);
- }
+ return output;
}
-JSON::String
-PolylineCompressor::printEncodedString(const std::vector<SegmentInformation> &polyline) const
+std::string
+PolylineCompressor::get_encoded_string(const std::vector<SegmentInformation> &polyline) const
{
- std::string output;
- std::vector<int> delta_numbers;
- if (!polyline.empty())
+ if (polyline.empty())
{
- FixedPointCoordinate last_coordinate = {0, 0};
- for (const auto &segment : polyline)
- {
- if (segment.necessary)
- {
- const int lat_diff = segment.location.lat - last_coordinate.lat;
- const int lon_diff = segment.location.lon - last_coordinate.lon;
- delta_numbers.emplace_back(lat_diff);
- delta_numbers.emplace_back(lon_diff);
- last_coordinate = segment.location;
- }
- }
- encodeVectorSignedNumber(delta_numbers, output);
+ return {};
}
- JSON::String return_value(output);
- return return_value;
-}
-JSON::Array
-PolylineCompressor::printUnencodedString(const std::vector<SegmentInformation> &polyline) const
-{
- JSON::Array json_geometry_array;
+ std::vector<int> delta_numbers;
+ delta_numbers.reserve((polyline.size() - 1) * 2);
+ FixedPointCoordinate previous_coordinate = {0, 0};
for (const auto &segment : polyline)
{
if (segment.necessary)
{
- 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);
+ const int lat_diff = segment.location.lat - previous_coordinate.lat;
+ const int lon_diff = segment.location.lon - previous_coordinate.lon;
+ delta_numbers.emplace_back(lat_diff);
+ delta_numbers.emplace_back(lon_diff);
+ previous_coordinate = segment.location;
}
}
- return json_geometry_array;
+ return encode_vector(delta_numbers);
}
diff --git a/3party/osrm/osrm-backend/Algorithms/PolylineCompressor.h b/3party/osrm/osrm-backend/algorithms/polyline_compressor.hpp
index 5472bd808a..933ac7afab 100644..100755
--- a/3party/osrm/osrm-backend/Algorithms/PolylineCompressor.h
+++ b/3party/osrm/osrm-backend/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,
@@ -30,22 +30,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct SegmentInformation;
-#include "../DataStructures/JSONContainer.h"
-
#include <string>
#include <vector>
class PolylineCompressor
{
private:
- void encodeVectorSignedNumber(std::vector<int> &numbers, std::string &output) const;
+ std::string encode_vector(std::vector<int> &numbers) const;
- void encodeNumber(int number_to_encode, std::string &output) const;
+ std::string encode_number(const int number_to_encode) const;
public:
- JSON::String printEncodedString(const std::vector<SegmentInformation> &polyline) const;
-
- JSON::Array printUnencodedString(const std::vector<SegmentInformation> &polyline) const;
+ std::string get_encoded_string(const std::vector<SegmentInformation> &polyline) const;
};
#endif /* POLYLINECOMPRESSOR_H_ */
diff --git a/3party/osrm/osrm-backend/Util/Azimuth.h b/3party/osrm/osrm-backend/algorithms/polyline_formatter.cpp
index c4bf815bde..670a6121ff 100644..100755
--- a/3party/osrm/osrm-backend/Util/Azimuth.h
+++ b/3party/osrm/osrm-backend/algorithms/polyline_formatter.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,49 +25,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef AZIMUTH_H
-#define AZIMUTH_H
+#include "polyline_formatter.hpp"
-#include <string>
+#include "polyline_compressor.hpp"
+#include "../data_structures/segment_information.hpp"
-struct Azimuth
+#include <osrm/coordinate.hpp>
+
+osrm::json::String
+PolylineFormatter::printEncodedString(const std::vector<SegmentInformation> &polyline) const
+{
+ return osrm::json::String(PolylineCompressor().get_encoded_string(polyline));
+}
+
+osrm::json::Array
+PolylineFormatter::printUnencodedString(const std::vector<SegmentInformation> &polyline) const
{
- static std::string Get(const double heading)
+ osrm::json::Array json_geometry_array;
+ for (const auto &segment : polyline)
{
- 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 (segment.necessary)
{
- return "SW";
+ 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);
}
- if (heading > 247.5 && heading <= 292.5)
- {
- return "W";
- }
- if (heading > 292.5 && heading <= 337.5)
- {
- return "NW";
- }
- return "N";
}
-};
-
-#endif // AZIMUTH_H
+ return json_geometry_array;
+}
diff --git a/3party/osrm/osrm-backend/algorithms/polyline_formatter.hpp b/3party/osrm/osrm-backend/algorithms/polyline_formatter.hpp
new file mode 100755
index 0000000000..68cc70293e
--- /dev/null
+++ b/3party/osrm/osrm-backend/algorithms/polyline_formatter.hpp
@@ -0,0 +1,45 @@
+/*
+
+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.
+
+*/
+
+#ifndef POLYLINE_FORMATTER_HPP
+#define POLYLINE_FORMATTER_HPP
+
+struct SegmentInformation;
+
+#include <osrm/json_container.hpp>
+
+#include <string>
+#include <vector>
+
+struct PolylineFormatter
+{
+ osrm::json::String printEncodedString(const std::vector<SegmentInformation> &polyline) const;
+
+ osrm::json::Array printUnencodedString(const std::vector<SegmentInformation> &polyline) const;
+};
+
+#endif /* POLYLINE_FORMATTER_HPP */
diff --git a/3party/osrm/osrm-backend/Algorithms/ExtractRouteNames.h b/3party/osrm/osrm-backend/algorithms/route_name_extraction.hpp
index 519452f986..00dae89c4a 100644..100755
--- a/3party/osrm/osrm-backend/Algorithms/ExtractRouteNames.h
+++ b/3party/osrm/osrm-backend/algorithms/route_name_extraction.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -54,7 +54,8 @@ template <class DataFacadeT, class SegmentT> 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 <class DataFacadeT, class SegmentT> 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 <class DataFacadeT, class SegmentT> 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 <class DataFacadeT, class SegmentT> struct ExtractRouteNames
// alternative
std::vector<SegmentT> 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(shortest_path_set_difference.begin(),
- shortest_path_set_difference.end(),
+ 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(),
length_comperator);
shortest_segment_2 =
PickNextLongestSegment(shortest_path_set_difference, shortest_segment_1.name_id);
@@ -116,29 +117,23 @@ template <class DataFacadeT, class SegmentT> 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<SegmentT> 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::sort(alternative_path_set_difference.begin(),
- alternative_path_set_difference.end(),
+ 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(),
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.
@@ -152,15 +147,13 @@ template <class DataFacadeT, class SegmentT> 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/3party/osrm/osrm-backend/algorithms/tiny_components.hpp b/3party/osrm/osrm-backend/algorithms/tiny_components.hpp
new file mode 100755
index 0000000000..8eb61a9128
--- /dev/null
+++ b/3party/osrm/osrm-backend/algorithms/tiny_components.hpp
@@ -0,0 +1,239 @@
+/*
+
+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 TINY_COMPONENTS_HPP
+#define TINY_COMPONENTS_HPP
+
+#include "../typedefs.h"
+#include "../data_structures/deallocating_vector.hpp"
+#include "../data_structures/import_edge.hpp"
+#include "../data_structures/query_node.hpp"
+#include "../data_structures/percent.hpp"
+#include "../data_structures/restriction.hpp"
+#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 <osrm/coordinate.hpp>
+
+#include <boost/assert.hpp>
+
+#include <tbb/parallel_sort.h>
+
+#include <cstdint>
+
+#include <memory>
+#include <stack>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+template <typename GraphT> class TarjanSCC
+{
+ struct TarjanStackFrame
+ {
+ explicit TarjanStackFrame(NodeID v, NodeID parent) : v(v), parent(parent) {}
+ NodeID v;
+ NodeID parent;
+ };
+
+ struct TarjanNode
+ {
+ TarjanNode() : index(SPECIAL_NODEID), low_link(SPECIAL_NODEID), on_stack(false) {}
+ unsigned index;
+ unsigned low_link;
+ bool on_stack;
+ };
+
+ std::vector<unsigned> components_index;
+ std::vector<NodeID> component_size_vector;
+ std::shared_ptr<GraphT> m_node_based_graph;
+ std::unordered_set<NodeID> barrier_node_set;
+ RestrictionMap m_restriction_map;
+ std::size_t size_one_counter;
+
+ public:
+ template <class ContainerT>
+ TarjanSCC(std::shared_ptr<GraphT> 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)
+ {
+ barrier_node_set.insert(std::begin(barrier_node_list), std::end(barrier_node_list));
+ BOOST_ASSERT(m_node_based_graph->GetNumberOfNodes() > 0);
+ }
+
+ 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<TarjanStackFrame> recursion_stack;
+ // true = stuff before, false = stuff after call
+ std::stack<NodeID> tarjan_stack;
+ std::vector<TarjanNode> tarjan_node_list(max_node_id);
+ unsigned component_index = 0, size_of_current_component = 0;
+ unsigned index = 0;
+ std::vector<bool> processing_node_before_recursion(max_node_id, true);
+ for (const NodeID node : osrm::irange(0u, max_node_id))
+ {
+ if (SPECIAL_NODEID == components_index[node])
+ {
+ recursion_stack.emplace(TarjanStackFrame(node, node));
+ }
+
+ while (!recursion_stack.empty())
+ {
+ TarjanStackFrame currentFrame = recursion_stack.top();
+ const NodeID u = currentFrame.parent;
+ const NodeID v = currentFrame.v;
+ recursion_stack.pop();
+
+ const bool before_recursion = processing_node_before_recursion[v];
+
+ if (before_recursion && tarjan_node_list[v].index != UINT_MAX)
+ {
+ continue;
+ }
+
+ if (before_recursion)
+ {
+ // Mark frame to handle tail of recursion
+ recursion_stack.emplace(currentFrame);
+ processing_node_before_recursion[v] = false;
+
+ // Mark essential information for SCC
+ tarjan_node_list[v].index = index;
+ tarjan_node_list[v].low_link = index;
+ tarjan_stack.push(v);
+ tarjan_node_list[v].on_stack = true;
+ ++index;
+
+ const NodeID to_node_of_only_restriction =
+ m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
+
+ for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(v))
+ {
+ 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)
+ {
+ // continue;
+ }
+
+ if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
+ vprime == to_node_of_only_restriction)
+ {
+ // At an only_-restriction but not at the right turn
+ // continue;
+ }
+
+ if (m_restriction_map.CheckIfTurnIsRestricted(u, v, vprime))
+ {
+ // continue;
+ }
+
+ if (SPECIAL_NODEID == tarjan_node_list[vprime].index)
+ {
+ recursion_stack.emplace(TarjanStackFrame(vprime, v));
+ }
+ else
+ {
+ if (tarjan_node_list[vprime].on_stack &&
+ tarjan_node_list[vprime].index < tarjan_node_list[v].low_link)
+ {
+ tarjan_node_list[v].low_link = tarjan_node_list[vprime].index;
+ }
+ }
+ }
+ }
+ else
+ {
+ processing_node_before_recursion[v] = true;
+ tarjan_node_list[currentFrame.parent].low_link =
+ std::min(tarjan_node_list[currentFrame.parent].low_link,
+ tarjan_node_list[v].low_link);
+ // after recursion, lets do cycle checking
+ // Check if we found a cycle. This is the bottom part of the recursion
+ if (tarjan_node_list[v].low_link == tarjan_node_list[v].index)
+ {
+ NodeID vprime;
+ do
+ {
+ vprime = tarjan_stack.top();
+ tarjan_stack.pop();
+ tarjan_node_list[vprime].on_stack = false;
+ components_index[vprime] = component_index;
+ ++size_of_current_component;
+ } while (v != vprime);
+
+ component_size_vector.emplace_back(size_of_current_component);
+
+ if (size_of_current_component > 1000)
+ {
+ SimpleLogger().Write() << "large component [" << component_index
+ << "]=" << size_of_current_component;
+ }
+
+ ++component_index;
+ size_of_current_component = 0;
+ }
+ }
+ }
+ }
+
+ TIMER_STOP(SCC_RUN);
+ 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(),
+ [](unsigned value)
+ {
+ return 1 == value;
+ });
+ }
+
+ std::size_t get_number_of_components() const { return component_size_vector.size(); }
+
+ std::size_t 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]; }
+};
+
+#endif /* TINY_COMPONENTS_HPP */
diff --git a/3party/osrm/osrm-backend/appveyor.yml b/3party/osrm/osrm-backend/appveyor.yml
index 9c3dcdee24..afb8dd4061 100644..100755
--- a/3party/osrm/osrm-backend/appveyor.yml
+++ b/3party/osrm/osrm-backend/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
@@ -38,13 +35,18 @@ build_script:
- SET P=c:/projects/osrm
- set TBB_INSTALL_DIR=%P%/tbb
- set TBB_ARCH_PLATFORM=intel64/vc12
- - cmake .. -G "Visual Studio 12 Win64" -DCMAKE_BUILD_TYPE=%Configuration% -DBZIP2_INCLUDE_DIR=%P%/libs/include -DBZIP2_LIBRARIES=%P%/libs/lib/libbz2.lib -DCMAKE_INSTALL_PREFIX=%P%/libs -DBOOST_ROOT=%P%/boost_min -DBoost_USE_STATIC_LIBS=ON -T CTP_Nov2013
+ - cmake .. -G "Visual Studio 12 Win64" -DCMAKE_BUILD_TYPE=%Configuration% -DCMAKE_INSTALL_PREFIX=%P%/libs -DBOOST_ROOT=%P%/boost_min -DBoost_ADDITIONAL_VERSIONS=1.57 -DBoost_USE_STATIC_LIBS=ON -T CTP_Nov2013
- msbuild /clp:Verbosity=minimal /nologo OSRM.sln
- msbuild /clp:Verbosity=minimal /nologo tests.vcxproj
+ - cd %Configuration%
- if "%APPVEYOR_REPO_BRANCH%"=="develop" (7z a %P%/osrm_%Configuration%.zip *.exe *.pdb %P%/libs/bin/*.dll -tzip)
+ - cd ..\..\profiles
+ - echo disk=c:\temp\stxxl,10000,wincall > .stxxl.txt
+ - if "%APPVEYOR_REPO_BRANCH%"=="develop" (7z a %P%/osrm_%Configuration%.zip * -tzip)
- set PATH=%PATH%;c:/projects/osrm/libs/bin
- cd c:/projects/osrm/build/%Configuration%
- datastructure-tests.exe
+ - algorithm-tests.exe
test: off
diff --git a/3party/osrm/osrm-backend/benchmarks/static_rtree.cpp b/3party/osrm/osrm-backend/benchmarks/static_rtree.cpp
new file mode 100755
index 0000000000..9d883311b0
--- /dev/null
+++ b/3party/osrm/osrm-backend/benchmarks/static_rtree.cpp
@@ -0,0 +1,184 @@
+/*
+
+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 "../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/boost_filesystem_2_fix.hpp"
+#include "../data_structures/edge_based_node.hpp"
+
+#include <osrm/coordinate.hpp>
+
+#include <random>
+
+// Choosen by a fair W20 dice roll (this value is completely arbitrary)
+constexpr unsigned RANDOM_SEED = 13;
+constexpr int32_t WORLD_MIN_LAT = -90 * COORDINATE_PRECISION;
+constexpr int32_t WORLD_MAX_LAT = 90 * COORDINATE_PRECISION;
+constexpr int32_t WORLD_MIN_LON = -180 * COORDINATE_PRECISION;
+constexpr int32_t WORLD_MAX_LON = 180 * COORDINATE_PRECISION;
+
+using RTreeLeaf = EdgeBasedNode;
+using FixedPointCoordinateListPtr = std::shared_ptr<std::vector<FixedPointCoordinate>>;
+using BenchStaticRTree = StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, false>::vector, false>;
+
+FixedPointCoordinateListPtr LoadCoordinates(const boost::filesystem::path &nodes_file)
+{
+ boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary);
+
+ QueryNode current_node;
+ unsigned coordinate_count = 0;
+ nodes_input_stream.read((char *)&coordinate_count, sizeof(unsigned));
+ auto coords = std::make_shared<std::vector<FixedPointCoordinate>>(coordinate_count);
+ for (unsigned i = 0; i < coordinate_count; ++i)
+ {
+ nodes_input_stream.read((char *)&current_node, sizeof(QueryNode));
+ coords->at(i) = FixedPointCoordinate(current_node.lat, current_node.lon);
+ BOOST_ASSERT((std::abs(coords->at(i).lat) >> 30) == 0);
+ BOOST_ASSERT((std::abs(coords->at(i).lon) >> 30) == 0);
+ }
+ nodes_input_stream.close();
+ return coords;
+}
+
+void Benchmark(BenchStaticRTree &rtree, unsigned num_queries)
+{
+ std::mt19937 mt_rand(RANDOM_SEED);
+ std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT);
+ std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON);
+ std::vector<FixedPointCoordinate> queries;
+ for (unsigned i = 0; i < num_queries; i++)
+ {
+ queries.emplace_back(FixedPointCoordinate(lat_udist(mt_rand), lon_udist(mt_rand)));
+ }
+
+ {
+ const unsigned num_results = 5;
+ std::cout << "#### IncrementalFindPhantomNodeForCoordinate : " << num_results
+ << " phantom nodes"
+ << "\n";
+
+ TIMER_START(query_phantom);
+ std::vector<PhantomNode> phantom_node_vector;
+ for (const auto &q : queries)
+ {
+ phantom_node_vector.clear();
+ rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 3, num_results);
+ phantom_node_vector.clear();
+ rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 17, num_results);
+ }
+ TIMER_STOP(query_phantom);
+
+ std::cout << "Took " << TIMER_MSEC(query_phantom) << " msec for " << num_queries
+ << " queries."
+ << "\n";
+ std::cout << TIMER_MSEC(query_phantom) / ((double)num_queries) << " msec/query."
+ << "\n";
+
+ std::cout << "#### LocateClosestEndPointForCoordinate"
+ << "\n";
+ }
+
+ TIMER_START(query_endpoint);
+ FixedPointCoordinate result;
+ for (const auto &q : queries)
+ {
+ rtree.LocateClosestEndPointForCoordinate(q, result, 3);
+ }
+ TIMER_STOP(query_endpoint);
+
+ std::cout << "Took " << TIMER_MSEC(query_endpoint) << " msec for " << num_queries << " queries."
+ << "\n";
+ std::cout << TIMER_MSEC(query_endpoint) / ((double)num_queries) << " msec/query."
+ << "\n";
+
+ std::cout << "#### FindPhantomNodeForCoordinate"
+ << "\n";
+
+ TIMER_START(query_node);
+ for (const auto &q : queries)
+ {
+ PhantomNode phantom;
+ rtree.FindPhantomNodeForCoordinate(q, phantom, 3);
+ }
+ TIMER_STOP(query_node);
+
+ 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";
+
+ {
+ const unsigned num_results = 1;
+ std::cout << "#### IncrementalFindPhantomNodeForCoordinate : " << num_results
+ << " phantom nodes"
+ << "\n";
+
+ TIMER_START(query_phantom);
+ std::vector<PhantomNode> phantom_node_vector;
+ for (const auto &q : queries)
+ {
+ phantom_node_vector.clear();
+ rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 3, num_results);
+ phantom_node_vector.clear();
+ rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 17, num_results);
+ }
+ TIMER_STOP(query_phantom);
+
+ std::cout << "Took " << TIMER_MSEC(query_phantom) << " msec for " << num_queries
+ << " queries."
+ << "\n";
+ std::cout << TIMER_MSEC(query_phantom) / ((double)num_queries) << " msec/query."
+ << "\n";
+
+ std::cout << "#### LocateClosestEndPointForCoordinate"
+ << "\n";
+ }
+}
+
+int main(int argc, char **argv)
+{
+ if (argc < 4)
+ {
+ std::cout << "./rtree-bench file.ramIndex file.fileIndx file.nodes"
+ << "\n";
+ return 1;
+ }
+
+ const char *ramPath = argv[1];
+ const char *filePath = argv[2];
+ const char *nodesPath = argv[3];
+
+ auto coords = LoadCoordinates(nodesPath);
+
+ BenchStaticRTree rtree(ramPath, filePath, coords);
+
+ Benchmark(rtree, 10000);
+
+ return 0;
+}
diff --git a/3party/osrm/osrm-backend/cmake/CPackDebianConfig.cmake b/3party/osrm/osrm-backend/cmake/CPackDebianConfig.cmake
index 065c429001..065c429001 100644..100755
--- a/3party/osrm/osrm-backend/cmake/CPackDebianConfig.cmake
+++ b/3party/osrm/osrm-backend/cmake/CPackDebianConfig.cmake
diff --git a/3party/osrm/osrm-backend/cmake/CheckCXXCompilerFlag.cmake b/3party/osrm/osrm-backend/cmake/CheckCXXCompilerFlag.cmake
index e396f75a92..e396f75a92 100644..100755
--- a/3party/osrm/osrm-backend/cmake/CheckCXXCompilerFlag.cmake
+++ b/3party/osrm/osrm-backend/cmake/CheckCXXCompilerFlag.cmake
diff --git a/3party/osrm/osrm-backend/cmake/FindDebArch.cmake b/3party/osrm/osrm-backend/cmake/FindDebArch.cmake
index 5b405bc39b..5b405bc39b 100644..100755
--- a/3party/osrm/osrm-backend/cmake/FindDebArch.cmake
+++ b/3party/osrm/osrm-backend/cmake/FindDebArch.cmake
diff --git a/3party/osrm/osrm-backend/cmake/FindLua52.cmake b/3party/osrm/osrm-backend/cmake/FindLua52.cmake
index 04dcf7ac7f..d17fbf61d3 100644..100755
--- a/3party/osrm/osrm-backend/cmake/FindLua52.cmake
+++ b/3party/osrm/osrm-backend/cmake/FindLua52.cmake
@@ -79,3 +79,4 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lua52
VERSION_VAR LUA_VERSION_STRING)
mark_as_advanced(LUA_INCLUDE_DIR LUA_LIBRARIES LUA_LIBRARY LUA_MATH_LIBRARY)
+
diff --git a/3party/osrm/osrm-backend/cmake/FindLuaJIT.cmake b/3party/osrm/osrm-backend/cmake/FindLuaJIT.cmake
index 5d5e6aceb4..5d5e6aceb4 100644..100755
--- a/3party/osrm/osrm-backend/cmake/FindLuaJIT.cmake
+++ b/3party/osrm/osrm-backend/cmake/FindLuaJIT.cmake
diff --git a/3party/osrm/osrm-backend/cmake/FindLuabind.cmake b/3party/osrm/osrm-backend/cmake/FindLuabind.cmake
index 4b99b3c0e6..4b99b3c0e6 100644..100755
--- a/3party/osrm/osrm-backend/cmake/FindLuabind.cmake
+++ b/3party/osrm/osrm-backend/cmake/FindLuabind.cmake
diff --git a/3party/osrm/osrm-backend/cmake/FindOSMPBF.cmake b/3party/osrm/osrm-backend/cmake/FindOSMPBF.cmake
index ca310a491a..78b1d9dc82 100644..100755
--- a/3party/osrm/osrm-backend/cmake/FindOSMPBF.cmake
+++ b/3party/osrm/osrm-backend/cmake/FindOSMPBF.cmake
@@ -51,4 +51,4 @@ IF( NOT OSMPBF_FIND_QUIETLY )
ENDIF()
ENDIF()
-#MARK_AS_ADVANCED(OSMPBF_INCLUDE_DIR OSMPBF_LIBRARIES OSMPBF_LIBRARY OSMPBF_LIBRARY_DBG)
+#MARK_AS_ADVANCED(OSMPBF_INCLUDE_DIR OSMPBF_LIBRARIES OSMPBF_LIBRARY OSMPBF_LIBRARY_DBG)
diff --git a/3party/osrm/osrm-backend/cmake/FindSTXXL.cmake b/3party/osrm/osrm-backend/cmake/FindSTXXL.cmake
index 76a2722b03..76a2722b03 100644..100755
--- a/3party/osrm/osrm-backend/cmake/FindSTXXL.cmake
+++ b/3party/osrm/osrm-backend/cmake/FindSTXXL.cmake
diff --git a/3party/osrm/osrm-backend/cmake/FindTBB.cmake b/3party/osrm/osrm-backend/cmake/FindTBB.cmake
index 886d72e923..e5ca100391 100644..100755
--- a/3party/osrm/osrm-backend/cmake/FindTBB.cmake
+++ b/3party/osrm/osrm-backend/cmake/FindTBB.cmake
@@ -193,7 +193,7 @@ mark_as_advanced(TBB_INCLUDE_DIR)
#-- Look for libraries
# GvdB: $ENV{TBB_ARCH_PLATFORM} is set by the build script tbbvars[.bat|.sh|.csh]
if (NOT $ENV{TBB_ARCH_PLATFORM} STREQUAL "")
- set (_TBB_LIBRARY_DIR
+ set (_TBB_LIBRARY_DIR
${_TBB_INSTALL_DIR}/lib/$ENV{TBB_ARCH_PLATFORM}
${_TBB_INSTALL_DIR}/$ENV{TBB_ARCH_PLATFORM}/lib
)
diff --git a/3party/osrm/osrm-backend/cmake/FingerPrint-Config.cmake b/3party/osrm/osrm-backend/cmake/FingerPrint-Config.cmake
index 7b45d5cfc0..a3325d3059 100644..100755
--- a/3party/osrm/osrm-backend/cmake/FingerPrint-Config.cmake
+++ b/3party/osrm/osrm-backend/cmake/FingerPrint-Config.cmake
@@ -1,10 +1,10 @@
-set(OLDFILE ${SOURCE_DIR}/Util/FingerPrint.cpp)
+set(OLDFILE ${SOURCE_DIR}/util/fingerprint_impl.hpp)
if (EXISTS ${OLDFILE})
file(REMOVE_RECURSE ${OLDFILE})
endif()
file(MD5 ${SOURCE_DIR}/prepare.cpp MD5PREPARE)
-file(MD5 ${SOURCE_DIR}/DataStructures/StaticRTree.h MD5RTREE)
-file(MD5 ${SOURCE_DIR}/Util/GraphLoader.h MD5GRAPH)
-file(MD5 ${SOURCE_DIR}/Server/DataStructures/InternalDataFacade.h MD5OBJECTS)
+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/3party/osrm/osrm-backend/cmake/GetGitRevisionDescription.cmake b/3party/osrm/osrm-backend/cmake/GetGitRevisionDescription.cmake
index 1bf0230088..1bf0230088 100644..100755
--- a/3party/osrm/osrm-backend/cmake/GetGitRevisionDescription.cmake
+++ b/3party/osrm/osrm-backend/cmake/GetGitRevisionDescription.cmake
diff --git a/3party/osrm/osrm-backend/cmake/GetGitRevisionDescription.cmake.in b/3party/osrm/osrm-backend/cmake/GetGitRevisionDescription.cmake.in
index 6faa374a8d..888ce13aab 100644..100755
--- a/3party/osrm/osrm-backend/cmake/GetGitRevisionDescription.cmake.in
+++ b/3party/osrm/osrm-backend/cmake/GetGitRevisionDescription.cmake.in
@@ -1,4 +1,4 @@
-#
+#
# Internal file for GetGitRevisionDescription.cmake
#
# Requires CMake 2.6 or newer (uses the 'function' command)
diff --git a/3party/osrm/osrm-backend/cmake/check_luabind.cmake b/3party/osrm/osrm-backend/cmake/check_luabind.cmake
index 18f065666b..18f065666b 100644..100755
--- a/3party/osrm/osrm-backend/cmake/check_luabind.cmake
+++ b/3party/osrm/osrm-backend/cmake/check_luabind.cmake
diff --git a/3party/osrm/osrm-backend/cmake/cmake_options_script.py b/3party/osrm/osrm-backend/cmake/cmake_options_script.py
index 52e943e799..52e943e799 100644..100755
--- a/3party/osrm/osrm-backend/cmake/cmake_options_script.py
+++ b/3party/osrm/osrm-backend/cmake/cmake_options_script.py
diff --git a/3party/osrm/osrm-backend/cmake/pkgconfig.in b/3party/osrm/osrm-backend/cmake/pkgconfig.in
index e81febad8b..e81febad8b 100644..100755
--- a/3party/osrm/osrm-backend/cmake/pkgconfig.in
+++ b/3party/osrm/osrm-backend/cmake/pkgconfig.in
diff --git a/3party/osrm/osrm-backend/cmake/postinst.in b/3party/osrm/osrm-backend/cmake/postinst.in
index 92f2fde4fb..92f2fde4fb 100644..100755
--- a/3party/osrm/osrm-backend/cmake/postinst.in
+++ b/3party/osrm/osrm-backend/cmake/postinst.in
diff --git a/3party/osrm/osrm-backend/config/cucumber.yml b/3party/osrm/osrm-backend/config/cucumber.yml
index 2cdea36886..2cdea36886 100644..100755
--- a/3party/osrm/osrm-backend/config/cucumber.yml
+++ b/3party/osrm/osrm-backend/config/cucumber.yml
diff --git a/3party/osrm/osrm-backend/Contractor/Contractor.h b/3party/osrm/osrm-backend/contractor/contractor.hpp
index 9e1214f630..ccfabbc8f3 100644..100755
--- a/3party/osrm/osrm-backend/Contractor/Contractor.h
+++ b/3party/osrm/osrm-backend/contractor/contractor.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,20 +25,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef CONTRACTOR_H
-#define CONTRACTOR_H
-
-#include "../DataStructures/BinaryHeap.h"
-#include "../DataStructures/DeallocatingVector.h"
-#include "../DataStructures/DynamicGraph.h"
-#include "../DataStructures/Percent.h"
-#include "../DataStructures/QueryEdge.h"
-#include "../DataStructures/Range.h"
-#include "../DataStructures/XORFastHash.h"
-#include "../DataStructures/XORFastHashStorage.h"
-#include "../Util/simple_logger.hpp"
-#include "../Util/StringUtil.h"
-#include "../Util/TimingUtil.h"
+#ifndef CONTRACTOR_HPP
+#define CONTRACTOR_HPP
+
+#include "../data_structures/binary_heap.hpp"
+#include "../data_structures/deallocating_vector.hpp"
+#include "../data_structures/dynamic_graph.hpp"
+#include "../data_structures/percent.hpp"
+#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 "../typedefs.h"
#include <boost/assert.hpp>
@@ -93,9 +92,11 @@ class Contractor
};
using ContractorGraph = DynamicGraph<ContractorEdgeData>;
- // using ContractorHeap = BinaryHeap<NodeID, NodeID, int, ContractorHeapData, ArrayStorage<NodeID, NodeID>
+ // using ContractorHeap = BinaryHeap<NodeID, NodeID, int, ContractorHeapData,
+ // ArrayStorage<NodeID, NodeID>
// >;
- using ContractorHeap = BinaryHeap<NodeID, NodeID, int, ContractorHeapData, XORFastHashStorage<NodeID, NodeID>>;
+ using ContractorHeap =
+ BinaryHeap<NodeID, NodeID, int, ContractorHeapData, XORFastHashStorage<NodeID, NodeID>>;
using ContractorEdge = ContractorGraph::InputEdge;
struct ContractorThreadData
@@ -132,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<ContractorThreadData>(number_of_nodes);
@@ -150,7 +150,8 @@ class Contractor
}
int number_of_nodes;
- using EnumerableThreadData = tbb::enumerable_thread_specific<std::shared_ptr<ContractorThreadData>>;
+ using EnumerableThreadData =
+ tbb::enumerable_thread_specific<std::shared_ptr<ContractorThreadData>>;
EnumerableThreadData data;
};
@@ -163,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<unsigned int>(std::max(diter->weight, 1)) > 0, "edge distance < 1");
+ BOOST_ASSERT_MSG(static_cast<unsigned int>(std::max(diter->weight, 1)) > 0,
+ "edge distance < 1");
#ifndef NDEBUG
if (static_cast<unsigned int>(std::max(diter->weight, 1)) > 24 * 60 * 60 * 10)
{
- SimpleLogger().Write(logWARNING) << "Edge weight large -> "
- << static_cast<unsigned int>(std::max(diter->weight, 1));
+ SimpleLogger().Write(logWARNING)
+ << "Edge weight large -> "
+ << static_cast<unsigned int>(std::max(diter->weight, 1));
}
#endif
edges.emplace_back(diter->source, diter->target,
- static_cast<unsigned int>(std::max(diter->weight, 1)),
- 1,
- diter->edge_id,
- false,
- diter->forward ? true : false,
- diter->backward ? true : false);
+ static_cast<unsigned int>(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<unsigned int>(std::max(diter->weight, 1)),
- 1,
- diter->edge_id,
- false,
- diter->backward ? true : false,
- diter->forward ? true : false);
+ static_cast<unsigned int>(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();
@@ -283,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);
@@ -308,30 +305,28 @@ class Contractor
std::vector<float> node_priorities(number_of_nodes);
std::vector<NodePriorityData> node_data(number_of_nodes);
-
// initialize priorities in parallel
tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, InitGrainSize),
- [&remaining_nodes](const tbb::blocked_range<int>& range)
- {
- for (int x = range.begin(); x != range.end(); ++x)
- {
- remaining_nodes[x].id = x;
- }
- }
- );
-
+ [&remaining_nodes](const tbb::blocked_range<int> &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<int>(0, number_of_nodes, PQGrainSize),
- [this, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range<int>& 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<int> &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;
@@ -369,7 +364,8 @@ class Contractor
remaining_nodes[new_node_id].id = new_node_id;
}
// walk over all nodes
- for (const auto i : osrm::irange<std::size_t>(0, contractor_graph->GetNumberOfNodes()))
+ for (const auto i :
+ osrm::irange<std::size_t>(0, contractor_graph->GetNumberOfNodes()))
{
const NodeID source = i;
for (auto current_edge : contractor_graph->GetAdjacentEdgeRange(source))
@@ -385,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],
@@ -428,28 +422,30 @@ class Contractor
const int last = (int)remaining_nodes.size();
tbb::parallel_for(tbb::blocked_range<int>(0, last, IndependentGrainSize),
- [this, &node_priorities, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& 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(),
+ [this, &node_priorities, &remaining_nodes, &thread_data_list](
+ const tbb::blocked_range<int> &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(),
[](RemainingNodeData node_data)
- { return !node_data.is_independent; });
+ {
+ return !node_data.is_independent;
+ });
const int first_independent_node = static_cast<int>(first - remaining_nodes.begin());
// contract independent nodes
- tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, ContractGrainSize),
- [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range)
+ tbb::parallel_for(
+ tbb::blocked_range<int>(first_independent_node, last, ContractGrainSize),
+ [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range)
{
ContractorThreadData *data = thread_data_list.getThreadData();
for (int position = range.begin(); position != range.end(); ++position)
@@ -457,19 +453,18 @@ class Contractor
const NodeID x = remaining_nodes[position].id;
this->ContractNode<false>(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<int>(first_independent_node, last, DeleteGrainSize),
- [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range)
+ for (auto &data : range)
+ std::sort(data->inserted_edges.begin(), data->inserted_edges.end());
+ });
+ tbb::parallel_for(
+ tbb::blocked_range<int>(first_independent_node, last, DeleteGrainSize),
+ [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range)
{
ContractorThreadData *data = thread_data_list.getThreadData();
for (int position = range.begin(); position != range.end(); ++position)
@@ -477,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 &current_data =
@@ -504,8 +499,10 @@ class Contractor
data->inserted_edges.clear();
}
- tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, NeighboursGrainSize),
- [this, &remaining_nodes, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range<int>& range)
+ tbb::parallel_for(
+ tbb::blocked_range<int>(first_independent_node, last, NeighboursGrainSize),
+ [this, &remaining_nodes, &node_priorities, &node_data, &thread_data_list](
+ const tbb::blocked_range<int> &range)
{
ContractorThreadData *data = thread_data_list.getThreadData();
for (int position = range.begin(); position != range.end(); ++position)
@@ -513,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;
@@ -775,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);
}
}
}
@@ -884,10 +874,9 @@ class Contractor
return true;
}
- inline bool IsNodeIndependent(
- const std::vector<float> &priorities,
- ContractorThreadData *const data,
- NodeID node) const
+ inline bool IsNodeIndependent(const std::vector<float> &priorities,
+ ContractorThreadData *const data,
+ NodeID node) const
{
const float priority = priorities[node];
@@ -970,4 +959,4 @@ class Contractor
XORFastHash fast_hash;
};
-#endif // CONTRACTOR_H
+#endif // CONTRACTOR_HPP
diff --git a/3party/osrm/osrm-backend/Contractor/EdgeBasedGraphFactory.cpp b/3party/osrm/osrm-backend/contractor/edge_based_graph_factory.cpp
index fa0c4995e0..268bb9f8d0 100644..100755
--- a/3party/osrm/osrm-backend/Contractor/EdgeBasedGraphFactory.cpp
+++ b/3party/osrm/osrm-backend/contractor/edge_based_graph_factory.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,14 +25,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "EdgeBasedGraphFactory.h"
-#include "../Algorithms/BFSComponentExplorer.h"
-#include "../DataStructures/Percent.h"
-#include "../DataStructures/Range.h"
-#include "../Util/compute_angle.hpp"
-#include "../Util/LuaUtil.h"
-#include "../Util/simple_logger.hpp"
-#include "../Util/TimingUtil.h"
+#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 <boost/assert.hpp>
@@ -42,19 +42,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph,
- const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph_origin,
std::unique_ptr<RestrictionMap> restriction_map,
std::vector<NodeID> &barrier_node_list,
std::vector<NodeID> &traffic_light_node_list,
- std::vector<NodeInfo> &node_info_list,
+ std::vector<QueryNode> &node_info_list,
SpeedProfileProperties &speed_profile)
: speed_profile(speed_profile),
m_number_of_edge_based_nodes(std::numeric_limits<unsigned>::max()),
m_node_info_list(node_info_list), m_node_based_graph(node_based_graph),
- m_node_based_graph_origin(node_based_graph_origin),
- m_restriction_map(std::move(restriction_map)), max_id(0)
+ m_restriction_map(std::move(restriction_map)), max_id(0), removed_node_count(0)
{
-
// insert into unordered sets for fast lookup
m_barrier_nodes.insert(barrier_node_list.begin(), barrier_node_list.end());
m_traffic_lights.insert(traffic_light_node_list.begin(), traffic_light_node_list.end());
@@ -80,36 +77,25 @@ void EdgeBasedGraphFactory::GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes)
nodes.swap(m_edge_based_node_list);
}
-void EdgeBasedGraphFactory::GetEdgeBasedNodeData(osrm::NodeDataVectorT &data)
-{
- data.swap(m_edge_based_node_data);
-}
-
-void
-EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeID node_v, const bool belongs_to_tiny_cc)
+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);
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);
+ BOOST_ASSERT(edge_id_2 != SPECIAL_EDGEID);
-#ifndef NDEBUG
- if (e2 == 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);
+ const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(edge_id_2);
if (forward_data.edgeBasedNodeID == SPECIAL_NODEID &&
reverse_data.edgeBasedNodeID == SPECIAL_NODEID)
@@ -117,20 +103,20 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeID nod
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<GeometryCompressor::CompressedNode> &forward_geometry =
- m_geometry_compressor.GetBucketReference(e1);
+ m_geometry_compressor.GetBucketReference(edge_id_1);
const std::vector<GeometryCompressor::CompressedNode> &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 = forward_geometry.size();
+ const unsigned geometry_size = static_cast<unsigned>(forward_geometry.size());
BOOST_ASSERT(geometry_size > 1);
// reconstruct bidirectional edge with individual weights and put each into the NN index
@@ -178,22 +164,13 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeID nod
BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id);
// build edges
- m_edge_based_node_list.emplace_back(forward_data.way_id,
- reverse_data.way_id,
- 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),
- i,
- belongs_to_tiny_cc,
- 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(edge_id_1),
+ 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());
@@ -210,7 +187,7 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeID nod
}
else
{
- BOOST_ASSERT(!m_geometry_compressor.HasEntryForID(e2));
+ BOOST_ASSERT(!m_geometry_compressor.HasEntryForID(edge_id_2));
if (forward_data.edgeBasedNodeID != SPECIAL_NODEID)
{
@@ -232,22 +209,10 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeID nod
BOOST_ASSERT(forward_data.edgeBasedNodeID != SPECIAL_NODEID ||
reverse_data.edgeBasedNodeID != SPECIAL_NODEID);
- m_edge_based_node_list.emplace_back(forward_data.way_id,
- reverse_data.way_id,
- forward_data.edgeBasedNodeID,
- reverse_data.edgeBasedNodeID,
- node_u,
- node_v,
- forward_data.nameID,
- forward_data.distance,
- reverse_data.distance,
- 0,
- 0,
- SPECIAL_EDGEID,
- 0,
- belongs_to_tiny_cc,
- 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());
}
}
@@ -255,7 +220,8 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeID nod
void EdgeBasedGraphFactory::FlushVectorToStream(
std::ofstream &edge_data_file, std::vector<OriginalEdgeData> &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]),
@@ -284,10 +250,6 @@ void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
GenerateEdgeExpandedEdges(original_edge_data_filename, lua_state);
TIMER_STOP(generate_edges);
- TIMER_START(generate_node_data);
- GenerateEdgeBasedNodeData();
- TIMER_STOP(generate_node_data);
-
m_geometry_compressor.SerializeInternalVector(geometry_filename);
SimpleLogger().Write() << "Timing statistics for edge-expanded graph:";
@@ -295,7 +257,6 @@ void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
SimpleLogger().Write() << "Renumbering edges: " << TIMER_SEC(renumber) << "s";
SimpleLogger().Write() << "Generating nodes: " << TIMER_SEC(generate_nodes) << "s";
SimpleLogger().Write() << "Generating edges: " << TIMER_SEC(generate_edges) << "s";
- SimpleLogger().Write() << "Generating node data: " << TIMER_SEC(generate_node_data) << "s";
}
void EdgeBasedGraphFactory::CompressGeometry()
@@ -306,7 +267,6 @@ void EdgeBasedGraphFactory::CompressGeometry()
const unsigned original_number_of_edges = m_node_based_graph->GetNumberOfEdges();
Percent progress(original_number_of_nodes);
- unsigned removed_node_count = 0;
for (const NodeID node_v : osrm::irange(0u, original_number_of_nodes))
{
@@ -348,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);
@@ -358,15 +317,13 @@ 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;
}
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;
@@ -381,13 +338,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;
@@ -405,28 +361,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_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_weight1 +
- (add_traffic_signal_penalty ? speed_profile.traffic_signal_penalty : 0),
+ forward_e1, forward_e2, node_v, node_w,
+ 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_e1, reverse_e2, node_v, node_u, reverse_weight1,
+ reverse_weight2 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0));
++removed_node_count;
BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID ==
@@ -439,7 +388,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)
{
@@ -448,10 +397,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;
}
/**
@@ -461,10 +410,9 @@ void EdgeBasedGraphFactory::RenumberEdges()
{
// renumber edge based node IDs
unsigned numbered_edges_count = 0;
- for (NodeID current_node = 0; current_node < m_node_based_graph->GetNumberOfNodes();
- ++current_node)
+ for (const auto current_node : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
{
- for (EdgeID current_edge : m_node_based_graph->GetAdjacentEdgeRange(current_node))
+ for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(current_node))
{
EdgeData &edge_data = m_node_based_graph->GetEdgeData(current_edge);
if (!edge_data.forward)
@@ -482,157 +430,77 @@ void EdgeBasedGraphFactory::RenumberEdges()
m_number_of_edge_based_nodes = numbered_edges_count;
}
-void EdgeBasedGraphFactory::GenerateEdgeBasedNodeData()
-{
- BOOST_ASSERT(m_node_based_graph->GetNumberOfNodes() == m_node_based_graph_origin->GetNumberOfNodes());
-
- m_edge_based_node_data.resize(m_number_of_edge_based_nodes);
- std::vector<bool> found;
- found.resize(m_number_of_edge_based_nodes, false);
-
- for (NodeID current_node = 0; current_node < m_node_based_graph->GetNumberOfNodes();
- ++current_node)
- {
- for (EdgeID current_edge : m_node_based_graph->GetAdjacentEdgeRange(current_node))
- {
- EdgeData & edge_data = m_node_based_graph->GetEdgeData(current_edge);
- if (!edge_data.forward)
- {
- continue;
- }
-
- NodeID target = m_node_based_graph->GetTarget(current_edge);
-
- osrm::NodeData data;
- if (m_geometry_compressor.HasEntryForID(current_edge))
- {
- const std::vector<GeometryCompressor::CompressedNode> & via_nodes = m_geometry_compressor.GetBucketReference(current_edge);
- assert(via_nodes.size() > 0);
- std::vector< std::pair< NodeID, FixedPointCoordinate > > nodes;
- if (via_nodes.front().first != current_node)
- nodes.emplace_back(current_node, FixedPointCoordinate(m_node_info_list[current_node].lat, m_node_info_list[current_node].lon));
- for (auto n : via_nodes)
- nodes.emplace_back(n.first, FixedPointCoordinate(m_node_info_list[n.first].lat, m_node_info_list[n.first].lon));
- if (via_nodes.back().first != target)
- nodes.emplace_back(target, FixedPointCoordinate(m_node_info_list[target].lat, m_node_info_list[target].lon));
-
- for (uint32_t i = 1; i < nodes.size(); ++i)
- {
- auto n1 = nodes[i - 1];
- auto n2 = nodes[i];
-
- if (n1.first == n2.first)
- {
- SimpleLogger().Write() << "Error: Equal values " << n1.first << " and " << n2.first;
- SimpleLogger().Write() << "i: "<< i << " nodes: " << nodes.size();
- throw std::exception();
- }
-
- EdgeID e = m_node_based_graph_origin->FindEdge(n1.first, n2.first);
- if (e == SPECIAL_EDGEID)
- {
- SimpleLogger().Write() << "Error: Can't find edge between nodes " << n1.first << " and " << n2.first;
- continue;
- }
-
- EdgeData &ed = m_node_based_graph_origin->GetEdgeData(e);
-
- data.AddSegment(ed.way_id,
- m_node_info_list[n1.first].lat / COORDINATE_PRECISION,
- m_node_info_list[n1.first].lon / COORDINATE_PRECISION,
- m_node_info_list[n2.first].lat / COORDINATE_PRECISION,
- m_node_info_list[n2.first].lon / COORDINATE_PRECISION);
- }
-
- } else
- {
- data.AddSegment(edge_data.way_id,
- m_node_info_list[current_node].lat / COORDINATE_PRECISION,
- m_node_info_list[current_node].lon / COORDINATE_PRECISION,
- m_node_info_list[target].lat / COORDINATE_PRECISION,
- m_node_info_list[target].lon / COORDINATE_PRECISION);
- }
-
- if (found[edge_data.edgeBasedNodeID])
- {
- if (m_edge_based_node_data[edge_data.edgeBasedNodeID] != data)
- {
- std::cout << "Error!" << std::endl;
- throw std::exception();
- }
- } else
- {
- found[edge_data.edgeBasedNodeID] = true;
- m_edge_based_node_data[edge_data.edgeBasedNodeID] = data;
- }
- }
- }
-
- for (auto v : found)
- {
- if (!v)
- {
- std::cout << "Error2" << std::endl;
- throw std::exception();
- }
- }
-
- SimpleLogger().Write() << "Edge based node data count: " << m_edge_based_node_data.size();
-}
-
/**
* Creates the nodes in the edge expanded graph from edges in the node-based graph.
*/
void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
{
- SimpleLogger().Write() << "Identifying components of the road network";
+ SimpleLogger().Write() << "Identifying components of the (compressed) road network";
// Run a BFS on the undirected graph and identify small components
- BFSComponentExplorer<NodeBasedDynamicGraph> component_explorer(
- *m_node_based_graph, *m_restriction_map, m_barrier_nodes);
+ TarjanSCC<NodeBasedDynamicGraph> component_explorer(m_node_based_graph, *m_restriction_map,
+ m_barrier_nodes);
component_explorer.run();
- SimpleLogger().Write() << "identified: " << component_explorer.GetNumberOfComponents()
- << " many components";
+ 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
+ << " (compressed) SCCs of size 1";
SimpleLogger().Write() << "generating edge-expanded nodes";
Percent progress(m_node_based_graph->GetNumberOfNodes());
// loop over all edges and generate new set of nodes
- for (NodeID u = 0, end = m_node_based_graph->GetNumberOfNodes(); u < end; ++u)
+ 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.GetComponentSize(u),
- component_explorer.GetComponentSize(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 = [node_u, node_v, &component_explorer]
+ {
+ if (component_explorer.get_component_size(node_u) <
+ component_explorer.get_component_size(node_v))
+ {
+ return component_explorer.get_component_id(node_u);
+ }
+ 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)
{
- InsertEdgeBasedNode(v, u, component_is_tiny);
+ InsertEdgeBasedNode(node_v, node_u,
+ (component_is_tiny ? id_of_smaller_component + 1 : 0));
}
else
{
- InsertEdgeBasedNode(u, v, component_is_tiny);
+ InsertEdgeBasedNode(node_u, node_v,
+ (component_is_tiny ? id_of_smaller_component + 1 : 0));
}
}
}
@@ -644,9 +512,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";
@@ -671,10 +538,10 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
Percent progress(m_node_based_graph->GetNumberOfNodes());
- for (NodeID u = 0, end = m_node_based_graph->GetNumberOfNodes(); u < end; ++u)
+ 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)
{
@@ -682,21 +549,21 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
}
++node_based_edge_counter;
- const NodeID 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());
+ const NodeID node_v = m_node_based_graph->GetTarget(e1);
+ 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();
- for (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))
+ 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;
@@ -705,7 +572,7 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
if (is_barrier_node)
{
- if (u != w)
+ if (node_u != node_w)
{
++skipped_barrier_turns_counter;
continue;
@@ -713,7 +580,7 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
}
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;
@@ -722,9 +589,9 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
// 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) &&
- (to_node_of_only_restriction == SPECIAL_NODEID) &&
- (w != to_node_of_only_restriction))
+ if (m_restriction_map->CheckIfTurnIsRestricted(node_u, node_v, node_w) &&
+ (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;
@@ -741,26 +608,28 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
// 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;
}
// 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)
+ : 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)];
+ const auto third_coordinate =
+ m_node_info_list[(m_geometry_compressor.HasEntryForID(e2)
+ ? m_geometry_compressor.GetFirstNodeIDOfBucket(e2)
+ : 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;
@@ -775,10 +644,8 @@ 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_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : node_v),
+ edge_data1.nameID, turn_instruction, edge_is_compressed,
edge_data2.travel_mode);
++original_edges_counter;
@@ -791,12 +658,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));
}
}
}
@@ -827,7 +691,10 @@ int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) co
// call lua profile to compute turn penalty
return luabind::call_function<int>(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;
}
@@ -835,8 +702,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/3party/osrm/osrm-backend/Contractor/EdgeBasedGraphFactory.h b/3party/osrm/osrm-backend/contractor/edge_based_graph_factory.hpp
index 2362301794..95b65babc4 100644..100755
--- a/3party/osrm/osrm-backend/Contractor/EdgeBasedGraphFactory.h
+++ b/3party/osrm/osrm-backend/contractor/edge_based_graph_factory.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+Copyright (c) 2014, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -27,19 +27,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This class constructs the edge-expanded routing graph
-#ifndef EDGEBASEDGRAPHFACTORY_H_
-#define EDGEBASEDGRAPHFACTORY_H_
+#ifndef EDGE_BASED_GRAPH_FACTORY_HPP_
+#define EDGE_BASED_GRAPH_FACTORY_HPP_
+#include "geometry_compressor.hpp"
#include "../typedefs.h"
-#include "../DataStructures/DeallocatingVector.h"
-#include "../DataStructures/EdgeBasedNode.h"
-#include "../DataStructures/OriginalEdgeData.h"
-#include "../DataStructures/QueryNode.h"
-#include "../DataStructures/TurnInstructions.h"
-#include "../DataStructures/NodeBasedGraph.h"
-#include "../DataStructures/RestrictionMap.h"
-#include "../DataStructures/EdgeBasedNodeData.h"
-#include "GeometryCompressor.h"
+#include "../data_structures/deallocating_vector.hpp"
+#include "../data_structures/edge_based_node.hpp"
+#include "../data_structures/original_edge_data.hpp"
+#include "../data_structures/query_node.hpp"
+#include "../data_structures/turn_instructions.hpp"
+#include "../data_structures/node_based_graph.hpp"
+#include "../data_structures/restriction_map.hpp"
#include <algorithm>
#include <iosfwd>
@@ -61,11 +60,10 @@ class EdgeBasedGraphFactory
struct SpeedProfileProperties;
explicit EdgeBasedGraphFactory(const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph,
- const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph_origin,
std::unique_ptr<RestrictionMap> restricion_map,
std::vector<NodeID> &barrier_node_list,
std::vector<NodeID> &traffic_light_node_list,
- std::vector<NodeInfo> &m_node_info_list,
+ std::vector<QueryNode> &node_info_list,
SpeedProfileProperties &speed_profile);
void Run(const std::string &original_edge_data_filename,
@@ -76,8 +74,6 @@ class EdgeBasedGraphFactory
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
- void GetEdgeBasedNodeData(osrm::NodeDataVectorT &data);
-
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, const double angle) const;
int GetTurnPenalty(double angle, lua_State *lua_state) const;
@@ -101,33 +97,32 @@ class EdgeBasedGraphFactory
unsigned m_number_of_edge_based_nodes;
- std::vector<NodeInfo> m_node_info_list;
+ std::vector<QueryNode> m_node_info_list;
std::vector<EdgeBasedNode> m_edge_based_node_list;
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
std::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
- std::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph_origin;
std::unordered_set<NodeID> m_barrier_nodes;
std::unordered_set<NodeID> m_traffic_lights;
std::unique_ptr<RestrictionMap> m_restriction_map;
- std::vector<osrm::NodeData> m_edge_based_node_data;
GeometryCompressor m_geometry_compressor;
void CompressGeometry();
void RenumberEdges();
- void GenerateEdgeBasedNodeData();
void GenerateEdgeExpandedNodes();
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
lua_State *lua_state);
- void InsertEdgeBasedNode(const NodeID u, const NodeID v, const bool belongsToTinyComponent);
+ void InsertEdgeBasedNode(const NodeID u, const NodeID v, const unsigned component_id);
void FlushVectorToStream(std::ofstream &edge_data_file,
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
NodeID max_id;
+ std::size_t removed_node_count;
+
};
-#endif /* EDGEBASEDGRAPHFACTORY_H_ */
+#endif /* EDGE_BASED_GRAPH_FACTORY_HPP_ */
diff --git a/3party/osrm/osrm-backend/Contractor/GeometryCompressor.cpp b/3party/osrm/osrm-backend/contractor/geometry_compressor.cpp
index be4dc7afd5..3997cdc99d 100644..100755
--- a/3party/osrm/osrm-backend/Contractor/GeometryCompressor.cpp
+++ b/3party/osrm/osrm-backend/contractor/geometry_compressor.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "GeometryCompressor.h"
-#include "../Util/simple_logger.hpp"
+#include "geometry_compressor.hpp"
+#include "../util/simple_logger.hpp"
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
@@ -35,9 +35,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <limits>
#include <string>
-int free_list_maximum = 0;
-int UniqueNumber() { return ++free_list_maximum; }
-
GeometryCompressor::GeometryCompressor()
{
m_free_list.reserve(100);
@@ -174,8 +171,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 +208,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,15 +222,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/3party/osrm/osrm-backend/Contractor/GeometryCompressor.h b/3party/osrm/osrm-backend/contractor/geometry_compressor.hpp
index f0af3710c0..ca83fa44c9 100644..100755
--- a/3party/osrm/osrm-backend/Contractor/GeometryCompressor.h
+++ b/3party/osrm/osrm-backend/contractor/geometry_compressor.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, Project OSRM, Dennis Luxen, others
+Copyright (c) 2014, 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 GEOMETRY_COMPRESSOR_H
-#define GEOMETRY_COMPRESSOR_H
+#ifndef GEOMETRY_COMPRESSOR_HPP_
+#define GEOMETRY_COMPRESSOR_HPP_
#include "../typedefs.h"
@@ -58,10 +58,12 @@ class GeometryCompressor
NodeID GetLastNodeIDOfBucket(const EdgeID edge_id) const;
private:
+ int free_list_maximum = 0;
+
void IncreaseFreeList();
std::vector<std::vector<CompressedNode>> m_compressed_geometries;
std::vector<unsigned> m_free_list;
std::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map;
};
-#endif // GEOMETRY_COMPRESSOR_H
+#endif // GEOMETRY_COMPRESSOR_HPP_
diff --git a/3party/osrm/osrm-backend/Contractor/Prepare.cpp b/3party/osrm/osrm-backend/contractor/processing_chain.cpp
index 807b7560f9..ccff7fd093 100644..100755
--- a/3party/osrm/osrm-backend/Contractor/Prepare.cpp
+++ b/3party/osrm/osrm-backend/contractor/processing_chain.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,24 +25,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "Prepare.h"
+#include "processing_chain.hpp"
-#include "Contractor.h"
+#include "contractor.hpp"
-#include "../Algorithms/IteratorBasedCRC32.h"
-#include "../DataStructures/BinaryHeap.h"
-#include "../DataStructures/DeallocatingVector.h"
-#include "../DataStructures/Range.h"
-#include "../DataStructures/StaticRTree.h"
-#include "../DataStructures/RestrictionMap.h"
+#include "../algorithms/crc32_processor.hpp"
+#include "../data_structures/deallocating_vector.hpp"
+#include "../data_structures/static_rtree.hpp"
+#include "../data_structures/restriction_map.hpp"
-#include "../Util/GitDescription.h"
-#include "../Util/LuaUtil.h"
-#include "../Util/make_unique.hpp"
-#include "../Util/OSRMException.h"
-#include "../Util/simple_logger.hpp"
-#include "../Util/StringUtil.h"
-#include "../Util/TimingUtil.h"
+#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 <boost/filesystem/fstream.hpp>
@@ -117,7 +117,6 @@ int Prepare::Process(int argc, char *argv[])
graph_out = input_path.string() + ".hsgr";
rtree_nodes_path = input_path.string() + ".ramIndex";
rtree_leafs_path = input_path.string() + ".fileIndex";
- node_data_filename = input_path.string() + ".nodeData";
/*** Setup Scripting Environment ***/
// Create a new lua state
@@ -136,16 +135,12 @@ int Prepare::Process(int argc, char *argv[])
#ifdef WIN32
#pragma message("Memory consumption on Windows can be higher due to different bit packing")
#else
- static_assert(sizeof(ImportEdge) == 24,
+ 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())
@@ -163,11 +158,9 @@ int Prepare::Process(int argc, char *argv[])
DeallocatingVector<EdgeBasedEdge> 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);
@@ -344,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<boost::filesystem::path>(&config_file_path)
- ->default_value("contractor.ini"),
+ "config,c", boost::program_options::value<boost::filesystem::path>(&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
@@ -355,22 +347,18 @@ bool Prepare::ParseArguments(int argc, char *argv[])
"restrictions,r",
boost::program_options::value<boost::filesystem::path>(&restrictions_path),
"Restrictions file in .osrm.restrictions format")(
- "profile,p",
- boost::program_options::value<boost::filesystem::path>(&profile_path)
- ->default_value("profile.lua"),
+ "profile,p", boost::program_options::value<boost::filesystem::path>(&profile_path)
+ ->default_value("profile.lua"),
"Path to LUA routing profile")(
- "threads,t",
- boost::program_options::value<unsigned int>(&requested_num_threads)
- ->default_value(tbb::task_scheduler_init::default_num_threads()),
+ "threads,t", boost::program_options::value<unsigned int>(&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
- std::string string_input_path;
boost::program_options::options_description hidden_options("Hidden options");
hidden_options.add_options()(
- "input,i",
- boost::program_options::value<std::string>(&string_input_path),
+ "input,i", boost::program_options::value<boost::filesystem::path>(&input_path),
"Input file in .osm, .osm.bz2 or .osm.pbf format");
// positional option
@@ -396,6 +384,14 @@ bool Prepare::ParseArguments(int argc, char *argv[])
.run(),
option_variables);
+ const auto &temp_config_path = option_variables["config"].as<boost::filesystem::path>();
+ if (boost::filesystem::is_regular_file(temp_config_path))
+ {
+ boost::program_options::store(boost::program_options::parse_config_file<char>(
+ temp_config_path.string().c_str(), cmdline_options, true),
+ option_variables);
+ }
+
if (option_variables.count("version"))
{
SimpleLogger().Write() << g_GIT_DESCRIPTION;
@@ -421,8 +417,6 @@ bool Prepare::ParseArguments(int argc, char *argv[])
return false;
}
- input_path = boost::filesystem::path(string_input_path);
-
return true;
}
@@ -455,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);
@@ -507,19 +500,11 @@ Prepare::BuildEdgeExpandedGraph(lua_State *lua_state,
std::shared_ptr<NodeBasedDynamicGraph> node_based_graph =
NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list);
std::unique_ptr<RestrictionMap> restriction_map =
- std::unique_ptr<RestrictionMap>(new RestrictionMap(node_based_graph, restriction_list));
-
- std::shared_ptr<NodeBasedDynamicGraph> node_based_graph_origin =
- NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list);
-
+ osrm::make_unique<RestrictionMap>(restriction_list);
std::shared_ptr<EdgeBasedGraphFactory> edge_based_graph_factory =
- std::make_shared<EdgeBasedGraphFactory>(node_based_graph,
- node_based_graph_origin,
- std::move(restriction_map),
- barrier_node_list,
- traffic_light_list,
- internal_to_external_node_map,
- speed_profile);
+ std::make_shared<EdgeBasedGraphFactory>(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();
@@ -544,14 +529,6 @@ Prepare::BuildEdgeExpandedGraph(lua_State *lua_state,
edge_based_graph_factory->GetEdgeBasedEdges(edge_based_edge_list);
edge_based_graph_factory->GetEdgeBasedNodes(node_based_edge_list);
- // serialize node data
- osrm::NodeDataVectorT data;
- edge_based_graph_factory->GetEdgeBasedNodeData(data);
-
- SimpleLogger().Write() << "Serialize node data";
-
- osrm::SaveNodeDataToFile(node_data_filename, data);
-
edge_based_graph_factory.reset();
node_based_graph.reset();
@@ -570,7 +547,7 @@ void Prepare::WriteNodeMapping()
if (size_of_mapping > 0)
{
node_stream.write((char *)&(internal_to_external_node_map[0]),
- size_of_mapping * sizeof(NodeInfo));
+ size_of_mapping * sizeof(QueryNode));
}
node_stream.close();
internal_to_external_node_map.clear();
@@ -582,11 +559,9 @@ void Prepare::WriteNodeMapping()
Saves info to files: '.ramIndex' and '.fileIndex'.
*/
-void Prepare::BuildRTree(std::vector<EdgeBasedNode> &edge_based_node_list)
+void Prepare::BuildRTree(std::vector<EdgeBasedNode> &node_based_edge_list)
{
SimpleLogger().Write() << "building r-tree ...";
- StaticRTree<EdgeBasedNode>(edge_based_node_list,
- rtree_nodes_path.c_str(),
- rtree_leafs_path.c_str(),
- internal_to_external_node_map);
+ StaticRTree<EdgeBasedNode>(node_based_edge_list, rtree_nodes_path.c_str(),
+ rtree_leafs_path.c_str(), internal_to_external_node_map);
}
diff --git a/3party/osrm/osrm-backend/Contractor/Prepare.h b/3party/osrm/osrm-backend/contractor/processing_chain.hpp
index 9b9fa4c48c..933213a4c0 100644..100755
--- a/3party/osrm/osrm-backend/Contractor/Prepare.h
+++ b/3party/osrm/osrm-backend/contractor/processing_chain.hpp
@@ -1,14 +1,42 @@
-#ifndef PREPARE_H
-#define PREPARE_H
+/*
-#include "EdgeBasedGraphFactory.h"
-#include "../DataStructures/QueryEdge.h"
-#include "../DataStructures/StaticGraph.h"
-#include "../Util/GraphLoader.h"
+Copyright (c) 2014, Project OSRM, Dennis Luxen, others
+All rights reserved.
-#include <boost/filesystem.hpp>
+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 <luabind/luabind.hpp>
+#ifndef PROCESSING_CHAIN_HPP
+#define PROCESSING_CHAIN_HPP
+
+#include "edge_based_graph_factory.hpp"
+#include "../data_structures/query_edge.hpp"
+#include "../data_structures/static_graph.hpp"
+
+class FingerPrint;
+struct EdgeBasedNode;
+struct lua_State;
+
+#include <boost/filesystem.hpp>
#include <vector>
@@ -42,7 +70,7 @@ class Prepare
void BuildRTree(std::vector<EdgeBasedNode> &node_based_edge_list);
private:
- std::vector<NodeInfo> internal_to_external_node_map;
+ std::vector<QueryNode> internal_to_external_node_map;
std::vector<TurnRestriction> restriction_list;
std::vector<NodeID> barrier_node_list;
std::vector<NodeID> traffic_light_list;
@@ -62,7 +90,6 @@ class Prepare
std::string graph_out;
std::string rtree_nodes_path;
std::string rtree_leafs_path;
- std::string node_data_filename;
};
-#endif // PREPARE_H
+#endif // PROCESSING_CHAIN_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/BinaryHeap.h b/3party/osrm/osrm-backend/data_structures/binary_heap.hpp
index 24a65cbf08..a23a6b0f51 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/BinaryHeap.h
+++ b/3party/osrm/osrm-backend/data_structures/binary_heap.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -36,24 +36,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <type_traits>
#include <unordered_map>
#include <vector>
-#include <cstring>
template <typename NodeID, typename Key> class ArrayStorage
{
public:
- explicit ArrayStorage(size_t size) : positions(new Key[size])
- {
- memset(positions, 0, size * sizeof(Key));
- }
+ explicit ArrayStorage(size_t size) : positions(size, 0) {}
- ~ArrayStorage() { delete[] positions; }
+ ~ArrayStorage() {}
Key &operator[](NodeID node) { return positions[node]; }
+ Key peek_index(const NodeID node) const { return positions[node]; }
+
void Clear() {}
private:
- Key *positions;
+ std::vector<Key> positions;
};
template <typename NodeID, typename Key> class MapStorage
@@ -65,6 +63,16 @@ template <typename NodeID, typename Key> class MapStorage
void Clear() { nodes.clear(); }
+ Key peek_index(const NodeID node) const
+ {
+ const auto iter = nodes.find(node);
+ if (nodes.end() != iter)
+ {
+ return iter->second;
+ }
+ return std::numeric_limits<Key>::max();
+ }
+
private:
std::map<NodeID, Key> nodes;
};
@@ -76,6 +84,16 @@ template <typename NodeID, typename Key> 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 std::numeric_limits<Key>::max();
+ }
+
Key const &operator[](const NodeID node) const
{
auto iter = nodes.find(node);
@@ -132,13 +150,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,17 +166,17 @@ 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)
+ bool WasInserted(const NodeID node) const
{
- const Key index = node_index[node];
- if (index >= static_cast<Key>(inserted_nodes.size()))
+ const auto index = node_index.peek_index(node);
+ if (index >= static_cast<decltype(index)>(inserted_nodes.size()))
{
return false;
}
@@ -200,7 +218,7 @@ class BinaryHeap
void DecreaseKey(NodeID node, Weight weight)
{
BOOST_ASSERT(std::numeric_limits<NodeID>::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,12 +253,12 @@ class BinaryHeap
{
const Key droppingIndex = heap[key].index;
const Weight weight = heap[key].weight;
+ const Key heap_size = static_cast<Key>(heap.size());
Key nextKey = key << 1;
- while (nextKey < static_cast<Key>(heap.size()))
+ while (nextKey < heap_size)
{
const Key nextKeyOther = nextKey + 1;
- if ((nextKeyOther < static_cast<Key>(heap.size())) &&
- (heap[nextKey].weight > heap[nextKeyOther].weight))
+ if ((nextKeyOther < heap_size) && (heap[nextKey].weight > heap[nextKeyOther].weight))
{
nextKey = nextKeyOther;
}
@@ -279,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/3party/osrm/osrm-backend/DataStructures/ConcurrentQueue.h b/3party/osrm/osrm-backend/data_structures/concurrent_queue.hpp
index a61503a6dd..7341a8cc48 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/ConcurrentQueue.h
+++ b/3party/osrm/osrm-backend/data_structures/concurrent_queue.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef CONCURRENT_QUEUE_H
-#define CONCURRENT_QUEUE_H
+#ifndef CONCURRENT_QUEUE_HPP
+#define CONCURRENT_QUEUE_HPP
#include <boost/circular_buffer.hpp>
#include <condition_variable>
@@ -40,9 +40,10 @@ template <typename Data> class ConcurrentQueue
inline void push(const Data &data)
{
std::unique_lock<std::mutex> 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 <typename Data> class ConcurrentQueue
inline void wait_and_pop(Data &popped_value)
{
std::unique_lock<std::mutex> 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();
@@ -80,4 +82,4 @@ template <typename Data> class ConcurrentQueue
std::condition_variable m_not_full;
};
-#endif // CONCURRENT_QUEUE_H
+#endif // CONCURRENT_QUEUE_HPP
diff --git a/3party/osrm/osrm-backend/data_structures/coordinate.cpp b/3party/osrm/osrm-backend/data_structures/coordinate.cpp
new file mode 100755
index 0000000000..df3abe44ae
--- /dev/null
+++ b/3party/osrm/osrm-backend/data_structures/coordinate.cpp
@@ -0,0 +1,87 @@
+/*
+
+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 "coordinate_calculation.hpp"
+
+#ifndef NDEBUG
+#include "../util/simple_logger.hpp"
+#endif
+#include <osrm/coordinate.hpp>
+
+#ifndef NDEBUG
+#include <bitset>
+#endif
+#include <iostream>
+#include <limits>
+
+FixedPointCoordinate::FixedPointCoordinate()
+ : lat(std::numeric_limits<int>::min()), lon(std::numeric_limits<int>::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
+}
+
+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;
+}
+
+void FixedPointCoordinate::output(std::ostream &out) const
+{
+ out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
+}
+
+float FixedPointCoordinate::bearing(const FixedPointCoordinate &other) const
+{
+ return coordinate_calculation::bearing(other, *this);
+}
diff --git a/3party/osrm/osrm-backend/data_structures/coordinate_calculation.cpp b/3party/osrm/osrm-backend/data_structures/coordinate_calculation.cpp
new file mode 100755
index 0000000000..0c44989b4b
--- /dev/null
+++ b/3party/osrm/osrm-backend/data_structures/coordinate_calculation.cpp
@@ -0,0 +1,268 @@
+/*
+
+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 "coordinate_calculation.hpp"
+
+#include "../util/mercator.hpp"
+#include "../util/string_util.hpp"
+
+#include <boost/assert.hpp>
+
+#include <osrm/coordinate.hpp>
+
+#include <cmath>
+
+#include <limits>
+
+namespace
+{
+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;
+}
+
+double coordinate_calculation::great_circle_distance(const int lat1,
+ const int lon1,
+ const int lat2,
+ const int lon2)
+{
+ BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
+ BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
+ BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
+ BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
+ 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);
+
+ const double dlong1 = ln1 * (RAD);
+ const double dlat2 = lt2 * (RAD);
+ const double dlong2 = ln2 * (RAD);
+
+ const double dLong = dlong1 - dlong2;
+ const double dLat = dlat1 - dlat2;
+
+ 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;
+}
+
+double coordinate_calculation::great_circle_distance(const FixedPointCoordinate &coordinate_1,
+ const FixedPointCoordinate &coordinate_2)
+{
+ return great_circle_distance(coordinate_1.lat, coordinate_1.lon, coordinate_2.lat,
+ 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);
+}
+
+float coordinate_calculation::euclidean_distance(const int lat1,
+ const int lon1,
+ const int lat2,
+ const int lon2)
+{
+ BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
+ BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
+ BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
+ BOOST_ASSERT(lon2 != std::numeric_limits<int>::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) * 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;
+}
+
+float coordinate_calculation::perpendicular_distance(const FixedPointCoordinate &source_coordinate,
+ const FixedPointCoordinate &target_coordinate,
+ const FixedPointCoordinate &query_location)
+{
+ float ratio;
+ FixedPointCoordinate nearest_location;
+
+ return perpendicular_distance(source_coordinate, target_coordinate, query_location,
+ nearest_location, ratio);
+}
+
+float coordinate_calculation::perpendicular_distance(const FixedPointCoordinate &segment_source,
+ const FixedPointCoordinate &segment_target,
+ const FixedPointCoordinate &query_location,
+ FixedPointCoordinate &nearest_location,
+ float &ratio)
+{
+ 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(
+ const FixedPointCoordinate &source_coordinate,
+ const FixedPointCoordinate &target_coordinate,
+ const FixedPointCoordinate &query_location,
+ const std::pair<double, double> &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<double, double> &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<double>::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 =
+ static_cast<float>((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<float>::epsilon())
+ {
+ ratio = 0.f;
+ }
+ else if (std::abs(ratio - 1.f) <= std::numeric_limits<float>::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<int>(mercator::y2lat(p) * COORDINATE_PRECISION);
+ nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
+ }
+ BOOST_ASSERT(nearest_location.is_valid());
+
+ const float approximate_distance =
+ coordinate_calculation::euclidean_distance(query_location, nearest_location);
+ BOOST_ASSERT(0.f <= 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);
+}
+
+float coordinate_calculation::deg_to_rad(const float degree)
+{
+ return degree * (static_cast<float>(M_PI) / 180.f);
+}
+
+float coordinate_calculation::rad_to_deg(const float radian)
+{
+ return radian * (180.f * static_cast<float>(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 = 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)
+ {
+ result += 360.f;
+ }
+
+ while (result >= 360.f)
+ {
+ result -= 360.f;
+ }
+ return result;
+}
diff --git a/3party/osrm/osrm-backend/data_structures/coordinate_calculation.hpp b/3party/osrm/osrm-backend/data_structures/coordinate_calculation.hpp
new file mode 100755
index 0000000000..73183dfa4d
--- /dev/null
+++ b/3party/osrm/osrm-backend/data_structures/coordinate_calculation.hpp
@@ -0,0 +1,82 @@
+/*
+
+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 COORDINATE_CALCULATION
+#define COORDINATE_CALCULATION
+
+struct FixedPointCoordinate;
+
+#include <string>
+#include <utility>
+
+struct coordinate_calculation
+{
+ static double
+ great_circle_distance(const int lat1, const int lon1, const int lat2, const int lon2);
+
+ static double great_circle_distance(const FixedPointCoordinate &first_coordinate,
+ const FixedPointCoordinate &second_coordinate);
+
+ static float euclidean_distance(const FixedPointCoordinate &first_coordinate,
+ const FixedPointCoordinate &second_coordinate);
+
+ 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);
+
+ static float perpendicular_distance(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,
+ 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<double, double> &projected_coordinate);
+
+ static float perpendicular_distance_from_projected_coordinate(
+ const FixedPointCoordinate &segment_source,
+ const FixedPointCoordinate &segment_target,
+ const FixedPointCoordinate &query_location,
+ const std::pair<double, double> &projected_coordinate,
+ FixedPointCoordinate &nearest_location,
+ float &ratio);
+
+ 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/3party/osrm/osrm-backend/DataStructures/DeallocatingVector.h b/3party/osrm/osrm-backend/data_structures/deallocating_vector.hpp
index 422dd5f19d..de5a24d85f 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/DeallocatingVector.h
+++ b/3party/osrm/osrm-backend/data_structures/deallocating_vector.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,19 +25,23 @@ 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 "Range.h"
+#include "../util/integer_range.hpp"
#include <boost/iterator/iterator_facade.hpp>
+#include <limits>
#include <utility>
#include <vector>
template <typename ElementT> struct DeallocatingVectorIteratorState
{
- DeallocatingVectorIteratorState() : index(-1), bucket_list(nullptr) {}
+ DeallocatingVectorIteratorState()
+ : index(std::numeric_limits<std::size_t>::max()), bucket_list(nullptr)
+ {
+ }
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r)
: index(r.index), bucket_list(r.bucket_list)
{
@@ -50,7 +54,7 @@ template <typename ElementT> struct DeallocatingVectorIteratorState
std::size_t index;
std::vector<ElementT *> *bucket_list;
- inline DeallocatingVectorIteratorState &operator=(const DeallocatingVectorIteratorState &other)
+ DeallocatingVectorIteratorState &operator=(const DeallocatingVectorIteratorState &other)
{
index = other.index;
bucket_list = other.bucket_list;
@@ -171,17 +175,20 @@ class DeallocatingVector
// this forward-only iterator deallocates all buckets that have been visited
using deallocation_iterator = DeallocatingVectorRemoveIterator<ElementT, ELEMENTS_PER_BLOCK>;
- 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(); }
- inline void swap(DeallocatingVector<ElementT, ELEMENTS_PER_BLOCK> &other)
+ void swap(DeallocatingVector<ElementT, ELEMENTS_PER_BLOCK> &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)
@@ -192,11 +199,12 @@ class DeallocatingVector
bucket = nullptr;
}
}
- bucket_list.clear(); bucket_list.shrink_to_fit();
+ bucket_list.clear();
+ bucket_list.shrink_to_fit();
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 +217,7 @@ class DeallocatingVector
++current_size;
}
- template <typename... Ts> inline void emplace_back(Ts &&... element)
+ template <typename... Ts> void emplace_back(Ts &&... element)
{
const std::size_t current_capacity = capacity();
if (current_size == current_capacity)
@@ -222,9 +230,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)
{
@@ -234,9 +242,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])
{
@@ -248,58 +257,50 @@ 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<std::size_t>(0), &bucket_list); }
+ iterator begin() { return iterator(static_cast<std::size_t>(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<std::size_t>(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<std::size_t>(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;
return (bucket_list[_bucket][_index]);
}
- template<class InputIterator>
- const inline void append(InputIterator first, const InputIterator last)
+ template <class InputIterator> void append(InputIterator first, const InputIterator last)
{
InputIterator position = first;
while (position != last)
@@ -310,4 +311,4 @@ class DeallocatingVector
}
};
-#endif /* DEALLOCATINGVECTOR_H_ */
+#endif /* DEALLOCATING_VECTOR_HPP */
diff --git a/3party/osrm/osrm-backend/DataStructures/DynamicGraph.h b/3party/osrm/osrm-backend/data_structures/dynamic_graph.hpp
index 81b1afe117..43e6c3aca4 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/DynamicGraph.h
+++ b/3party/osrm/osrm-backend/data_structures/dynamic_graph.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,20 +25,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef DYNAMICGRAPH_H
-#define DYNAMICGRAPH_H
+#ifndef DYNAMICGRAPH_HPP
+#define DYNAMICGRAPH_HPP
-#include "DeallocatingVector.h"
-#include "Range.h"
+#include "deallocating_vector.hpp"
+#include "../util/integer_range.hpp"
+#include "../typedefs.h"
#include <boost/assert.hpp>
#include <cstdint>
#include <algorithm>
+#include <atomic>
#include <limits>
+#include <tuple>
#include <vector>
-#include <atomic>
template <typename EdgeDataT> class DynamicGraph
{
@@ -55,26 +57,29 @@ template <typename EdgeDataT> class DynamicGraph
NodeIterator target;
EdgeDataT data;
- InputEdge() : source(std::numeric_limits<NodeIterator>::max()), target(std::numeric_limits<NodeIterator>::max()) { }
+ InputEdge()
+ : source(std::numeric_limits<NodeIterator>::max()),
+ target(std::numeric_limits<NodeIterator>::max())
+ {
+ }
- template<typename... Ts>
- InputEdge(NodeIterator source, NodeIterator target, Ts &&...data) : source(source), target(target), data(std::forward<Ts>(data)...) { }
+ template <typename... Ts>
+ InputEdge(NodeIterator source, NodeIterator target, Ts &&... data)
+ : source(source), target(target), data(std::forward<Ts>(data)...)
+ {
+ }
- 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);
}
};
// 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);
@@ -83,30 +88,30 @@ template <typename EdgeDataT> class DynamicGraph
template <class ContainerT> DynamicGraph(const NodeIterator nodes, const ContainerT &graph)
{
number_of_nodes = nodes;
- number_of_edges = (EdgeIterator)graph.size();
- node_list.reserve(number_of_nodes + 1);
- node_list.resize(number_of_nodes + 1);
+ number_of_edges = static_cast<EdgeIterator>(graph.size());
+ // 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;
- edge_list.reserve((std::size_t)edge_list.size() * 1.1);
+ node_array.back().first_edge = position;
+ edge_list.reserve(static_cast<std::size_t>(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;
@@ -121,7 +126,7 @@ template <typename EdgeDataT> 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
{
@@ -146,12 +151,12 @@ template <typename EdgeDataT> 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
@@ -161,7 +166,7 @@ template <typename EdgeDataT> 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;
@@ -170,14 +175,14 @@ template <typename EdgeDataT> 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
{
@@ -192,32 +197,32 @@ template <typename EdgeDataT> 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<unsigned>::max() != node.edges);
- const unsigned last = node.firstEdge + node.edges;
+ const unsigned last = node.first_edge + node.edges;
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != last);
// swap with last edge
edge_list[e] = edge_list[last];
@@ -242,7 +247,7 @@ template <typename EdgeDataT> class DynamicGraph
}
number_of_edges -= deleted;
- node_list[source].edges -= deleted;
+ node_array[source].edges -= deleted;
return deleted;
}
@@ -257,7 +262,46 @@ template <typename EdgeDataT> class DynamicGraph
return i;
}
}
- return EndEdges(from);
+ return SPECIAL_EDGEID;
+ }
+
+ // 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;
+ }
+
+ 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:
@@ -274,7 +318,7 @@ template <typename EdgeDataT> class DynamicGraph
struct Node
{
// index of the first edge
- EdgeIterator firstEdge;
+ EdgeIterator first_edge;
// amount of edges
unsigned edges;
};
@@ -288,8 +332,8 @@ template <typename EdgeDataT> class DynamicGraph
NodeIterator number_of_nodes;
std::atomic_uint number_of_edges;
- std::vector<Node> node_list;
+ std::vector<Node> node_array;
DeallocatingVector<Edge> edge_list;
};
-#endif // DYNAMICGRAPH_H
+#endif // DYNAMICGRAPH_HPP
diff --git a/3party/osrm/osrm-backend/data_structures/edge_based_node.hpp b/3party/osrm/osrm-backend/data_structures/edge_based_node.hpp
new file mode 100755
index 0000000000..72a585a139
--- /dev/null
+++ b/3party/osrm/osrm-backend/data_structures/edge_based_node.hpp
@@ -0,0 +1,109 @@
+/*
+
+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 EDGE_BASED_NODE_HPP
+#define EDGE_BASED_NODE_HPP
+
+#include "../data_structures/travel_mode.hpp"
+#include "../typedefs.h"
+
+#include <boost/assert.hpp>
+
+#include <osrm/coordinate.hpp>
+
+#include <limits>
+
+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<unsigned short>::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)
+ {
+ 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)
+ {
+ FixedPointCoordinate centroid;
+ // 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 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
+ 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
+ TravelMode forward_travel_mode : 4;
+ TravelMode backward_travel_mode : 4;
+};
+
+#endif // EDGE_BASED_NODE_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/ImportNode.cpp b/3party/osrm/osrm-backend/data_structures/external_memory_node.cpp
index 8975d408ab..72b8198f9c 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/ImportNode.cpp
+++ b/3party/osrm/osrm-backend/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,
@@ -25,19 +25,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "ImportNode.h"
+#include "external_memory_node.hpp"
+#include "query_node.hpp"
#include <limits>
ExternalMemoryNode::ExternalMemoryNode(
- int lat, int lon, unsigned int node_id, bool bollard, bool traffic_light)
- : NodeInfo(lat, lon, node_id), bollard(bollard), trafficLight(traffic_light)
+ int lat, int lon, unsigned int node_id, bool barrier, bool traffic_lights)
+ : QueryNode(lat, lon, node_id), barrier(barrier), traffic_lights(traffic_lights)
{
}
-ExternalMemoryNode::ExternalMemoryNode() : bollard(false), trafficLight(false)
-{
-}
+ExternalMemoryNode::ExternalMemoryNode() : barrier(false), traffic_lights(false) {}
ExternalMemoryNode ExternalMemoryNode::min_value()
{
@@ -46,19 +45,22 @@ ExternalMemoryNode ExternalMemoryNode::min_value()
ExternalMemoryNode ExternalMemoryNode::max_value()
{
- return ExternalMemoryNode(std::numeric_limits<int>::max(),
- std::numeric_limits<int>::max(),
- std::numeric_limits<unsigned>::max(),
- false,
- false);
+ return ExternalMemoryNode(std::numeric_limits<int>::max(), std::numeric_limits<int>::max(),
+ std::numeric_limits<unsigned>::max(), false, false);
+}
+
+bool ExternalMemoryNodeSTXXLCompare::operator()(const ExternalMemoryNode &left,
+ const ExternalMemoryNode &right) const
+{
+ return left.node_id < right.node_id;
+}
+
+ExternalMemoryNodeSTXXLCompare::value_type ExternalMemoryNodeSTXXLCompare::max_value()
+{
+ return ExternalMemoryNode::max_value();
}
-void ImportNode::Clear()
+ExternalMemoryNodeSTXXLCompare::value_type ExternalMemoryNodeSTXXLCompare::min_value()
{
- keyVals.Clear();
- lat = 0;
- lon = 0;
- node_id = 0;
- bollard = false;
- trafficLight = false;
+ return ExternalMemoryNode::min_value();
}
diff --git a/3party/osrm/osrm-backend/DataStructures/ImportNode.h b/3party/osrm/osrm-backend/data_structures/external_memory_node.hpp
index b8a945120a..83b88e7592 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/ImportNode.h
+++ b/3party/osrm/osrm-backend/data_structures/external_memory_node.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,17 +25,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef IMPORTNODE_H_
-#define IMPORTNODE_H_
+#ifndef EXTERNAL_MEMORY_NODE_HPP_
+#define EXTERNAL_MEMORY_NODE_HPP_
-#include "QueryNode.h"
-#include "../DataStructures/HashTable.h"
+#include "query_node.hpp"
-#include <string>
+#include "../typedefs.h"
-struct ExternalMemoryNode : NodeInfo
+struct ExternalMemoryNode : QueryNode
{
- ExternalMemoryNode(int lat, int lon, unsigned int id, bool bollard, bool traffic_light);
+ ExternalMemoryNode(int lat, int lon, NodeID id, bool barrier, bool traffic_light);
ExternalMemoryNode();
@@ -43,15 +42,16 @@ struct ExternalMemoryNode : NodeInfo
static ExternalMemoryNode max_value();
- bool bollard;
- bool trafficLight;
+ bool barrier;
+ bool traffic_lights;
};
-struct ImportNode : public ExternalMemoryNode
+struct ExternalMemoryNodeSTXXLCompare
{
- HashTable<std::string, std::string> keyVals;
-
- inline void Clear();
+ using value_type = ExternalMemoryNode;
+ bool operator()(const ExternalMemoryNode &left, const ExternalMemoryNode &right) const;
+ value_type max_value();
+ value_type min_value();
};
-#endif /* IMPORTNODE_H_ */
+#endif /* EXTERNAL_MEMORY_NODE_HPP_ */
diff --git a/3party/osrm/osrm-backend/DataStructures/FixedPointNumber.h b/3party/osrm/osrm-backend/data_structures/fixed_point_number.hpp
index 77de365aa2..c7ed257e52 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/FixedPointNumber.h
+++ b/3party/osrm/osrm-backend/data_structures/fixed_point_number.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef OSRM_FIXED_POINT_NUMBER_H
-#define OSRM_FIXED_POINT_NUMBER_H
+#ifndef FIXED_POINT_NUMBER_HPP
+#define FIXED_POINT_NUMBER_HPP
#include <cmath>
#include <cstdint>
@@ -213,4 +213,4 @@ class FixedPointNumber
static_assert(4 == sizeof(FixedPointNumber<1>), "FP19 has wrong size != 4");
}
-#endif // OSRM_FIXED_POINT_NUMBER_H
+#endif // FIXED_POINT_NUMBER_HPP
diff --git a/3party/osrm/osrm-backend/data_structures/hidden_markov_model.hpp b/3party/osrm/osrm-backend/data_structures/hidden_markov_model.hpp
new file mode 100755
index 0000000000..cccaf7b5d2
--- /dev/null
+++ b/3party/osrm/osrm-backend/data_structures/hidden_markov_model.hpp
@@ -0,0 +1,158 @@
+/*
+
+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 "../util/integer_range.hpp"
+
+#include <boost/assert.hpp>
+
+#include <cmath>
+
+#include <limits>
+#include <vector>
+
+namespace osrm
+{
+namespace matching
+{
+static const double log_2_pi = std::log(2. * M_PI);
+static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits<double>::infinity();
+static const double MINIMAL_LOG_PROB = std::numeric_limits<double>::lowest();
+static const std::size_t INVALID_STATE = std::numeric_limits<std::size_t>::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 <class CandidateLists> struct HiddenMarkovModel
+{
+ std::vector<std::vector<double>> viterbi;
+ std::vector<std::vector<std::pair<unsigned, unsigned>>> parents;
+ std::vector<std::vector<float>> path_lengths;
+ std::vector<std::vector<bool>> pruned;
+ std::vector<std::vector<bool>> suspicious;
+ std::vector<bool> 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());
+ suspicious.emplace_back(l.size());
+ pruned.emplace_back(l.size());
+ }
+
+ clear(0);
+ }
+
+ 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 (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));
+ 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);
+ }
+
+ std::size_t initialize(std::size_t initial_timestamp)
+ {
+ BOOST_ASSERT(initial_timestamp < candidates_list.size());
+
+ do
+ {
+ for (const auto s : osrm::irange<std::size_t>(0u, viterbi[initial_timestamp].size()))
+ {
+ 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;
+ suspicious[initial_timestamp][s] = false;
+
+ 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/3party/osrm/osrm-backend/DataStructures/HilbertValue.cpp b/3party/osrm/osrm-backend/data_structures/hilbert_value.cpp
index 9cb88c79f3..c097731184 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/HilbertValue.cpp
+++ b/3party/osrm/osrm-backend/data_structures/hilbert_value.cpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,9 +25,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "HilbertValue.h"
+#include "hilbert_value.hpp"
-#include <osrm/Coordinate.h>
+#include <osrm/coordinate.hpp>
uint64_t HilbertCode::operator()(const FixedPointCoordinate &current_coordinate) const
{
diff --git a/3party/osrm/osrm-backend/DataStructures/HilbertValue.h b/3party/osrm/osrm-backend/data_structures/hilbert_value.hpp
index 9de23724f0..7b8bffa938 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/HilbertValue.h
+++ b/3party/osrm/osrm-backend/data_structures/hilbert_value.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef HILBERTVALUE_H_
-#define HILBERTVALUE_H_
+#ifndef HILBERT_VALUE_HPP
+#define HILBERT_VALUE_HPP
#include <cstdint>
@@ -46,4 +46,4 @@ class HilbertCode
inline void TransposeCoordinate(uint32_t *X) const;
};
-#endif /* HILBERTVALUE_H_ */
+#endif /* HILBERT_VALUE_HPP */
diff --git a/3party/osrm/osrm-backend/DataStructures/ImportEdge.cpp b/3party/osrm/osrm-backend/data_structures/import_edge.cpp
index e214aeafc8..f41b066b1a 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/ImportEdge.cpp
+++ b/3party/osrm/osrm-backend/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,
@@ -25,9 +25,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "ImportEdge.h"
+#include "import_edge.hpp"
-#include <boost/assert.hpp>
+#include "travel_mode.hpp"
+#include "../typedefs.h"
bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
{
@@ -46,8 +47,7 @@ bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
return source < other.source;
}
-NodeBasedEdge::NodeBasedEdge(unsigned way_id,
- NodeID source,
+NodeBasedEdge::NodeBasedEdge(NodeID source,
NodeID target,
NodeID name_id,
EdgeWeight weight,
@@ -58,8 +58,8 @@ NodeBasedEdge::NodeBasedEdge(unsigned way_id,
bool access_restricted,
TravelMode travel_mode,
bool is_split)
- : way_id(way_id), 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/3party/osrm/osrm-backend/DataStructures/ImportEdge.h b/3party/osrm/osrm-backend/data_structures/import_edge.hpp
index e6d09b099e..f422de116f 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/ImportEdge.h
+++ b/3party/osrm/osrm-backend/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,
@@ -25,18 +25,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef IMPORT_EDGE_H
-#define IMPORT_EDGE_H
+#ifndef IMPORT_EDGE_HPP
+#define IMPORT_EDGE_HPP
-#include "../DataStructures/TravelMode.h"
+#include "../data_structures/travel_mode.hpp"
#include "../typedefs.h"
struct NodeBasedEdge
{
bool operator<(const NodeBasedEdge &e) const;
- explicit NodeBasedEdge(unsigned way_id,
- NodeID source,
+ explicit NodeBasedEdge(NodeID source,
NodeID target,
NodeID name_id,
EdgeWeight weight,
@@ -48,7 +47,6 @@ struct NodeBasedEdge
TravelMode travel_mode,
bool is_split);
- unsigned way_id;
NodeID source;
NodeID target;
NodeID name_id;
@@ -90,4 +88,4 @@ struct EdgeBasedEdge
using ImportEdge = NodeBasedEdge;
-#endif /* IMPORT_EDGE_H */
+#endif /* IMPORT_EDGE_HPP */
diff --git a/3party/osrm/osrm-backend/DataStructures/RawRouteData.h b/3party/osrm/osrm-backend/data_structures/internal_route_result.hpp
index 9191a90113..068b63a800 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/RawRouteData.h
+++ b/3party/osrm/osrm-backend/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,
@@ -28,22 +28,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef RAW_ROUTE_DATA_H
#define RAW_ROUTE_DATA_H
-#include "../DataStructures/PhantomNodes.h"
-#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 "../Include/osrm/Coordinate.h"
+#include <osrm/coordinate.hpp>
#include <vector>
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;
@@ -63,17 +61,15 @@ struct PathData
TravelMode travel_mode : 4;
};
-struct RawRouteData
+struct InternalRouteResult
{
std::vector<std::vector<PathData>> unpacked_path_segments;
std::vector<PathData> unpacked_alternative;
std::vector<PhantomNodes> segment_end_coordinates;
- std::vector<FixedPointCoordinate> raw_via_node_coordinates;
std::vector<bool> source_traversed_in_reverse;
std::vector<bool> target_traversed_in_reverse;
std::vector<bool> alt_source_traversed_in_reverse;
std::vector<bool> alt_target_traversed_in_reverse;
- unsigned check_sum;
int shortest_path_length;
int alternative_path_length;
@@ -82,10 +78,8 @@ struct RawRouteData
return (leg != unpacked_path_segments.size() - 1);
}
- RawRouteData()
- : check_sum(SPECIAL_NODEID),
- 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/3party/osrm/osrm-backend/DataStructures/LRUCache.h b/3party/osrm/osrm-backend/data_structures/lru_cache.hpp
index 75b9139d76..155ab1ef49 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/LRUCache.h
+++ b/3party/osrm/osrm-backend/data_structures/lru_cache.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef LRUCACHE_H
-#define LRUCACHE_H
+#ifndef LRUCACHE_HPP
+#define LRUCACHE_HPP
#include <list>
#include <unordered_map>
@@ -86,7 +86,7 @@ template <typename KeyT, typename ValueT> 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;
}
@@ -94,4 +94,4 @@ template <typename KeyT, typename ValueT> class LRUCache
}
unsigned Size() const { return itemsInCache.size(); }
};
-#endif // LRUCACHE_H
+#endif // LRUCACHE_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/NodeBasedGraph.h b/3party/osrm/osrm-backend/data_structures/node_based_graph.hpp
index 94c62f3307..54e07a7ec6 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/NodeBasedGraph.h
+++ b/3party/osrm/osrm-backend/data_structures/node_based_graph.hpp
@@ -1,9 +1,36 @@
-#ifndef NODE_BASED_GRAPH_H_
-#define NODE_BASED_GRAPH_H_
+/*
-#include "DynamicGraph.h"
-#include "ImportEdge.h"
-#include "../Util/simple_logger.hpp"
+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 NODE_BASED_GRAPH_HPP
+#define NODE_BASED_GRAPH_HPP
+
+#include "dynamic_graph.hpp"
+#include "import_edge.hpp"
+#include "../util/simple_logger.hpp"
#include <tbb/parallel_sort.h>
@@ -12,14 +39,13 @@
struct NodeBasedEdgeData
{
NodeBasedEdgeData()
- : way_id(-1), distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID),
- nameID(std::numeric_limits<unsigned>::max()),
- isAccessRestricted(false), shortcut(false), forward(false), backward(false),
- roundabout(false), ignore_in_grid(false), travel_mode(TRAVEL_MODE_INACCESSIBLE)
+ : distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID),
+ nameID(std::numeric_limits<unsigned>::max()), isAccessRestricted(false), shortcut(false),
+ forward(false), backward(false), roundabout(false), ignore_in_grid(false),
+ travel_mode(TRAVEL_MODE_INACCESSIBLE)
{
}
- unsigned way_id;
int distance;
unsigned edgeBasedNodeID;
unsigned nameID;
@@ -59,7 +85,8 @@ using SimpleNodeBasedDynamicGraph = DynamicGraph<SimpleEdgeData>;
inline std::shared_ptr<NodeBasedDynamicGraph>
NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge> &input_edge_list)
{
- static_assert(sizeof(NodeBasedEdgeData) == 20, "changing node based edge data size changes memory consumption");
+ static_assert(sizeof(NodeBasedEdgeData) == 16,
+ "changing node based edge data size changes memory consumption");
DeallocatingVector<NodeBasedDynamicGraph::InputEdge> edges_list;
NodeBasedDynamicGraph::InputEdge edge;
@@ -80,14 +107,12 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge
edge.data.forward = import_edge.backward;
}
- edge.data.way_id = import_edge.way_id;
-
if (edge.source == edge.target)
{
continue;
}
- edge.data.distance = (std::max)((int)import_edge.weight, 1);
+ edge.data.distance = (std::max)(static_cast<int>(import_edge.weight), 1);
BOOST_ASSERT(edge.data.distance > 0);
edge.data.shortcut = false;
edge.data.roundabout = import_edge.roundabout;
@@ -110,7 +135,7 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge
// remove duplicate edges
tbb::parallel_sort(edges_list.begin(), edges_list.end());
NodeID edge_count = 0;
- for (NodeID i = 0; i < edges_list.size(); )
+ for (NodeID i = 0; i < edges_list.size();)
{
const NodeID source = edges_list[i].source;
const NodeID target = edges_list[i].target;
@@ -126,10 +151,10 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge
forward_edge.data.forward = reverse_edge.data.backward = true;
forward_edge.data.backward = reverse_edge.data.forward = false;
forward_edge.data.shortcut = reverse_edge.data.shortcut = false;
- forward_edge.data.distance = reverse_edge.data.distance =
- std::numeric_limits<int>::max();
+ forward_edge.data.distance = reverse_edge.data.distance = std::numeric_limits<int>::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)
{
@@ -146,7 +171,7 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge
// merge edges (s,t) and (t,s) into bidirectional edge
if (forward_edge.data.distance == reverse_edge.data.distance)
{
- if ((int)forward_edge.data.distance != std::numeric_limits<int>::max())
+ if (static_cast<int>(forward_edge.data.distance) != std::numeric_limits<int>::max())
{
forward_edge.data.backward = true;
edges_list[edge_count++] = forward_edge;
@@ -154,28 +179,31 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge
}
else
{ // insert seperate edges
- if (((int)forward_edge.data.distance) != std::numeric_limits<int>::max())
+ if (static_cast<int>(forward_edge.data.distance) != std::numeric_limits<int>::max())
{
edges_list[edge_count++] = forward_edge;
}
- if ((int)reverse_edge.data.distance != std::numeric_limits<int>::max())
+ if (static_cast<int>(reverse_edge.data.distance) != std::numeric_limits<int>::max())
{
edges_list[edge_count++] = reverse_edge;
}
}
}
edges_list.resize(edge_count);
- SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of " << edges_list.size();
+ SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of "
+ << edges_list.size();
- auto graph = std::make_shared<NodeBasedDynamicGraph>(static_cast<NodeBasedDynamicGraph::NodeIterator>(number_of_nodes), edges_list);
+ auto graph = std::make_shared<NodeBasedDynamicGraph>(
+ static_cast<NodeBasedDynamicGraph::NodeIterator>(number_of_nodes), edges_list);
return graph;
}
-template<class SimpleEdgeT>
+template <class SimpleEdgeT>
inline std::shared_ptr<SimpleNodeBasedDynamicGraph>
SimpleNodeBasedDynamicGraphFromEdges(int number_of_nodes, std::vector<SimpleEdgeT> &input_edge_list)
{
- static_assert(sizeof(NodeBasedEdgeData) == 20, "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<SimpleNodeBasedDynamicGraph::InputEdge> edges_list;
@@ -194,10 +222,10 @@ SimpleNodeBasedDynamicGraphFromEdges(int number_of_nodes, std::vector<SimpleEdge
edges_list.push_back(edge);
}
- // remove duplicate edges
+ // remove duplicate edges
tbb::parallel_sort(edges_list.begin(), edges_list.end());
NodeID edge_count = 0;
- for (NodeID i = 0; i < edges_list.size(); )
+ for (NodeID i = 0; i < edges_list.size();)
{
const NodeID source = edges_list[i].source;
const NodeID target = edges_list[i].target;
@@ -212,36 +240,40 @@ SimpleNodeBasedDynamicGraphFromEdges(int number_of_nodes, std::vector<SimpleEdge
forward_edge = reverse_edge = edges_list[i];
forward_edge.data.capacity = reverse_edge.data.capacity = INVALID_EDGE_WEIGHT;
// 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)
{
- forward_edge.data.capacity = std::min(edges_list[i].data.capacity, forward_edge.data.capacity);
- reverse_edge.data.capacity = std::min(edges_list[i].data.capacity, reverse_edge.data.capacity);
+ forward_edge.data.capacity =
+ std::min(edges_list[i].data.capacity, forward_edge.data.capacity);
+ reverse_edge.data.capacity =
+ std::min(edges_list[i].data.capacity, reverse_edge.data.capacity);
++i;
}
// merge edges (s,t) and (t,s) into bidirectional edge
if (forward_edge.data.capacity == reverse_edge.data.capacity)
{
- if ((int)forward_edge.data.capacity != INVALID_EDGE_WEIGHT)
+ if (static_cast<int>(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<int>(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<int>(reverse_edge.data.capacity) != INVALID_EDGE_WEIGHT)
{
edges_list[edge_count++] = reverse_edge;
}
}
}
- SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of " << edges_list.size();
+ SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of "
+ << edges_list.size();
auto graph = std::make_shared<SimpleNodeBasedDynamicGraph>(number_of_nodes, edges_list);
return graph;
}
-#endif // NODE_BASED_GRAPH_H_
+#endif // NODE_BASED_GRAPH_HPP
diff --git a/3party/osrm/osrm-backend/extractor.cpp b/3party/osrm/osrm-backend/data_structures/node_id.hpp
index 43a0296b1b..4d6fff0b2a 100644..100755
--- a/3party/osrm/osrm-backend/extractor.cpp
+++ b/3party/osrm/osrm-backend/data_structures/node_id.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,18 +25,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "Extractor/Extractor.h"
-#include "Util/simple_logger.hpp"
+#ifndef NODE_ID_HPP
+#define NODE_ID_HPP
-int main (int argc, char *argv[])
+#include "../typedefs.h"
+
+struct Cmp
{
- try
- {
- return Extractor().Run(argc, argv);
- }
- catch (const std::exception &e)
- {
- SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
- }
-
-}
+ using value_type = NodeID;
+ bool operator()(const NodeID left, const NodeID right) const { return left < right; }
+ value_type max_value() { return 0xffffffff; }
+ value_type min_value() { return 0x0; }
+};
+
+#endif // NODE_ID_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/OriginalEdgeData.h b/3party/osrm/osrm-backend/data_structures/original_edge_data.hpp
index 3d7c543301..cbbc1b2760 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/OriginalEdgeData.h
+++ b/3party/osrm/osrm-backend/data_structures/original_edge_data.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,11 +25,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ORIGINAL_EDGE_DATA_H
-#define ORIGINAL_EDGE_DATA_H
+#ifndef ORIGINAL_EDGE_DATA_HPP
+#define ORIGINAL_EDGE_DATA_HPP
-#include "TurnInstructions.h"
-#include "../DataStructures/TravelMode.h"
+#include "travel_mode.hpp"
+#include "turn_instructions.hpp"
#include "../typedefs.h"
#include <limits>
@@ -48,9 +48,8 @@ struct OriginalEdgeData
OriginalEdgeData()
: via_node(std::numeric_limits<unsigned>::max()),
- name_id(std::numeric_limits<unsigned>::max()),
- turn_instruction(TurnInstruction::NoTurn), compressed_geometry(false),
- travel_mode(TRAVEL_MODE_INACCESSIBLE)
+ name_id(std::numeric_limits<unsigned>::max()), turn_instruction(TurnInstruction::NoTurn),
+ compressed_geometry(false), travel_mode(TRAVEL_MODE_INACCESSIBLE)
{
}
@@ -61,4 +60,4 @@ struct OriginalEdgeData
TravelMode travel_mode;
};
-#endif // ORIGINAL_EDGE_DATA_H
+#endif // ORIGINAL_EDGE_DATA_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/Percent.h b/3party/osrm/osrm-backend/data_structures/percent.hpp
index f201fc8084..392417e76a 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/Percent.h
+++ b/3party/osrm/osrm-backend/data_structures/percent.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef PERCENT_H
-#define PERCENT_H
+#ifndef PERCENT_HPP
+#define PERCENT_HPP
#include <iostream>
#include <atomic>
@@ -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;
@@ -53,7 +53,7 @@ class Percent
if (current_value >= m_next_threshold)
{
m_next_threshold += m_percent_interval;
- printPercent(current_value / (double)m_max_value * 100);
+ printPercent(current_value / static_cast<double>(m_max_value) * 100.);
}
if (current_value + 1 == m_max_value)
std::cout << " 100%" << std::endl;
@@ -98,4 +98,4 @@ class Percent
}
};
-#endif // PERCENT_H
+#endif // PERCENT_HPP
diff --git a/3party/osrm/osrm-backend/data_structures/phantom_node.cpp b/3party/osrm/osrm-backend/data_structures/phantom_node.cpp
new file mode 100755
index 0000000000..eba6492cdd
--- /dev/null
+++ b/3party/osrm/osrm-backend/data_structures/phantom_node.cpp
@@ -0,0 +1,106 @@
+/*
+
+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 "phantom_node.hpp"
+
+#include "../typedefs.h"
+#include "travel_mode.hpp"
+
+#include <osrm/coordinate.hpp>
+
+#include <limits>
+
+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<unsigned>::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<unsigned>::max()),
+ fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
+ backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
+{
+}
+
+int PhantomNode::GetForwardWeightPlusOffset() const
+{
+ if (SPECIAL_NODEID == forward_node_id)
+ {
+ return 0;
+ }
+ return forward_offset + forward_weight;
+}
+
+int PhantomNode::GetReverseWeightPlusOffset() const
+{
+ if (SPECIAL_NODEID == reverse_node_id)
+ {
+ return 0;
+ }
+ return reverse_offset + reverse_weight;
+}
+
+bool PhantomNode::is_bidirected() const
+{
+ 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_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() && (name_id != INVALID_NAMEID); }
+
+bool PhantomNode::operator==(const PhantomNode &other) const { return location == other.location; }
diff --git a/3party/osrm/osrm-backend/data_structures/phantom_node.hpp b/3party/osrm/osrm-backend/data_structures/phantom_node.hpp
new file mode 100755
index 0000000000..b048eb7f21
--- /dev/null
+++ b/3party/osrm/osrm-backend/data_structures/phantom_node.hpp
@@ -0,0 +1,152 @@
+/*
+
+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 PHANTOM_NODES_H
+#define PHANTOM_NODES_H
+
+#include "travel_mode.hpp"
+#include "../typedefs.h"
+
+#include <osrm/coordinate.hpp>
+
+#include <iostream>
+#include <utility>
+#include <vector>
+
+struct 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);
+
+ PhantomNode();
+
+ template <class OtherT> 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;
+ 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 : 4;
+ TravelMode backward_travel_mode : 4;
+
+ int GetForwardWeightPlusOffset() const;
+
+ int GetReverseWeightPlusOffset() const;
+
+ bool is_bidirected() const;
+
+ bool is_compressed() const;
+
+ bool is_valid(const unsigned numberOfNodes) const;
+
+ bool is_valid() const;
+
+ bool is_in_tiny_component() const;
+
+ bool operator==(const PhantomNode &other) const;
+};
+
+using PhantomNodeArray = std::vector<std::vector<PhantomNode>>;
+
+class phantom_node_pair : public std::pair<PhantomNode, PhantomNode>
+{
+};
+
+struct PhantomNodeLists
+{
+ std::vector<PhantomNode> source_phantom_list;
+ std::vector<PhantomNode> target_phantom_list;
+};
+
+struct PhantomNodes
+{
+ PhantomNode source_phantom;
+ PhantomNode target_phantom;
+};
+
+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)
+{
+ 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;
+}
+
+#endif // PHANTOM_NODES_H
diff --git a/3party/osrm/osrm-backend/DataStructures/QueryEdge.h b/3party/osrm/osrm-backend/data_structures/query_edge.hpp
index c9c71962c4..417bb4a13f 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/QueryEdge.h
+++ b/3party/osrm/osrm-backend/data_structures/query_edge.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,11 +25,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef QUERYEDGE_H_
-#define QUERYEDGE_H_
+#ifndef QUERYEDGE_HPP
+#define QUERYEDGE_HPP
#include "../typedefs.h"
+#include <tuple>
+
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_H_ */
+#endif // QUERYEDGE_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/QueryNode.h b/3party/osrm/osrm-backend/data_structures/query_node.hpp
index a9d1aa92b7..f3e9904765 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/QueryNode.h
+++ b/3party/osrm/osrm-backend/data_structures/query_node.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,24 +25,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef QUERY_NODE_H
-#define QUERY_NODE_H
+#ifndef QUERY_NODE_HPP
+#define QUERY_NODE_HPP
#include "../typedefs.h"
-#include "../Include/osrm/Coordinate.h"
-
#include <boost/assert.hpp>
+#include <osrm/coordinate.hpp>
+
#include <limits>
-struct NodeInfo
+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 NodeInfo(int lat, int lon, NodeID node_id) : lat(lat), lon(lon), node_id(node_id) {}
- NodeInfo()
+ explicit QueryNode(int lat, int lon, NodeID node_id) : lat(lat), lon(lon), node_id(node_id) {}
+ QueryNode()
: lat(std::numeric_limits<int>::max()), lon(std::numeric_limits<int>::max()),
node_id(std::numeric_limits<unsigned>::max())
{
@@ -52,18 +52,18 @@ struct NodeInfo
int lon;
NodeID node_id;
- static NodeInfo min_value()
+ static QueryNode min_value()
{
- return NodeInfo(static_cast<int>(-90 * COORDINATE_PRECISION),
- static_cast<int>(-180 * COORDINATE_PRECISION),
- std::numeric_limits<NodeID>::min());
+ return QueryNode(static_cast<int>(-90 * COORDINATE_PRECISION),
+ static_cast<int>(-180 * COORDINATE_PRECISION),
+ std::numeric_limits<NodeID>::min());
}
- static NodeInfo max_value()
+ static QueryNode max_value()
{
- return NodeInfo(static_cast<int>(90 * COORDINATE_PRECISION),
- static_cast<int>(180 * COORDINATE_PRECISION),
- std::numeric_limits<NodeID>::max());
+ return QueryNode(static_cast<int>(90 * COORDINATE_PRECISION),
+ static_cast<int>(180 * COORDINATE_PRECISION),
+ std::numeric_limits<NodeID>::max());
}
value_type operator[](const std::size_t n) const
@@ -78,8 +78,8 @@ struct NodeInfo
break;
}
BOOST_ASSERT_MSG(false, "should not happen");
- return std::numeric_limits<unsigned>::max();
+ return std::numeric_limits<int>::lowest();
}
};
-#endif // QUERY_NODE_H
+#endif // QUERY_NODE_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/RangeTable.h b/3party/osrm/osrm-backend/data_structures/range_table.hpp
index 46333aefb5..4662f06c0a 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/RangeTable.h
+++ b/3party/osrm/osrm-backend/data_structures/range_table.hpp
@@ -1,9 +1,36 @@
-#ifndef RANGE_TABLE_H_
-#define RANGE_TABLE_H_
+/*
+
+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 "Range.h"
-#include "SharedMemoryFactory.h"
-#include "SharedMemoryVectorWrapper.h"
+*/
+
+#ifndef RANGE_TABLE_HPP
+#define RANGE_TABLE_HPP
+
+#include "../util/integer_range.hpp"
+#include "shared_memory_factory.hpp"
+#include "shared_memory_vector_wrapper.hpp"
#include <fstream>
#include <vector>
@@ -14,13 +41,13 @@
* and otherwise the compiler gets confused.
*/
-template<unsigned BLOCK_SIZE=16, bool USE_SHARED_MEMORY = false> class RangeTable;
+template <unsigned BLOCK_SIZE = 16, bool USE_SHARED_MEMORY = false> class RangeTable;
-template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
-std::ostream& operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
+template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
+std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
-template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
-std::istream& operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
+template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
+std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
/**
* Stores adjacent ranges in a compressed format.
@@ -31,33 +58,34 @@ std::istream& operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEM
* But each block consists of an absolute value and BLOCK_SIZE differential values.
* So the effective block size is sizeof(unsigned) + BLOCK_SIZE.
*/
-template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
-class RangeTable
+template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY> class RangeTable
{
-public:
-
+ public:
using BlockT = std::array<unsigned char, BLOCK_SIZE>;
using BlockContainerT = typename ShM<BlockT, USE_SHARED_MEMORY>::vector;
using OffsetContainerT = typename ShM<unsigned, USE_SHARED_MEMORY>::vector;
using RangeT = osrm::range<unsigned>;
- 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<unsigned>& lengths)
+ explicit RangeTable(const std::vector<unsigned> &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)
{
@@ -89,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)
@@ -109,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)
@@ -128,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;
}
@@ -145,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);
@@ -168,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;
@@ -179,8 +208,9 @@ private:
unsigned sum_lengths;
};
-template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
-unsigned RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY>::PrefixSumAtIndex(int index, const BlockT& block) const
+template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
+unsigned RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY>::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.)
@@ -193,39 +223,39 @@ unsigned RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY>::PrefixSumAtIndex(int index,
return sum;
}
-template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
-std::ostream& operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
+template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
+std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &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<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
-std::istream& operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
+template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
+std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &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_H_
+#endif // RANGE_TABLE_HPP
diff --git a/3party/osrm/osrm-backend/data_structures/rectangle.hpp b/3party/osrm/osrm-backend/data_structures/rectangle.hpp
new file mode 100755
index 0000000000..55720a37da
--- /dev/null
+++ b/3party/osrm/osrm-backend/data_structures/rectangle.hpp
@@ -0,0 +1,211 @@
+/*
+
+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 RECTANGLE_HPP
+#define RECTANGLE_HPP
+
+#include "coordinate_calculation.hpp"
+
+#include <boost/assert.hpp>
+
+#include <osrm/coordinate.hpp>
+
+#include <algorithm>
+#include <cstdint>
+#include <limits>
+
+// TODO: Make template type, add tests
+struct RectangleInt2D
+{
+ RectangleInt2D()
+ : min_lon(std::numeric_limits<int32_t>::max()),
+ max_lon(std::numeric_limits<int32_t>::min()),
+ min_lat(std::numeric_limits<int32_t>::max()), max_lat(std::numeric_limits<int32_t>::min())
+ {
+ }
+
+ int32_t min_lon, max_lon;
+ int32_t min_lat, max_lat;
+
+ void MergeBoundingBoxes(const RectangleInt2D &other)
+ {
+ min_lon = std::min(min_lon, other.min_lon);
+ max_lon = std::max(max_lon, other.max_lon);
+ min_lat = std::min(min_lat, other.min_lat);
+ max_lat = std::max(max_lat, other.max_lat);
+ BOOST_ASSERT(min_lat != std::numeric_limits<int32_t>::min());
+ BOOST_ASSERT(min_lon != std::numeric_limits<int32_t>::min());
+ BOOST_ASSERT(max_lat != std::numeric_limits<int32_t>::min());
+ BOOST_ASSERT(max_lon != std::numeric_limits<int32_t>::min());
+ }
+
+ FixedPointCoordinate Centroid() const
+ {
+ FixedPointCoordinate centroid;
+ // The coordinates of the midpoints are given by:
+ // x = (x1 + x2) /2 and y = (y1 + y2) /2.
+ centroid.lon = (min_lon + max_lon) / 2;
+ centroid.lat = (min_lat + max_lat) / 2;
+ return centroid;
+ }
+
+ bool Intersects(const RectangleInt2D &other) const
+ {
+ FixedPointCoordinate upper_left(other.max_lat, other.min_lon);
+ FixedPointCoordinate upper_right(other.max_lat, other.max_lon);
+ FixedPointCoordinate lower_right(other.min_lat, other.max_lon);
+ FixedPointCoordinate lower_left(other.min_lat, other.min_lon);
+
+ return (Contains(upper_left) || Contains(upper_right) || Contains(lower_right) ||
+ Contains(lower_left));
+ }
+
+ float GetMinDist(const FixedPointCoordinate &location) const
+ {
+ const bool is_contained = Contains(location);
+ if (is_contained)
+ {
+ return 0.0f;
+ }
+
+ enum Direction
+ {
+ INVALID = 0,
+ NORTH = 1,
+ SOUTH = 2,
+ EAST = 4,
+ NORTH_EAST = 5,
+ SOUTH_EAST = 6,
+ WEST = 8,
+ NORTH_WEST = 9,
+ SOUTH_WEST = 10
+ };
+
+ Direction d = INVALID;
+ if (location.lat > max_lat)
+ d = (Direction)(d | NORTH);
+ else if (location.lat < min_lat)
+ d = (Direction)(d | SOUTH);
+ if (location.lon > max_lon)
+ d = (Direction)(d | EAST);
+ else if (location.lon < min_lon)
+ d = (Direction)(d | WEST);
+
+ BOOST_ASSERT(d != INVALID);
+
+ float min_dist = std::numeric_limits<float>::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;
+ }
+
+ BOOST_ASSERT(min_dist < std::numeric_limits<float>::max());
+
+ return min_dist;
+ }
+
+ float GetMinMaxDist(const FixedPointCoordinate &location) const
+ {
+ float min_max_dist = std::numeric_limits<float>::max();
+ // Get minmax distance to each of the four sides
+ const FixedPointCoordinate upper_left(max_lat, min_lon);
+ const FixedPointCoordinate upper_right(max_lat, max_lon);
+ 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_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_left),
+ coordinate_calculation::euclidean_distance(location, upper_left)));
+ return min_max_dist;
+ }
+
+ 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;
+ }
+
+ 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 << ","
+ << rect.max_lon / COORDINATE_PRECISION;
+ return out;
+ }
+};
+
+#endif
diff --git a/3party/osrm/osrm-backend/DataStructures/Restriction.h b/3party/osrm/osrm-backend/data_structures/restriction.hpp
index bda0f01961..b808d3070b 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/Restriction.h
+++ b/3party/osrm/osrm-backend/data_structures/restriction.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef RESTRICTION_H
-#define RESTRICTION_H
+#ifndef RESTRICTION_HPP
+#define RESTRICTION_HPP
#include "../typedefs.h"
@@ -34,19 +34,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct TurnRestriction
{
- NodeID viaNode;
- NodeID fromNode;
- NodeID toNode;
+ union WayOrNode
+ {
+ NodeID node;
+ EdgeID way;
+ };
+ WayOrNode via;
+ WayOrNode from;
+ WayOrNode to;
+
struct Bits
{ // mostly unused
Bits()
- : isOnly(false), unused1(false), unused2(false), unused3(false), unused4(false),
+ : is_only(false), uses_via_way(false), unused2(false), unused3(false), unused4(false),
unused5(false), unused6(false), unused7(false)
{
}
- bool isOnly : 1;
- bool unused1 : 1;
+ bool is_only : 1;
+ bool uses_via_way : 1;
bool unused2 : 1;
bool unused3 : 1;
bool unused4 : 1;
@@ -55,72 +61,70 @@ struct TurnRestriction
bool unused7 : 1;
} flags;
- explicit TurnRestriction(NodeID viaNode)
- : viaNode(viaNode), fromNode(std::numeric_limits<unsigned>::max()),
- toNode(std::numeric_limits<unsigned>::max())
+ explicit TurnRestriction(NodeID node)
{
+ via.node = node;
+ from.node = SPECIAL_NODEID;
+ to.node = SPECIAL_NODEID;
}
- explicit TurnRestriction(const bool isOnly = false)
- : viaNode(std::numeric_limits<unsigned>::max()),
- fromNode(std::numeric_limits<unsigned>::max()),
- toNode(std::numeric_limits<unsigned>::max())
+ explicit TurnRestriction(const bool is_only = false)
{
- flags.isOnly = isOnly;
+ via.node = SPECIAL_NODEID;
+ from.node = SPECIAL_NODEID;
+ to.node = SPECIAL_NODEID;
+ flags.is_only = is_only;
}
};
struct InputRestrictionContainer
{
- EdgeID fromWay;
- EdgeID toWay;
- unsigned viaNode;
+ // EdgeID fromWay;
+ // EdgeID toWay;
+ // NodeID via_node;
TurnRestriction restriction;
- InputRestrictionContainer(EdgeID fromWay, EdgeID toWay, NodeID vn, unsigned vw)
- : fromWay(fromWay), toWay(toWay), viaNode(vw)
+ InputRestrictionContainer(EdgeID fromWay, EdgeID toWay, EdgeID vw)
{
- restriction.viaNode = vn;
+ restriction.from.way = fromWay;
+ restriction.to.way = toWay;
+ restriction.via.way = vw;
}
- explicit InputRestrictionContainer(bool isOnly = false)
- : fromWay(std::numeric_limits<unsigned>::max()),
- toWay(std::numeric_limits<unsigned>::max()), viaNode(std::numeric_limits<unsigned>::max())
+ explicit InputRestrictionContainer(bool is_only = false)
{
- restriction.flags.isOnly = isOnly;
+ restriction.from.way = SPECIAL_EDGEID;
+ restriction.to.way = SPECIAL_EDGEID;
+ restriction.via.node = SPECIAL_NODEID;
+ restriction.flags.is_only = is_only;
}
- static InputRestrictionContainer min_value() { return InputRestrictionContainer(0, 0, 0, 0); }
+ static InputRestrictionContainer min_value() { return InputRestrictionContainer(0, 0, 0); }
static InputRestrictionContainer max_value()
{
- return InputRestrictionContainer(std::numeric_limits<unsigned>::max(),
- std::numeric_limits<unsigned>::max(),
- std::numeric_limits<unsigned>::max(),
- std::numeric_limits<unsigned>::max());
+ return InputRestrictionContainer(SPECIAL_EDGEID, SPECIAL_EDGEID, SPECIAL_EDGEID);
}
};
struct CmpRestrictionContainerByFrom
{
using value_type = InputRestrictionContainer;
- inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
- const
+ bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b) const
{
- return a.fromWay < b.fromWay;
+ 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
{
using value_type = InputRestrictionContainer;
- inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
- const
+ bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b) const
{
- return a.toWay < b.toWay;
+ return a.restriction.to.way < b.restriction.to.way;
}
value_type max_value() const { return InputRestrictionContainer::max_value(); }
value_type min_value() const { return InputRestrictionContainer::min_value(); }
};
-#endif // RESTRICTION_H
+#endif // RESTRICTION_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/RestrictionMap.cpp b/3party/osrm/osrm-backend/data_structures/restriction_map.cpp
index f2c56e0cfd..017ee32513 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/RestrictionMap.cpp
+++ b/3party/osrm/osrm-backend/data_structures/restriction_map.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,28 +25,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "RestrictionMap.h"
-#include "NodeBasedGraph.h"
+#include "restriction_map.hpp"
-bool RestrictionMap::IsViaNode(const NodeID node) const
-{
- return m_no_turn_via_node_set.find(node) != m_no_turn_via_node_set.end();
-}
-
-RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
- const std::vector<TurnRestriction> &restriction_list)
- : m_count(0), m_graph(graph)
+RestrictionMap::RestrictionMap(const std::vector<TurnRestriction> &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)
{
- m_restriction_start_nodes.insert(restriction.fromNode);
- m_no_turn_via_node_set.insert(restriction.viaNode);
+ m_restriction_start_nodes.insert(restriction.from.node);
+ m_no_turn_via_node_set.insert(restriction.via.node);
- RestrictionSource restriction_source = {restriction.fromNode, restriction.viaNode};
+ RestrictionSource restriction_source = {restriction.from.node, restriction.via.node};
- unsigned index;
+ std::size_t index;
auto restriction_iter = m_restriction_map.find(restriction_source);
if (restriction_iter == m_restriction_map.end())
{
@@ -62,7 +54,7 @@ RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &gra
{
continue;
}
- else if (restriction.flags.isOnly)
+ 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();
@@ -71,54 +63,13 @@ RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &gra
}
++m_count;
m_restriction_bucket_list.at(index)
- .emplace_back(restriction.toNode, restriction.flags.isOnly);
+ .emplace_back(restriction.to.node, restriction.flags.is_only);
}
}
-// Replace end v with w in each turn restriction containing u as via node
-void RestrictionMap::FixupArrivingTurnRestriction(const NodeID node_u,
- const NodeID node_v,
- const NodeID node_w)
+bool RestrictionMap::IsViaNode(const NodeID node) const
{
- BOOST_ASSERT(node_u != SPECIAL_NODEID);
- BOOST_ASSERT(node_v != SPECIAL_NODEID);
- BOOST_ASSERT(node_w != SPECIAL_NODEID);
-
- if (!IsViaNode(node_u))
- {
- return;
- }
-
- // find all potential start edges. It is more efficent to get a (small) list
- // of potential start edges than iterating over all buckets
- std::vector<NodeID> predecessors;
- for (const EdgeID current_edge_id : m_graph->GetAdjacentEdgeRange(node_u))
- {
- const NodeID target = m_graph->GetTarget(current_edge_id);
- if (node_v != target)
- {
- predecessors.push_back(target);
- }
- }
-
- for (const NodeID node_x : predecessors)
- {
- const auto restriction_iterator = m_restriction_map.find({node_x, node_u});
- if (restriction_iterator == m_restriction_map.end())
- {
- continue;
- }
-
- 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)
- {
- restriction_target.target_node = node_w;
- }
- }
- }
+ 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.
@@ -191,18 +142,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);
- for (const RestrictionTarget &restriction_target : bucket)
+ return false;
+ }
+
+ 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;
- }
+ 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;
diff --git a/3party/osrm/osrm-backend/DataStructures/RestrictionMap.h b/3party/osrm/osrm-backend/data_structures/restriction_map.hpp
index 3945a3982b..27a6698dbc 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/RestrictionMap.h
+++ b/3party/osrm/osrm-backend/data_structures/restriction_map.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,28 +25,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef RESTRICTION_MAP_H_
-#define RESTRICTION_MAP_H_
+#ifndef RESTRICTION_MAP_HPP
+#define RESTRICTION_MAP_HPP
-#include <memory>
-
-#include "DynamicGraph.h"
-#include "Restriction.h"
-#include "NodeBasedGraph.h"
-#include "../Util/StdHashExtensions.h"
+#include "restriction.hpp"
+#include "../util/std_hash.hpp"
#include "../typedefs.h"
+#include <boost/assert.hpp>
+
+#include <memory>
#include <unordered_map>
#include <unordered_set>
+#include <vector>
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)
{
@@ -95,26 +91,79 @@ template <> struct hash<RestrictionTarget>
class RestrictionMap
{
public:
- RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
- const std::vector<TurnRestriction> &input_restrictions_list);
-
- void FixupArrivingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
- void FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
- NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
- bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
- bool IsViaNode(const NodeID node) const;
- std::size_t size()
+ RestrictionMap(const std::vector<TurnRestriction> &restriction_list);
+
+ // Replace end v with w in each turn restriction containing u as via node
+ template <class GraphT>
+ void FixupArrivingTurnRestriction(const NodeID node_u,
+ const NodeID node_v,
+ const NodeID node_w,
+ const std::shared_ptr<GraphT> &graph)
{
- return m_count;
+ BOOST_ASSERT(node_u != SPECIAL_NODEID);
+ BOOST_ASSERT(node_v != SPECIAL_NODEID);
+ BOOST_ASSERT(node_w != SPECIAL_NODEID);
+
+ if (!IsViaNode(node_u))
+ {
+ return;
+ }
+
+ // find all potential start edges. It is more efficent to get a (small) list
+ // of potential start edges than iterating over all buckets
+ std::vector<NodeID> predecessors;
+ for (const EdgeID current_edge_id : graph->GetAdjacentEdgeRange(node_u))
+ {
+ const NodeID target = graph->GetTarget(current_edge_id);
+ if (node_v != target)
+ {
+ predecessors.push_back(target);
+ }
+ }
+
+ for (const NodeID node_x : predecessors)
+ {
+ const auto restriction_iterator = m_restriction_map.find({node_x, node_u});
+ if (restriction_iterator == m_restriction_map.end())
+ {
+ continue;
+ }
+
+ 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)
+ {
+ restriction_target.target_node = node_w;
+ }
+ }
+ }
}
+ 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);
+
+ // 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 <u,v,w> is actually a turn restriction.
+ bool
+ CheckIfTurnIsRestricted(const NodeID node_u, const NodeID node_v, const NodeID node_w) const;
+
+ std::size_t size() { return m_count; }
+
private:
+ // check of node is the start of any restriction
bool IsSourceNode(const NodeID node) const;
+
using EmanatingRestrictionsVector = std::vector<RestrictionTarget>;
- using EdgeData = NodeBasedDynamicGraph::EdgeData;
std::size_t m_count;
- std::shared_ptr<NodeBasedDynamicGraph> m_graph;
//! index -> list of (target, isOnly)
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
//! maps (start, via) -> bucket index
@@ -123,4 +172,4 @@ class RestrictionMap
std::unordered_set<NodeID> m_no_turn_via_node_set;
};
-#endif //RESTRICTION_MAP_H_
+#endif // RESTRICTION_MAP_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/RouteParameters.cpp b/3party/osrm/osrm-backend/data_structures/route_parameters.cpp
index 1019a9149e..3b615e2c41 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/RouteParameters.cpp
+++ b/3party/osrm/osrm-backend/data_structures/route_parameters.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,15 +25,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <osrm/RouteParameters.h>
-
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/sequence/intrinsic.hpp>
#include <boost/fusion/include/at_c.hpp>
+#include <osrm/route_parameters.hpp>
+
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 &parameter)
@@ -99,6 +106,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;
@@ -108,10 +124,10 @@ void RouteParameters::setGeometryFlag(const bool flag) { geometry = flag; }
void RouteParameters::setCompressionFlag(const bool flag) { compression = flag; }
-void
-RouteParameters::addCoordinate(const boost::fusion::vector<double, double> &transmitted_coordinates)
+void RouteParameters::addCoordinate(
+ const boost::fusion::vector<double, double> &received_coordinates)
{
coordinates.emplace_back(
- static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<0>(transmitted_coordinates)),
- static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<1>(transmitted_coordinates)));
+ static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<0>(received_coordinates)),
+ static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<1>(received_coordinates)));
}
diff --git a/3party/osrm/osrm-backend/DataStructures/SearchEngine.h b/3party/osrm/osrm-backend/data_structures/search_engine.hpp
index 58f5e774d6..7e47b1f5df 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/SearchEngine.h
+++ b/3party/osrm/osrm-backend/data_structures/search_engine.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,13 +25,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SEARCHENGINE_H
-#define SEARCHENGINE_H
+#ifndef SEARCH_ENGINE_HPP
+#define SEARCH_ENGINE_HPP
-#include "SearchEngineData.h"
-#include "../RoutingAlgorithms/AlternativePathRouting.h"
-#include "../RoutingAlgorithms/ManyToManyRouting.h"
-#include "../RoutingAlgorithms/ShortestPathRouting.h"
+#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 <type_traits>
@@ -45,16 +46,21 @@ template <class DataFacadeT> class SearchEngine
ShortestPathRouting<DataFacadeT> shortest_path;
AlternativeRouting<DataFacadeT> alternative_path;
ManyToManyRouting<DataFacadeT> distance_table;
+ MapMatching<DataFacadeT> 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<DataFacadeT>::value, "don't instantiate with ptr type");
- static_assert(std::is_object<DataFacadeT>::value, "don't instantiate with void, function, or reference");
+ static_assert(std::is_object<DataFacadeT>::value,
+ "don't instantiate with void, function, or reference");
}
~SearchEngine() {}
};
-#endif // SEARCHENGINE_H
+#endif // SEARCH_ENGINE_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/SearchEngineData.cpp b/3party/osrm/osrm-backend/data_structures/search_engine_data.cpp
index a5e4bfcd88..3282a0ccb2 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/SearchEngineData.cpp
+++ b/3party/osrm/osrm-backend/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,
@@ -25,69 +25,69 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "SearchEngineData.h"
+#include "search_engine_data.hpp"
-#include "BinaryHeap.h"
+#include "binary_heap.hpp"
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/3party/osrm/osrm-backend/DataStructures/SearchEngineData.h b/3party/osrm/osrm-backend/data_structures/search_engine_data.hpp
index 378ff95496..8c1c1619e0 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/SearchEngineData.h
+++ b/3party/osrm/osrm-backend/data_structures/search_engine_data.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,13 +25,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SEARCH_ENGINE_DATA_H
-#define SEARCH_ENGINE_DATA_H
+#ifndef SEARCH_ENGINE_DATA_HPP
+#define SEARCH_ENGINE_DATA_HPP
-#include <boost/scoped_ptr.hpp>
+#include <boost/thread/tss.hpp>
#include "../typedefs.h"
-#include "BinaryHeap.h"
+#include "binary_heap.hpp"
struct HeapData
{
@@ -42,14 +42,14 @@ struct HeapData
struct SearchEngineData
{
using QueryHeap = BinaryHeap<NodeID, NodeID, int, HeapData, UnorderedMapStorage<NodeID, int>>;
- using SearchEngineHeapPtr = boost::scoped_ptr<QueryHeap>;
+ using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
- 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);
@@ -58,4 +58,4 @@ struct SearchEngineData
void InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes);
};
-#endif // SEARCH_ENGINE_DATA_H
+#endif // SEARCH_ENGINE_DATA_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/SegmentInformation.h b/3party/osrm/osrm-backend/data_structures/segment_information.hpp
index 6e8d683974..7118a320e8 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/SegmentInformation.h
+++ b/3party/osrm/osrm-backend/data_structures/segment_information.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,15 +25,15 @@ 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 "TurnInstructions.h"
+#include "turn_instructions.hpp"
-#include "../DataStructures/TravelMode.h"
+#include "../data_structures/travel_mode.hpp"
#include "../typedefs.h"
-#include <osrm/Coordinate.h>
+#include <osrm/coordinate.hpp>
// Struct fits everything in one cache line
struct SegmentInformation
@@ -75,4 +75,4 @@ struct SegmentInformation
}
};
-#endif /* SEGMENT_INFORMATION_H */
+#endif /* SEGMENT_INFORMATION_HPP */
diff --git a/3party/osrm/osrm-backend/DataStructures/SharedMemoryFactory.h b/3party/osrm/osrm-backend/data_structures/shared_memory_factory.hpp
index 7a0c0790b0..58fed9bb3f 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/SharedMemoryFactory.h
+++ b/3party/osrm/osrm-backend/data_structures/shared_memory_factory.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,25 +25,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SHARED_MEMORY_FACTORY_H
-#define SHARED_MEMORY_FACTORY_H
+#ifndef SHARED_MEMORY_FACTORY_HPP
+#define SHARED_MEMORY_FACTORY_HPP
-#include "../Util/OSRMException.h"
-#include "../Util/simple_logger.hpp"
+#include "../util/osrm_exception.hpp"
+#include "../util/simple_logger.hpp"
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/interprocess/mapped_region.hpp>
-#if !defined(WIN32) && !defined(__ANDROID__)
+#ifndef WIN32
#include <boost/interprocess/xsi_shared_memory.hpp>
#else
#include <boost/interprocess/shared_memory_object.hpp>
#endif
-//#ifdef __linux__
-//#include <sys/ipc.h>
-//#include <sys/shm.h>
-//#endif
+#ifdef __linux__
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif
// #include <cstring>
#include <cstdint>
@@ -61,7 +61,7 @@ struct OSRMLockFile
}
};
-#if !defined(WIN32) && !defined(__ANDROID__)
+#ifndef WIN32
class SharedMemory
{
@@ -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;
}
@@ -344,7 +355,7 @@ template <class LockFileT = OSRMLockFile> class SharedMemoryFactory_tmpl
{
if (0 == size)
{
- throw OSRMException("lock file does not exist, exiting");
+ throw osrm::exception("lock file does not exist, exiting");
}
else
{
@@ -358,7 +369,7 @@ template <class LockFileT = OSRMLockFile> class SharedMemoryFactory_tmpl
{
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what() << ", code "
<< e.get_error_code();
- throw OSRMException(e.what());
+ throw osrm::exception(e.what());
}
}
@@ -368,4 +379,4 @@ template <class LockFileT = OSRMLockFile> class SharedMemoryFactory_tmpl
using SharedMemoryFactory = SharedMemoryFactory_tmpl<>;
-#endif /* SHARED_MEMORY_POINTER_FACTORY_H */
+#endif // SHARED_MEMORY_FACTORY_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/SharedMemoryVectorWrapper.h b/3party/osrm/osrm-backend/data_structures/shared_memory_vector_wrapper.hpp
index bcc30a7f2c..dc51cff0d4 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/SharedMemoryVectorWrapper.h
+++ b/3party/osrm/osrm-backend/data_structures/shared_memory_vector_wrapper.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SHARED_MEMORY_VECTOR_WRAPPER_H
-#define SHARED_MEMORY_VECTOR_WRAPPER_H
+#ifndef SHARED_MEMORY_VECTOR_WRAPPER_HPP
+#define SHARED_MEMORY_VECTOR_WRAPPER_HPP
#include <boost/assert.hpp>
@@ -147,8 +147,8 @@ template <> class SharedMemoryWrapper<bool>
template <typename DataT, bool UseSharedMemory> struct ShM
{
using vector = typename std::conditional<UseSharedMemory,
- SharedMemoryWrapper<DataT>,
- std::vector<DataT>>::type;
+ SharedMemoryWrapper<DataT>,
+ std::vector<DataT>>::type;
};
-#endif // SHARED_MEMORY_VECTOR_WRAPPER_H
+#endif // SHARED_MEMORY_VECTOR_WRAPPER_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/StaticGraph.h b/3party/osrm/osrm-backend/data_structures/static_graph.hpp
index b18ac0dfda..7434b56de6 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/StaticGraph.h
+++ b/3party/osrm/osrm-backend/data_structures/static_graph.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,12 +25,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef STATIC_GRAPH_H
-#define STATIC_GRAPH_H
+#ifndef STATIC_GRAPH_HPP
+#define STATIC_GRAPH_HPP
-#include "Percent.h"
-#include "Range.h"
-#include "SharedMemoryVectorWrapper.h"
+#include "percent.hpp"
+#include "shared_memory_vector_wrapper.hpp"
+#include "../util/integer_range.hpp"
#include "../typedefs.h"
#include <boost/assert.hpp>
@@ -55,8 +55,11 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
NodeIterator target;
EdgeDataT data;
- template<typename... Ts>
- InputEdge(NodeIterator source, NodeIterator target, Ts &&...data) : source(source), target(target), data(std::forward<Ts>(data)...) { }
+ template <typename... Ts>
+ InputEdge(NodeIterator source, NodeIterator target, Ts &&... data)
+ : source(source), target(target), data(std::forward<Ts>(data)...)
+ {
+ }
bool operator<(const InputEdge &right) const
{
if (source != right.source)
@@ -86,13 +89,12 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
StaticGraph(const int nodes, std::vector<InputEdge> &graph)
{
- std::sort(graph.begin(), graph.end());
number_of_nodes = nodes;
- number_of_edges = (EdgeIterator)graph.size();
+ number_of_edges = static_cast<EdgeIterator>(graph.size());
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)
@@ -107,11 +109,10 @@ template <typename EdgeDataT, bool UseSharedMemory = false> 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++;
}
}
@@ -138,7 +139,7 @@ template <typename EdgeDataT, bool UseSharedMemory = false> 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; }
@@ -155,6 +156,19 @@ template <typename EdgeDataT, bool UseSharedMemory = false> 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 SPECIAL_EDGEID;
+ }
+
+ // 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))
@@ -199,4 +213,4 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector edge_array;
};
-#endif // STATIC_GRAPH_H
+#endif // STATIC_GRAPH_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/StaticKDTree.h b/3party/osrm/osrm-backend/data_structures/static_kdtree.hpp
index 4e93884472..1e65dc8449 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/StaticKDTree.h
+++ b/3party/osrm/osrm-backend/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,
@@ -27,8 +27,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// KD Tree coded by Christian Vetter, Monav Project
-#ifndef STATICKDTREE_H_INCLUDED
-#define STATICKDTREE_H_INCLUDED
+#ifndef STATICKDTREE_HPP
+#define STATICKDTREE_HPP
#include <boost/assert.hpp>
#include <vector>
@@ -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));
}
@@ -257,4 +257,4 @@ class StaticKDTree
};
}
-#endif // STATICKDTREE_H_INCLUDED
+#endif // STATICKDTREE_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/StaticRTree.h b/3party/osrm/osrm-backend/data_structures/static_rtree.hpp
index 260a9ca4ca..f219a64755 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/StaticRTree.h
+++ b/3party/osrm/osrm-backend/data_structures/static_rtree.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,31 +25,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef STATICRTREE_H
-#define STATICRTREE_H
-
-#include "DeallocatingVector.h"
-#include "HilbertValue.h"
-#include "PhantomNodes.h"
-#include "QueryNode.h"
-#include "SharedMemoryFactory.h"
-#include "SharedMemoryVectorWrapper.h"
-
-#include "../ThirdParty/variant/variant.hpp"
-#include "../Util/floating_point.hpp"
-#include "../Util/MercatorUtil.h"
-#include "../Util/OSRMException.h"
-#include "../Util/simple_logger.hpp"
-#include "../Util/TimingUtil.h"
+#ifndef STATIC_RTREE_HPP
+#define STATIC_RTREE_HPP
+
+#include "deallocating_vector.hpp"
+#include "hilbert_value.hpp"
+#include "phantom_node.hpp"
+#include "query_node.hpp"
+#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"
+#include "../util/mercator.hpp"
+#include "../util/osrm_exception.hpp"
+#include "../util/simple_logger.hpp"
+#include "../util/timing_util.hpp"
#include "../typedefs.h"
-#include <osrm/Coordinate.h>
+#include <osrm/coordinate.hpp>
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/thread.hpp>
+#include <tbb/parallel_for.h>
+#include <tbb/parallel_sort.h>
+
+#include <variant/variant.hpp>
+
#include <algorithm>
#include <array>
#include <limits>
@@ -62,8 +69,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
template <class EdgeDataT,
class CoordinateListT = std::vector<FixedPointCoordinate>,
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:
@@ -76,23 +83,19 @@ class StaticRTree
inline void InitializeMBRectangle(const std::array<EdgeDataT, LEAF_NODE_SIZE> &objects,
const uint32_t element_count,
- const std::vector<NodeInfo> &coordinate_list)
+ const std::vector<QueryNode> &coordinate_list)
{
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_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_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));
}
BOOST_ASSERT(min_lat != std::numeric_limits<int>::min());
BOOST_ASSERT(min_lon != std::numeric_limits<int>::min());
@@ -143,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<float>::max();
switch (d)
{
- case NORTH:
- min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, location.lon));
- break;
- case SOUTH:
- min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, location.lon));
- break;
- case WEST:
- min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, min_lon));
- break;
- case EAST:
- min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, max_lon));
- break;
- case NORTH_EAST:
- min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, max_lon));
- break;
- case NORTH_WEST:
- min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, min_lon));
- break;
- case SOUTH_EAST:
- min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, max_lon));
- break;
- case SOUTH_WEST:
- min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(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<float>::max());
@@ -213,25 +224,23 @@ class StaticRTree
min_max_dist = std::min(
min_max_dist,
- std::max(
- FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left),
- FixedPointCoordinate::ApproximateEuclideanDistance(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(
- FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right),
- FixedPointCoordinate::ApproximateEuclideanDistance(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,
- std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right),
- FixedPointCoordinate::ApproximateEuclideanDistance(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(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left),
- FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left)));
+ std::max(coordinate_calculation::euclidean_distance(location, lower_left),
+ coordinate_calculation::euclidean_distance(location, upper_left)));
return min_max_dist;
}
@@ -338,7 +347,7 @@ class StaticRTree
explicit StaticRTree(std::vector<EdgeDataT> &input_data_vector,
const std::string tree_node_filename,
const std::string leaf_node_filename,
- const std::vector<NodeInfo> &coordinate_list)
+ const std::vector<QueryNode> &coordinate_list)
: m_element_count(input_data_vector.size()), m_leaf_node_filename(leaf_node_filename)
{
SimpleLogger().Write() << "constructing r-tree of " << m_element_count
@@ -351,31 +360,39 @@ class StaticRTree
HilbertCode get_hilbert_number;
// generate auxiliary vector of hilbert-values
- for (uint64_t element_counter = 0; element_counter != m_element_count; ++element_counter)
- {
- WrappedInputElement &current_wrapper = input_wrapper_vector[element_counter];
- current_wrapper.m_array_index = element_counter;
-
- EdgeDataT const &current_element = input_data_vector[element_counter];
-
- // Get Hilbert-Value for centroid in mercartor projection
- FixedPointCoordinate current_centroid = EdgeDataT::Centroid(
- FixedPointCoordinate(coordinate_list.at(current_element.u).lat,
- coordinate_list.at(current_element.u).lon),
- 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);
-
- current_wrapper.m_hilbert_value = get_hilbert_number(current_centroid);
- }
+ tbb::parallel_for(
+ tbb::blocked_range<uint64_t>(0, m_element_count),
+ [&input_data_vector, &input_wrapper_vector, &get_hilbert_number, &coordinate_list](
+ const tbb::blocked_range<uint64_t> &range)
+ {
+ for (uint64_t element_counter = range.begin(); element_counter != range.end();
+ ++element_counter)
+ {
+ WrappedInputElement &current_wrapper = input_wrapper_vector[element_counter];
+ current_wrapper.m_array_index = element_counter;
+
+ EdgeDataT const &current_element = input_data_vector[element_counter];
+
+ // Get Hilbert-Value for centroid in mercartor projection
+ FixedPointCoordinate current_centroid = EdgeDataT::Centroid(
+ FixedPointCoordinate(coordinate_list.at(current_element.u).lat,
+ coordinate_list.at(current_element.u).lon),
+ 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);
+
+ current_wrapper.m_hilbert_value = get_hilbert_number(current_centroid);
+ }
+ });
// open leaf file
boost::filesystem::ofstream leaf_node_file(leaf_node_filename, std::ios::binary);
leaf_node_file.write((char *)&m_element_count, sizeof(uint64_t));
// sort the hilbert-value representatives
- sort(input_wrapper_vector.begin(), input_wrapper_vector.end());
+ tbb::parallel_sort(input_wrapper_vector.begin(), input_wrapper_vector.end());
std::vector<TreeNode> tree_nodes_in_level;
// pack M elements into leaf node and write to leaf file
@@ -402,8 +419,8 @@ class StaticRTree
}
// generate tree node that resemble the objects in leaf and store it for next level
- current_node.minimum_bounding_rectangle.InitializeMBRectangle(
- 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);
@@ -426,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())
{
@@ -457,17 +473,20 @@ class StaticRTree
std::reverse(m_search_tree.begin(), m_search_tree.end());
uint32_t search_tree_size = m_search_tree.size();
-
- for (uint32_t i = 0; i != search_tree_size; ++i)
- {
- TreeNode &current_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;
- }
- }
+ tbb::parallel_for(tbb::blocked_range<uint32_t>(0, search_tree_size),
+ [this, &search_tree_size](const tbb::blocked_range<uint32_t> &range)
+ {
+ for (uint32_t i = range.begin(); i != range.end(); ++i)
+ {
+ TreeNode &current_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);
@@ -495,11 +514,11 @@ class StaticRTree
if (!boost::filesystem::exists(node_file))
{
- throw OSRMException("ram index file does not exist");
+ throw osrm::exception("ram index file does not exist");
}
if (0 == boost::filesystem::file_size(node_file))
{
- throw OSRMException("ram index file is empty");
+ throw osrm::exception("ram index file is empty");
}
boost::filesystem::ifstream tree_node_file(node_file, std::ios::binary);
@@ -515,11 +534,11 @@ class StaticRTree
// open leaf node file and store thread specific pointer
if (!boost::filesystem::exists(leaf_file))
{
- throw OSRMException("mem index file does not exist");
+ throw osrm::exception("mem index file does not exist");
}
if (0 == boost::filesystem::file_size(leaf_file))
{
- throw OSRMException("mem index file is empty");
+ throw osrm::exception("mem index file is empty");
}
leaves_stream.open(leaf_file, std::ios::binary);
@@ -539,11 +558,11 @@ class StaticRTree
// open leaf node file and store thread specific pointer
if (!boost::filesystem::exists(leaf_file))
{
- throw OSRMException("mem index file does not exist");
+ throw osrm::exception("mem index file does not exist");
}
if (0 == boost::filesystem::file_size(leaf_file))
{
- throw OSRMException("mem index file is empty");
+ throw osrm::exception("mem index file is empty");
}
leaves_stream.open(leaf_file, std::ios::binary);
@@ -584,17 +603,15 @@ class StaticRTree
for (uint32_t i = 0; i < current_leaf_node.object_count; ++i)
{
EdgeDataT const &current_edge = current_leaf_node.objects[i];
- if (ignore_tiny_components && current_edge.is_in_tiny_cc)
+ if (ignore_tiny_components && current_edge.component_id != 0)
{
continue;
}
- float current_minimum_distance =
- FixedPointCoordinate::ApproximateEuclideanDistance(
- 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
@@ -602,12 +619,10 @@ class StaticRTree
result_coordinate = m_coordinate_list->at(current_edge.u);
}
- current_minimum_distance =
- FixedPointCoordinate::ApproximateEuclideanDistance(
- 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)
{
@@ -619,39 +634,33 @@ 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.isValid();
+ return result_coordinate.is_valid();
}
- // implementation of the Hjaltason/Samet query [3], a BFS traversal of the tree
- bool
- IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
- std::vector<PhantomNode> &result_phantom_node_vector,
- const unsigned zoom_level,
- const unsigned number_of_results,
- const unsigned max_checked_segments = 4*LEAF_NODE_SIZE)
+ bool IncrementalFindPhantomNodeForCoordinate(
+ const FixedPointCoordinate &input_coordinate,
+ std::vector<PhantomNode> &result_phantom_node_vector,
+ const unsigned max_number_of_phantom_nodes,
+ const unsigned max_checked_elements = 4 * LEAF_NODE_SIZE)
{
- // TIMER_START(samet);
- // SimpleLogger().Write(logDEBUG) << "searching for " << number_of_results << " results";
- std::vector<float> min_found_distances(number_of_results, std::numeric_limits<float>::max());
-
- unsigned dequeues = 0;
- unsigned inspected_mbrs = 0;
- unsigned loaded_leafs = 0;
- unsigned inspected_segments = 0;
+ unsigned inspected_elements = 0;
+ unsigned number_of_elements_from_big_cc = 0;
+ unsigned number_of_elements_from_tiny_cc = 0;
+
+#ifdef NDEBUG
unsigned pruned_elements = 0;
- unsigned ignored_segments = 0;
- unsigned ignored_mbrs = 0;
+#endif
+ std::pair<double, double> projected_coordinate = {
+ mercator::lat2y(input_coordinate.lat / COORDINATE_PRECISION),
+ input_coordinate.lon / COORDINATE_PRECISION};
- unsigned number_of_results_found_in_big_cc = 0;
- unsigned number_of_results_found_in_tiny_cc = 0;
+ // upper bound pruning technique
+ upper_bound<float> pruning_bound(max_number_of_phantom_nodes);
// initialize queue with root element
std::priority_queue<IncrementalQueryCandidate> traversal_queue;
@@ -662,202 +671,152 @@ class StaticRTree
const IncrementalQueryCandidate current_query_node = traversal_queue.top();
traversal_queue.pop();
- ++dequeues;
-
- const float current_min_dist = min_found_distances[number_of_results-1];
-
- if (current_query_node.min_dist > current_min_dist)
- {
- ++pruned_elements;
- continue;
- }
-
if (current_query_node.node.template is<TreeNode>())
- {
- const TreeNode & current_tree_node = current_query_node.node.template get<TreeNode>();
+ { // current object is a tree node
+ const TreeNode &current_tree_node =
+ current_query_node.node.template get<TreeNode>();
if (current_tree_node.child_is_on_disk)
{
- ++loaded_leafs;
- // SimpleLogger().Write(logDEBUG) << "loading leaf: " << current_tree_node.children[0] << " w/ mbr [" <<
- // current_tree_node.minimum_bounding_rectangle.min_lat/COORDINATE_PRECISION << "," <<
- // current_tree_node.minimum_bounding_rectangle.min_lon/COORDINATE_PRECISION << "," <<
- // current_tree_node.minimum_bounding_rectangle.max_lat/COORDINATE_PRECISION << "-" <<
- // current_tree_node.minimum_bounding_rectangle.max_lon/COORDINATE_PRECISION << "]";
-
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 &current_edge = current_leaf_node.objects[i];
- const float current_perpendicular_distance =
- FixedPointCoordinate::ComputePerpendicularDistance(
+ 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);
}
+#ifdef NDEBUG
else
{
- ++ignored_segments;
+ ++pruned_elements;
}
+#endif
}
- // SimpleLogger().Write(logDEBUG) << "added " << current_leaf_node.object_count << " roads into queue of " << traversal_queue.size();
}
else
{
- ++inspected_mbrs;
- // explore inner node
- // SimpleLogger().Write(logDEBUG) << "explore inner node w/ mbr [" <<
- // current_tree_node.minimum_bounding_rectangle.min_lat/COORDINATE_PRECISION << "," <<
- // current_tree_node.minimum_bounding_rectangle.min_lon/COORDINATE_PRECISION << "," <<
- // current_tree_node.minimum_bounding_rectangle.max_lat/COORDINATE_PRECISION << "-" <<
- // current_tree_node.minimum_bounding_rectangle.max_lon/COORDINATE_PRECISION << "," << "]";
-
- // 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];
- 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);
- // 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);
- }
- else
- {
- ++ignored_mbrs;
- }
+ 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 & current_segment = current_query_node.node.template get<EdgeDataT>();
+ const EdgeDataT &current_segment =
+ current_query_node.node.template get<EdgeDataT>();
- // 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 =
- FixedPointCoordinate::ComputePerpendicularDistance(
- m_coordinate_list->at(current_segment.u),
- m_coordinate_list->at(current_segment.v),
- input_coordinate,
- foot_point_coordinate_on_segment,
- current_ratio);
- BOOST_ASSERT(0. <= current_perpendicular_distance);
+ // 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);
- 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.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_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());
-
- // 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;
- }
+ // store phantom node in result vector
+ 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());
+
+ // set forward and reverse weights on the phantom node
+ SetForwardAndReverseWeightsOnPhantomNode(current_segment,
+ result_phantom_node_vector.back());
+
+ // 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<IncrementalQueryCandidate>{};
}
}
-
- // for (const PhantomNode& result_node : result_phantom_node_vector)
- // {
- // SimpleLogger().Write(logDEBUG) << std::setprecision(8) << "found location " << result_node.forward_node_id << " at " << result_node.location;
- // }
- // SimpleLogger().Write(logDEBUG) << "dequeues: " << dequeues;
- // SimpleLogger().Write(logDEBUG) << "inspected_mbrs: " << inspected_mbrs;
- // SimpleLogger().Write(logDEBUG) << "loaded_leafs: " << loaded_leafs;
- // SimpleLogger().Write(logDEBUG) << "inspected_segments: " << inspected_segments;
- // SimpleLogger().Write(logDEBUG) << "pruned_elements: " << pruned_elements;
- // SimpleLogger().Write(logDEBUG) << "ignored_segments: " << ignored_segments;
- // SimpleLogger().Write(logDEBUG) << "ignored_mbrs: " << ignored_mbrs;
-
- // SimpleLogger().Write(logDEBUG) << "number_of_results_found_in_big_cc: " << number_of_results_found_in_big_cc;
- // SimpleLogger().Write(logDEBUG) << "number_of_results_found_in_tiny_cc: " << number_of_results_found_in_tiny_cc;
- // TIMER_STOP(samet);
- // SimpleLogger().Write() << "query took " << TIMER_MSEC(samet) << "ms";
-
- // if we found an element in either category, then we are good
+#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();
}
- // implementation of the Hjaltason/Samet query [3], a BFS traversal of the tree
- bool
- IncrementalFindPhantomNodeForCoordinateWithDistance(const FixedPointCoordinate &input_coordinate,
- std::vector<std::pair<PhantomNode, double>> &result_phantom_node_vector,
- const unsigned zoom_level,
- const unsigned number_of_results,
- const unsigned max_checked_segments = 4*LEAF_NODE_SIZE)
+ // 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<std::pair<PhantomNode, double>> &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)
{
- std::vector<float> min_found_distances(number_of_results, std::numeric_limits<float>::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<double, double> projected_coordinate = {
+ mercator::lat2y(input_coordinate.lat / COORDINATE_PRECISION),
+ input_coordinate.lon / COORDINATE_PRECISION};
+
+ // upper bound pruning technique
+ upper_bound<float> pruning_bound(max_number_of_phantom_nodes);
// initialize queue with root element
std::priority_queue<IncrementalQueryCandidate> traversal_queue;
@@ -868,144 +827,141 @@ 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())
- {
- const TreeNode & current_tree_node = current_query_node.node.template get<TreeNode>();
+ if (current_query_node.node.template is<TreeNode>())
+ { // current object is a tree node
+ const TreeNode &current_tree_node =
+ current_query_node.node.template get<TreeNode>();
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 &current_edge = current_leaf_node.objects[i];
- const float current_perpendicular_distance =
- FixedPointCoordinate::ComputePerpendicularDistance(
+ 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];
- 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);
- // 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 & current_segment = current_query_node.node.template get<EdgeDataT>();
+ const EdgeDataT &current_segment =
+ current_query_node.node.template get<EdgeDataT>();
- // 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 - 1 &&
+ 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 =
- 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,
- foot_point_coordinate_on_segment,
- current_ratio);
-
- BOOST_ASSERT(0. <= current_perpendicular_distance);
+ m_coordinate_list->at(current_segment.v), input_coordinate,
+ projected_coordinate, foot_point_coordinate_on_segment, current_ratio);
- if ((current_perpendicular_distance < current_min_dist) &&
- !osrm::epsilon_compare(current_perpendicular_distance, current_min_dist))
+ if (number_of_elements_from_big_cc > 0 &&
+ result_phantom_node_vector.size() >= min_number_of_phantom_nodes &&
+ current_perpendicular_distance >= max_distance)
{
- // store phantom node in result vector
- result_phantom_node_vector.emplace_back(
+ traversal_queue = std::priority_queue<IncrementalQueryCandidate>{};
+ continue;
+ }
+
+ // 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,
- 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());
-
- // 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;
- }
+ 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.
+ FixUpRoundingIssue(input_coordinate, result_phantom_node_vector.back().first);
+
+ // set forward and reverse weights on the phantom node
+ SetForwardAndReverseWeightsOnPhantomNode(current_segment,
+ result_phantom_node_vector.back().first);
+
+ // 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<IncrementalQueryCandidate>{};
}
}
+ // 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)
@@ -1036,7 +992,7 @@ class StaticRTree
for (uint32_t i = 0; i < current_leaf_node.object_count; ++i)
{
const EdgeDataT &current_edge = current_leaf_node.objects[i];
- if (ignore_tiny_components && current_edge.is_in_tiny_cc)
+ if (ignore_tiny_components && current_edge.component_id != 0)
{
continue;
}
@@ -1044,11 +1000,9 @@ class StaticRTree
float current_ratio = 0.;
FixedPointCoordinate nearest;
const float current_perpendicular_distance =
- FixedPointCoordinate::ComputePerpendicularDistance(
+ 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);
@@ -1065,6 +1019,7 @@ class StaticRTree
current_edge.forward_offset,
current_edge.reverse_offset,
current_edge.packed_geometry_id,
+ current_edge.component_id,
nearest,
current_edge.fwd_segment_position,
current_edge.forward_travel_mode,
@@ -1075,16 +1030,13 @@ 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);
}
}
}
- if (result_phantom_node.location.isValid())
+ if (result_phantom_node.location.is_valid())
{
// Hack to fix rounding errors and wandering via nodes.
FixUpRoundingIssue(input_coordinate, result_phantom_node);
@@ -1092,42 +1044,50 @@ class StaticRTree
// set forward and reverse weights on the phantom node
SetForwardAndReverseWeightsOnPhantomNode(nearest_edge, result_phantom_node);
}
- return result_phantom_node.location.isValid();
+ return result_phantom_node.location.is_valid();
}
private:
-
- inline void SetForwardAndReverseWeightsOnPhantomNode(const EdgeDataT & nearest_edge,
+ inline void SetForwardAndReverseWeightsOnPhantomNode(const EdgeDataT &nearest_edge,
PhantomNode &result_phantom_node) const
{
- const float distance_1 = FixedPointCoordinate::ApproximateEuclideanDistance(
+ const float distance_1 = coordinate_calculation::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::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);
+ using TreeWeightType = decltype(result_phantom_node.forward_weight);
+ static_assert(std::is_same<decltype(result_phantom_node.forward_weight),
+ decltype(result_phantom_node.reverse_weight)>::value,
+ "forward and reverse weight type in tree must be the same");
+
if (SPECIAL_NODEID != result_phantom_node.forward_node_id)
{
- result_phantom_node.forward_weight *= ratio;
+ const auto new_weight =
+ static_cast<TreeWeightType>(result_phantom_node.forward_weight * ratio);
+ result_phantom_node.forward_weight = new_weight;
}
if (SPECIAL_NODEID != result_phantom_node.reverse_node_id)
{
- result_phantom_node.reverse_weight *= (1.f - ratio);
+ const auto new_weight =
+ static_cast<TreeWeightType>(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 <class QueueT>
@@ -1173,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.");
}
@@ -1186,10 +1145,37 @@ class StaticRTree
{
return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
}
+
+ inline void InitializeMBRectangle(RectangleT &rectangle,
+ const std::array<EdgeDataT, LEAF_NODE_SIZE> &objects,
+ const uint32_t element_count,
+ const std::vector<QueryNode> &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_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<int>::min());
+ BOOST_ASSERT(rectangle.min_lon != std::numeric_limits<int>::min());
+ BOOST_ASSERT(rectangle.max_lat != std::numeric_limits<int>::min());
+ BOOST_ASSERT(rectangle.max_lon != std::numeric_limits<int>::min());
+ }
};
//[1] "On Packing R-Trees"; I. Kamel, C. Faloutsos; 1993; DOI: 10.1145/170088.170403
//[2] "Nearest Neighbor Queries", N. Roussopulos et al; 1995; DOI: 10.1145/223784.223794
//[3] "Distance Browsing in Spatial Databases"; G. Hjaltason, H. Samet; 1999; ACM Trans. DB Sys
// Vol.24 No.2, pp.265-318
-#endif // STATICRTREE_H
+#endif // STATIC_RTREE_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/TravelMode.h b/3party/osrm/osrm-backend/data_structures/travel_mode.hpp
index 7ccc24d215..2bbe463177 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/TravelMode.h
+++ b/3party/osrm/osrm-backend/data_structures/travel_mode.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,11 +25,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TRAVEL_MODE_H
-#define TRAVEL_MODE_H
+#ifndef TRAVEL_MODE_HPP
+#define TRAVEL_MODE_HPP
+namespace
+{
using TravelMode = unsigned char;
static const TravelMode TRAVEL_MODE_INACCESSIBLE = 0;
static const TravelMode TRAVEL_MODE_DEFAULT = 1;
-
-#endif /* TRAVEL_MODE_H */
+}
+#endif /* TRAVEL_MODE_HPP */
diff --git a/3party/osrm/osrm-backend/data_structures/tribool.hpp b/3party/osrm/osrm-backend/data_structures/tribool.hpp
new file mode 100755
index 0000000000..2d4b6108dd
--- /dev/null
+++ b/3party/osrm/osrm-backend/data_structures/tribool.hpp
@@ -0,0 +1,40 @@
+/*
+
+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 TRIBOOL_HPP
+#define TRIBOOL_HPP
+
+namespace osrm
+{
+enum class tribool : char
+{
+ yes,
+ no,
+ indeterminate
+};
+}
+#endif // TRIBOOL_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/TurnInstructions.h b/3party/osrm/osrm-backend/data_structures/turn_instructions.hpp
index 611b574ddd..1ca065f680 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/TurnInstructions.h
+++ b/3party/osrm/osrm-backend/data_structures/turn_instructions.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,15 +25,29 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TURN_INSTRUCTIONS_H
-#define TURN_INSTRUCTIONS_H
+#ifndef TURN_INSTRUCTIONS_HPP
+#define TURN_INSTRUCTIONS_HPP
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;
}
@@ -87,4 +102,4 @@ struct TurnInstructionsClass
}
};
-#endif /* TURN_INSTRUCTIONS_H */
+#endif /* TURN_INSTRUCTIONS_HPP */
diff --git a/3party/osrm/osrm-backend/data_structures/upper_bound.hpp b/3party/osrm/osrm-backend/data_structures/upper_bound.hpp
new file mode 100755
index 0000000000..80695f2c51
--- /dev/null
+++ b/3party/osrm/osrm-backend/data_structures/upper_bound.hpp
@@ -0,0 +1,77 @@
+/*
+
+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 LOWER_BOUND_HPP
+#define LOWER_BOUND_HPP
+
+#include <functional>
+#include <limits>
+#include <queue>
+#include <type_traits>
+
+// 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 <typename key_type> class upper_bound
+{
+ private:
+ using parameter_type =
+ typename std::conditional<std::is_fundamental<key_type>::value, key_type, key_type &>::type;
+
+ public:
+ upper_bound() = delete;
+ upper_bound(std::size_t size) : size(size) {}
+
+ key_type get() const
+ {
+ if (queue.size() < size)
+ {
+ return std::numeric_limits<key_type>::max();
+ }
+ return queue.top();
+ }
+
+ void insert(const parameter_type key)
+ {
+ if (key < get())
+ {
+ queue.emplace(key);
+ while (queue.size() > size)
+ {
+ queue.pop();
+ }
+ }
+ }
+
+ private:
+ std::priority_queue<key_type, std::vector<key_type>, std::less<key_type>> queue;
+ const std::size_t size;
+};
+
+#endif // LOWER_BOUND_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/XORFastHash.h b/3party/osrm/osrm-backend/data_structures/xor_fast_hash.hpp
index aba6ef40a8..3af5ab1dbd 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/XORFastHash.h
+++ b/3party/osrm/osrm-backend/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,
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef XOR_FAST_HASH_H
-#define XOR_FAST_HASH_H
+#ifndef XOR_FAST_HASH_HPP
+#define XOR_FAST_HASH_HPP
#include <algorithm>
#include <vector>
@@ -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<unsigned short>(i);
+ table2[i] = static_cast<unsigned short>(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<unsigned char>(i);
+ table2[i] = static_cast<unsigned char>(i);
+ table3[i] = static_cast<unsigned char>(i);
+ table4[i] = static_cast<unsigned char>(i);
}
std::random_shuffle(table1.begin(), table1.end());
std::random_shuffle(table2.begin(), table2.end());
@@ -112,4 +112,4 @@ class XORMiniHash
}
};
-#endif // XOR_FAST_HASH_H
+#endif // XOR_FAST_HASH_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/XORFastHashStorage.h b/3party/osrm/osrm-backend/data_structures/xor_fast_hash_storage.hpp
index 18de3c52c8..ff65717a3a 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/XORFastHashStorage.h
+++ b/3party/osrm/osrm-backend/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,
@@ -25,10 +25,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef XOR_FAST_HASH_STORAGE_H
-#define XOR_FAST_HASH_STORAGE_H
+#ifndef XOR_FAST_HASH_STORAGE_HPP
+#define XOR_FAST_HASH_STORAGE_HPP
-#include "XORFastHash.h"
+#include "xor_fast_hash.hpp"
#include <limits>
#include <vector>
@@ -38,22 +38,24 @@ template <typename NodeID, typename Key> class XORFastHashStorage
public:
struct HashCell
{
- Key key;
- NodeID id;
unsigned time;
+ NodeID id;
+ Key key;
HashCell()
- : key(std::numeric_limits<unsigned>::max()), id(std::numeric_limits<unsigned>::max()),
- time(std::numeric_limits<unsigned>::max())
+ : time(std::numeric_limits<unsigned>::max()), id(std::numeric_limits<unsigned>::max()),
+ key(std::numeric_limits<unsigned>::max())
{
}
- 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; }
+ 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)
@@ -64,26 +66,36 @@ template <typename NodeID, typename Key> 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<unsigned>::max() == current_timestamp)
{
positions.clear();
- positions.resize((2 << 16));
+ positions.resize(2 << 16);
}
}
private:
- XORFastHashStorage() : positions(2 << 16), current_timestamp(0) {}
std::vector<HashCell> positions;
XORFastHash fast_hasher;
unsigned current_timestamp;
};
-#endif // XOR_FAST_HASH_STORAGE_H
+#endif // XOR_FAST_HASH_STORAGE_HPP
diff --git a/3party/osrm/osrm-backend/datastore.cpp b/3party/osrm/osrm-backend/datastore.cpp
index e26ab4b8ac..3c032a2a96 100644..100755
--- a/3party/osrm/osrm-backend/datastore.cpp
+++ b/3party/osrm/osrm-backend/datastore.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,24 +25,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "DataStructures/OriginalEdgeData.h"
-#include "DataStructures/RangeTable.h"
-#include "DataStructures/QueryEdge.h"
-#include "DataStructures/SharedMemoryFactory.h"
-#include "DataStructures/SharedMemoryVectorWrapper.h"
-#include "DataStructures/StaticGraph.h"
-#include "DataStructures/StaticRTree.h"
-#include "DataStructures/TurnInstructions.h"
-#include "Server/DataStructures/BaseDataFacade.h"
-#include "Server/DataStructures/SharedDataType.h"
-#include "Server/DataStructures/SharedBarriers.h"
-#include "Util/BoostFileSystemFix.h"
-#include "Util/DataStoreOptions.h"
-#include "Util/simple_logger.hpp"
-#include "Util/FingerPrint.h"
+#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"
+#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 "typedefs.h"
-#include <osrm/Coordinate.h>
+#include <osrm/coordinate.hpp>
+#include <osrm/server_paths.hpp>
using RTreeLeaf = BaseDataFacade<QueryEdge::EdgeData>::RTreeLeaf;
using RTreeNode = StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>::TreeNode;
@@ -102,7 +106,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
@@ -133,31 +138,31 @@ int main(const int argc, const char *argv[])
if (server_paths.find("hsgrdata") == server_paths.end())
{
- throw OSRMException("no hsgr file found");
+ throw osrm::exception("no hsgr file found");
}
if (server_paths.find("ramindex") == server_paths.end())
{
- throw OSRMException("no ram index file found");
+ throw osrm::exception("no ram index file found");
}
if (server_paths.find("fileindex") == server_paths.end())
{
- throw OSRMException("no leaf index file found");
+ throw osrm::exception("no leaf index file found");
}
if (server_paths.find("nodesdata") == server_paths.end())
{
- throw OSRMException("no nodes file found");
+ throw osrm::exception("no nodes file found");
}
if (server_paths.find("edgesdata") == server_paths.end())
{
- throw OSRMException("no edges file found");
+ throw osrm::exception("no edges file found");
}
if (server_paths.find("namesdata") == server_paths.end())
{
- throw OSRMException("no names file found");
+ throw osrm::exception("no names file found");
}
if (server_paths.find("geometry") == server_paths.end())
{
- throw OSRMException("no geometry file found");
+ throw osrm::exception("no geometry file found");
}
ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata");
@@ -339,8 +344,8 @@ int main(const int argc, const char *argv[])
geometry_input_stream.read((char *)&number_of_geometries_indices, sizeof(unsigned));
shared_layout_ptr->SetBlockSize<unsigned>(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<unsigned>(SharedDataLayout::GEOMETRIES_LIST,
number_of_compressed_geometries);
@@ -409,9 +414,8 @@ int main(const int argc, const char *argv[])
unsigned *name_id_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
shared_memory_ptr, SharedDataLayout::NAME_ID_LIST);
- TravelMode *travel_mode_ptr =
- shared_layout_ptr->GetBlockPtr<TravelMode, true>(
- shared_memory_ptr, SharedDataLayout::TRAVEL_MODE);
+ TravelMode *travel_mode_ptr = shared_layout_ptr->GetBlockPtr<TravelMode, true>(
+ shared_memory_ptr, SharedDataLayout::TRAVEL_MODE);
TurnInstruction *turn_instructions_ptr =
shared_layout_ptr->GetBlockPtr<TurnInstruction, true>(
@@ -481,10 +485,10 @@ int main(const int argc, const char *argv[])
shared_layout_ptr->GetBlockPtr<FixedPointCoordinate, true>(
shared_memory_ptr, SharedDataLayout::COORDINATE_LIST);
- NodeInfo current_node;
+ QueryNode current_node;
for (unsigned i = 0; i < coordinate_list_size; ++i)
{
- nodes_input_stream.read((char *)&current_node, sizeof(NodeInfo));
+ nodes_input_stream.read((char *)&current_node, sizeof(QueryNode));
coordinates_ptr[i] = FixedPointCoordinate(current_node.lat, current_node.lon);
}
nodes_input_stream.close();
diff --git a/3party/osrm/osrm-backend/descriptors/description_factory.cpp b/3party/osrm/osrm-backend/descriptors/description_factory.cpp
new file mode 100755
index 0000000000..e4665622f0
--- /dev/null
+++ b/3party/osrm/osrm-backend/descriptors/description_factory.cpp
@@ -0,0 +1,244 @@
+/*
+
+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 "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 "../util/container.hpp"
+#include "../util/integer_range.hpp"
+#include "../typedefs.h"
+
+DescriptionFactory::DescriptionFactory() : entire_length(0) { via_indices.push_back(0); }
+
+std::vector<unsigned> const &DescriptionFactory::GetViaIndices() const { return via_indices; }
+
+void DescriptionFactory::SetStartSegment(const PhantomNode &source, const bool traversed_in_reverse)
+{
+ start_phantom = source;
+ const EdgeWeight segment_duration =
+ (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));
+ BOOST_ASSERT(path_description.back().duration == segment_duration);
+}
+
+void DescriptionFactory::SetEndSegment(const PhantomNode &target,
+ const bool traversed_in_reverse,
+ const bool is_via_location)
+{
+ target_phantom = target;
+ const EdgeWeight segment_duration =
+ (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,
+ is_via_location ? TurnInstruction::ReachViaLocation
+ : TurnInstruction::NoTurn,
+ true, true, travel_mode);
+ BOOST_ASSERT(path_description.back().duration == segment_duration);
+}
+
+void DescriptionFactory::AppendSegment(const FixedPointCoordinate &coordinate,
+ const PathData &path_point)
+{
+ // if the start location is on top of a node, the first movement might be zero-length,
+ // in which case we dont' add a new description, but instead update the existing one
+ if ((1 == path_description.size()) && (path_description.front().location == coordinate))
+ {
+ if (path_point.segment_duration > 0)
+ {
+ path_description.front().name_id = path_point.name_id;
+ path_description.front().travel_mode = path_point.travel_mode;
+ }
+ return;
+ }
+
+ // make sure mode changes are announced, even when there otherwise is no turn
+ const TurnInstruction turn = [&]() -> TurnInstruction
+ {
+ if (TurnInstruction::NoTurn == path_point.turn_instruction &&
+ path_description.front().travel_mode != path_point.travel_mode &&
+ path_point.segment_duration > 0)
+ {
+ return TurnInstruction::GoStraight;
+ }
+ 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);
+}
+
+osrm::json::Value DescriptionFactory::AppendGeometryString(const bool return_encoded)
+{
+ if (return_encoded)
+ {
+ return PolylineFormatter().printEncodedString(path_description);
+ }
+ return PolylineFormatter().printUnencodedString(path_description);
+}
+
+void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time)
+{
+ summary.source_name_id = start_phantom.name_id;
+ 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.f;
+ for (const auto i : osrm::irange<std::size_t>(1, path_description.size()))
+ {
+ // 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::euclidean_distance(
+ 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.;
+ EdgeWeight segment_duration = 0;
+ std::size_t segment_start_index = 0;
+
+ for (const auto i : osrm::irange<std::size_t>(1, path_description.size()))
+ {
+ 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 (path_description.size() > 2 &&
+ std::numeric_limits<float>::epsilon() > path_description.back().length)
+ {
+ 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 (path_description.size() > 2 &&
+ std::numeric_limits<float>::epsilon() > path_description.front().length)
+ {
+ 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_segments = 0; // a running index that counts the necessary pieces
+ osrm::for_each_pair(
+ path_description, [&](SegmentInformation &first, const SegmentInformation &second)
+ {
+ if (!first.necessary)
+ {
+ return;
+ }
+
+ ++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<short>(angle * 10);
+ });
+
+ via_indices.push_back(necessary_segments + 1);
+ BOOST_ASSERT(via_indices.size() >= 2);
+ return;
+}
diff --git a/3party/osrm/osrm-backend/descriptors/description_factory.hpp b/3party/osrm/osrm-backend/descriptors/description_factory.hpp
new file mode 100755
index 0000000000..985f9c1c5d
--- /dev/null
+++ b/3party/osrm/osrm-backend/descriptors/description_factory.hpp
@@ -0,0 +1,96 @@
+/*
+
+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 DESCRIPTION_FACTORY_HPP
+#define DESCRIPTION_FACTORY_HPP
+
+#include "../algorithms/douglas_peucker.hpp"
+#include "../data_structures/phantom_node.hpp"
+#include "../data_structures/segment_information.hpp"
+#include "../data_structures/turn_instructions.hpp"
+
+#include <boost/assert.hpp>
+
+#include <osrm/coordinate.hpp>
+#include <osrm/json_container.hpp>
+
+#include <cmath>
+
+#include <limits>
+#include <vector>
+
+struct PathData;
+/* This class is fed with all way segments in consecutive order
+ * and produces the description plus the encoded polyline */
+
+class DescriptionFactory
+{
+ DouglasPeucker polyline_generalizer;
+ PhantomNode start_phantom, target_phantom;
+
+ double DegreeToRadian(const double degree) const;
+ double RadianToDegree(const double degree) const;
+
+ std::vector<unsigned> via_indices;
+
+ double entire_length;
+
+ public:
+ struct RouteSummary
+ {
+ unsigned distance;
+ EdgeWeight duration;
+ unsigned source_name_id;
+ unsigned target_name_id;
+ RouteSummary() : distance(0), duration(0), source_name_id(0), target_name_id(0) {}
+
+ void BuildDurationAndLengthStrings(const double raw_distance, const unsigned raw_duration)
+ {
+ // compute distance/duration for route summary
+ distance = static_cast<unsigned>(std::round(raw_distance));
+ duration = static_cast<EdgeWeight>(std::round(raw_duration / 10.));
+ }
+ } summary;
+
+ // I know, declaring this public is considered bad. I'm lazy
+ std::vector<SegmentInformation> path_description;
+ DescriptionFactory();
+ void AppendSegment(const FixedPointCoordinate &coordinate, const PathData &data);
+ void BuildRouteSummary(const double distance, const unsigned time);
+ void SetStartSegment(const PhantomNode &start_phantom, const bool traversed_in_reverse);
+ void SetEndSegment(const PhantomNode &start_phantom,
+ const bool traversed_in_reverse,
+ const bool is_via_location = false);
+ osrm::json::Value AppendGeometryString(const bool return_encoded);
+ std::vector<unsigned> const &GetViaIndices() const;
+
+ double get_entire_length() const { return entire_length; }
+
+ void Run(const unsigned zoom_level);
+};
+
+#endif /* DESCRIPTION_FACTORY_HPP */
diff --git a/3party/osrm/osrm-backend/Descriptors/BaseDescriptor.h b/3party/osrm/osrm-backend/descriptors/descriptor_base.hpp
index d06b9b6cb6..497c2161d5 100644..100755
--- a/3party/osrm/osrm-backend/Descriptors/BaseDescriptor.h
+++ b/3party/osrm/osrm-backend/descriptors/descriptor_base.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,27 +25,53 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef BASE_DESCRIPTOR_H
-#define BASE_DESCRIPTOR_H
+#ifndef DESCRIPTOR_BASE_HPP
+#define DESCRIPTOR_BASE_HPP
-#include "../DataStructures/PhantomNodes.h"
-#include "../DataStructures/RawRouteData.h"
+#include "../data_structures/coordinate_calculation.hpp"
+#include "../data_structures/internal_route_result.hpp"
+#include "../data_structures/phantom_node.hpp"
#include "../typedefs.h"
-#include <osrm/Reply.h>
+#include <boost/assert.hpp>
+
+#include <osrm/json_container.hpp>
#include <string>
+#include <unordered_map>
#include <vector>
+struct DescriptorTable : public std::unordered_map<std::string, unsigned>
+{
+ unsigned get_id(const std::string &key)
+ {
+ auto iter = find(key);
+ if (iter != end())
+ {
+ return iter->second;
+ }
+ return 0;
+ }
+};
+
struct DescriptorConfig
{
DescriptorConfig() : instructions(true), geometry(true), encode_geometry(true), zoom_level(18)
{
}
+
+ template <class OtherT>
+ 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);
+ }
+
bool instructions;
bool geometry;
bool encode_geometry;
- unsigned short zoom_level;
+ short zoom_level;
};
template <class DataFacadeT> class BaseDescriptor
@@ -54,8 +80,8 @@ template <class DataFacadeT> 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 InternalRouteResult &raw_route, osrm::json::Object &json_result) = 0;
+ virtual void SetConfig(const DescriptorConfig &c) = 0;
};
-#endif // BASE_DESCRIPTOR_H
+#endif // DESCRIPTOR_BASE_HPP
diff --git a/3party/osrm/osrm-backend/descriptors/gpx_descriptor.hpp b/3party/osrm/osrm-backend/descriptors/gpx_descriptor.hpp
new file mode 100755
index 0000000000..fb4c5b9de9
--- /dev/null
+++ b/3party/osrm/osrm-backend/descriptors/gpx_descriptor.hpp
@@ -0,0 +1,94 @@
+/*
+
+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 GPX_DESCRIPTOR_HPP
+#define GPX_DESCRIPTOR_HPP
+
+#include "descriptor_base.hpp"
+#include "../util/xml_renderer.hpp"
+
+#include <osrm/json_container.hpp>
+
+#include <iostream>
+
+template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<DataFacadeT>
+{
+ private:
+ DescriptorConfig config;
+ DataFacadeT *facade;
+
+ void AddRoutePoint(const FixedPointCoordinate &coordinate, osrm::json::Array &json_route)
+ {
+ osrm::json::Object json_lat;
+ osrm::json::Object json_lon;
+ osrm::json::Array json_row;
+
+ std::string tmp;
+
+ coordinate_calculation::lat_or_lon_to_string(coordinate.lat, tmp);
+ json_lat.values["_lat"] = tmp;
+
+ coordinate_calculation::lat_or_lon_to_string(coordinate.lon, tmp);
+ json_lon.values["_lon"] = tmp;
+
+ json_row.values.push_back(json_lat);
+ json_row.values.push_back(json_lon);
+ osrm::json::Object entry;
+ entry.values["rtept"] = json_row;
+ json_route.values.push_back(entry);
+ }
+
+ public:
+ explicit GPXDescriptor(DataFacadeT *facade) : facade(facade) {}
+
+ virtual void SetConfig(const DescriptorConfig &c) final { config = c; }
+
+ virtual void Run(const InternalRouteResult &raw_route, osrm::json::Object &json_result) final
+ {
+ osrm::json::Array json_route;
+ if (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT)
+ {
+ AddRoutePoint(raw_route.segment_end_coordinates.front().source_phantom.location,
+ json_route);
+
+ for (const std::vector<PathData> &path_data_vector : raw_route.unpacked_path_segments)
+ {
+ for (const PathData &path_data : path_data_vector)
+ {
+ const FixedPointCoordinate current_coordinate =
+ facade->GetCoordinateOfNode(path_data.node);
+ AddRoutePoint(current_coordinate, json_route);
+ }
+ }
+ AddRoutePoint(raw_route.segment_end_coordinates.back().target_phantom.location,
+ json_route);
+ }
+ // osrm::json::gpx_render(reply.content, json_route);
+ json_result.values["route"] = json_route;
+ }
+};
+#endif // GPX_DESCRIPTOR_HPP
diff --git a/3party/osrm/osrm-backend/Descriptors/JSONDescriptor.h b/3party/osrm/osrm-backend/descriptors/json_descriptor.hpp
index 9e095c151e..13b68c6ecd 100644..100755
--- a/3party/osrm/osrm-backend/Descriptors/JSONDescriptor.h
+++ b/3party/osrm/osrm-backend/descriptors/json_descriptor.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,20 +25,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSON_DESCRIPTOR_H_
-#define JSON_DESCRIPTOR_H_
-
-#include "BaseDescriptor.h"
-#include "DescriptionFactory.h"
-#include "../Algorithms/ObjectToBase64.h"
-#include "../Algorithms/ExtractRouteNames.h"
-#include "../DataStructures/JSONContainer.h"
-#include "../DataStructures/Range.h"
-#include "../DataStructures/SegmentInformation.h"
-#include "../DataStructures/TurnInstructions.h"
-#include "../Util/Azimuth.h"
-#include "../Util/StringUtil.h"
-#include "../Util/TimingUtil.h"
+#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/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 <osrm/json_container.hpp>
#include <algorithm>
@@ -70,11 +73,13 @@ template <class DataFacadeT> class JSONDescriptor final : public BaseDescriptor<
ExtractRouteNames<DataFacadeT, Segment> 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; }
+ virtual void SetConfig(const DescriptorConfig &c) override final { config = c; }
- unsigned DescribeLeg(const std::vector<PathData> route_leg,
+ unsigned DescribeLeg(const std::vector<PathData> &route_leg,
const PhantomNodes &leg_phantoms,
const bool target_traversed_in_reverse,
const bool is_via_leg)
@@ -88,29 +93,26 @@ template <class DataFacadeT> 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;
}
- void Run(const RawRouteData &raw_route, http::Reply &reply) final
+ virtual void Run(const InternalRouteResult &raw_route,
+ osrm::json::Object &json_result) override 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);
+ // osrm::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());
@@ -128,42 +130,39 @@ template <class DataFacadeT> 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(facade, config.zoom_level);
+ description_factory.Run(config.zoom_level);
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;
- BuildTextualDescription(description_factory,
- json_route_instructions,
- raw_route.shortest_path_length,
- shortest_path_segments);
+ 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.entireLength,
+ 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"] =
- 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());
- 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);
@@ -174,7 +173,7 @@ template <class DataFacadeT> 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 /
@@ -183,7 +182,7 @@ template <class DataFacadeT> 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<unsigned> const &shortest_leg_end_indices = description_factory.GetViaIndices();
json_via_indices_array.values.insert(json_via_indices_array.values.end(),
@@ -194,7 +193,7 @@ template <class DataFacadeT> 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,
@@ -208,47 +207,47 @@ template <class DataFacadeT> 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)
{
- 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(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.entireLength, 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;
+ 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"] =
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;
std::vector<unsigned> 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());
@@ -256,51 +255,53 @@ template <class DataFacadeT> 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;
- json_hint_object.values["checksum"] = raw_route.check_sum;
- JSON::Array json_location_hint_array;
+ osrm::json::Object json_hint_object;
+ json_hint_object.values["checksum"] = facade->GetCheckSum();
+ osrm::json::Array json_location_hint_array;
std::string hint;
for (const auto i : osrm::irange<std::size_t>(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;
// 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);
+ // 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<Segment> &route_segments_list)
{
@@ -314,7 +315,7 @@ template <class DataFacadeT> 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))
@@ -329,8 +330,8 @@ template <class DataFacadeT> 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);
@@ -339,27 +340,26 @@ template <class DataFacadeT> 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);
- 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(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<unsigned>(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<unsigned>(round(bearing_value)));
json_instruction_row.values.push_back(segment.travel_mode);
route_segments_list.emplace_back(
- segment.name_id,
- static_cast<int>(segment.length),
+ segment.name_id, static_cast<int>(segment.length),
static_cast<unsigned>(route_segments_list.size()));
json_instruction_array.values.push_back(json_instruction_row);
}
@@ -374,15 +374,16 @@ template <class DataFacadeT> class JSONDescriptor final : public BaseDescriptor<
}
}
- JSON::Array json_last_instruction_row;
- temp_instruction = cast::integral_to_string(cast::enum_to_underlying(TurnInstruction::ReachedYourDestination));
+ 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);
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(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/3party/osrm/osrm-backend/extract.cpp b/3party/osrm/osrm-backend/extract.cpp
new file mode 100755
index 0000000000..a147629834
--- /dev/null
+++ b/3party/osrm/osrm-backend/extract.cpp
@@ -0,0 +1,83 @@
+/*
+
+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/extractor.hpp"
+#include "extractor/extractor_options.hpp"
+#include "util/simple_logger.hpp"
+
+#include <boost/filesystem.hpp>
+
+#include <exception>
+
+int main(int argc, char *argv[])
+{
+ try
+ {
+ LogPolicy::GetInstance().Unmute();
+ ExtractorConfig 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)
+ {
+ 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();
+ return 1;
+ }
+}
diff --git a/3party/osrm/osrm-backend/Extractor/ExtractionContainers.cpp b/3party/osrm/osrm-backend/extractor/extraction_containers.cpp
index eb45efee3f..8c484eb814 100644..100755
--- a/3party/osrm/osrm-backend/Extractor/ExtractionContainers.cpp
+++ b/3party/osrm/osrm-backend/extractor/extraction_containers.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,12 +25,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "ExtractionContainers.h"
-#include "ExtractionWay.h"
-#include "../Util/OSRMException.h"
-#include "../Util/simple_logger.hpp"
-#include "../Util/TimingUtil.h"
-#include "../DataStructures/RangeTable.h"
+#include "extraction_containers.hpp"
+#include "extraction_way.hpp"
+
+#include "../data_structures/coordinate_calculation.hpp"
+#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 <boost/assert.hpp>
#include <boost/filesystem.hpp>
@@ -79,71 +83,61 @@ 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(), CmpNodeByID(), stxxl_memory);
+ 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(), CmpWayByID(), 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. 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;
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->wayID < restrictions_iterator->fromWay)
+ if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.from.way)
{
++way_start_and_end_iterator;
continue;
}
- if (way_start_and_end_iterator->wayID > restrictions_iterator->fromWay)
+ if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.from.way)
{
++restrictions_iterator;
continue;
}
- BOOST_ASSERT(way_start_and_end_iterator->wayID == restrictions_iterator->fromWay);
- const NodeID via_node_id = restrictions_iterator->restriction.viaNode;
+ 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->firstStart == via_node_id)
+ if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
{
- restrictions_iterator->restriction.fromNode =
- way_start_and_end_iterator->firstTarget;
+ restrictions_iterator->restriction.from.node =
+ way_start_and_end_iterator->first_segment_target_id;
}
- else if (way_start_and_end_iterator->firstTarget == via_node_id)
+ else if (way_start_and_end_iterator->last_segment_target_id == via_node_id)
{
- restrictions_iterator->restriction.fromNode =
- way_start_and_end_iterator->firstStart;
- }
- else if (way_start_and_end_iterator->lastStart == via_node_id)
- {
- restrictions_iterator->restriction.fromNode =
- way_start_and_end_iterator->lastTarget;
- }
- else if (way_start_and_end_iterator->lastTarget == via_node_id)
- {
- restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastStart;
+ restrictions_iterator->restriction.from.node =
+ way_start_and_end_iterator->last_segment_source_id;
}
++restrictions_iterator;
}
@@ -153,76 +147,70 @@ 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;
- 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->wayID < restrictions_iterator->toWay)
+ if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.to.way)
{
++way_start_and_end_iterator;
continue;
}
- if (way_start_and_end_iterator->wayID > restrictions_iterator->toWay)
+ if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.to.way)
{
++restrictions_iterator;
continue;
}
- NodeID via_node_id = restrictions_iterator->restriction.viaNode;
- if (way_start_and_end_iterator->lastStart == via_node_id)
- {
- restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastTarget;
- }
- else if (way_start_and_end_iterator->lastTarget == via_node_id)
- {
- restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastStart;
- }
- else if (way_start_and_end_iterator->firstStart == via_node_id)
- {
- restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstTarget;
- }
- else if (way_start_and_end_iterator->firstTarget == 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.toNode = way_start_and_end_iterator->firstStart;
+ restrictions_iterator->restriction.to.node =
+ way_start_and_end_iterator->first_segment_target_id;
}
-
- if (std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.fromNode &&
- std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.toNode)
+ else if (way_start_and_end_iterator->last_segment_target_id == via_node_id)
{
- ++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)
+ for (const auto &restriction_container : restrictions_list)
{
- if (std::numeric_limits<unsigned>::max() != restriction_container.restriction.fromNode &&
- std::numeric_limits<unsigned>::max() != restriction_container.restriction.toNode)
+ 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);
@@ -272,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));
@@ -303,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;
@@ -333,22 +321,20 @@ 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 = FixedPointCoordinate::ApproximateEuclideanDistance(
- edge_iterator->source_coordinate.lat,
- edge_iterator->source_coordinate.lon,
- node_iterator->lat,
- node_iterator->lon);
+ const double distance = coordinate_calculation::euclidean_distance(
+ 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));
- int integer_distance = std::max(1, (int)distance);
- short zero = 0;
- short one = 1;
-
- file_out_stream.write((char *)&edge_iterator->way_id, sizeof(unsigned));
+ 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;
+ 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));
file_out_stream.write((char *)&integer_distance, sizeof(int));
@@ -367,20 +353,48 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
file_out_stream.write((char *)&one, sizeof(short));
break;
default:
- throw OSRMException("edge has broken direction");
+ throw osrm::exception("edge has broken direction");
}
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));
+ 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;
+ 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));
+ 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;
@@ -404,7 +418,8 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
std::vector<unsigned> name_lengths;
for (const std::string &temp_string : name_list)
{
- const unsigned string_length = std::min(static_cast<unsigned>(temp_string.length()), 255u);
+ const unsigned string_length =
+ std::min(static_cast<unsigned>(temp_string.length()), 255u);
name_lengths.push_back(string_length);
total_length += string_length;
}
@@ -412,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<unsigned>(temp_string.length()), 255u);
+ const unsigned string_length =
+ std::min(static_cast<unsigned>(temp_string.length()), 255u);
name_file_stream.write(temp_string.c_str(), string_length);
}
@@ -427,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/3party/osrm/osrm-backend/Extractor/ExtractionContainers.h b/3party/osrm/osrm-backend/extractor/extraction_containers.hpp
index bfb318ba7a..12d88a26c8 100644..100755
--- a/3party/osrm/osrm-backend/Extractor/ExtractionContainers.h
+++ b/3party/osrm/osrm-backend/extractor/extraction_containers.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,30 +25,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef EXTRACTIONCONTAINERS_H_
-#define EXTRACTIONCONTAINERS_H_
+#ifndef EXTRACTION_CONTAINERS_HPP
+#define EXTRACTION_CONTAINERS_HPP
-#include "InternalExtractorEdge.h"
-#include "ExtractorStructs.h"
-#include "../DataStructures/Restriction.h"
-#include "../Util/FingerPrint.h"
+#include "internal_extractor_edge.hpp"
+#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 <stxxl/vector>
class ExtractionContainers
{
#ifndef _MSC_VER
- constexpr static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? std::numeric_limits<int>::max() : std::numeric_limits<unsigned>::max());
+ constexpr static unsigned stxxl_memory =
+ ((sizeof(std::size_t) == 4) ? std::numeric_limits<int>::max()
+ : std::numeric_limits<unsigned>::max());
#else
const static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? INT_MAX : UINT_MAX);
#endif
public:
- using STXXLNodeIDVector = stxxl::vector<NodeID>;
- using STXXLNodeVector = stxxl::vector<ExternalMemoryNode>;
- using STXXLEdgeVector = stxxl::vector<InternalExtractorEdge>;
- using STXXLStringVector = stxxl::vector<std::string>;
- using STXXLRestrictionsVector = stxxl::vector<InputRestrictionContainer>;
- using STXXLWayIDStartEndVector = stxxl::vector<WayIDStartAndEndEdge>;
+ using STXXLNodeIDVector = stxxl::vector<NodeID>;
+ using STXXLNodeVector = stxxl::vector<ExternalMemoryNode>;
+ using STXXLEdgeVector = stxxl::vector<InternalExtractorEdge>;
+ using STXXLStringVector = stxxl::vector<std::string>;
+ using STXXLRestrictionsVector = stxxl::vector<InputRestrictionContainer>;
+ using STXXLWayIDStartEndVector = stxxl::vector<FirstAndLastSegmentOfWay>;
STXXLNodeIDVector used_node_id_list;
STXXLNodeVector all_nodes_list;
@@ -66,4 +69,4 @@ class ExtractionContainers
const std::string &restrictions_file_name);
};
-#endif /* EXTRACTIONCONTAINERS_H_ */
+#endif /* EXTRACTION_CONTAINERS_HPP */
diff --git a/3party/osrm/osrm-backend/extractor/extraction_helper_functions.hpp b/3party/osrm/osrm-backend/extractor/extraction_helper_functions.hpp
new file mode 100755
index 0000000000..d10200abbe
--- /dev/null
+++ b/3party/osrm/osrm-backend/extractor/extraction_helper_functions.hpp
@@ -0,0 +1,119 @@
+/*
+
+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 EXTRACTION_HELPER_FUNCTIONS_HPP
+#define EXTRACTION_HELPER_FUNCTIONS_HPP
+
+#include "../util/cast.hpp"
+#include "../util/iso_8601_duration_parser.hpp"
+
+#include <boost/algorithm/string.hpp>
+#include <boost/algorithm/string_regex.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/regex.hpp>
+
+#include <limits>
+
+bool simple_duration_is_valid(const std::string &s)
+{
+ 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);
+
+ 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<std::string::const_iterator> 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)
+{
+ if (simple_duration_is_valid(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<std::string> result;
+ boost::algorithm::split_regex(result, s, boost::regex(":"));
+ const bool matched = regex_match(s, e);
+ if (matched)
+ {
+ 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);
+ }
+ }
+ else if (iso_8601_duration_is_valid(s))
+ {
+ iso_8601_grammar<std::string::const_iterator> iso_parser;
+ qi::parse(s.begin(), s.end(), iso_parser);
+
+ return iso_parser.get_duration();
+ }
+
+ return std::numeric_limits<unsigned>::max();
+}
+
+#endif // EXTRACTION_HELPER_FUNCTIONS_HPP
diff --git a/3party/osrm/osrm-backend/extractor/extraction_node.hpp b/3party/osrm/osrm-backend/extractor/extraction_node.hpp
new file mode 100755
index 0000000000..e821d6ffa1
--- /dev/null
+++ b/3party/osrm/osrm-backend/extractor/extraction_node.hpp
@@ -0,0 +1,38 @@
+/*
+
+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.
+
+*/
+
+#ifndef EXTRACTION_NODE_HPP
+#define EXTRACTION_NODE_HPP
+
+struct ExtractionNode
+{
+ ExtractionNode() : traffic_lights(false), barrier(false) {}
+ void clear() { traffic_lights = barrier = false; }
+ bool traffic_lights;
+ bool barrier;
+};
+#endif // EXTRACTION_NODE_HPP
diff --git a/3party/osrm/osrm-backend/Extractor/ExtractionWay.h b/3party/osrm/osrm-backend/extractor/extraction_way.hpp
index 1a197b6599..d47de20b08 100644..100755
--- a/3party/osrm/osrm-backend/Extractor/ExtractionWay.h
+++ b/3party/osrm/osrm-backend/extractor/extraction_way.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,11 +25,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef EXTRACTION_WAY_H
-#define EXTRACTION_WAY_H
+#ifndef EXTRACTION_WAY_HPP
+#define EXTRACTION_WAY_HPP
-#include "../DataStructures/HashTable.h"
-#include "../DataStructures/TravelMode.h"
+#include "../data_structures/travel_mode.hpp"
#include "../typedefs.h"
#include <string>
@@ -37,35 +36,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct ExtractionWay
{
- ExtractionWay() { Clear(); }
+ ExtractionWay() { clear(); }
- inline void Clear()
+ void clear()
{
- id = SPECIAL_NODEID;
- nameID = INVALID_NAMEID;
- path.clear();
- keyVals.Clear();
forward_speed = -1;
backward_speed = -1;
duration = -1;
- access = true;
roundabout = false;
- isAccessRestricted = false;
- ignoreInGrid = false;
+ is_access_restricted = false;
+ ignore_in_grid = false;
+ name.clear();
forward_travel_mode = TRAVEL_MODE_DEFAULT;
backward_travel_mode = TRAVEL_MODE_DEFAULT;
}
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
// accessors translate to/from the mode attributes.
- inline void set_direction(const Directions m)
+ void set_direction(const Directions m)
{
if (Directions::oneway == m)
{
@@ -74,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;
}
}
- inline const Directions get_direction() const
+ 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;
}
@@ -106,25 +104,20 @@ struct ExtractionWay
// These accessors exists because it's not possible to take the address of a bitfield,
// and LUA therefore cannot read/write the mode attributes directly.
- inline void set_forward_mode(const TravelMode m) { forward_travel_mode = m; }
- inline const TravelMode get_forward_mode() const { return forward_travel_mode; }
- inline void set_backward_mode(const TravelMode m) { backward_travel_mode = m; }
- inline const TravelMode get_backward_mode() const { return backward_travel_mode; }
+ void set_forward_mode(const TravelMode m) { forward_travel_mode = m; }
+ TravelMode get_forward_mode() const { return forward_travel_mode; }
+ void set_backward_mode(const TravelMode m) { backward_travel_mode = m; }
+ TravelMode get_backward_mode() const { return backward_travel_mode; }
- unsigned id;
- unsigned nameID;
double forward_speed;
double backward_speed;
double duration;
std::string name;
- bool access;
bool roundabout;
- bool isAccessRestricted;
- bool ignoreInGrid;
- std::vector<NodeID> path;
- HashTable<std::string, std::string> keyVals;
+ bool is_access_restricted;
+ bool ignore_in_grid;
TravelMode forward_travel_mode : 4;
TravelMode backward_travel_mode : 4;
};
-#endif // EXTRACTION_WAY_H
+#endif // EXTRACTION_WAY_HPP
diff --git a/3party/osrm/osrm-backend/extractor/extractor.cpp b/3party/osrm/osrm-backend/extractor/extractor.cpp
new file mode 100755
index 0000000000..0581e4e5cd
--- /dev/null
+++ b/3party/osrm/osrm-backend/extractor/extractor.cpp
@@ -0,0 +1,239 @@
+/*
+
+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.hpp"
+
+#include "extraction_containers.hpp"
+#include "extraction_node.hpp"
+#include "extraction_way.hpp"
+#include "extractor_callbacks.hpp"
+#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 "../typedefs.h"
+
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+#include <luabind/luabind.hpp>
+
+#include <osmium/io/any_input.hpp>
+
+#include <tbb/parallel_for.h>
+#include <tbb/task_scheduler_init.h>
+
+#include <variant/optional.hpp>
+
+#include <cstdlib>
+
+#include <algorithm>
+#include <atomic>
+#include <chrono>
+#include <fstream>
+#include <iostream>
+#include <thread>
+#include <unordered_map>
+#include <vector>
+
+int extractor::run(const ExtractorConfig &extractor_config)
+{
+ try
+ {
+ LogPolicy::GetInstance().Unmute();
+ TIMER_START(extracting);
+
+ 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);
+ tbb::task_scheduler_init init(number_of_threads);
+
+ SimpleLogger().Write() << "Input file: " << extractor_config.input_path.filename().string();
+ SimpleLogger().Write() << "Profile: " << extractor_config.profile_path.filename().string();
+ SimpleLogger().Write() << "Threads: " << number_of_threads;
+
+ // setup scripting environment
+ ScriptingEnvironment scripting_environment(extractor_config.profile_path.string().c_str());
+
+ std::unordered_map<std::string, NodeID> string_map;
+ string_map[""] = 0;
+
+ ExtractionContainers extraction_containers;
+ auto extractor_callbacks =
+ osrm::make_unique<ExtractorCallbacks>(extraction_containers, string_map);
+
+ const osmium::io::File input_file(extractor_config.input_path.string());
+ osmium::io::Reader reader(input_file);
+ const osmium::io::Header header = reader.header();
+
+ std::atomic<unsigned> number_of_nodes{0};
+ std::atomic<unsigned> number_of_ways{0};
+ std::atomic<unsigned> number_of_relations{0};
+ std::atomic<unsigned> number_of_others{0};
+
+ SimpleLogger().Write() << "Parsing in progress..";
+ TIMER_START(parsing);
+
+ std::string generator = header.get("generator");
+ if (generator.empty())
+ {
+ generator = "unknown tool";
+ }
+ SimpleLogger().Write() << "input file generated by " << generator;
+
+ // write .timestamp data file
+ std::string timestamp = header.get("osmosis_replication_timestamp");
+ if (timestamp.empty())
+ {
+ timestamp = "n/a";
+ }
+ SimpleLogger().Write() << "timestamp: " << timestamp;
+
+ boost::filesystem::ofstream timestamp_out(extractor_config.timestamp_file_name);
+ timestamp_out.write(timestamp.c_str(), timestamp.length());
+ timestamp_out.close();
+
+ // initialize vectors holding parsed objects
+ tbb::concurrent_vector<std::pair<std::size_t, ExtractionNode>> resulting_nodes;
+ tbb::concurrent_vector<std::pair<std::size_t, ExtractionWay>> resulting_ways;
+ tbb::concurrent_vector<mapbox::util::optional<InputRestrictionContainer>>
+ resulting_restrictions;
+
+ // setup restriction parser
+ const RestrictionParser restriction_parser(scripting_environment.get_lua_state());
+
+ while (const osmium::memory::Buffer buffer = reader.read())
+ {
+ // create a vector of iterators into the buffer
+ std::vector<osmium::memory::Buffer::const_iterator> osm_elements;
+ for (auto iter = std::begin(buffer); iter != std::end(buffer); ++iter)
+ {
+ osm_elements.push_back(iter);
+ }
+
+ // clear resulting vectors
+ resulting_nodes.clear();
+ resulting_ways.clear();
+ resulting_restrictions.clear();
+
+ // parse OSM entities in parallel, store in resulting vectors
+ tbb::parallel_for(
+ tbb::blocked_range<std::size_t>(0, osm_elements.size()),
+ [&](const tbb::blocked_range<std::size_t> &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];
+
+ switch (entity->type())
+ {
+ case osmium::item_type::node:
+ result_node.clear();
+ ++number_of_nodes;
+ luabind::call_function<void>(
+ local_state, "node_function",
+ boost::cref(static_cast<const osmium::Node &>(*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<void>(
+ local_state, "way_function",
+ boost::cref(static_cast<const osmium::Way &>(*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<const osmium::Relation &>(*entity)));
+ break;
+ default:
+ ++number_of_others;
+ break;
+ }
+ }
+ });
+
+ // put parsed objects thru extractor callbacks
+ for (const auto &result : resulting_nodes)
+ {
+ extractor_callbacks->ProcessNode(
+ static_cast<const osmium::Node &>(*(osm_elements[result.first])),
+ result.second);
+ }
+ for (const auto &result : resulting_ways)
+ {
+ extractor_callbacks->ProcessWay(
+ static_cast<const osmium::Way &>(*(osm_elements[result.first])), result.second);
+ }
+ for (const auto &result : resulting_restrictions)
+ {
+ extractor_callbacks->ProcessRestriction(result);
+ }
+ }
+ TIMER_STOP(parsing);
+ SimpleLogger().Write() << "Parsing finished after " << TIMER_SEC(parsing) << " seconds";
+
+ 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();
+
+ if (extraction_containers.all_edges_list.empty())
+ {
+ SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
+ return 1;
+ }
+
+ extraction_containers.PrepareData(extractor_config.output_file_name,
+ extractor_config.restriction_file_name);
+ TIMER_STOP(extracting);
+ SimpleLogger().Write() << "extraction finished after " << TIMER_SEC(extracting) << "s";
+ SimpleLogger().Write() << "To prepare the data for routing, run: "
+ << "./osrm-prepare " << extractor_config.output_file_name
+ << std::endl;
+ }
+ catch (std::exception &e)
+ {
+ SimpleLogger().Write(logWARNING) << e.what();
+ return 1;
+ }
+ return 0;
+}
diff --git a/3party/osrm/osrm-backend/extractor/extractor.hpp b/3party/osrm/osrm-backend/extractor/extractor.hpp
new file mode 100755
index 0000000000..8ea56c3cb0
--- /dev/null
+++ b/3party/osrm/osrm-backend/extractor/extractor.hpp
@@ -0,0 +1,37 @@
+/*
+
+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 EXTRACTOR_HPP
+#define EXTRACTOR_HPP
+
+#include "extractor_options.hpp"
+
+struct extractor
+{
+ int run(const ExtractorConfig &extractor_config);
+};
+#endif /* EXTRACTOR_HPP */
diff --git a/3party/osrm/osrm-backend/extractor/extractor_callbacks.cpp b/3party/osrm/osrm-backend/extractor/extractor_callbacks.cpp
new file mode 100755
index 0000000000..224468b060
--- /dev/null
+++ b/3party/osrm/osrm-backend/extractor/extractor_callbacks.cpp
@@ -0,0 +1,211 @@
+/*
+
+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_callbacks.hpp"
+#include "extraction_containers.hpp"
+#include "extraction_node.hpp"
+#include "extraction_way.hpp"
+
+#include "../data_structures/external_memory_node.hpp"
+#include "../data_structures/restriction.hpp"
+#include "../util/container.hpp"
+#include "../util/simple_logger.hpp"
+
+#include <osrm/coordinate.hpp>
+
+#include <limits>
+#include <string>
+#include <vector>
+
+ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers,
+ std::unordered_map<std::string, NodeID> &string_map)
+ : string_map(string_map), external_memory(extraction_containers)
+{
+}
+
+/** warning: caller needs to take care of synchronization! */
+void ExtractorCallbacks::ProcessNode(const osmium::Node &input_node,
+ const ExtractionNode &result_node)
+{
+ external_memory.all_nodes_list.push_back(
+ {static_cast<int>(input_node.location().lat() * COORDINATE_PRECISION),
+ static_cast<int>(input_node.location().lon() * COORDINATE_PRECISION),
+ static_cast<NodeID>(input_node.id()),
+ result_node.barrier,
+ result_node.traffic_lights});
+}
+
+void ExtractorCallbacks::ProcessRestriction(
+ const mapbox::util::optional<InputRestrictionContainer> &restriction)
+{
+ if (restriction)
+ {
+ external_memory.restrictions_list.push_back(restriction.get());
+ // 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");
+ }
+}
+/** warning: caller needs to take care of synchronization! */
+void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const ExtractionWay &parsed_way)
+{
+ if (((0 >= parsed_way.forward_speed) ||
+ (TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode)) &&
+ ((0 >= parsed_way.backward_speed) ||
+ (TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode)) &&
+ (0 >= parsed_way.duration))
+ { // Only true if the way is specified by the speed profile
+ return;
+ }
+
+ if (input_way.nodes().size() <= 1)
+ { // safe-guard against broken data
+ return;
+ }
+
+ if (std::numeric_limits<decltype(input_way.id())>::max() == input_way.id())
+ {
+ SimpleLogger().Write(logDEBUG) << "found bogus way with id: " << input_way.id()
+ << " of size " << input_way.nodes().size();
+ return;
+ }
+ if (0 < parsed_way.duration)
+ {
+ // TODO: iterate all way segments and set duration corresponding to the length of each
+ // segment
+ const_cast<ExtractionWay &>(parsed_way).forward_speed =
+ parsed_way.duration / (input_way.nodes().size() - 1);
+ const_cast<ExtractionWay &>(parsed_way).backward_speed =
+ parsed_way.duration / (input_way.nodes().size() - 1);
+ }
+
+ if (std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.forward_speed))
+ {
+ SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << input_way.id();
+ return;
+ }
+
+ // Get the unique identifier for the street name
+ const auto &string_map_iterator = string_map.find(parsed_way.name);
+ unsigned name_id = external_memory.name_list.size();
+ if (string_map.end() == string_map_iterator)
+ {
+ external_memory.name_list.push_back(parsed_way.name);
+ string_map.insert(std::make_pair(parsed_way.name, name_id));
+ }
+ else
+ {
+ name_id = string_map_iterator->second;
+ }
+
+ const bool split_edge = (parsed_way.forward_speed > 0) &&
+ (TRAVEL_MODE_INACCESSIBLE != parsed_way.forward_travel_mode) &&
+ (parsed_way.backward_speed > 0) &&
+ (TRAVEL_MODE_INACCESSIBLE != parsed_way.backward_travel_mode) &&
+ ((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)
+ {
+ // 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(),
+ ((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));
+ 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<ExtractionWay &>(parsed_way).forward_travel_mode =
+ parsed_way.backward_travel_mode;
+ const_cast<ExtractionWay &>(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);
+ external_memory.used_node_id_list.push_back(input_way.nodes().back().ref());
+ }
+
+ // The following information is needed to identify start and end segments of restrictions
+ external_memory.way_start_end_id_list.push_back(
+ {(EdgeID)input_way.id(),
+ (NodeID)input_way.nodes()[0].ref(),
+ (NodeID)input_way.nodes()[1].ref(),
+ (NodeID)input_way.nodes()[input_way.nodes().size() - 2].ref(),
+ (NodeID)input_way.nodes().back().ref()});
+
+ 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)
+ {
+ // 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));
+ };
+
+ if (is_opposite_way)
+ {
+ // SimpleLogger().Write() << "opposite2";
+ 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);
+ external_memory.used_node_id_list.push_back(input_way.nodes().back().ref());
+ }
+
+ external_memory.way_start_end_id_list.push_back(
+ {(EdgeID)input_way.id(),
+ (NodeID)input_way.nodes()[1].ref(),
+ (NodeID)input_way.nodes()[0].ref(),
+ (NodeID)input_way.nodes().back().ref(),
+ (NodeID)input_way.nodes()[input_way.nodes().size() - 2].ref()});
+ }
+}
diff --git a/3party/osrm/osrm-backend/Extractor/ExtractorCallbacks.h b/3party/osrm/osrm-backend/extractor/extractor_callbacks.hpp
index fcdb272da8..8eab0182b1 100644..100755
--- a/3party/osrm/osrm-backend/Extractor/ExtractorCallbacks.h
+++ b/3party/osrm/osrm-backend/extractor/extractor_callbacks.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,18 +25,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef EXTRACTOR_CALLBACKS_H
-#define EXTRACTOR_CALLBACKS_H
+#ifndef EXTRACTOR_CALLBACKS_HPP
+#define EXTRACTOR_CALLBACKS_HPP
+#include "extraction_way.hpp"
#include "../typedefs.h"
-#include <unordered_map>
+#include <osmium/osm.hpp>
+
+#include <variant/optional.hpp>
+
#include <string>
+#include <unordered_map>
struct ExternalMemoryNode;
class ExtractionContainers;
-struct ExtractionWay;
struct InputRestrictionContainer;
+struct ExtractionNode;
class ExtractorCallbacks
{
@@ -51,13 +56,13 @@ class ExtractorCallbacks
std::unordered_map<std::string, NodeID> &string_map);
// warning: caller needs to take care of synchronization!
- void ProcessNode(const ExternalMemoryNode &node);
+ void ProcessNode(const osmium::Node &current_node, const ExtractionNode &result_node);
// warning: caller needs to take care of synchronization!
- bool ProcessRestriction(const InputRestrictionContainer &restriction);
+ void ProcessRestriction(const mapbox::util::optional<InputRestrictionContainer> &restriction);
// warning: caller needs to take care of synchronization!
- void ProcessWay(ExtractionWay &way);
+ void ProcessWay(const osmium::Way &current_way, const ExtractionWay &result_way);
};
-#endif /* EXTRACTOR_CALLBACKS_H */
+#endif /* EXTRACTOR_CALLBACKS_HPP */
diff --git a/3party/osrm/osrm-backend/extractor/extractor_options.cpp b/3party/osrm/osrm-backend/extractor/extractor_options.cpp
new file mode 100755
index 0000000000..9ae5cd4c10
--- /dev/null
+++ b/3party/osrm/osrm-backend/extractor/extractor_options.cpp
@@ -0,0 +1,174 @@
+/*
+
+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_options.hpp"
+
+#include "../util/git_sha.hpp"
+#include "../util/ini_file.hpp"
+#include "../util/simple_logger.hpp"
+
+#include <boost/filesystem.hpp>
+#include <boost/program_options.hpp>
+
+#include <tbb/task_scheduler_init.h>
+
+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");
+ generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")(
+ "config,c", boost::program_options::value<boost::filesystem::path>(
+ &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
+ boost::program_options::options_description config_options("Configuration");
+ config_options.add_options()("profile,p",
+ boost::program_options::value<boost::filesystem::path>(
+ &extractor_config.profile_path)->default_value("profile.lua"),
+ "Path to LUA routing profile")(
+ "threads,t",
+ boost::program_options::value<unsigned int>(&extractor_config.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<boost::filesystem::path>(
+ &extractor_config.input_path),
+ "Input file in .osm, .osm.bz2 or .osm.pbf format");
+
+ // positional option
+ boost::program_options::positional_options_description positional_options;
+ positional_options.add("input", 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]) + " <input.osm/.osm.bz2/.osm.pbf> [options]");
+ visible_options.add(generic_options).add(config_options);
+
+ // parse command line options
+ try
+ {
+ 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 =
+ 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);
+ 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;
+ }
+
+ return return_code::ok;
+}
+
+void ExtractorOptions::GenerateOutputFilesNames(ExtractorConfig &extractor_config)
+{
+ boost::filesystem::path &input_path = extractor_config.input_path;
+ extractor_config.output_file_name = input_path.string();
+ extractor_config.restriction_file_name = input_path.string();
+ extractor_config.timestamp_file_name = input_path.string();
+ std::string::size_type pos = extractor_config.output_file_name.find(".osm.bz2");
+ if (pos == std::string::npos)
+ {
+ pos = extractor_config.output_file_name.find(".osm.pbf");
+ if (pos == std::string::npos)
+ {
+ pos = extractor_config.output_file_name.find(".osm.xml");
+ }
+ }
+ if (pos == std::string::npos)
+ {
+ pos = extractor_config.output_file_name.find(".pbf");
+ }
+ if (pos == std::string::npos)
+ {
+ pos = extractor_config.output_file_name.find(".osm");
+ if (pos == std::string::npos)
+ {
+ extractor_config.output_file_name.append(".osrm");
+ extractor_config.restriction_file_name.append(".osrm.restrictions");
+ extractor_config.timestamp_file_name.append(".osrm.timestamp");
+ }
+ else
+ {
+ extractor_config.output_file_name.replace(pos, 5, ".osrm");
+ extractor_config.restriction_file_name.replace(pos, 5, ".osrm.restrictions");
+ extractor_config.timestamp_file_name.replace(pos, 5, ".osrm.timestamp");
+ }
+ }
+ else
+ {
+ extractor_config.output_file_name.replace(pos, 8, ".osrm");
+ extractor_config.restriction_file_name.replace(pos, 8, ".osrm.restrictions");
+ extractor_config.timestamp_file_name.replace(pos, 8, ".osrm.timestamp");
+ }
+}
diff --git a/3party/osrm/osrm-backend/extractor/extractor_options.hpp b/3party/osrm/osrm-backend/extractor/extractor_options.hpp
new file mode 100755
index 0000000000..5712ea01a3
--- /dev/null
+++ b/3party/osrm/osrm-backend/extractor/extractor_options.hpp
@@ -0,0 +1,63 @@
+/*
+
+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 EXTRACTOR_OPTIONS_HPP
+#define EXTRACTOR_OPTIONS_HPP
+
+#include <boost/filesystem/path.hpp>
+
+#include <string>
+
+enum class return_code : unsigned
+{
+ ok,
+ fail,
+ exit
+};
+
+struct ExtractorConfig
+{
+ ExtractorConfig() noexcept : requested_num_threads(0) {}
+ boost::filesystem::path config_file_path;
+ boost::filesystem::path input_path;
+ boost::filesystem::path profile_path;
+
+ std::string output_file_name;
+ std::string restriction_file_name;
+ std::string timestamp_file_name;
+
+ unsigned requested_num_threads;
+};
+
+struct ExtractorOptions
+{
+ static return_code ParseArguments(int argc, char *argv[], ExtractorConfig &extractor_config);
+
+ static void GenerateOutputFilesNames(ExtractorConfig &extractor_config);
+};
+
+#endif // EXTRACTOR_OPTIONS_HPP
diff --git a/3party/osrm/osrm-backend/extractor/first_and_last_segment_of_way.hpp b/3party/osrm/osrm-backend/extractor/first_and_last_segment_of_way.hpp
new file mode 100755
index 0000000000..3a26be7ced
--- /dev/null
+++ b/3party/osrm/osrm-backend/extractor/first_and_last_segment_of_way.hpp
@@ -0,0 +1,88 @@
+/*
+
+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.
+
+*/
+
+#ifndef FIRST_AND_LAST_SEGMENT_OF_WAY_HPP
+#define FIRST_AND_LAST_SEGMENT_OF_WAY_HPP
+
+#include "../data_structures/external_memory_node.hpp"
+#include "../typedefs.h"
+
+#include <limits>
+#include <string>
+
+struct FirstAndLastSegmentOfWay
+{
+ EdgeID way_id;
+ NodeID first_segment_source_id;
+ NodeID first_segment_target_id;
+ NodeID last_segment_source_id;
+ NodeID last_segment_target_id;
+ FirstAndLastSegmentOfWay()
+ : way_id(std::numeric_limits<EdgeID>::max()),
+ first_segment_source_id(std::numeric_limits<NodeID>::max()),
+ first_segment_target_id(std::numeric_limits<NodeID>::max()),
+ last_segment_source_id(std::numeric_limits<NodeID>::max()),
+ last_segment_target_id(std::numeric_limits<NodeID>::max())
+ {
+ }
+
+ FirstAndLastSegmentOfWay(EdgeID w, NodeID fs, NodeID ft, NodeID ls, NodeID lt)
+ : way_id(w), first_segment_source_id(fs), first_segment_target_id(ft),
+ last_segment_source_id(ls), last_segment_target_id(lt)
+ {
+ }
+
+ static FirstAndLastSegmentOfWay min_value()
+ {
+ return {std::numeric_limits<EdgeID>::min(),
+ std::numeric_limits<NodeID>::min(),
+ std::numeric_limits<NodeID>::min(),
+ std::numeric_limits<NodeID>::min(),
+ std::numeric_limits<NodeID>::min()};
+ }
+ static FirstAndLastSegmentOfWay max_value()
+ {
+ return {std::numeric_limits<EdgeID>::max(),
+ std::numeric_limits<NodeID>::max(),
+ std::numeric_limits<NodeID>::max(),
+ std::numeric_limits<NodeID>::max(),
+ std::numeric_limits<NodeID>::max()};
+ }
+};
+
+struct FirstAndLastSegmentOfWayStxxlCompare
+{
+ using value_type = FirstAndLastSegmentOfWay;
+ bool operator()(const FirstAndLastSegmentOfWay &a, const FirstAndLastSegmentOfWay &b) const
+ {
+ return a.way_id < b.way_id;
+ }
+ value_type max_value() { return FirstAndLastSegmentOfWay::max_value(); }
+ value_type min_value() { return FirstAndLastSegmentOfWay::min_value(); }
+};
+
+#endif /* FIRST_AND_LAST_SEGMENT_OF_WAY_HPP */
diff --git a/3party/osrm/osrm-backend/Extractor/InternalExtractorEdge.h b/3party/osrm/osrm-backend/extractor/internal_extractor_edge.hpp
index 30809bddc2..27e1af146f 100644..100755
--- a/3party/osrm/osrm-backend/Extractor/InternalExtractorEdge.h
+++ b/3party/osrm/osrm-backend/extractor/internal_extractor_edge.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,26 +25,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef INTERNAL_EXTRACTOR_EDGE_H
-#define INTERNAL_EXTRACTOR_EDGE_H
+#ifndef INTERNAL_EXTRACTOR_EDGE_HPP
+#define INTERNAL_EXTRACTOR_EDGE_HPP
#include "../typedefs.h"
-#include "../DataStructures/TravelMode.h"
-#include <osrm/Coordinate.h>
+#include "../data_structures/travel_mode.hpp"
#include <boost/assert.hpp>
+#include <osrm/coordinate.hpp>
+
struct InternalExtractorEdge
{
InternalExtractorEdge()
- : way_id(0), 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)
{
}
- explicit InternalExtractorEdge(unsigned id,
- NodeID start,
+ explicit InternalExtractorEdge(NodeID start,
NodeID target,
short direction,
double speed,
@@ -55,36 +55,36 @@ struct InternalExtractorEdge
bool is_access_restricted,
TravelMode travel_mode,
bool is_split)
- : way_id(id), 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)
{
}
// necessary static util functions for stxxl's sorting
static InternalExtractorEdge min_value()
{
- return InternalExtractorEdge(0, 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, 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);
}
- unsigned way_id;
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;
@@ -117,4 +117,4 @@ struct CmpEdgeByTargetID
value_type min_value() { return InternalExtractorEdge::min_value(); }
};
-#endif // INTERNAL_EXTRACTOR_EDGE_H
+#endif // INTERNAL_EXTRACTOR_EDGE_HPP
diff --git a/3party/osrm/osrm-backend/extractor/restriction_parser.cpp b/3party/osrm/osrm-backend/extractor/restriction_parser.cpp
new file mode 100755
index 0000000000..6781040d4a
--- /dev/null
+++ b/3party/osrm/osrm-backend/extractor/restriction_parser.cpp
@@ -0,0 +1,233 @@
+/*
+
+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 "restriction_parser.hpp"
+#include "extraction_way.hpp"
+#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 <boost/algorithm/string.hpp>
+#include <boost/algorithm/string/regex.hpp>
+#include <boost/ref.hpp>
+#include <boost/regex.hpp>
+
+#include <algorithm>
+
+namespace
+{
+int lua_error_callback(lua_State *lua_state)
+{
+ luabind::object error_msg(luabind::from_stack(lua_state, -1));
+ std::ostringstream error_stream;
+ error_stream << error_msg;
+ throw osrm::exception("ERROR occured in profile script:\n" + error_stream.str());
+}
+}
+
+RestrictionParser::RestrictionParser(lua_State *lua_state)
+ : /*lua_state(scripting_environment.getLuaState()),*/ use_turn_restrictions(true)
+{
+ ReadUseRestrictionsSetting(lua_state);
+
+ if (use_turn_restrictions)
+ {
+ ReadRestrictionExceptions(lua_state);
+ }
+}
+
+void RestrictionParser::ReadUseRestrictionsSetting(lua_State *lua_state)
+{
+ if (0 == luaL_dostring(lua_state, "return use_turn_restrictions\n") &&
+ lua_isboolean(lua_state, -1))
+ {
+ use_turn_restrictions = lua_toboolean(lua_state, -1);
+ }
+
+ if (use_turn_restrictions)
+ {
+ SimpleLogger().Write() << "Using turn restrictions";
+ }
+ else
+ {
+ SimpleLogger().Write() << "Ignoring turn restrictions";
+ }
+}
+
+void RestrictionParser::ReadRestrictionExceptions(lua_State *lua_state)
+{
+ if (lua_function_exists(lua_state, "get_exceptions"))
+ {
+ luabind::set_pcall_callback(&lua_error_callback);
+ // get list of turn restriction exceptions
+ luabind::call_function<void>(lua_state, "get_exceptions",
+ boost::ref(restriction_exceptions));
+ const unsigned exception_count = restriction_exceptions.size();
+ SimpleLogger().Write() << "Found " << exception_count
+ << " exceptions to turn restrictions:";
+ for (const std::string &str : restriction_exceptions)
+ {
+ SimpleLogger().Write() << " " << str;
+ }
+ }
+ else
+ {
+ SimpleLogger().Write() << "Found no exceptions to turn restrictions";
+ }
+}
+
+mapbox::util::optional<InputRestrictionContainer>
+RestrictionParser::TryParse(const osmium::Relation &relation) const
+{
+ // return if turn restrictions should be ignored
+ if (!use_turn_restrictions)
+ {
+ return mapbox::util::optional<InputRestrictionContainer>();
+ }
+
+ osmium::tags::KeyPrefixFilter filter(false);
+ filter.add(true, "restriction");
+
+ const osmium::TagList &tag_list = relation.tags();
+
+ osmium::tags::KeyPrefixFilter::iterator fi_begin(filter, tag_list.begin(), tag_list.end());
+ osmium::tags::KeyPrefixFilter::iterator fi_end(filter, tag_list.end(), tag_list.end());
+
+ // if it's a restriction, continue;
+ if (std::distance(fi_begin, fi_end) == 0)
+ {
+ return mapbox::util::optional<InputRestrictionContainer>();
+ }
+
+ // check if the restriction should be ignored
+ const char *except = relation.get_value_by_key("except");
+ if (except != nullptr && ShouldIgnoreRestriction(except))
+ {
+ return mapbox::util::optional<InputRestrictionContainer>();
+ }
+
+ bool is_only_restriction = false;
+
+ for (auto iter = fi_begin; iter != fi_end; ++iter)
+ {
+ if (std::string("restriction") == iter->key() ||
+ std::string("restriction::hgv") == iter->key())
+ {
+ const std::string restriction_value(iter->value());
+
+ if (restriction_value.find("only_") == 0)
+ {
+ is_only_restriction = true;
+ }
+ }
+ }
+
+ InputRestrictionContainer restriction_container(is_only_restriction);
+
+ for (const auto &member : relation.members())
+ {
+ const char *role = member.role();
+ if (strcmp("from", role) != 0 && strcmp("to", role) != 0 && strcmp("via", role) != 0)
+ {
+ continue;
+ }
+
+ switch (member.type())
+ {
+ case osmium::item_type::node:
+ // Make sure nodes appear only in the role if a via node
+ if (0 == strcmp("from", role) || 0 == strcmp("to", role))
+ {
+ continue;
+ }
+ BOOST_ASSERT(0 == strcmp("via", role));
+
+ // set via node id
+ restriction_container.restriction.via.node = member.ref();
+ break;
+
+ case osmium::item_type::way:
+ BOOST_ASSERT(0 == strcmp("from", role) || 0 == strcmp("to", role) ||
+ 0 == strcmp("via", role));
+ if (0 == strcmp("from", role))
+ {
+ restriction_container.restriction.from.way = member.ref();
+ }
+ else if (0 == strcmp("to", role))
+ {
+ restriction_container.restriction.to.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...
+ break;
+ default:
+ // shouldn't ever happen
+ break;
+ }
+ }
+ return mapbox::util::optional<InputRestrictionContainer>(restriction_container);
+}
+
+bool RestrictionParser::ShouldIgnoreRestriction(const std::string &except_tag_string) const
+{
+ // should this restriction be ignored? yes if there's an overlap between:
+ // a) the list of modes in the except tag of the restriction
+ // (except_tag_string), eg: except=bus;bicycle
+ // b) the lua profile defines a hierachy of modes,
+ // eg: [access, vehicle, bicycle]
+
+ if (except_tag_string.empty())
+ {
+ return false;
+ }
+
+ // Be warned, this is quadratic work here, but we assume that
+ // only a few exceptions are actually defined.
+ std::vector<std::string> exceptions;
+ boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*"));
+
+ return std::any_of(std::begin(exceptions), std::end(exceptions),
+ [&](const std::string &current_string)
+ {
+ if (std::end(restriction_exceptions) !=
+ std::find(std::begin(restriction_exceptions),
+ std::end(restriction_exceptions), current_string))
+ {
+ return true;
+ }
+ return false;
+ });
+}
diff --git a/3party/osrm/osrm-backend/extractor/restriction_parser.hpp b/3party/osrm/osrm-backend/extractor/restriction_parser.hpp
new file mode 100755
index 0000000000..0a632d83ec
--- /dev/null
+++ b/3party/osrm/osrm-backend/extractor/restriction_parser.hpp
@@ -0,0 +1,62 @@
+/*
+
+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.
+
+*/
+
+#ifndef RESTRICTION_PARSER_HPP
+#define RESTRICTION_PARSER_HPP
+
+#include "../data_structures/restriction.hpp"
+
+#include <osmium/osm.hpp>
+#include <osmium/tags/regex_filter.hpp>
+
+#include <variant/optional.hpp>
+
+#include <string>
+#include <vector>
+
+struct lua_State;
+class ScriptingEnvironment;
+
+class RestrictionParser
+{
+ public:
+ // RestrictionParser(ScriptingEnvironment &scripting_environment);
+ RestrictionParser(lua_State *lua_state);
+ mapbox::util::optional<InputRestrictionContainer>
+ TryParse(const osmium::Relation &relation) const;
+
+ private:
+ void ReadUseRestrictionsSetting(lua_State *lua_state);
+ void ReadRestrictionExceptions(lua_State *lua_state);
+ bool ShouldIgnoreRestriction(const std::string &except_tag_string) const;
+
+ // lua_State *lua_state;
+ std::vector<std::string> restriction_exceptions;
+ bool use_turn_restrictions;
+};
+
+#endif /* RESTRICTION_PARSER_HPP */
diff --git a/3party/osrm/osrm-backend/extractor/scripting_environment.cpp b/3party/osrm/osrm-backend/extractor/scripting_environment.cpp
new file mode 100755
index 0000000000..972772246a
--- /dev/null
+++ b/3party/osrm/osrm-backend/extractor/scripting_environment.cpp
@@ -0,0 +1,151 @@
+/*
+
+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 "scripting_environment.hpp"
+
+#include "extraction_helper_functions.hpp"
+#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 "../typedefs.h"
+
+#include <luabind/tag_function.hpp>
+
+#include <osmium/osm.hpp>
+
+#include <sstream>
+namespace
+{
+// wrapper method as luabind doesn't automatically overload funcs w/ default parameters
+template <class T>
+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, "");
+}
+
+int lua_error_callback(lua_State *L) // This is so I can use my own function as an
+// exception handler, pcall_log()
+{
+ luabind::object error_msg(luabind::from_stack(L, -1));
+ std::ostringstream error_stream;
+ error_stream << error_msg;
+ throw osrm::exception("ERROR occured in profile script:\n" + error_stream.str());
+}
+}
+
+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)
+{
+ typedef double (osmium::Location::*location_member_ptr_type)() const;
+
+ luabind::open(lua_state);
+ // open utility libraries string library;
+ luaL_openlibs(lua_state);
+
+ luaAddScriptFolderToLoadPath(lua_state, file_name.c_str());
+
+ // Add our function to the state's global scope
+ luabind::module(lua_state)[
+ luabind::def("print", LUA_print<std::string>),
+ luabind::def("durationIsValid", durationIsValid),
+ luabind::def("parseDuration", parseDuration),
+
+ luabind::class_<std::vector<std::string>>("vector")
+ .def("Add", static_cast<void (std::vector<std::string>::*)(const std::string &)>(
+ &std::vector<std::string>::push_back)),
+
+ luabind::class_<osmium::Location>("Location")
+ .def<location_member_ptr_type>("lat", &osmium::Location::lat)
+ .def<location_member_ptr_type>("lon", &osmium::Location::lon),
+
+ luabind::class_<osmium::Node>("Node")
+ // .def<node_member_ptr_type>("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<osmium::Node>)
+ .def("id", &osmium::Node::id),
+
+ luabind::class_<ExtractionNode>("ResultNode")
+ .def_readwrite("traffic_lights", &ExtractionNode::traffic_lights)
+ .def_readwrite("barrier", &ExtractionNode::barrier),
+
+ luabind::class_<ExtractionWay>("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)
+ ],
+ luabind::class_<osmium::Way>("Way")
+ .def("get_value_by_key", &osmium::Way::get_value_by_key)
+ .def("get_value_by_key", &get_value_by_key<osmium::Way>)
+ .def("id", &osmium::Way::id)
+ ];
+
+ if (0 != luaL_dofile(lua_state, file_name.c_str()))
+ {
+ luabind::object error_msg(luabind::from_stack(lua_state, -1));
+ std::ostringstream error_stream;
+ error_stream << error_msg;
+ throw osrm::exception("ERROR occured in profile script:\n" + error_stream.str());
+ }
+}
+
+lua_State *ScriptingEnvironment::get_lua_state()
+{
+ std::lock_guard<std::mutex> lock(init_mutex);
+ bool initialized = false;
+ auto &ref = script_contexts.local(initialized);
+ if (!initialized)
+ {
+ std::shared_ptr<lua_State> state(luaL_newstate(), lua_close);
+ ref = state;
+ init_lua_state(ref.get());
+ }
+ luabind::set_pcall_callback(&lua_error_callback);
+
+ return ref.get();
+}
diff --git a/3party/osrm/osrm-backend/Extractor/ScriptingEnvironment.h b/3party/osrm/osrm-backend/extractor/scripting_environment.hpp
index 2b1fffead9..be05103c8c 100644..100755
--- a/3party/osrm/osrm-backend/Extractor/ScriptingEnvironment.h
+++ b/3party/osrm/osrm-backend/extractor/scripting_environment.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,11 +25,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SCRIPTINGENVIRONMENT_H_
-#define SCRIPTINGENVIRONMENT_H_
+#ifndef SCRIPTING_ENVIRONMENT_HPP
+#define SCRIPTING_ENVIRONMENT_HPP
#include <string>
#include <memory>
+#include <mutex>
#include <tbb/enumerable_thread_specific.h>
struct lua_State;
@@ -37,16 +38,16 @@ struct lua_State;
class ScriptingEnvironment
{
public:
- ScriptingEnvironment();
- explicit ScriptingEnvironment(const char *file_name);
+ ScriptingEnvironment() = delete;
+ explicit ScriptingEnvironment(const std::string &file_name);
- lua_State *getLuaState();
+ lua_State *get_lua_state();
private:
- void initLuaState(lua_State* lua_state);
-
+ void init_lua_state(lua_State *lua_state);
+ std::mutex init_mutex;
std::string file_name;
tbb::enumerable_thread_specific<std::shared_ptr<lua_State>> script_contexts;
};
-#endif /* SCRIPTINGENVIRONMENT_H_ */
+#endif /* SCRIPTING_ENVIRONMENT_HPP */
diff --git a/3party/osrm/osrm-backend/features/bicycle/access.feature b/3party/osrm/osrm-backend/features/bicycle/access.feature
index 2087327cae..2087327cae 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/access.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/access.feature
diff --git a/3party/osrm/osrm-backend/features/bicycle/access_node.feature b/3party/osrm/osrm-backend/features/bicycle/access_node.feature
index 5a6f2b5f95..5a6f2b5f95 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/access_node.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/access_node.feature
diff --git a/3party/osrm/osrm-backend/features/bicycle/area.feature b/3party/osrm/osrm-backend/features/bicycle/area.feature
index 062e86f153..062e86f153 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/area.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/area.feature
diff --git a/3party/osrm/osrm-backend/features/bicycle/barrier.feature b/3party/osrm/osrm-backend/features/bicycle/barrier.feature
index d39a570d7f..d39a570d7f 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/barrier.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/barrier.feature
diff --git a/3party/osrm/osrm-backend/features/bicycle/bridge.feature b/3party/osrm/osrm-backend/features/bicycle/bridge.feature
new file mode 100755
index 0000000000..232581647e
--- /dev/null
+++ b/3party/osrm/osrm-backend/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,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
+ | 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,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/3party/osrm/osrm-backend/features/bicycle/cycleway.feature b/3party/osrm/osrm-backend/features/bicycle/cycleway.feature
index 643fdcea2f..643fdcea2f 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/cycleway.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/cycleway.feature
diff --git a/3party/osrm/osrm-backend/features/bicycle/destination.feature b/3party/osrm/osrm-backend/features/bicycle/destination.feature
index 9c71198887..9c71198887 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/destination.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/destination.feature
diff --git a/3party/osrm/osrm-backend/features/bicycle/ferry.feature b/3party/osrm/osrm-backend/features/bicycle/ferry.feature
index 85c925f8be..85c925f8be 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/ferry.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/ferry.feature
diff --git a/3party/osrm/osrm-backend/features/bicycle/maxspeed.feature b/3party/osrm/osrm-backend/features/bicycle/maxspeed.feature
index ba5bfba4bc..ba5bfba4bc 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/maxspeed.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/maxspeed.feature
diff --git a/3party/osrm/osrm-backend/features/bicycle/mode.feature b/3party/osrm/osrm-backend/features/bicycle/mode.feature
index 195a37f67b..2bfa4de5b3 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/mode.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/mode.feature
@@ -9,145 +9,145 @@ Feature: Bike - Mode flag
Background:
Given the profile "bicycle"
-
+
Scenario: Bike - Mode when using a ferry
- Given the node map
- | a | b | |
- | | c | d |
-
- And the ways
- | nodes | highway | route | duration |
- | ab | primary | | |
- | bc | | ferry | 0:01 |
- | cd | primary | | |
-
- When I route I should get
- | from | to | route | turns | modes |
- | a | d | ab,bc,cd | head,right,left,destination | 1,3,1 |
- | d | a | cd,bc,ab | head,right,left,destination | 1,3,1 |
- | c | a | bc,ab | head,left,destination | 3,1 |
- | d | b | cd,bc | head,right,destination | 1,3 |
- | a | c | ab,bc | head,right,destination | 1,3 |
- | b | d | bc,cd | head,left,destination | 3,1 |
+ Given the node map
+ | a | b | |
+ | | c | d |
+
+ And the ways
+ | nodes | highway | route | duration |
+ | ab | primary | | |
+ | bc | | ferry | 0:01 |
+ | cd | primary | | |
+
+ When I route I should get
+ | from | to | route | turns | modes |
+ | a | d | ab,bc,cd | head,right,left,destination | 1,3,1 |
+ | d | a | cd,bc,ab | head,right,left,destination | 1,3,1 |
+ | c | a | bc,ab | head,left,destination | 3,1 |
+ | d | b | cd,bc | head,right,destination | 1,3 |
+ | a | c | ab,bc | head,right,destination | 1,3 |
+ | b | d | bc,cd | head,left,destination | 3,1 |
Scenario: Bike - Mode when using a train
- Given the node map
- | a | b | |
- | | c | d |
-
- And the ways
- | nodes | highway | railway | bicycle |
- | ab | primary | | |
- | bc | | train | yes |
- | cd | primary | | |
-
- When I route I should get
- | from | to | route | turns | modes |
- | a | d | ab,bc,cd | head,right,left,destination | 1,4,1 |
- | d | a | cd,bc,ab | head,right,left,destination | 1,4,1 |
- | c | a | bc,ab | head,left,destination | 4,1 |
- | d | b | cd,bc | head,right,destination | 1,4 |
- | a | c | ab,bc | head,right,destination | 1,4 |
- | b | d | bc,cd | head,left,destination | 4,1 |
+ Given the node map
+ | a | b | |
+ | | c | d |
+
+ And the ways
+ | nodes | highway | railway | bicycle |
+ | ab | primary | | |
+ | bc | | train | yes |
+ | cd | primary | | |
+
+ When I route I should get
+ | from | to | route | turns | modes |
+ | a | d | ab,bc,cd | head,right,left,destination | 1,4,1 |
+ | d | a | cd,bc,ab | head,right,left,destination | 1,4,1 |
+ | c | a | bc,ab | head,left,destination | 4,1 |
+ | d | b | cd,bc | head,right,destination | 1,4 |
+ | a | c | ab,bc | head,right,destination | 1,4 |
+ | b | d | bc,cd | head,left,destination | 4,1 |
Scenario: Bike - Mode when pushing bike against oneways
- Given the node map
- | a | b | |
- | | c | d |
-
- And the ways
- | nodes | highway | oneway |
- | ab | primary | |
- | bc | primary | yes |
- | cd | primary | |
-
- When I route I should get
- | from | to | route | turns | modes |
- | a | d | ab,bc,cd | head,right,left,destination | 1,1,1 |
- | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 |
- | c | a | bc,ab | head,left,destination | 2,1 |
- | d | b | cd,bc | head,right,destination | 1,2 |
- | a | c | ab,bc | head,right,destination | 1,1 |
- | b | d | bc,cd | head,left,destination | 1,1 |
+ Given the node map
+ | a | b | |
+ | | c | d |
+
+ And the ways
+ | nodes | highway | oneway |
+ | ab | primary | |
+ | bc | primary | yes |
+ | cd | primary | |
+
+ When I route I should get
+ | from | to | route | turns | modes |
+ | a | d | ab,bc,cd | head,right,left,destination | 1,1,1 |
+ | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 |
+ | c | a | bc,ab | head,left,destination | 2,1 |
+ | d | b | cd,bc | head,right,destination | 1,2 |
+ | a | c | ab,bc | head,right,destination | 1,1 |
+ | b | d | bc,cd | head,left,destination | 1,1 |
Scenario: Bike - Mode when pushing on pedestrain streets
- Given the node map
- | a | b | |
- | | c | d |
-
- And the ways
- | nodes | highway |
- | ab | primary |
- | bc | pedestrian |
- | cd | primary |
-
- When I route I should get
- | from | to | route | turns | modes |
- | a | d | ab,bc,cd | head,right,left,destination | 1,2,1 |
- | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 |
- | c | a | bc,ab | head,left,destination | 2,1 |
- | d | b | cd,bc | head,right,destination | 1,2 |
- | a | c | ab,bc | head,right,destination | 1,2 |
- | b | d | bc,cd | head,left,destination | 2,1 |
+ Given the node map
+ | a | b | |
+ | | c | d |
+
+ And the ways
+ | nodes | highway |
+ | ab | primary |
+ | bc | pedestrian |
+ | cd | primary |
+
+ When I route I should get
+ | from | to | route | turns | modes |
+ | a | d | ab,bc,cd | head,right,left,destination | 1,2,1 |
+ | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 |
+ | c | a | bc,ab | head,left,destination | 2,1 |
+ | d | b | cd,bc | head,right,destination | 1,2 |
+ | a | c | ab,bc | head,right,destination | 1,2 |
+ | b | d | bc,cd | head,left,destination | 2,1 |
Scenario: Bike - Mode when pushing on pedestrain areas
- Given the node map
- | a | b | | |
- | | c | d | f |
-
- And the ways
- | nodes | highway | area |
- | ab | primary | |
- | bcd | pedestrian | yes |
- | df | primary | |
-
- When I route I should get
- | from | to | route | modes |
- | a | f | ab,bcd,df | 1,2,1 |
- | f | a | df,bcd,ab | 1,2,1 |
- | d | a | bcd,ab | 2,1 |
- | f | b | df,bcd | 1,2 |
- | a | d | ab,bcd | 1,2 |
- | b | f | bcd,df | 2,1 |
+ Given the node map
+ | a | b | | |
+ | | c | d | f |
+
+ And the ways
+ | nodes | highway | area |
+ | ab | primary | |
+ | bcd | pedestrian | yes |
+ | df | primary | |
+
+ When I route I should get
+ | from | to | route | modes |
+ | a | f | ab,bcd,df | 1,2,1 |
+ | f | a | df,bcd,ab | 1,2,1 |
+ | d | a | bcd,ab | 2,1 |
+ | f | b | df,bcd | 1,2 |
+ | a | d | ab,bcd | 1,2 |
+ | b | f | bcd,df | 2,1 |
Scenario: Bike - Mode when pushing on steps
- Given the node map
- | a | b | | |
- | | c | d | f |
-
- And the ways
- | nodes | highway |
- | ab | primary |
- | bc | steps |
- | cd | primary |
-
- When I route I should get
- | from | to | route | turns | modes |
- | a | d | ab,bc,cd | head,right,left,destination | 1,2,1 |
- | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 |
- | c | a | bc,ab | head,left,destination | 2,1 |
- | d | b | cd,bc | head,right,destination | 1,2 |
- | a | c | ab,bc | head,right,destination | 1,2 |
- | b | d | bc,cd | head,left,destination | 2,1 |
+ Given the node map
+ | a | b | | |
+ | | c | d | f |
+
+ And the ways
+ | nodes | highway |
+ | ab | primary |
+ | bc | steps |
+ | cd | primary |
+
+ When I route I should get
+ | from | to | route | turns | modes |
+ | a | d | ab,bc,cd | head,right,left,destination | 1,2,1 |
+ | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 |
+ | c | a | bc,ab | head,left,destination | 2,1 |
+ | d | b | cd,bc | head,right,destination | 1,2 |
+ | a | c | ab,bc | head,right,destination | 1,2 |
+ | b | d | bc,cd | head,left,destination | 2,1 |
Scenario: Bike - Mode when bicycle=dismount
- Given the node map
- | a | b | | |
- | | c | d | f |
-
- And the ways
- | nodes | highway | bicycle |
- | ab | primary | |
- | bc | primary | dismount |
- | cd | primary | |
-
- When I route I should get
- | from | to | route | turns | modes |
- | a | d | ab,bc,cd | head,right,left,destination | 1,2,1 |
- | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 |
- | c | a | bc,ab | head,left,destination | 2,1 |
- | d | b | cd,bc | head,right,destination | 1,2 |
- | a | c | ab,bc | head,right,destination | 1,2 |
+ Given the node map
+ | a | b | | |
+ | | c | d | f |
+
+ And the ways
+ | nodes | highway | bicycle |
+ | ab | primary | |
+ | bc | primary | dismount |
+ | cd | primary | |
+
+ When I route I should get
+ | from | to | route | turns | modes |
+ | a | d | ab,bc,cd | head,right,left,destination | 1,2,1 |
+ | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 |
+ | c | a | bc,ab | head,left,destination | 2,1 |
+ | d | b | cd,bc | head,right,destination | 1,2 |
+ | a | c | ab,bc | head,right,destination | 1,2 |
| b | d | bc,cd | head,left,destination | 2,1 |
Scenario: Bicycle - Modes when starting on forward oneway
diff --git a/3party/osrm/osrm-backend/features/bicycle/names.feature b/3party/osrm/osrm-backend/features/bicycle/names.feature
index b0e2ec0485..b0e2ec0485 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/names.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/names.feature
diff --git a/3party/osrm/osrm-backend/features/bicycle/oneway.feature b/3party/osrm/osrm-backend/features/bicycle/oneway.feature
index 4dd9e1fa7f..4dd9e1fa7f 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/oneway.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/oneway.feature
diff --git a/3party/osrm/osrm-backend/features/bicycle/pushing.feature b/3party/osrm/osrm-backend/features/bicycle/pushing.feature
index 7cb5400bca..5741fb1c0a 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/pushing.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/pushing.feature
@@ -32,7 +32,7 @@ Feature: Bike - Accessability of different way types
| primary | -1 | foot | bike |
| pedestrian | -1 | foot | foot |
- @square
+ @square
Scenario: Bike - Push bikes on pedestrian areas
Given the node map
| x | |
@@ -62,7 +62,7 @@ Feature: Bike - Accessability of different way types
| motorway | yes | foot | |
| runway | | | |
| runway | yes | foot | foot |
-
+
@todo
Scenario: Bike - Pushing bikes on ways with foot=yes in one direction
Then routability should be
@@ -72,20 +72,20 @@ Feature: Bike - Accessability of different way types
| motorway | | yes | | foot |
@construction
- Scenario: Bike - Don't allow routing on ways still under construction
+ Scenario: Bike - Don't allow routing on ways still under construction
Then routability should be
| highway | foot | bicycle | bothw |
| primary | | | x |
| construction | | | |
| construction | yes | | |
| construction | | yes | |
-
+
@roundabout
Scenario: Bike - Don't push bikes against oneway flow on roundabouts
Then routability should be
| junction | forw | backw |
| roundabout | x | |
-
+
Scenario: Bike - Instructions when pushing bike on oneways
Given the node map
| a | b | |
diff --git a/3party/osrm/osrm-backend/features/bicycle/ref.feature b/3party/osrm/osrm-backend/features/bicycle/ref.feature
index 3afde7738d..3afde7738d 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/ref.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/ref.feature
diff --git a/3party/osrm/osrm-backend/features/bicycle/restrictions.feature b/3party/osrm/osrm-backend/features/bicycle/restrictions.feature
index 6218d812bf..6218d812bf 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/restrictions.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/restrictions.feature
diff --git a/3party/osrm/osrm-backend/features/bicycle/roundabout.feature b/3party/osrm/osrm-backend/features/bicycle/roundabout.feature
index 6123280ed7..6123280ed7 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/roundabout.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/roundabout.feature
diff --git a/3party/osrm/osrm-backend/features/bicycle/stop_area.feature b/3party/osrm/osrm-backend/features/bicycle/stop_area.feature
index 5f6c3bc26a..5f6c3bc26a 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/stop_area.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/stop_area.feature
diff --git a/3party/osrm/osrm-backend/features/bicycle/surface.feature b/3party/osrm/osrm-backend/features/bicycle/surface.feature
index 216307b215..216307b215 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/surface.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/surface.feature
diff --git a/3party/osrm/osrm-backend/features/bicycle/train.feature b/3party/osrm/osrm-backend/features/bicycle/train.feature
index aafa2030bd..aafa2030bd 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/train.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/train.feature
diff --git a/3party/osrm/osrm-backend/features/bicycle/turn_penalty.feature b/3party/osrm/osrm-backend/features/bicycle/turn_penalty.feature
index d8c46b88e8..d8c46b88e8 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/turn_penalty.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/turn_penalty.feature
diff --git a/3party/osrm/osrm-backend/features/bicycle/way.feature b/3party/osrm/osrm-backend/features/bicycle/way.feature
index b9beb5f0f5..b9beb5f0f5 100644..100755
--- a/3party/osrm/osrm-backend/features/bicycle/way.feature
+++ b/3party/osrm/osrm-backend/features/bicycle/way.feature
diff --git a/3party/osrm/osrm-backend/features/car/access.feature b/3party/osrm/osrm-backend/features/car/access.feature
index 37dfed4c60..5fd56f3951 100644..100755
--- a/3party/osrm/osrm-backend/features/car/access.feature
+++ b/3party/osrm/osrm-backend/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/3party/osrm/osrm-backend/features/car/barrier.feature b/3party/osrm/osrm-backend/features/car/barrier.feature
index e637049860..7c89688c9e 100644..100755
--- a/3party/osrm/osrm-backend/features/car/barrier.feature
+++ b/3party/osrm/osrm-backend/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/3party/osrm/osrm-backend/features/car/bridge.feature b/3party/osrm/osrm-backend/features/car/bridge.feature
new file mode 100755
index 0000000000..41dc10bdb6
--- /dev/null
+++ b/3party/osrm/osrm-backend/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/3party/osrm/osrm-backend/features/car/destination.feature b/3party/osrm/osrm-backend/features/car/destination.feature
index 506aa2101a..506aa2101a 100644..100755
--- a/3party/osrm/osrm-backend/features/car/destination.feature
+++ b/3party/osrm/osrm-backend/features/car/destination.feature
diff --git a/3party/osrm/osrm-backend/features/car/ferry.feature b/3party/osrm/osrm-backend/features/car/ferry.feature
index 0e1fe98e52..eb245598ab 100644..100755
--- a/3party/osrm/osrm-backend/features/car/ferry.feature
+++ b/3party/osrm/osrm-backend/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 | | |
@@ -41,7 +41,26 @@ Feature: Car - Handle ferry routes
When I route I should get
| from | to | route | modes | speed |
- | a | g | abc,cde,efg | 1,2,1 | 24 km/h |
- | b | f | abc,cde,efg | 1,2,1 | 19 km/h |
+ | 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 |
+
+ 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/3party/osrm/osrm-backend/features/car/link.feature b/3party/osrm/osrm-backend/features/car/link.feature
index f4628e4cec..f4628e4cec 100644..100755
--- a/3party/osrm/osrm-backend/features/car/link.feature
+++ b/3party/osrm/osrm-backend/features/car/link.feature
diff --git a/3party/osrm/osrm-backend/features/car/maxspeed.feature b/3party/osrm/osrm-backend/features/car/maxspeed.feature
index 4a548020c4..781f4c6173 100644..100755
--- a/3party/osrm/osrm-backend/features/car/maxspeed.feature
+++ b/3party/osrm/osrm-backend/features/car/maxspeed.feature
@@ -8,19 +8,25 @@ OSRM will use 4/5 of the projected free-flow speed.
Scenario: Car - Respect maxspeeds when lower that way type speed
Given the node map
- | a | b | c | d |
+ | a | b | c | d | e | f | g |
And the ways
- | nodes | highway | maxspeed |
- | ab | trunk | |
- | bc | trunk | 60 |
- | cd | trunk | FR:urban |
+ | nodes | highway | maxspeed |
+ | ab | trunk | |
+ | bc | trunk | 60 |
+ | cd | trunk | FR:urban |
+ | de | trunk | CH:rural |
+ | ef | trunk | CH:trunk |
+ | fg | trunk | CH:motorway |
When I route I should get
- | from | to | route | speed |
- | a | b | ab | 67 km/h |
- | b | c | bc | 48 km/h +- 1 |
- | c | d | cd | 40 km/h |
+ | from | to | route | speed |
+ | a | b | ab | 78 km/h |
+ | b | c | bc | 59 km/h +- 1 |
+ | c | d | cd | 50 km/h |
+ | d | e | de | 75 km/h |
+ | e | f | ef | 90 km/h |
+ | f | g | fg | 105 km/h |
Scenario: Car - Do not ignore maxspeed when higher than way speed
Given the node map
@@ -34,22 +40,22 @@ OSRM will use 4/5 of the projected free-flow speed.
When I route I should get
| from | to | route | speed |
- | a | b | ab | 20 km/h |
- | b | c | bc | 72 km/h +- 1 |
- | c | d | cd | 40 km/h |
+ | a | b | ab | 31 km/h |
+ | b | c | bc | 83 km/h +- 1 |
+ | c | d | cd | 50 km/h |
Scenario: Car - Forward/backward maxspeed
Given a grid size of 100 meters
Then routability should be
| highway | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw |
- | primary | | | | 51 km/h | 51 km/h |
- | primary | 60 | | | 48 km/h | 48 km/h |
- | primary | | 60 | | 48 km/h | 51 km/h |
- | primary | | | 60 | 51 km/h | 48 km/h |
- | primary | 15 | 60 | | 48 km/h | 12 km/h |
- | primary | 15 | | 60 | 12 km/h | 48 km/h |
- | primary | 15 | 30 | 60 | 24 km/h | 48 km/h |
+ | primary | | | | 65 km/h | 65 km/h |
+ | primary | 60 | | | 60 km/h | 60 km/h |
+ | primary | | 60 | | 60 km/h | 65 km/h |
+ | primary | | | 60 | 65 km/h | 60 km/h |
+ | primary | 15 | 60 | | 60 km/h | 23 km/h |
+ | primary | 15 | | 60 | 23 km/h | 60 km/h |
+ | primary | 15 | 30 | 60 | 34 km/h | 60 km/h |
Scenario: Car - Maxspeed should not allow routing on unroutable ways
Then routability should be
@@ -67,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 | | | 32 km/h | 32 km/h |
+ | primary | 60 | | | | 59 km/h | 59 km/h |
+ | primary | 60 | 3 | | | 30 km/h | 30 km/h |
+ | primary | | | 60 | | 59 km/h | 63 km/h |
+ | primary | | 3 | 60 | | 30 km/h | 32 km/h |
+ | primary | | | | 60 | 63 km/h | 59 km/h |
+ | primary | | 3 | | 60 | 32 km/h | 30 km/h |
+ | primary | 15 | | 60 | | 59 km/h | 23 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 | 7 km/h | 30 km/h |
+ | primary | 15 | | 30 | 60 | 34 km/h | 59 km/h |
+ | primary | 15 | 3 | 30 | 60 | 15 km/h | 30 km/h |
+
diff --git a/3party/osrm/osrm-backend/features/car/names.feature b/3party/osrm/osrm-backend/features/car/names.feature
index ac4bfc8e23..ac4bfc8e23 100644..100755
--- a/3party/osrm/osrm-backend/features/car/names.feature
+++ b/3party/osrm/osrm-backend/features/car/names.feature
diff --git a/3party/osrm/osrm-backend/features/car/oneway.feature b/3party/osrm/osrm-backend/features/car/oneway.feature
index b47c3c6fd4..b47c3c6fd4 100644..100755
--- a/3party/osrm/osrm-backend/features/car/oneway.feature
+++ b/3party/osrm/osrm-backend/features/car/oneway.feature
diff --git a/3party/osrm/osrm-backend/features/car/permissive.feature b/3party/osrm/osrm-backend/features/car/permissive.feature
index e69de29bb2..e69de29bb2 100644..100755
--- a/3party/osrm/osrm-backend/features/car/permissive.feature
+++ b/3party/osrm/osrm-backend/features/car/permissive.feature
diff --git a/3party/osrm/osrm-backend/features/car/restrictions.feature b/3party/osrm/osrm-backend/features/car/restrictions.feature
index a54f054baf..f381f2f8c0 100644..100755
--- a/3party/osrm/osrm-backend/features/car/restrictions.feature
+++ b/3party/osrm/osrm-backend/features/car/restrictions.feature
@@ -380,3 +380,4 @@ Feature: Car - Turn restrictions
| from | to | route |
| a | b | ax,xy,yb |
| b | a | yb,xy,ax |
+
diff --git a/3party/osrm/osrm-backend/features/car/roundabout.feature b/3party/osrm/osrm-backend/features/car/roundabout.feature
index 2965479b94..2965479b94 100644..100755
--- a/3party/osrm/osrm-backend/features/car/roundabout.feature
+++ b/3party/osrm/osrm-backend/features/car/roundabout.feature
diff --git a/3party/osrm/osrm-backend/features/car/shuttle_train.feature b/3party/osrm/osrm-backend/features/car/shuttle_train.feature
index 97f32e5651..97f32e5651 100644..100755
--- a/3party/osrm/osrm-backend/features/car/shuttle_train.feature
+++ b/3party/osrm/osrm-backend/features/car/shuttle_train.feature
diff --git a/3party/osrm/osrm-backend/features/car/speed.feature b/3party/osrm/osrm-backend/features/car/speed.feature
index 5682f31949..a81baeb85a 100644..100755
--- a/3party/osrm/osrm-backend/features/car/speed.feature
+++ b/3party/osrm/osrm-backend/features/car/speed.feature
@@ -8,17 +8,17 @@ Feature: Car - speeds
Scenario: Car - speed of various way types
Then routability should be
| highway | oneway | bothw |
- | motorway | no | 72 km/h |
- | motorway_link | no | 36 km/h |
- | trunk | no | 67 km/h +- 1 |
- | trunk_link | no | 32 km/h +- 1 |
- | primary | no | 52 km/h +- 1 |
- | primary_link | no | 24 km/h |
- | secondary | no | 43 km/h +- 1 |
- | secondary_link | no | 20 km/h |
- | tertiary | no | 32 km/h |
- | tertiary_link | no | 16 km/h |
- | unclassified | no | 20 km/h |
- | residential | no | 20 km/h |
- | living_street | no | 8 km/h |
- | service | no | 12 km/h |
+ | motorway | no | 82 km/h |
+ | motorway_link | no | 47 km/h |
+ | trunk | no | 79 km/h +- 1 |
+ | trunk_link | no | 43 km/h +- 1 |
+ | primary | no | 63 km/h +- 1 |
+ | primary_link | no | 34 km/h |
+ | secondary | no | 54 km/h +- 1 |
+ | secondary_link | no | 31 km/h |
+ | tertiary | no | 43 km/h |
+ | tertiary_link | no | 26 km/h |
+ | unclassified | no | 31 km/h |
+ | residential | no | 31 km/h |
+ | living_street | no | 18 km/h |
+ | service | no | 23 km/h |
diff --git a/3party/osrm/osrm-backend/features/car/surface.feature b/3party/osrm/osrm-backend/features/car/surface.feature
index cd31acc983..5dd4ed66db 100644..100755
--- a/3party/osrm/osrm-backend/features/car/surface.feature
+++ b/3party/osrm/osrm-backend/features/car/surface.feature
@@ -26,7 +26,7 @@ Feature: Car - Surfaces
| trunk | very_horrible | x |
| trunk | impassable | |
| trunk | nonsense | x |
-
+
Scenario: Car - Routabiliy of surface tags
Then routability should be
| highway | surface | bothw |
@@ -64,64 +64,64 @@ Feature: Car - Surfaces
Scenario: Car - Surface should reduce speed
Then routability should be
| highway | oneway | surface | forw | backw |
- | motorway | no | | 72 km/h +-1 | 72 km/h +-1 |
- | motorway | no | asphalt | 72 km/h +-1 | 72 km/h +-1 |
- | motorway | no | concrete | 72 km/h +-1 | 72 km/h +-1 |
- | motorway | no | concrete:plates | 72 km/h +-1 | 72 km/h +-1 |
- | motorway | no | concrete:lanes | 72 km/h +-1 | 72 km/h +-1 |
- | motorway | no | paved | 72 km/h +-1 | 72 km/h +-1 |
- | motorway | no | cement | 65 km/h +-1 | 65 km/h +-1 |
- | motorway | no | compacted | 65 km/h +-1 | 65 km/h +-1 |
- | motorway | no | fine_gravel | 65 km/h +-1 | 65 km/h +-1 |
- | motorway | no | paving_stones | 48 km/h +-1 | 48 km/h +-1 |
- | motorway | no | metal | 48 km/h +-1 | 48 km/h +-1 |
- | motorway | no | bricks | 48 km/h +-1 | 48 km/h +-1 |
- | motorway | no | grass | 32 km/h +-1 | 32 km/h +-1 |
- | motorway | no | wood | 32 km/h +-1 | 32 km/h +-1 |
- | motorway | no | sett | 32 km/h +-1 | 32 km/h +-1 |
- | motorway | no | grass_paver | 32 km/h +-1 | 32 km/h +-1 |
- | motorway | no | gravel | 32 km/h +-1 | 32 km/h +-1 |
- | motorway | no | unpaved | 32 km/h +-1 | 32 km/h +-1 |
- | motorway | no | ground | 32 km/h +-1 | 32 km/h +-1 |
- | motorway | no | dirt | 32 km/h +-1 | 32 km/h +-1 |
- | motorway | no | pebblestone | 32 km/h +-1 | 32 km/h +-1 |
- | motorway | no | tartan | 32 km/h +-1 | 32 km/h +-1 |
- | motorway | no | cobblestone | 24 km/h +-1 | 24 km/h +-1 |
- | motorway | no | clay | 24 km/h +-1 | 24 km/h +-1 |
- | motorway | no | earth | 16 km/h +-1 | 16 km/h +-1 |
- | motorway | no | stone | 16 km/h +-1 | 16 km/h +-1 |
- | motorway | no | rocky | 16 km/h +-1 | 16 km/h +-1 |
- | motorway | no | sand | 16 km/h +-1 | 16 km/h +-1 |
+ | motorway | no | | 80 km/h +-1 | 80 km/h +-1 |
+ | motorway | no | asphalt | 80 km/h +-1 | 80 km/h +-1 |
+ | motorway | no | concrete | 80 km/h +-1 | 80 km/h +-1 |
+ | motorway | no | concrete:plates | 80 km/h +-1 | 80 km/h +-1 |
+ | motorway | no | concrete:lanes | 80 km/h +-1 | 80 km/h +-1 |
+ | motorway | no | paved | 80 km/h +-1 | 80 km/h +-1 |
+ | motorway | no | cement | 72 km/h +-1 | 72 km/h +-1 |
+ | motorway | no | compacted | 72 km/h +-1 | 72 km/h +-1 |
+ | motorway | no | fine_gravel | 72 km/h +-1 | 72 km/h +-1 |
+ | motorway | no | paving_stones | 60 km/h +-1 | 60 km/h +-1 |
+ | motorway | no | metal | 60 km/h +-1 | 60 km/h +-1 |
+ | motorway | no | bricks | 60 km/h +-1 | 60 km/h +-1 |
+ | motorway | no | grass | 42 km/h +-1 | 42 km/h +-1 |
+ | motorway | no | wood | 42 km/h +-1 | 42 km/h +-1 |
+ | motorway | no | sett | 42 km/h +-1 | 42 km/h +-1 |
+ | motorway | no | grass_paver | 42 km/h +-1 | 42 km/h +-1 |
+ | motorway | no | gravel | 42 km/h +-1 | 42 km/h +-1 |
+ | motorway | no | unpaved | 42 km/h +-1 | 42 km/h +-1 |
+ | motorway | no | ground | 42 km/h +-1 | 42 km/h +-1 |
+ | motorway | no | dirt | 42 km/h +-1 | 42 km/h +-1 |
+ | motorway | no | pebblestone | 42 km/h +-1 | 42 km/h +-1 |
+ | motorway | no | tartan | 42 km/h +-1 | 42 km/h +-1 |
+ | motorway | no | cobblestone | 34 km/h +-1 | 34 km/h +-1 |
+ | motorway | no | clay | 34 km/h +-1 | 34 km/h +-1 |
+ | motorway | no | earth | 26 km/h +-1 | 26 km/h +-1 |
+ | motorway | no | stone | 26 km/h +-1 | 26 km/h +-1 |
+ | motorway | no | rocky | 26 km/h +-1 | 26 km/h +-1 |
+ | motorway | no | sand | 26 km/h +-1 | 26 km/h +-1 |
Scenario: Car - Tracktypes should reduce speed
Then routability should be
| highway | oneway | tracktype | forw | backw |
- | motorway | no | | 72 km/h +-1 | 72 km/h +-1 |
- | motorway | no | grade1 | 48 km/h +-1 | 48 km/h +-1 |
- | motorway | no | grade2 | 32 km/h +-1 | 32 km/h +-1 |
- | motorway | no | grade3 | 24 km/h +-1 | 24 km/h +-1 |
- | motorway | no | grade4 | 20 km/h +-1 | 20 km/h +-1 |
- | motorway | no | grade5 | 16 km/h +-1 | 16 km/h +-1 |
+ | motorway | no | | 80 km/h +-1 | 80 km/h +-1 |
+ | motorway | no | grade1 | 60 km/h +-1 | 60 km/h +-1 |
+ | motorway | no | grade2 | 42 km/h +-1 | 42 km/h +-1 |
+ | motorway | no | grade3 | 34 km/h +-1 | 34 km/h +-1 |
+ | motorway | no | grade4 | 31 km/h +-1 | 31 km/h +-1 |
+ | motorway | no | grade5 | 26 km/h +-1 | 26 km/h +-1 |
Scenario: Car - Smoothness should reduce speed
Then routability should be
| highway | oneway | smoothness | forw | backw |
- | motorway | no | | 72 km/h +-1 | 72 km/h +-1 |
- | motorway | no | intermediate | 65 km/h +-1 | 65 km/h +-1 |
- | motorway | no | bad | 32 km/h +-1 | 32 km/h +-1 |
- | motorway | no | very_bad | 16 km/h +-1 | 16 km/h +-1 |
- | motorway | no | horrible | 8 km/h +-1 | 8 km/h +-1 |
- | motorway | no | very_horrible | 4 km/h +-1 | 4 km/h +-1 |
+ | motorway | no | | 80 km/h +-1 | 80 km/h +-1 |
+ | motorway | no | intermediate | 72 km/h +-1 | 72 km/h +-1 |
+ | motorway | no | bad | 42 km/h +-1 | 42 km/h +-1 |
+ | motorway | no | very_bad | 26 km/h +-1 | 26 km/h +-1 |
+ | motorway | no | horrible | 18 km/h +-1 | 18 km/h +-1 |
+ | motorway | no | very_horrible | 15 km/h +-1 | 15 km/h +-1 |
Scenario: Car - Combination of surface tags should use lowest speed
Then routability should be
| highway | oneway | tracktype | surface | smoothness | backw | forw |
- | motorway | no | | | | 72 km/h | 72 km/h |
- | service | no | grade1 | asphalt | excellent | 12 km/h | 12 km/h |
- | motorway | no | grade5 | asphalt | excellent | 16 km/h | 16 km/h |
- | motorway | no | grade1 | mud | excellent | 8 km/h | 8 km/h |
- | motorway | no | grade1 | asphalt | very_horrible | 4 km/h | 4 km/h |
- | service | no | grade5 | mud | very_horrible | 4 km/h | 4 km/h |
+ | motorway | no | | | | 80 km/h | 80 km/h |
+ | service | no | grade1 | asphalt | excellent | 23 km/h | 23 km/h |
+ | motorway | no | grade5 | asphalt | excellent | 26 km/h | 26 km/h |
+ | motorway | no | grade1 | mud | excellent | 18 km/h | 18 km/h |
+ | motorway | no | grade1 | asphalt | very_horrible | 15 km/h | 15 km/h |
+ | service | no | grade5 | mud | very_horrible | 15 km/h | 15 km/h |
Scenario: Car - Surfaces should not affect oneway direction
Then routability should be
@@ -138,3 +138,4 @@ Feature: Car - Surfaces
| primary | -1 | grade1 | excellent | asphalt | | x |
| primary | -1 | grade5 | very_bad | mud | | x |
| primary | -1 | nonsense | nonsense | nonsense | | x |
+
diff --git a/3party/osrm/osrm-backend/features/car/way.feature b/3party/osrm/osrm-backend/features/car/way.feature
index d6d324c3df..d6d324c3df 100644..100755
--- a/3party/osrm/osrm-backend/features/car/way.feature
+++ b/3party/osrm/osrm-backend/features/car/way.feature
diff --git a/3party/osrm/osrm-backend/features/foot/access.feature b/3party/osrm/osrm-backend/features/foot/access.feature
index 4d81d0e456..4d81d0e456 100644..100755
--- a/3party/osrm/osrm-backend/features/foot/access.feature
+++ b/3party/osrm/osrm-backend/features/foot/access.feature
diff --git a/3party/osrm/osrm-backend/features/foot/access_node.feature b/3party/osrm/osrm-backend/features/foot/access_node.feature
index 5a4a1314ea..5a4a1314ea 100644..100755
--- a/3party/osrm/osrm-backend/features/foot/access_node.feature
+++ b/3party/osrm/osrm-backend/features/foot/access_node.feature
diff --git a/3party/osrm/osrm-backend/features/foot/area.feature b/3party/osrm/osrm-backend/features/foot/area.feature
index 6edd585d6a..6edd585d6a 100644..100755
--- a/3party/osrm/osrm-backend/features/foot/area.feature
+++ b/3party/osrm/osrm-backend/features/foot/area.feature
diff --git a/3party/osrm/osrm-backend/features/foot/barrier.feature b/3party/osrm/osrm-backend/features/foot/barrier.feature
index 18fa4deac9..18fa4deac9 100644..100755
--- a/3party/osrm/osrm-backend/features/foot/barrier.feature
+++ b/3party/osrm/osrm-backend/features/foot/barrier.feature
diff --git a/3party/osrm/osrm-backend/features/foot/ferry.feature b/3party/osrm/osrm-backend/features/foot/ferry.feature
index 866644d26a..866644d26a 100644..100755
--- a/3party/osrm/osrm-backend/features/foot/ferry.feature
+++ b/3party/osrm/osrm-backend/features/foot/ferry.feature
diff --git a/3party/osrm/osrm-backend/features/foot/maxspeed.feature b/3party/osrm/osrm-backend/features/foot/maxspeed.feature
index d4e3583516..d4e3583516 100644..100755
--- a/3party/osrm/osrm-backend/features/foot/maxspeed.feature
+++ b/3party/osrm/osrm-backend/features/foot/maxspeed.feature
diff --git a/3party/osrm/osrm-backend/features/foot/names.feature b/3party/osrm/osrm-backend/features/foot/names.feature
index d5fdcc7e4a..d5fdcc7e4a 100644..100755
--- a/3party/osrm/osrm-backend/features/foot/names.feature
+++ b/3party/osrm/osrm-backend/features/foot/names.feature
diff --git a/3party/osrm/osrm-backend/features/foot/oneway.feature b/3party/osrm/osrm-backend/features/foot/oneway.feature
index 77562e5e22..77562e5e22 100644..100755
--- a/3party/osrm/osrm-backend/features/foot/oneway.feature
+++ b/3party/osrm/osrm-backend/features/foot/oneway.feature
diff --git a/3party/osrm/osrm-backend/features/foot/ref.feature b/3party/osrm/osrm-backend/features/foot/ref.feature
index bc0c77e142..bc0c77e142 100644..100755
--- a/3party/osrm/osrm-backend/features/foot/ref.feature
+++ b/3party/osrm/osrm-backend/features/foot/ref.feature
diff --git a/3party/osrm/osrm-backend/features/foot/restrictions.feature b/3party/osrm/osrm-backend/features/foot/restrictions.feature
index 8d6a0297fc..8d6a0297fc 100644..100755
--- a/3party/osrm/osrm-backend/features/foot/restrictions.feature
+++ b/3party/osrm/osrm-backend/features/foot/restrictions.feature
diff --git a/3party/osrm/osrm-backend/features/foot/roundabout.feature b/3party/osrm/osrm-backend/features/foot/roundabout.feature
index 7808c46e88..5aa9860fb3 100644..100755
--- a/3party/osrm/osrm-backend/features/foot/roundabout.feature
+++ b/3party/osrm/osrm-backend/features/foot/roundabout.feature
@@ -3,12 +3,12 @@ Feature: Roundabout Instructions
Background:
Given the profile "foot"
-
+
@todo
Scenario: Foot - Roundabout instructions
# You can walk in both directions on a roundabout, bu the normal roundabout instructions don't
# make sense when you're going the opposite way around the roundabout.
-
+
Given the node map
| | | v | | |
| | | d | | |
diff --git a/3party/osrm/osrm-backend/features/foot/surface.feature b/3party/osrm/osrm-backend/features/foot/surface.feature
index 556c3d8935..556c3d8935 100644..100755
--- a/3party/osrm/osrm-backend/features/foot/surface.feature
+++ b/3party/osrm/osrm-backend/features/foot/surface.feature
diff --git a/3party/osrm/osrm-backend/features/foot/way.feature b/3party/osrm/osrm-backend/features/foot/way.feature
index 653c7736c2..653c7736c2 100644..100755
--- a/3party/osrm/osrm-backend/features/foot/way.feature
+++ b/3party/osrm/osrm-backend/features/foot/way.feature
diff --git a/3party/osrm/osrm-backend/features/locate/locate.feature b/3party/osrm/osrm-backend/features/locate/locate.feature
index 838bcd5cdb..838bcd5cdb 100644..100755
--- a/3party/osrm/osrm-backend/features/locate/locate.feature
+++ b/3party/osrm/osrm-backend/features/locate/locate.feature
diff --git a/3party/osrm/osrm-backend/features/nearest/pick.feature b/3party/osrm/osrm-backend/features/nearest/pick.feature
index 08e665243c..08e665243c 100644..100755
--- a/3party/osrm/osrm-backend/features/nearest/pick.feature
+++ b/3party/osrm/osrm-backend/features/nearest/pick.feature
diff --git a/3party/osrm/osrm-backend/features/nearest/projection.feature b/3party/osrm/osrm-backend/features/nearest/projection.feature
index 33a827813a..33a827813a 100644..100755
--- a/3party/osrm/osrm-backend/features/nearest/projection.feature
+++ b/3party/osrm/osrm-backend/features/nearest/projection.feature
diff --git a/3party/osrm/osrm-backend/features/options/extract/files.feature b/3party/osrm/osrm-backend/features/options/extract/files.feature
index aceab19f74..aceab19f74 100644..100755
--- a/3party/osrm/osrm-backend/features/options/extract/files.feature
+++ b/3party/osrm/osrm-backend/features/options/extract/files.feature
diff --git a/3party/osrm/osrm-backend/features/options/extract/help.feature b/3party/osrm/osrm-backend/features/options/extract/help.feature
index 3215e6aeff..3215e6aeff 100644..100755
--- a/3party/osrm/osrm-backend/features/options/extract/help.feature
+++ b/3party/osrm/osrm-backend/features/options/extract/help.feature
diff --git a/3party/osrm/osrm-backend/features/options/extract/invalid.feature b/3party/osrm/osrm-backend/features/options/extract/invalid.feature
index 169e53caa9..169e53caa9 100644..100755
--- a/3party/osrm/osrm-backend/features/options/extract/invalid.feature
+++ b/3party/osrm/osrm-backend/features/options/extract/invalid.feature
diff --git a/3party/osrm/osrm-backend/features/options/extract/version.feature b/3party/osrm/osrm-backend/features/options/extract/version.feature
index 1f2ef91fdc..0dd5f65886 100644..100755
--- a/3party/osrm/osrm-backend/features/options/extract/version.feature
+++ b/3party/osrm/osrm-backend/features/options/extract/version.feature
@@ -6,7 +6,7 @@ Feature: osrm-extract command line options: version
Background:
Given the profile "testbot"
-
+
Scenario: osrm-extract - Version, short
When I run "osrm-extract --v"
Then stderr should be empty
diff --git a/3party/osrm/osrm-backend/features/options/prepare/files.feature b/3party/osrm/osrm-backend/features/options/prepare/files.feature
index 6e82a6b1b8..6e82a6b1b8 100644..100755
--- a/3party/osrm/osrm-backend/features/options/prepare/files.feature
+++ b/3party/osrm/osrm-backend/features/options/prepare/files.feature
diff --git a/3party/osrm/osrm-backend/features/options/prepare/help.feature b/3party/osrm/osrm-backend/features/options/prepare/help.feature
index 49497ae859..49497ae859 100644..100755
--- a/3party/osrm/osrm-backend/features/options/prepare/help.feature
+++ b/3party/osrm/osrm-backend/features/options/prepare/help.feature
diff --git a/3party/osrm/osrm-backend/features/options/prepare/invalid.feature b/3party/osrm/osrm-backend/features/options/prepare/invalid.feature
index 7450390a8f..7450390a8f 100644..100755
--- a/3party/osrm/osrm-backend/features/options/prepare/invalid.feature
+++ b/3party/osrm/osrm-backend/features/options/prepare/invalid.feature
diff --git a/3party/osrm/osrm-backend/features/options/prepare/version.feature b/3party/osrm/osrm-backend/features/options/prepare/version.feature
index 196409b9bd..7a821c626e 100644..100755
--- a/3party/osrm/osrm-backend/features/options/prepare/version.feature
+++ b/3party/osrm/osrm-backend/features/options/prepare/version.feature
@@ -6,7 +6,7 @@ Feature: osrm-prepare command line options: version
Background:
Given the profile "testbot"
-
+
Scenario: osrm-prepare - Version, short
When I run "osrm-prepare --v"
Then stderr should be empty
diff --git a/3party/osrm/osrm-backend/features/options/routed/files.feature b/3party/osrm/osrm-backend/features/options/routed/files.feature
index 9be77f775e..15ce679eb3 100644..100755
--- a/3party/osrm/osrm-backend/features/options/routed/files.feature
+++ b/3party/osrm/osrm-backend/features/options/routed/files.feature
@@ -3,7 +3,7 @@ Feature: osrm-routed command line options: files
# Normally when launching osrm-routed, it will keep running as a server until it's shut down.
# For testing program options, the --trial option is used, which causes osrm-routed to quit
# immediately after initialization. This makes testing easier and faster.
-#
+#
# The {prepared_base} part of the options to osrm-routed will be expanded to the actual base path of
# the prepared input file.
diff --git a/3party/osrm/osrm-backend/features/options/routed/help.feature b/3party/osrm/osrm-backend/features/options/routed/help.feature
index 9603c40dde..c0fca4717c 100644..100755
--- a/3party/osrm/osrm-backend/features/options/routed/help.feature
+++ b/3party/osrm/osrm-backend/features/options/routed/help.feature
@@ -24,8 +24,10 @@ 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 22 lines
+ And stdout should contain "--shared-memory"
+ And stdout should contain "--max-table-size"
+ 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
@@ -48,8 +50,10 @@ 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 22 lines
+ And stdout should contain "--shared-memory"
+ And stdout should contain "--max-table-size"
+ 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
@@ -72,6 +76,8 @@ 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 22 lines
+ And stdout should contain "--shared-memory"
+ And stdout should contain "--max-table-size"
+ And stdout should contain "--max-matching-size"
+ And stdout should contain 26 lines
And it should exit with code 0
diff --git a/3party/osrm/osrm-backend/features/options/routed/invalid.feature b/3party/osrm/osrm-backend/features/options/routed/invalid.feature
index a6d62d7e0a..a6d62d7e0a 100644..100755
--- a/3party/osrm/osrm-backend/features/options/routed/invalid.feature
+++ b/3party/osrm/osrm-backend/features/options/routed/invalid.feature
diff --git a/3party/osrm/osrm-backend/features/options/routed/version.feature b/3party/osrm/osrm-backend/features/options/routed/version.feature
index ea600c0646..b544e36e6e 100644..100755
--- a/3party/osrm/osrm-backend/features/options/routed/version.feature
+++ b/3party/osrm/osrm-backend/features/options/routed/version.feature
@@ -6,7 +6,7 @@ Feature: osrm-routed command line options: version
Background:
Given the profile "testbot"
-
+
Scenario: osrm-routed - Version, short
When I run "osrm-routed --v"
Then stderr should be empty
diff --git a/3party/osrm/osrm-backend/features/step_definitions/data.rb b/3party/osrm/osrm-backend/features/step_definitions/data.rb
index f1e58bae22..f1e58bae22 100644..100755
--- a/3party/osrm/osrm-backend/features/step_definitions/data.rb
+++ b/3party/osrm/osrm-backend/features/step_definitions/data.rb
diff --git a/3party/osrm/osrm-backend/features/step_definitions/distance_matrix.rb b/3party/osrm/osrm-backend/features/step_definitions/distance_matrix.rb
new file mode 100755
index 0000000000..f85bdcc073
--- /dev/null
+++ b/3party/osrm/osrm-backend/features/step_definitions/distance_matrix.rb
@@ -0,0 +1,56 @@
+When /^I request a travel time matrix I should get$/ do |table|
+
+ no_route = 2147483647 # MAX_INT
+
+ raise "*** Top-left cell of matrix table must be empty" unless table.headers[0]==""
+
+ nodes = []
+ column_headers = table.headers[1..-1]
+ row_headers = table.rows.map { |h| h.first }
+ unless column_headers==row_headers
+ raise "*** Column and row headers must match in matrix table, got #{column_headers.inspect} and #{row_headers.inspect}"
+ end
+ column_headers.each do |node_name|
+ node = find_node_by_name(node_name)
+ raise "*** unknown node '#{node_name}" unless node
+ nodes << node
+ end
+
+ reprocess
+ actual = []
+ actual << table.headers
+ OSRMLoader.load(self,"#{prepared_file}.osrm") do
+
+ # compute matrix
+ params = @query_params
+ response = request_table nodes, params
+ if response.body.empty? == false
+ json = JSON.parse response.body
+ result = json['distance_table']
+ end
+
+ # compare actual and expected result, one row at a time
+ table.rows.each_with_index do |row,ri|
+
+ # fuzzy match
+ ok = true
+ 0.upto(nodes.size-1) do |i|
+ if FuzzyMatch.match result[ri][i], row[i+1]
+ result[ri][i] = row[i+1]
+ elsif row[i+1]=="" and result[ri][i]==no_route
+ result[ri][i] = ""
+ else
+ result[ri][i] = result[ri][i].to_s
+ ok = false
+ end
+ end
+
+ # add row header
+ r = [row[0],result[ri]].flatten
+
+ # store row for comparison
+ actual << r
+ end
+ end
+ table.routing_diff! actual
+end
diff --git a/3party/osrm/osrm-backend/features/step_definitions/locate.rb b/3party/osrm/osrm-backend/features/step_definitions/locate.rb
index 3e67be3c96..3e67be3c96 100644..100755
--- a/3party/osrm/osrm-backend/features/step_definitions/locate.rb
+++ b/3party/osrm/osrm-backend/features/step_definitions/locate.rb
diff --git a/3party/osrm/osrm-backend/features/step_definitions/matching.rb b/3party/osrm/osrm-backend/features/step_definitions/matching.rb
new file mode 100755
index 0000000000..3f3181f64f
--- /dev/null
+++ b/3party/osrm/osrm-backend/features/step_definitions/matching.rb
@@ -0,0 +1,96 @@
+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'].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 trace"
+ 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|
+ 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]
+ 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']
+ got['timestamps'] = row['timestamps']
+ 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/3party/osrm/osrm-backend/features/step_definitions/nearest.rb b/3party/osrm/osrm-backend/features/step_definitions/nearest.rb
index 532c1f0d74..532c1f0d74 100644..100755
--- a/3party/osrm/osrm-backend/features/step_definitions/nearest.rb
+++ b/3party/osrm/osrm-backend/features/step_definitions/nearest.rb
diff --git a/3party/osrm/osrm-backend/features/step_definitions/options.rb b/3party/osrm/osrm-backend/features/step_definitions/options.rb
index e2e50661e2..e2e50661e2 100644..100755
--- a/3party/osrm/osrm-backend/features/step_definitions/options.rb
+++ b/3party/osrm/osrm-backend/features/step_definitions/options.rb
diff --git a/3party/osrm/osrm-backend/features/step_definitions/requests.rb b/3party/osrm/osrm-backend/features/step_definitions/requests.rb
index 41257e5b9d..41257e5b9d 100644..100755
--- a/3party/osrm/osrm-backend/features/step_definitions/requests.rb
+++ b/3party/osrm/osrm-backend/features/step_definitions/requests.rb
diff --git a/3party/osrm/osrm-backend/features/step_definitions/routability.rb b/3party/osrm/osrm-backend/features/step_definitions/routability.rb
index dcbde5afad..dcbde5afad 100644..100755
--- a/3party/osrm/osrm-backend/features/step_definitions/routability.rb
+++ b/3party/osrm/osrm-backend/features/step_definitions/routability.rb
diff --git a/3party/osrm/osrm-backend/features/step_definitions/routing.rb b/3party/osrm/osrm-backend/features/step_definitions/routing.rb
index c25f5b7c8c..c25f5b7c8c 100644..100755
--- a/3party/osrm/osrm-backend/features/step_definitions/routing.rb
+++ b/3party/osrm/osrm-backend/features/step_definitions/routing.rb
diff --git a/3party/osrm/osrm-backend/features/step_definitions/timestamp.rb b/3party/osrm/osrm-backend/features/step_definitions/timestamp.rb
index 77a614c964..df456152be 100644..100755
--- a/3party/osrm/osrm-backend/features/step_definitions/timestamp.rb
+++ b/3party/osrm/osrm-backend/features/step_definitions/timestamp.rb
@@ -3,5 +3,5 @@ Then /^I should get a valid timestamp/ do
step "response should be valid JSON"
step "response should be well-formed"
expect(@json['timestamp'].class).to eq(String)
- expect(@json['timestamp']).to eq(OSM_TIMESTAMP)
+ expect(@json['timestamp']).to eq("2000-01-01T00:00:00Z")
end
diff --git a/3party/osrm/osrm-backend/features/stress/launch.feature b/3party/osrm/osrm-backend/features/stress/launch.feature
index 10c13c8fc1..10c13c8fc1 100644..100755
--- a/3party/osrm/osrm-backend/features/stress/launch.feature
+++ b/3party/osrm/osrm-backend/features/stress/launch.feature
diff --git a/3party/osrm/osrm-backend/features/support/config.rb b/3party/osrm/osrm-backend/features/support/config.rb
index e61c9fc74f..e61c9fc74f 100644..100755
--- a/3party/osrm/osrm-backend/features/support/config.rb
+++ b/3party/osrm/osrm-backend/features/support/config.rb
diff --git a/3party/osrm/osrm-backend/features/support/cucumber.rb b/3party/osrm/osrm-backend/features/support/cucumber.rb
index a43082a7ab..a43082a7ab 100644..100755
--- a/3party/osrm/osrm-backend/features/support/cucumber.rb
+++ b/3party/osrm/osrm-backend/features/support/cucumber.rb
diff --git a/3party/osrm/osrm-backend/features/support/data.rb b/3party/osrm/osrm-backend/features/support/data.rb
index 1ff186181f..1ff186181f 100644..100755
--- a/3party/osrm/osrm-backend/features/support/data.rb
+++ b/3party/osrm/osrm-backend/features/support/data.rb
diff --git a/3party/osrm/osrm-backend/features/support/env.rb b/3party/osrm/osrm-backend/features/support/env.rb
index a01341dd6a..f9a4fe4367 100644..100755
--- a/3party/osrm/osrm-backend/features/support/env.rb
+++ b/3party/osrm/osrm-backend/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
diff --git a/3party/osrm/osrm-backend/features/support/exceptions.rb b/3party/osrm/osrm-backend/features/support/exceptions.rb
index 02f59d388a..02f59d388a 100644..100755
--- a/3party/osrm/osrm-backend/features/support/exceptions.rb
+++ b/3party/osrm/osrm-backend/features/support/exceptions.rb
diff --git a/3party/osrm/osrm-backend/features/support/file.rb b/3party/osrm/osrm-backend/features/support/file.rb
index dfaae0a451..dfaae0a451 100644..100755
--- a/3party/osrm/osrm-backend/features/support/file.rb
+++ b/3party/osrm/osrm-backend/features/support/file.rb
diff --git a/3party/osrm/osrm-backend/features/support/fuzzy.rb b/3party/osrm/osrm-backend/features/support/fuzzy.rb
index 066d9c5a86..066d9c5a86 100644..100755
--- a/3party/osrm/osrm-backend/features/support/fuzzy.rb
+++ b/3party/osrm/osrm-backend/features/support/fuzzy.rb
diff --git a/3party/osrm/osrm-backend/features/support/hash.rb b/3party/osrm/osrm-backend/features/support/hash.rb
index 6980b66456..6980b66456 100644..100755
--- a/3party/osrm/osrm-backend/features/support/hash.rb
+++ b/3party/osrm/osrm-backend/features/support/hash.rb
diff --git a/3party/osrm/osrm-backend/features/support/hooks.rb b/3party/osrm/osrm-backend/features/support/hooks.rb
index 3370142468..3370142468 100644..100755
--- a/3party/osrm/osrm-backend/features/support/hooks.rb
+++ b/3party/osrm/osrm-backend/features/support/hooks.rb
diff --git a/3party/osrm/osrm-backend/features/support/launch.rb b/3party/osrm/osrm-backend/features/support/launch.rb
index f6667fad6d..d8d23aeaa6 100644..100755
--- a/3party/osrm/osrm-backend/features/support/launch.rb
+++ b/3party/osrm/osrm-backend/features/support/launch.rb
@@ -1,5 +1,6 @@
require 'socket'
require 'open3'
+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.
@@ -117,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
diff --git a/3party/osrm/osrm-backend/features/support/locate.rb b/3party/osrm/osrm-backend/features/support/locate.rb
index 9007247034..9007247034 100644..100755
--- a/3party/osrm/osrm-backend/features/support/locate.rb
+++ b/3party/osrm/osrm-backend/features/support/locate.rb
diff --git a/3party/osrm/osrm-backend/features/support/log.rb b/3party/osrm/osrm-backend/features/support/log.rb
index e480bdb0c4..8e6f9c1463 100644..100755
--- a/3party/osrm/osrm-backend/features/support/log.rb
+++ b/3party/osrm/osrm-backend/features/support/log.rb
@@ -6,7 +6,7 @@ LOG_FILE = 'fail.log'
def clear_log_files
Dir.chdir TEST_FOLDER do
- # emptying existing files, rather than deleting and writing new ones makes it
+ # emptying existing files, rather than deleting and writing new ones makes it
# easier to use tail -f from the command line
`echo '' > #{OSRM_ROUTED_LOG_FILE}`
`echo '' > #{PREPROCESS_LOG_FILE}`
diff --git a/3party/osrm/osrm-backend/features/support/match.rb b/3party/osrm/osrm-backend/features/support/match.rb
new file mode 100755
index 0000000000..bf51189a40
--- /dev/null
+++ b/3party/osrm/osrm-backend/features/support/match.rb
@@ -0,0 +1,26 @@
+require 'net/http'
+
+HOST = "http://127.0.0.1:#{OSRM_PORT}"
+
+def request_matching trace=[], timestamps=[], options={}
+ defaults = { 'output' => 'json' }
+ locs = trace.compact.map { |w| "loc=#{w.lat},#{w.lon}" }
+ ts = timestamps.compact.map { |t| "t=#{t}" }
+ 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
+ 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
+
diff --git a/3party/osrm/osrm-backend/features/support/nearest.rb b/3party/osrm/osrm-backend/features/support/nearest.rb
index 77fc351a9e..77fc351a9e 100644..100755
--- a/3party/osrm/osrm-backend/features/support/nearest.rb
+++ b/3party/osrm/osrm-backend/features/support/nearest.rb
diff --git a/3party/osrm/osrm-backend/features/support/osm_parser.rb b/3party/osrm/osrm-backend/features/support/osm_parser.rb
index 1da7c73189..1da7c73189 100644..100755
--- a/3party/osrm/osrm-backend/features/support/osm_parser.rb
+++ b/3party/osrm/osrm-backend/features/support/osm_parser.rb
diff --git a/3party/osrm/osrm-backend/features/support/osmlib.rb b/3party/osrm/osrm-backend/features/support/osmlib.rb
index 6b03dfa4a8..6b03dfa4a8 100644..100755
--- a/3party/osrm/osrm-backend/features/support/osmlib.rb
+++ b/3party/osrm/osrm-backend/features/support/osmlib.rb
diff --git a/3party/osrm/osrm-backend/features/support/route.rb b/3party/osrm/osrm-backend/features/support/route.rb
index 745edc0fdb..a8c78227ed 100644..100755
--- a/3party/osrm/osrm-backend/features/support/route.rb
+++ b/3party/osrm/osrm-backend/features/support/route.rb
@@ -43,6 +43,11 @@ def request_route waypoints, params={}
request_path "viaroute", waypoints, defaults.merge(params)
end
+def request_table waypoints, params={}
+ defaults = { 'output' => 'json' }
+ request_path "table", waypoints, defaults.merge(params)
+end
+
def got_route? response
if response.code == "200" && !response.body.empty?
json = JSON.parse response.body
diff --git a/3party/osrm/osrm-backend/features/support/run.rb b/3party/osrm/osrm-backend/features/support/run.rb
index 0e64b93de5..42dc597a15 100644..100755
--- a/3party/osrm/osrm-backend/features/support/run.rb
+++ b/3party/osrm/osrm-backend/features/support/run.rb
@@ -4,20 +4,20 @@ def run_bin bin, options
if opt.include? '{osm_base}'
raise "*** {osm_base} is missing" unless osm_file
- opt.gsub! "{osm_base}", "#{osm_file}"
+ opt.gsub! "{osm_base}", "#{osm_file}"
end
if opt.include? '{extracted_base}'
raise "*** {extracted_base} is missing" unless extracted_file
- opt.gsub! "{extracted_base}", "#{extracted_file}"
+ opt.gsub! "{extracted_base}", "#{extracted_file}"
end
if opt.include? '{prepared_base}'
raise "*** {prepared_base} is missing" unless prepared_file
- opt.gsub! "{prepared_base}", "#{prepared_file}"
+ opt.gsub! "{prepared_base}", "#{prepared_file}"
end
if opt.include? '{profile}'
- opt.gsub! "{profile}", "#{PROFILES_PATH}/#{@profile}.lua"
+ opt.gsub! "{profile}", "#{PROFILES_PATH}/#{@profile}.lua"
end
cmd = "#{QQ}#{BIN_PATH}/#{bin}#{EXE}#{QQ} #{opt} 2>error.log"
diff --git a/3party/osrm/osrm-backend/features/support/shortcuts.rb b/3party/osrm/osrm-backend/features/support/shortcuts.rb
index 20bc3c0fec..20bc3c0fec 100644..100755
--- a/3party/osrm/osrm-backend/features/support/shortcuts.rb
+++ b/3party/osrm/osrm-backend/features/support/shortcuts.rb
diff --git a/3party/osrm/osrm-backend/features/testbot/bad.feature b/3party/osrm/osrm-backend/features/testbot/bad.feature
index d7e3c95af1..d7e3c95af1 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/bad.feature
+++ b/3party/osrm/osrm-backend/features/testbot/bad.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/basic.feature b/3party/osrm/osrm-backend/features/testbot/basic.feature
index 2b35d29a01..599b0628af 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/basic.feature
+++ b/3party/osrm/osrm-backend/features/testbot/basic.feature
@@ -233,7 +233,7 @@ Feature: Basic Routing
| d | a | abcd |
| a | m | aeim |
| m | a | aeim |
-
+
Scenario: Testbot - Triangle challenge
Given the node map
| | | | d |
diff --git a/3party/osrm/osrm-backend/features/testbot/bearing.feature b/3party/osrm/osrm-backend/features/testbot/bearing.feature
index 9b3dc4eb7a..9b3dc4eb7a 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/bearing.feature
+++ b/3party/osrm/osrm-backend/features/testbot/bearing.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/bearing_param.feature b/3party/osrm/osrm-backend/features/testbot/bearing_param.feature
index 810f690384..810f690384 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/bearing_param.feature
+++ b/3party/osrm/osrm-backend/features/testbot/bearing_param.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/bugs.feature b/3party/osrm/osrm-backend/features/testbot/bugs.feature
index 26be28aa6f..26be28aa6f 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/bugs.feature
+++ b/3party/osrm/osrm-backend/features/testbot/bugs.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/compression.feature b/3party/osrm/osrm-backend/features/testbot/compression.feature
index 146ad63df7..146ad63df7 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/compression.feature
+++ b/3party/osrm/osrm-backend/features/testbot/compression.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/datastore.feature b/3party/osrm/osrm-backend/features/testbot/datastore.feature
index 568ae7aa4b..568ae7aa4b 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/datastore.feature
+++ b/3party/osrm/osrm-backend/features/testbot/datastore.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/distance.feature b/3party/osrm/osrm-backend/features/testbot/distance.feature
index 1f777d24f4..55b5f64165 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/distance.feature
+++ b/3party/osrm/osrm-backend/features/testbot/distance.feature
@@ -145,7 +145,7 @@ Feature: Distance calculation
| a | h | abcdefgh | 70m +-14 |
Scenario: Geometric distances
- Given a grid size of 1000 meters
+ Given a grid size of 100 meters
Given the node map
| v | w | y | a | b | c | d |
| u | | | | | | e |
@@ -184,30 +184,30 @@ Feature: Distance calculation
When I route I should get
| from | to | route | distance |
- | x | a | xa | 3000m +-2 |
- | x | b | xb | 3162m +-2 |
- | x | c | xc | 3606m +-2 |
- | x | d | xd | 4243m +-2 |
- | x | e | xe | 3606m +-2 |
- | x | f | xf | 3162m +-2 |
- | x | g | xg | 3000m +-2 |
- | x | h | xh | 3162m +-2 |
- | x | i | xi | 3606m +-2 |
- | x | j | xj | 4243m +-2 |
- | x | k | xk | 3606m +-2 |
- | x | l | xl | 3162m +-2 |
- | x | m | xm | 3000m +-2 |
- | x | n | xn | 3162m +-2 |
- | x | o | xo | 3606m +-2 |
- | x | p | xp | 4243m +-2 |
- | x | q | xq | 3606m +-2 |
- | x | r | xr | 3162m +-2 |
- | x | s | xs | 3000m +-2 |
- | x | t | xt | 3162m +-2 |
- | x | u | xu | 3606m +-2 |
- | x | v | xv | 4243m +-2 |
- | x | w | xw | 3606m +-2 |
- | x | y | xy | 3162m +-2 |
+ | x | a | xa | 300m +-2 |
+ | x | b | xb | 316m +-2 |
+ | x | c | xc | 360m +-2 |
+ | x | d | xd | 424m +-2 |
+ | x | e | xe | 360m +-2 |
+ | x | f | xf | 316m +-2 |
+ | x | g | xg | 300m +-2 |
+ | x | h | xh | 316m +-2 |
+ | x | i | xi | 360m +-2 |
+ | x | j | xj | 424m +-2 |
+ | x | k | xk | 360m +-2 |
+ | x | l | xl | 316m +-2 |
+ | x | m | xm | 300m +-2 |
+ | x | n | xn | 316m +-2 |
+ | x | o | xo | 360m +-2 |
+ | x | p | xp | 424m +-2 |
+ | x | q | xq | 360m +-2 |
+ | x | r | xr | 316m +-2 |
+ | x | s | xs | 300m +-2 |
+ | x | t | xt | 316m +-2 |
+ | x | u | xu | 360m +-2 |
+ | x | v | xv | 424m +-2 |
+ | x | w | xw | 360m +-2 |
+ | x | y | xy | 316m +-2 |
@maze
Scenario: Distance of a maze of short segments
diff --git a/3party/osrm/osrm-backend/features/testbot/distance_matrix.feature b/3party/osrm/osrm-backend/features/testbot/distance_matrix.feature
new file mode 100755
index 0000000000..390ae9847d
--- /dev/null
+++ b/3party/osrm/osrm-backend/features/testbot/distance_matrix.feature
@@ -0,0 +1,102 @@
+@matrix @testbot
+Feature: Basic Distance Matrix
+# note that results are travel time, specified in 1/10th of seconds
+# since testbot uses a default speed of 100m/10s, the result matches
+# the number of meters as long as the way type is the default 'primary'
+
+ Background:
+ Given the profile "testbot"
+
+ Scenario: Testbot - Travel time matrix of minimal network
+ Given the node map
+ | a | b |
+
+ And the ways
+ | nodes |
+ | ab |
+
+ When I request a travel time matrix I should get
+ | | a | b |
+ | a | 0 | 100 |
+ | b | 100 | 0 |
+
+ Scenario: Testbot - Travel time matrix with different way speeds
+ Given the node map
+ | a | b | c | d |
+
+ And the ways
+ | nodes | highway |
+ | ab | primary |
+ | bc | secondary |
+ | cd | tertiary |
+
+ When I request a travel time matrix I should get
+ | | a | b | c | d |
+ | a | 0 | 100 | 300 | 600 |
+ | b | 100 | 0 | 200 | 500 |
+ | c | 300 | 200 | 0 | 300 |
+ | d | 600 | 500 | 300 | 0 |
+
+ Scenario: Testbot - Travel time matrix with fuzzy match
+ Given the node map
+ | a | b |
+
+ And the ways
+ | nodes |
+ | ab |
+
+ When I request a travel time matrix I should get
+ | | a | b |
+ | a | 0 | 95 +- 10 |
+ | b | 95 ~10% | 0 |
+
+ Scenario: Testbot - Travel time matrix of small grid
+ Given the node map
+ | a | b | c |
+ | d | e | f |
+
+ And the ways
+ | nodes |
+ | abc |
+ | def |
+ | ad |
+ | be |
+ | cf |
+
+ When I request a travel time matrix I should get
+ | | a | b | e | f |
+ | a | 0 | 100 | 200 | 300 |
+ | b | 100 | 0 | 100 | 200 |
+ | e | 200 | 100 | 0 | 100 |
+ | f | 300 | 200 | 100 | 0 |
+
+ Scenario: Testbot - Travel time matrix of network with unroutable parts
+ Given the node map
+ | a | b |
+
+ And the ways
+ | nodes | oneway |
+ | ab | yes |
+
+ When I request a travel time matrix I should get
+ | | a | b |
+ | a | 0 | 100 |
+ | b | | 0 |
+
+ Scenario: Testbot - Travel time matrix of network with oneways
+ Given the node map
+ | x | a | b | y |
+ | | d | e | |
+
+ And the ways
+ | nodes | oneway |
+ | abeda | yes |
+ | xa | |
+ | by | |
+
+ When I request a travel time matrix I should get
+ | | x | y | d | e |
+ | x | 0 | 300 | 400 | 300 |
+ | y | 500 | 0 | 300 | 200 |
+ | d | 200 | 300 | 0 | 300 |
+ | e | 300 | 400 | 100 | 0 |
diff --git a/3party/osrm/osrm-backend/features/testbot/duration.feature b/3party/osrm/osrm-backend/features/testbot/duration.feature
index d5c6e46ec3..d5c6e46ec3 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/duration.feature
+++ b/3party/osrm/osrm-backend/features/testbot/duration.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/example.feature b/3party/osrm/osrm-backend/features/testbot/example.feature
index c2aa1e926b..c2aa1e926b 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/example.feature
+++ b/3party/osrm/osrm-backend/features/testbot/example.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/fastest.feature b/3party/osrm/osrm-backend/features/testbot/fastest.feature
index 8c24a5334d..8c24a5334d 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/fastest.feature
+++ b/3party/osrm/osrm-backend/features/testbot/fastest.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/ferry.feature b/3party/osrm/osrm-backend/features/testbot/ferry.feature
index 55160614ba..55160614ba 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/ferry.feature
+++ b/3party/osrm/osrm-backend/features/testbot/ferry.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/fixed.feature b/3party/osrm/osrm-backend/features/testbot/fixed.feature
index 0edf25c155..0edf25c155 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/fixed.feature
+++ b/3party/osrm/osrm-backend/features/testbot/fixed.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/geometry.feature b/3party/osrm/osrm-backend/features/testbot/geometry.feature
index 8b38c06f81..8b38c06f81 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/geometry.feature
+++ b/3party/osrm/osrm-backend/features/testbot/geometry.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/graph.feature b/3party/osrm/osrm-backend/features/testbot/graph.feature
index adff998681..adff998681 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/graph.feature
+++ b/3party/osrm/osrm-backend/features/testbot/graph.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/impedance.feature b/3party/osrm/osrm-backend/features/testbot/impedance.feature
index cab9ec3da4..cab9ec3da4 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/impedance.feature
+++ b/3party/osrm/osrm-backend/features/testbot/impedance.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/load.feature b/3party/osrm/osrm-backend/features/testbot/load.feature
index cf5e470bdc..cf5e470bdc 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/load.feature
+++ b/3party/osrm/osrm-backend/features/testbot/load.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/loop.feature b/3party/osrm/osrm-backend/features/testbot/loop.feature
index fe898ecf08..72cad33c03 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/loop.feature
+++ b/3party/osrm/osrm-backend/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 |
diff --git a/3party/osrm/osrm-backend/features/testbot/matching.feature b/3party/osrm/osrm-backend/features/testbot/matching.feature
new file mode 100755
index 0000000000..774e8a9d69
--- /dev/null
+++ b/3party/osrm/osrm-backend/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 62 63 | 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 |
+
diff --git a/3party/osrm/osrm-backend/features/testbot/maxspeed.feature b/3party/osrm/osrm-backend/features/testbot/maxspeed.feature
index 5b27f9d9db..5b27f9d9db 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/maxspeed.feature
+++ b/3party/osrm/osrm-backend/features/testbot/maxspeed.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/mode.feature b/3party/osrm/osrm-backend/features/testbot/mode.feature
index 54b99d3a11..11fe83a427 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/mode.feature
+++ b/3party/osrm/osrm-backend/features/testbot/mode.feature
@@ -11,7 +11,7 @@ Feature: Testbot - Travel mode
Background:
Given the profile "testbot"
-
+
Scenario: Testbot - Modes in each direction, different forward/backward speeds
Given the node map
| | 0 | 1 | |
diff --git a/3party/osrm/osrm-backend/features/testbot/oneway.feature b/3party/osrm/osrm-backend/features/testbot/oneway.feature
index 766bf8b3b9..766bf8b3b9 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/oneway.feature
+++ b/3party/osrm/osrm-backend/features/testbot/oneway.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/opposite.feature b/3party/osrm/osrm-backend/features/testbot/opposite.feature
index c19755cdc5..c19755cdc5 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/opposite.feature
+++ b/3party/osrm/osrm-backend/features/testbot/opposite.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/origin.feature b/3party/osrm/osrm-backend/features/testbot/origin.feature
index b5b1945020..b5b1945020 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/origin.feature
+++ b/3party/osrm/osrm-backend/features/testbot/origin.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/overlap.feature b/3party/osrm/osrm-backend/features/testbot/overlap.feature
index 6599e3c766..509867fb5d 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/overlap.feature
+++ b/3party/osrm/osrm-backend/features/testbot/overlap.feature
@@ -1,11 +1,11 @@
@routing @testbot @overlap
Feature: Testbot - overlapping ways
-
+
Background:
Given the profile "testbot"
@bug @610
- Scenario: Testbot - multiple way between same nodes
+ Scenario: Testbot - multiple way between same nodes
Note that cb is connecting the same two nodes as bc
Given the node map
| a | b | c | d |
@@ -21,7 +21,7 @@ Feature: Testbot - overlapping ways
| from | to | route |
| a | d | ab,bc,cd |
| d | a | cd,bc,ab |
-
+
@bug @610
Scenario: Testbot - area on top of way
Given the node map
diff --git a/3party/osrm/osrm-backend/features/testbot/penalty.feature b/3party/osrm/osrm-backend/features/testbot/penalty.feature
index e4f3cb632f..e4f3cb632f 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/penalty.feature
+++ b/3party/osrm/osrm-backend/features/testbot/penalty.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/planetary.feature b/3party/osrm/osrm-backend/features/testbot/planetary.feature
index 19925fe27f..19925fe27f 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/planetary.feature
+++ b/3party/osrm/osrm-backend/features/testbot/planetary.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/projection.feature b/3party/osrm/osrm-backend/features/testbot/projection.feature
index d7a0b89930..d7a0b89930 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/projection.feature
+++ b/3party/osrm/osrm-backend/features/testbot/projection.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/protobuffer.feature b/3party/osrm/osrm-backend/features/testbot/protobuffer.feature
index e32de26c25..e32de26c25 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/protobuffer.feature
+++ b/3party/osrm/osrm-backend/features/testbot/protobuffer.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/roundabout.feature b/3party/osrm/osrm-backend/features/testbot/roundabout.feature
index 570b14bed5..570b14bed5 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/roundabout.feature
+++ b/3party/osrm/osrm-backend/features/testbot/roundabout.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/routes.feature b/3party/osrm/osrm-backend/features/testbot/routes.feature
index bc1d75eb4d..bc1d75eb4d 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/routes.feature
+++ b/3party/osrm/osrm-backend/features/testbot/routes.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/snap.feature b/3party/osrm/osrm-backend/features/testbot/snap.feature
index bee75bc445..bee75bc445 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/snap.feature
+++ b/3party/osrm/osrm-backend/features/testbot/snap.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/speed.feature b/3party/osrm/osrm-backend/features/testbot/speed.feature
index 2eb3724f56..2eb3724f56 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/speed.feature
+++ b/3party/osrm/osrm-backend/features/testbot/speed.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/status.feature b/3party/osrm/osrm-backend/features/testbot/status.feature
index 1b12b33ea8..1b12b33ea8 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/status.feature
+++ b/3party/osrm/osrm-backend/features/testbot/status.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/time.feature b/3party/osrm/osrm-backend/features/testbot/time.feature
index c838796f23..c838796f23 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/time.feature
+++ b/3party/osrm/osrm-backend/features/testbot/time.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/turns.feature b/3party/osrm/osrm-backend/features/testbot/turns.feature
index 6eba4f9e9f..6eba4f9e9f 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/turns.feature
+++ b/3party/osrm/osrm-backend/features/testbot/turns.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/utf.feature b/3party/osrm/osrm-backend/features/testbot/utf.feature
index d979e9f925..d979e9f925 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/utf.feature
+++ b/3party/osrm/osrm-backend/features/testbot/utf.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/uturn.feature b/3party/osrm/osrm-backend/features/testbot/uturn.feature
index 943796e698..943796e698 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/uturn.feature
+++ b/3party/osrm/osrm-backend/features/testbot/uturn.feature
diff --git a/3party/osrm/osrm-backend/features/testbot/via.feature b/3party/osrm/osrm-backend/features/testbot/via.feature
index 9eb8f556ec..9eb8f556ec 100644..100755
--- a/3party/osrm/osrm-backend/features/testbot/via.feature
+++ b/3party/osrm/osrm-backend/features/testbot/via.feature
diff --git a/3party/osrm/osrm-backend/features/timestamp/timestamp.feature b/3party/osrm/osrm-backend/features/timestamp/timestamp.feature
index 70ef91c2b8..70ef91c2b8 100644..100755
--- a/3party/osrm/osrm-backend/features/timestamp/timestamp.feature
+++ b/3party/osrm/osrm-backend/features/timestamp/timestamp.feature
diff --git a/3party/osrm/osrm-backend/include/osrm/coordinate.hpp b/3party/osrm/osrm-backend/include/osrm/coordinate.hpp
new file mode 100755
index 0000000000..6318465e19
--- /dev/null
+++ b/3party/osrm/osrm-backend/include/osrm/coordinate.hpp
@@ -0,0 +1,71 @@
+/*
+
+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 COORDINATE_HPP_
+#define COORDINATE_HPP_
+
+#include <iosfwd> //for std::ostream
+#include <string>
+#include <type_traits>
+
+namespace
+{
+constexpr static const float COORDINATE_PRECISION = 1000000.f;
+}
+
+struct FixedPointCoordinate
+{
+ int lat;
+ int lon;
+
+ FixedPointCoordinate();
+ FixedPointCoordinate(int lat, int lon);
+
+ template <class T>
+ FixedPointCoordinate(const T &coordinate)
+ : lat(coordinate.lat), lon(coordinate.lon)
+ {
+ static_assert(std::is_same<decltype(lat), decltype(coordinate.lat)>::value,
+ "coordinate types incompatible");
+ static_assert(std::is_same<decltype(lon), decltype(coordinate.lon)>::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/3party/osrm/osrm-backend/include/osrm/json_container.hpp b/3party/osrm/osrm-backend/include/osrm/json_container.hpp
new file mode 100755
index 0000000000..40f39b8257
--- /dev/null
+++ b/3party/osrm/osrm-backend/include/osrm/json_container.hpp
@@ -0,0 +1,96 @@
+/*
+
+Copyright (c) 2013, 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_CONTAINER_HPP
+#define JSON_CONTAINER_HPP
+
+#include <variant/variant.hpp>
+
+#include <iostream>
+#include <vector>
+#include <string>
+#include <unordered_map>
+
+namespace osrm
+{
+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<double>(value)) {}
+ double value;
+};
+
+struct True
+{
+};
+
+struct False
+{
+};
+
+struct Null
+{
+};
+
+using Value = mapbox::util::variant<String,
+ Number,
+ mapbox::util::recursive_wrapper<Object>,
+ mapbox::util::recursive_wrapper<Array>,
+ True,
+ False,
+ Null>;
+
+struct Object
+{
+ std::unordered_map<std::string, Value> values;
+};
+
+struct Array
+{
+ std::vector<Value> values;
+};
+
+} // namespace JSON
+} // namespace osrm
+#endif // JSON_CONTAINER_HPP
diff --git a/3party/osrm/osrm-backend/Util/MachineInfo.h b/3party/osrm/osrm-backend/include/osrm/libosrm_config.hpp
index a9a88a1ec0..500abf5bd6 100644..100755
--- a/3party/osrm/osrm-backend/Util/MachineInfo.h
+++ b/3party/osrm/osrm-backend/include/osrm/libosrm_config.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,33 +25,30 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef MACHINE_INFO_H
-#define MACHINE_INFO_H
+#ifndef SERVER_CONFIG_HPP
+#define SERVER_CONFIG_HPP
-enum Endianness
-{ LittleEndian = 1,
- BigEndian = 2 };
+#include <osrm/server_paths.hpp>
-// Function is optimized to a single 'mov eax,1' on GCC, clang and icc using -O3
-Endianness GetMachineEndianness()
+struct libosrm_config
{
- int i(1);
- char *p = (char *)&i;
- if (1 == p[0])
+ libosrm_config(const libosrm_config &) = delete;
+ libosrm_config()
+ : max_locations_distance_table(100), max_locations_map_matching(-1),
+ use_shared_memory(false)
{
- return LittleEndian;
}
- return BigEndian;
-}
-// Reverses Network Byte Order into something usable, compiles down to a bswap-mov combination
-unsigned SwapEndian(unsigned x)
-{
- if (GetMachineEndianness() == LittleEndian)
+ 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)
{
- return ((x >> 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x << 24));
}
- return x;
-}
-#endif // MACHINE_INFO_H
+ ServerPaths server_paths;
+ int max_locations_distance_table;
+ int max_locations_map_matching;
+ bool use_shared_memory;
+};
+
+#endif // SERVER_CONFIG_HPP
diff --git a/3party/osrm/osrm-backend/Include/osrm/RouteParameters.h b/3party/osrm/osrm-backend/include/osrm/route_parameters.hpp
index 62f45148a5..9babbd763b 100644..100755
--- a/3party/osrm/osrm-backend/Include/osrm/RouteParameters.h
+++ b/3party/osrm/osrm-backend/include/osrm/route_parameters.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,10 +25,10 @@ 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 <osrm/Coordinate.h>
+#include <osrm/coordinate.hpp>
#include <boost/fusion/container/vector/vector_fwd.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);
@@ -63,13 +69,15 @@ struct RouteParameters
void addHint(const std::string &hint);
+ void addTimestamp(const unsigned timestamp);
+
void setLanguage(const std::string &language);
void setGeometryFlag(const bool flag);
void setCompressionFlag(const bool flag);
- void addCoordinate(const boost::fusion::vector<double, double> &coordinates);
+ void addCoordinate(const boost::fusion::vector<double, double> &received_coordinates);
short zoom_level;
bool print_instructions;
@@ -78,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;
@@ -85,8 +96,9 @@ struct RouteParameters
std::string jsonp_parameter;
std::string language;
std::vector<std::string> hints;
+ std::vector<unsigned> timestamps;
std::vector<bool> uturns;
std::vector<FixedPointCoordinate> coordinates;
};
-#endif // ROUTE_PARAMETERS_H
+#endif // ROUTE_PARAMETERS_HPP
diff --git a/3party/osrm/osrm-backend/Include/osrm/ServerPaths.h b/3party/osrm/osrm-backend/include/osrm/server_paths.hpp
index 52b60c7c42..669ee7de0f 100644..100755
--- a/3party/osrm/osrm-backend/Include/osrm/ServerPaths.h
+++ b/3party/osrm/osrm-backend/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,
@@ -33,6 +33,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <unordered_map>
#include <string>
-typedef std::unordered_map<std::string, boost::filesystem::path> ServerPaths;
+using ServerPaths = std::unordered_map<std::string, boost::filesystem::path>;
#endif // SERVER_PATH_H
diff --git a/3party/osrm/osrm-backend/Library/OSRM.h b/3party/osrm/osrm-backend/library/osrm.hpp
index 372e82c391..27acb40394 100644..100755
--- a/3party/osrm/osrm-backend/Library/OSRM.h
+++ b/3party/osrm/osrm-backend/library/osrm.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,19 +25,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef OSRM_H
-#define OSRM_H
+#ifndef OSRM_HPP
+#define OSRM_HPP
-#include <osrm/ServerPaths.h>
+#include <osrm/libosrm_config.hpp>
#include <memory>
class OSRM_impl;
struct RouteParameters;
-namespace http
+namespace osrm
{
-class Reply;
+namespace json
+{
+struct Object;
+}
}
class OSRM
@@ -46,9 +49,9 @@ class OSRM
std::unique_ptr<OSRM_impl> OSRM_pimpl_;
public:
- explicit OSRM(ServerPaths paths, const bool use_shared_memory = false);
+ explicit OSRM(libosrm_config &lib_config);
~OSRM();
- void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
+ int RunQuery(RouteParameters &route_parameters, osrm::json::Object &json_result);
};
-#endif // OSRM_H
+#endif // OSRM_HPP
diff --git a/3party/osrm/osrm-backend/library/osrm_impl.cpp b/3party/osrm/osrm-backend/library/osrm_impl.cpp
new file mode 100755
index 0000000000..5bb58d1749
--- /dev/null
+++ b/3party/osrm/osrm-backend/library/osrm_impl.cpp
@@ -0,0 +1,181 @@
+/*
+
+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.
+
+*/
+
+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 "../plugins/match.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 <boost/assert.hpp>
+#include <boost/interprocess/sync/named_condition.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+
+#include <osrm/route_parameters.hpp>
+
+#include <algorithm>
+#include <fstream>
+#include <utility>
+#include <vector>
+
+OSRM_impl::OSRM_impl(libosrm_config &lib_config)
+{
+ if (lib_config.use_shared_memory)
+ {
+ barrier = osrm::make_unique<SharedBarriers>();
+ query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>();
+ }
+ else
+ {
+ // populate base path
+ populate_base_path(lib_config.server_paths);
+ query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(lib_config.server_paths);
+ }
+
+ // The following plugins handle all requests.
+ RegisterPlugin(new DistanceTablePlugin<BaseDataFacade<QueryEdge::EdgeData>>(
+ query_data_facade, lib_config.max_locations_distance_table));
+ RegisterPlugin(new HelloWorldPlugin());
+ RegisterPlugin(new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
+ RegisterPlugin(new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
+ RegisterPlugin(new MapMatchingPlugin<BaseDataFacade<QueryEdge::EdgeData>>(
+ query_data_facade, lib_config.max_locations_map_matching));
+ RegisterPlugin(new TimestampPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
+ RegisterPlugin(new ViaRoutePlugin<BaseDataFacade<QueryEdge::EdgeData>>(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, osrm::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<boost::interprocess::named_mutex> 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<boost::interprocess::named_mutex> pending_lock(
+ barrier->pending_update_mutex);
+
+ // lock query
+ boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
+ barrier->query_mutex);
+
+ // unlock update pending
+ pending_lock.unlock();
+
+ // increment query count
+ ++(barrier->number_of_queries);
+
+ (static_cast<SharedDataFacade<QueryEdge::EdgeData> *>(query_data_facade))
+ ->CheckAndReloadFacade();
+}
+
+// proxy code for compilation firewall
+OSRM::OSRM(libosrm_config &lib_config) : OSRM_pimpl_(osrm::make_unique<OSRM_impl>(lib_config)) {}
+
+OSRM::~OSRM() { OSRM_pimpl_.reset(); }
+
+int OSRM::RunQuery(RouteParameters &route_parameters, osrm::json::Object &json_result)
+{
+ return OSRM_pimpl_->RunQuery(route_parameters, json_result);
+}
diff --git a/3party/osrm/osrm-backend/Library/OSRM_impl.h b/3party/osrm/osrm-backend/library/osrm_impl.hpp
index a4af62cb65..a736c042f6 100644..100755
--- a/3party/osrm/osrm-backend/Library/OSRM_impl.h
+++ b/3party/osrm/osrm-backend/library/osrm_impl.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,16 +25,16 @@ 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; }
struct RouteParameters;
-#include <osrm/ServerPaths.h>
+#include "../data_structures/query_edge.hpp"
-#include "../DataStructures/QueryEdge.h"
+#include <osrm/json_container.hpp>
+#include <osrm/libosrm_config.hpp>
#include <memory>
#include <unordered_map>
@@ -49,10 +49,10 @@ class OSRM_impl
using PluginMap = std::unordered_map<std::string, BasePlugin *>;
public:
- OSRM_impl(ServerPaths paths, const bool use_shared_memory);
+ OSRM_impl(libosrm_config &lib_config);
OSRM_impl(const OSRM_impl &) = delete;
virtual ~OSRM_impl();
- void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
+ int RunQuery(RouteParameters &route_parameters, osrm::json::Object &json_result);
private:
void RegisterPlugin(BasePlugin *plugin);
@@ -61,6 +61,11 @@ class OSRM_impl
std::unique_ptr<SharedBarriers> barrier;
// base class pointer to the objects
BaseDataFacade<QueryEdge::EdgeData> *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
+#endif // OSRM_IMPL_HPP
diff --git a/3party/osrm/osrm-backend/mapsme/converter.cpp b/3party/osrm/osrm-backend/mapsme/converter.cpp
deleted file mode 100644
index 307c1d32f1..0000000000
--- a/3party/osrm/osrm-backend/mapsme/converter.cpp
+++ /dev/null
@@ -1,388 +0,0 @@
-#include "converter.hpp"
-
-#include <iostream>
-
-
-#include "../../../../base/bits.hpp"
-#include "../../../../base/logging.hpp"
-#include "../../../../base/scope_guard.hpp"
-
-#include "../../../../coding/matrix_traversal.hpp"
-#include "../../../../coding/internal/file_data.hpp"
-
-#include "../../../../routing/osrm_data_facade.hpp"
-
-#include "../../../succinct/elias_fano.hpp"
-#include "../../../succinct/elias_fano_compressed_list.hpp"
-#include "../../../succinct/gamma_vector.hpp"
-#include "../../../succinct/rs_bit_vector.hpp"
-#include "../../../succinct/mapper.hpp"
-
-#include "../Server/DataStructures/InternalDataFacade.h"
-
-namespace mapsme
-{
-
-typedef pair<NodeID, QueryEdge::EdgeData> EdgeOsrmT;
-
-struct EdgeLess
-{
- bool operator () (EdgeOsrmT const & e1, EdgeOsrmT const & e2) const
- {
- if (e1.first != e2.first)
- return e1.first < e2.first;
-
- QueryEdge::EdgeData const & d1 = e1.second;
- QueryEdge::EdgeData const & d2 = e2.second;
-
- if (d1.distance != d2.distance)
- return d1.distance < d2.distance;
-
- if (d1.shortcut != d2.shortcut)
- return d1.shortcut < d2.shortcut;
-
- if (d1.forward != d2.forward)
- return d1.forward < d2.forward;
-
- if (d1.backward != d2.backward)
- return e1.second.backward < d2.backward;
-
- if (d1.id != d2.id)
- return d1.id < d2.id;
-
- return false;
- }
-};
-
-void PrintStatus(bool b)
-{
- std::cout << (b ? "[Ok]" : "[Fail]") << std::endl;
-}
-
-string EdgeDataToString(EdgeOsrmT const & d)
-{
- stringstream ss;
- ss << "[" << d.first << ", " << d.second.distance << ", " << d.second.shortcut << ", " << d.second.forward << ", "
- << d.second.backward << ", " << d.second.id << "]";
- return ss.str();
-}
-
-
-
-void GenerateRoutingIndex(const std::string & fPath)
-{
- ServerPaths server_paths;
-
- server_paths["hsgrdata"] = boost::filesystem::path(fPath + ".hsgr");
- server_paths["ramindex"] = boost::filesystem::path(fPath + ".ramIndex");
- server_paths["fileindex"] = boost::filesystem::path(fPath + ".fileIndex");
- server_paths["geometries"] = boost::filesystem::path(fPath + ".geometry");
- server_paths["nodesdata"] = boost::filesystem::path(fPath + ".nodes");
- server_paths["edgesdata"] = boost::filesystem::path(fPath + ".edges");
- server_paths["namesdata"] = boost::filesystem::path(fPath + ".names");
- server_paths["timestamp"] = boost::filesystem::path(fPath + ".timestamp");
-
- std::cout << "Create internal data facade for file: " << fPath << "...";
- InternalDataFacade<QueryEdge::EdgeData> facade(server_paths);
- PrintStatus(true);
-
- uint32_t const nodeCount = facade.GetNumberOfNodes();
-
- std::vector<uint64_t> edges;
- std::vector<uint32_t> edgesData;
- std::vector<bool> shortcuts;
- std::vector<uint64_t> edgeId;
-
- std::cout << "Repack graph..." << std::endl;
-
- typedef pair<uint64_t, QueryEdge::EdgeData> EdgeInfoT;
- typedef vector<EdgeInfoT> EdgeInfoVecT;
-
- uint64_t copiedEdges = 0, ignoredEdges = 0;
- for (uint32_t node = 0; node < nodeCount; ++node)
- {
- EdgeInfoVecT edgesInfo;
- for (auto edge : facade.GetAdjacentEdgeRange(node))
- {
- uint64_t target = facade.GetTarget(edge);
- auto const & data = facade.GetEdgeData(edge);
-
- edgesInfo.push_back(EdgeInfoT(target, data));
- }
-
- sort(edgesInfo.begin(), edgesInfo.end(), [](EdgeInfoT const & a, EdgeInfoT const & b)
- {
- if (a.first != b.first)
- return a.first < b.first;
-
- if (a.second.forward != b.second.forward)
- return a.second.forward > b.second.forward;
-
- return a.second.id < b.second.id;
- });
-
- uint64_t lastTarget = 0;
- for (auto edge : edgesInfo)
- {
- uint64_t const target = edge.first;
- auto const & data = edge.second;
-
- if (target < lastTarget)
- LOG(LCRITICAL, ("Invalid order of target nodes", target, lastTarget));
-
- lastTarget = target;
- assert(data.forward || data.backward);
-
- auto addDataFn = [&](bool b)
- {
- uint64_t const e = TraverseMatrixInRowOrder<uint64_t>(nodeCount, node, target, b);
-
- auto compressId = [&](uint64_t id)
- {
- return bits::ZigZagEncode(int64_t(node) - int64_t(id));
- };
-
- if (!edges.empty())
- CHECK_GREATER_OR_EQUAL(e, edges.back(), ());
-
- if (!edges.empty() && (edges.back() == e))
- {
- LOG(LWARNING, ("Invalid order of edges", e, edges.back(), nodeCount, node, target, b));
- CHECK(data.shortcut == shortcuts.back(), ());
-
- auto const last = edgesData.back();
- if (static_cast<uint32_t>(data.distance) <= last)
- {
- if (!edgeId.empty() && data.shortcut)
- {
- CHECK(shortcuts.back(), ());
- unsigned oldId = node - bits::ZigZagDecode(edgeId.back());
-
- if (static_cast<uint32_t>(data.distance) == last)
- edgeId.back() = compressId(min(oldId, data.id));
- else
- edgeId.back() = compressId(data.id);
- }
-
- edgesData.back() = data.distance;
- }
-
- ++ignoredEdges;
- return;
- }
-
- edges.push_back(e);
- edgesData.push_back(data.distance);
- shortcuts.push_back(data.shortcut);
-
- if (data.shortcut)
- edgeId.push_back(compressId(data.id));
- };
-
- if (data.forward && data.backward)
- {
- addDataFn(false);
- addDataFn(true);
- copiedEdges++;
- }
- else
- addDataFn(data.backward);
- }
- }
-
- std::cout << "Edges count: " << edgeId.size() << std::endl;
- PrintStatus(true);
-
- std::cout << "Sort edges...";
- std::sort(edges.begin(), edges.end());
- PrintStatus(true);
-
- std::cout << "Edges count: " << edges.size() << std::endl;
- std::cout << "Nodes count: " << nodeCount << std::endl;
-
- std::cout << "--- Save matrix" << std::endl;
- succinct::elias_fano::elias_fano_builder builder(edges.back(), edges.size());
- for (auto e : edges)
- builder.push_back(e);
- succinct::elias_fano matrix(&builder);
-
- std::string fileName = fPath + "." + ROUTING_MATRIX_FILE_TAG;
- std::ofstream fout(fileName, std::ios::binary);
- fout.write((const char*)&nodeCount, sizeof(nodeCount));
- succinct::mapper::freeze(matrix, fout);
- fout.close();
-
- std::cout << "--- Save edge data" << std::endl;
- succinct::elias_fano_compressed_list edgeVector(edgesData);
- fileName = fPath + "." + ROUTING_EDGEDATA_FILE_TAG;
- succinct::mapper::freeze(edgeVector, fileName.c_str());
-
- succinct::elias_fano_compressed_list edgeIdVector(edgeId);
- fileName = fPath + "." + ROUTING_EDGEID_FILE_TAG;
- succinct::mapper::freeze(edgeIdVector, fileName.c_str());
-
- std::cout << "--- Save edge shortcuts" << std::endl;
- succinct::rs_bit_vector shortcutsVector(shortcuts);
- fileName = fPath + "." + ROUTING_SHORTCUTS_FILE_TAG;
- succinct::mapper::freeze(shortcutsVector, fileName.c_str());
-
- if (edgeId.size() != shortcutsVector.num_ones())
- LOG(LCRITICAL, ("Invalid data"));
-
- std::cout << "--- Test packed data" << std::endl;
- std::string path = fPath + ".test";
-
- {
- FilesContainerW routingCont(path);
-
- auto appendFile = [&] (string const & tag)
- {
- string const fileName = fPath + "." + tag;
- routingCont.Write(fileName, tag);
- };
-
- appendFile(ROUTING_SHORTCUTS_FILE_TAG);
- appendFile(ROUTING_EDGEDATA_FILE_TAG);
- appendFile(ROUTING_MATRIX_FILE_TAG);
- appendFile(ROUTING_EDGEID_FILE_TAG);
-
- routingCont.Finish();
- }
-
- MY_SCOPE_GUARD(testFileGuard, bind(&my::DeleteFileX, cref(path)));
-
- FilesMappingContainer container;
- container.Open(path);
- typedef routing::OsrmDataFacade<QueryEdge::EdgeData> DataFacadeT;
- DataFacadeT facadeNew;
- facadeNew.Load(container);
-
- uint64_t edgesCount = facadeNew.GetNumberOfEdges() - copiedEdges + ignoredEdges;
- std::cout << "Check node count " << facade.GetNumberOfNodes() << " == " << facadeNew.GetNumberOfNodes() << "..." << std::endl;
- CHECK_EQUAL(facade.GetNumberOfNodes(), facadeNew.GetNumberOfNodes(), ());
- std::cout << "Check edges count " << facade.GetNumberOfEdges() << " == " << edgesCount << "..." << std::endl;
- CHECK_EQUAL(facade.GetNumberOfEdges(), edgesCount, ());
-
- std::cout << "Check edges data ...";
- bool error = false;
-
- assert(facade.GetNumberOfEdges() == facadeNew.GetNumberOfEdges());
- for (uint32_t i = 0; i < facade.GetNumberOfNodes(); ++i)
- {
- // get all edges from osrm datafacade and store just minimal weights for duplicates
- vector<EdgeOsrmT> edgesOsrm;
- for (auto e : facade.GetAdjacentEdgeRange(i))
- edgesOsrm.push_back(EdgeOsrmT(facade.GetTarget(e), facade.GetEdgeData(e)));
-
- sort(edgesOsrm.begin(), edgesOsrm.end(), [](EdgeOsrmT const & a, EdgeOsrmT const & b)
- {
- if (a.first != b.first)
- return a.first < b.first;
-
- QueryEdge::EdgeData const & d1 = a.second;
- QueryEdge::EdgeData const & d2 = b.second;
-
- if (d1.forward != d2.forward)
- return d1.forward < d2.forward;
-
- if (d1.backward != d2.backward)
- return d1.backward < d2.backward;
-
- if (d1.distance != d2.distance)
- return d1.distance < d2.distance;
-
- return d1.id < d2.id;
- });
-
- for (size_t k = 1; k < edgesOsrm.size();)
- {
- auto const & e1 = edgesOsrm[k - 1];
- auto const & e2 = edgesOsrm[k];
-
- if (e1.first != e2.first ||
- e1.second.forward != e2.second.forward ||
- e1.second.backward != e2.second.backward)
- {
- ++k;
- continue;
- }
-
- if (e1.second.distance > e2.second.distance)
- edgesOsrm.erase(edgesOsrm.begin() + k - 1);
- else
- edgesOsrm.erase(edgesOsrm.begin() + k);
- }
-
- vector<EdgeOsrmT> v1, v2;
- for (auto e : edgesOsrm)
- {
- QueryEdge::EdgeData d = e.second;
- if (d.forward && d.backward)
- {
- d.backward = false;
- v1.push_back(EdgeOsrmT(e.first, d));
- d.forward = false;
- d.backward = true;
- }
-
- v1.push_back(EdgeOsrmT(e.first, d));
- }
-
- for (auto e : facadeNew.GetAdjacentEdgeRange(i))
- v2.push_back(EdgeOsrmT(facadeNew.GetTarget(e), facadeNew.GetEdgeData(e, i)));
-
- if (v1.size() != v2.size())
- {
- auto printV = [](vector<EdgeOsrmT> const & v, stringstream & ss)
- {
- for (auto i : v)
- ss << EdgeDataToString(i) << std::endl;
- };
-
- sort(v1.begin(), v1.end(), EdgeLess());
- sort(v2.begin(), v2.end(), EdgeLess());
-
- stringstream ss;
- ss << "File name: " << fPath << std::endl;
- ss << "Not equal edges count for node: " << i << std::endl;
- ss << "v1: " << v1.size() << " v2: " << v2.size() << std::endl;
- ss << "--- v1 ---" << std::endl;
- printV(v1, ss);
- ss << "--- v2 ---" << std::endl;
- printV(v2, ss);
-
- LOG(LCRITICAL, (ss.str()));
- }
-
- sort(v1.begin(), v1.end(), EdgeLess());
- sort(v2.begin(), v2.end(), EdgeLess());
-
- // compare vectors
- for (size_t k = 0; k < v1.size(); ++k)
- {
- EdgeOsrmT const & e1 = v1[k];
- EdgeOsrmT const & e2 = v2[k];
-
- QueryEdge::EdgeData const & d1 = e1.second;
- QueryEdge::EdgeData const & d2 = e2.second;
-
- if (e1.first != e2.first ||
- d1.backward != d2.backward ||
- d1.forward != d2.forward ||
- d1.distance != d2.distance ||
- (d1.id != d2.id && (d1.shortcut || d2.shortcut)) ||
- d1.shortcut != d2.shortcut)
- {
- std::cout << "--- " << std::endl;
- for (size_t j = 0; j < v1.size(); ++j)
- std::cout << EdgeDataToString(v1[j]) << " - " << EdgeDataToString(v2[j]) << std::endl;
-
- LOG(LCRITICAL, ("File:", fPath, "Node:", i, EdgeDataToString(e1), EdgeDataToString(e2)));
- }
- }
-
- }
- PrintStatus(!error);
-}
-
-}
diff --git a/3party/osrm/osrm-backend/mapsme/converter.hpp b/3party/osrm/osrm-backend/mapsme/converter.hpp
deleted file mode 100644
index 77961dd3ca..0000000000
--- a/3party/osrm/osrm-backend/mapsme/converter.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-
-#include <string>
-
-#include "../DataStructures/QueryEdge.h"
-
-namespace mapsme
-{
-
-
-void GenerateRoutingIndex(const std::string & fPath);
-
-}
diff --git a/3party/osrm/osrm-backend/mapsme/main.cpp b/3party/osrm/osrm-backend/mapsme/main.cpp
deleted file mode 100644
index 5d626a9e61..0000000000
--- a/3party/osrm/osrm-backend/mapsme/main.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <stdlib.h>
-
-#include <iostream>
-#include <boost/program_options.hpp>
-#include "converter.hpp"
-
-int main(int argc, char **argv)
-{
-
- boost::program_options::options_description descr;
-
- descr.add_options()
- ("help", "h")
- ("input,i", boost::program_options::value<std::string>(), "Path to input osrm file (belarus.osrm)");
-
- boost::program_options::variables_map vm;
- boost::program_options::store(boost::program_options::command_line_parser(argc, argv).options(descr).run(), vm);
- boost::program_options::notify(vm);
- if (vm.count("help") || !vm.count("input"))
- {
- std::cout << descr;
- return 0;
- }
-
-
- mapsme::GenerateRoutingIndex(vm["input"].as<std::string>());
-
- return 0;
-}
diff --git a/3party/osrm/osrm-backend/Plugins/DistanceTablePlugin.h b/3party/osrm/osrm-backend/plugins/distance_table.hpp
index 715c4f52cf..d7a980419b 100644..100755
--- a/3party/osrm/osrm-backend/Plugins/DistanceTablePlugin.h
+++ b/3party/osrm/osrm-backend/plugins/distance_table.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,
@@ -25,19 +25,21 @@ 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 "BasePlugin.h"
+#include "plugin_base.hpp"
-#include "../Algorithms/ObjectToBase64.h"
-#include "../DataStructures/JSONContainer.h"
-#include "../DataStructures/QueryEdge.h"
-#include "../DataStructures/SearchEngine.h"
-#include "../Descriptors/BaseDescriptor.h"
-#include "../Util/make_unique.hpp"
-#include "../Util/StringUtil.h"
-#include "../Util/TimingUtil.h"
+#include "../algorithms/object_encoder.hpp"
+#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 <osrm/json_container.hpp>
#include <cstdlib>
@@ -51,68 +53,51 @@ template <class DataFacadeT> class DistanceTablePlugin final : public BasePlugin
{
private:
std::unique_ptr<SearchEngine<DataFacadeT>> 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<SearchEngine<DataFacadeT>>(facade);
}
virtual ~DistanceTablePlugin() {}
- const std::string GetDescriptor() const final { return descriptor_string; }
+ const std::string GetDescriptor() const override final { return descriptor_string; }
- void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
+ int HandleRequest(const RouteParameters &route_parameters,
+ osrm::json::Object &json_result) override final
{
- // check number of parameters
- if (2 > route_parameters.coordinates.size())
- {
- reply = http::Reply::StockReply(http::Reply::badRequest);
- return;
- }
-
- RawRouteData raw_route;
- raw_route.check_sum = facade->GetCheckSum();
-
- if (std::any_of(begin(route_parameters.coordinates),
- end(route_parameters.coordinates),
- [&](FixedPointCoordinate coordinate)
- {
- return !coordinate.isValid();
- }))
+ if (!check_all_coordinates(route_parameters.coordinates))
{
- reply = http::Reply::StockReply(http::Reply::badRequest);
- return;
+ return 400;
}
- for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
- {
- raw_route.raw_via_node_coordinates.emplace_back(std::move(coordinate));
- }
-
- const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
+ const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());
unsigned max_locations =
- std::min(100u, static_cast<unsigned>(raw_route.raw_via_node_coordinates.size()));
+ std::min(static_cast<unsigned>(max_locations_distance_table),
+ static_cast<unsigned>(route_parameters.coordinates.size()));
+
PhantomNodeArray phantom_node_vector(max_locations);
- for (unsigned i = 0; i < max_locations; ++i)
+ for (const auto i : osrm::irange(0u, max_locations))
{
if (checksum_OK && i < route_parameters.hints.size() &&
!route_parameters.hints[i].empty())
{
PhantomNode current_phantom_node;
ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], current_phantom_node);
- if (current_phantom_node.isValid(facade->GetNumberOfNodes()))
+ if (current_phantom_node.is_valid(facade->GetNumberOfNodes()))
{
phantom_node_vector[i].emplace_back(std::move(current_phantom_node));
continue;
}
}
- facade->IncrementalFindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
- phantom_node_vector[i],
- route_parameters.zoom_level,
- 1);
+ facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i],
+ phantom_node_vector[i], 1);
- BOOST_ASSERT(phantom_node_vector[i].front().isValid(facade->GetNumberOfNodes()));
+ BOOST_ASSERT(phantom_node_vector[i].front().is_valid(facade->GetNumberOfNodes()));
}
// TIMER_START(distance_table);
@@ -122,22 +107,22 @@ template <class DataFacadeT> 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 unsigned number_of_locations = static_cast<unsigned>(phantom_node_vector.size());
- for (unsigned row = 0; row < number_of_locations; ++row)
+
+ osrm::json::Array json_array;
+ const auto number_of_locations = phantom_node_vector.size();
+ for (const auto row : osrm::irange<std::size_t>(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_object.values["distance_table"] = json_array;
- JSON::render(reply.content, json_object);
+ json_result.values["distance_table"] = json_array;
+ // osrm::json::render(reply.content, json_object);
+ return 200;
}
private:
@@ -145,4 +130,4 @@ template <class DataFacadeT> class DistanceTablePlugin final : public BasePlugin
DataFacadeT *facade;
};
-#endif // DISTANCE_TABLE_PLUGIN_H
+#endif // DISTANCE_TABLE_HPP
diff --git a/3party/osrm/osrm-backend/Plugins/HelloWorldPlugin.h b/3party/osrm/osrm-backend/plugins/hello_world.hpp
index d9b4a8d0e2..faf5b10489 100644..100755
--- a/3party/osrm/osrm-backend/Plugins/HelloWorldPlugin.h
+++ b/3party/osrm/osrm-backend/plugins/hello_world.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,12 +25,15 @@ 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 "BasePlugin.h"
-#include "../DataStructures/JSONContainer.h"
-#include "../Util/cast.hpp"
+#include "plugin_base.hpp"
+
+#include "../util/cast.hpp"
+#include "../util/json_renderer.hpp"
+
+#include <osrm/json_container.hpp>
#include <string>
@@ -42,13 +45,11 @@ 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; }
- void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply) final
+ int HandleRequest(const RouteParameters &routeParameters,
+ osrm::json::Object &json_result) override final
{
- reply.status = http::Reply::ok;
-
- JSON::Object json_result;
std::string temp_string;
json_result.values["title"] = "Hello World";
@@ -70,15 +71,17 @@ 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(coordinate.lat / COORDINATE_PRECISION);
- json_coordinates.values.push_back(coordinate.lon / COORDINATE_PRECISION);
+ json_coordinates.values.push_back(
+ static_cast<double>(coordinate.lat / COORDINATE_PRECISION));
+ json_coordinates.values.push_back(
+ static_cast<double>(coordinate.lon / COORDINATE_PRECISION));
json_location.values[cast::integral_to_string(counter)] = json_coordinates;
json_locations.values.push_back(json_location);
++counter;
@@ -86,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 &current_hint : routeParameters.hints)
{
@@ -94,12 +97,11 @@ class HelloWorldPlugin final : public BasePlugin
++counter;
}
json_result.values["hints"] = json_hints;
-
- JSON::render(reply.content, json_result);
+ return 200;
}
private:
std::string descriptor_string;
};
-#endif // HELLO_WORLD_PLUGIN_H
+#endif // HELLO_WORLD_HPP
diff --git a/3party/osrm/osrm-backend/Plugins/LocatePlugin.h b/3party/osrm/osrm-backend/plugins/locate.hpp
index 1701bbe15a..144765ad82 100644..100755
--- a/3party/osrm/osrm-backend/Plugins/LocatePlugin.h
+++ b/3party/osrm/osrm-backend/plugins/locate.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,12 +25,15 @@ 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 "BasePlugin.h"
-#include "../DataStructures/JSONContainer.h"
-#include "../Util/StringUtil.h"
+#include "plugin_base.hpp"
+
+#include "../util/json_renderer.hpp"
+#include "../util/string_util.hpp"
+
+#include <osrm/json_container.hpp>
#include <string>
@@ -39,18 +42,18 @@ template <class DataFacadeT> 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; }
- void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
+ int HandleRequest(const RouteParameters &route_parameters,
+ osrm::json::Object &json_result) override final
{
// check number of parameters
- if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().isValid())
+ 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))
@@ -59,15 +62,13 @@ template <class DataFacadeT> class LocatePlugin final : public BasePlugin
}
else
{
- reply.status = http::Reply::ok;
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;
}
-
- JSON::render(reply.content, json_result);
+ return 200;
}
private:
@@ -75,4 +76,4 @@ template <class DataFacadeT> class LocatePlugin final : public BasePlugin
DataFacadeT *facade;
};
-#endif /* LOCATE_PLUGIN_H */
+#endif /* LOCATE_HPP */
diff --git a/3party/osrm/osrm-backend/plugins/match.hpp b/3party/osrm/osrm-backend/plugins/match.hpp
new file mode 100755
index 0000000000..a866947b4b
--- /dev/null
+++ b/3party/osrm/osrm-backend/plugins/match.hpp
@@ -0,0 +1,314 @@
+/*
+
+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 MATCH_HPP
+#define MATCH_HPP
+
+#include "plugin_base.hpp"
+
+#include "../algorithms/bayes_classifier.hpp"
+#include "../algorithms/object_encoder.hpp"
+#include "../data_structures/search_engine.hpp"
+#include "../descriptors/descriptor_base.hpp"
+#include "../descriptors/json_descriptor.hpp"
+#include "../routing_algorithms/map_matching.hpp"
+#include "../util/compute_angle.hpp"
+#include "../util/integer_range.hpp"
+#include "../util/json_logger.hpp"
+#include "../util/json_util.hpp"
+#include "../util/string_util.hpp"
+
+#include <cstdlib>
+
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <vector>
+
+template <class DataFacadeT> class MapMatchingPlugin : public BasePlugin
+{
+ constexpr static const unsigned max_number_of_candidates = 10;
+
+ std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
+
+ using ClassifierT = BayesClassifier<LaplaceDistribution, LaplaceDistribution, double>;
+ using TraceClassification = ClassifierT::ClassificationT;
+
+ 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.005986, 0.016646),
+ LaplaceDistribution(0.054385, 0.458432),
+ 0.696774) // valid apriori probability
+ {
+ search_engine_ptr = std::make_shared<SearchEngine<DataFacadeT>>(facade);
+ }
+
+ virtual ~MapMatchingPlugin() {}
+
+ const std::string GetDescriptor() const final { return descriptor_string; }
+
+ TraceClassification
+ classify(const float trace_length, const float matched_length, const int removed_points) const
+ {
+ const double distance_feature = -std::log(trace_length) + std::log(matched_length);
+
+ // matched to the same point
+ if (!std::isfinite(distance_feature))
+ {
+ return std::make_pair(ClassifierT::ClassLabel::NEGATIVE, 1.0);
+ }
+
+ const auto label_with_confidence = classifier.classify(distance_feature);
+
+ return label_with_confidence;
+ }
+
+ bool getCandiates(const std::vector<FixedPointCoordinate> &input_coords,
+ std::vector<double> &sub_trace_lengths,
+ osrm::matching::CandidateLists &candidates_lists)
+ {
+ 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<std::size_t>(0, input_coords.size()))
+ {
+ bool allow_uturn = false;
+ 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;
+ }
+
+ 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 <= 90.0 || turn_angle >= 270.0)
+ {
+ allow_uturn = true;
+ }
+ }
+
+ std::vector<std::pair<PhantomNode, double>> candidates;
+ if (!facade->IncrementalFindPhantomNodeForCoordinateWithMaxDistance(
+ input_coords[current_coordinate], candidates, last_distance / 2.0, 5,
+ max_number_of_candidates))
+ {
+ return false;
+ }
+
+ if (allow_uturn)
+ {
+ candidates_lists.push_back(candidates);
+ }
+ else
+ {
+ const auto compact_size = candidates.size();
+ for (const auto i : osrm::irange<std::size_t>(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 &&
+ 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;
+ }
+
+ osrm::json::Object submatchingToJSON(const osrm::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<std::size_t>(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));
+ }
+ // 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);
+ }
+
+ subtrace.values["indices"] = osrm::json::make_array(sub.indices);
+
+ osrm::json::Array points;
+ for (const auto &node : sub.nodes)
+ {
+ 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
+ {
+ // check number of parameters
+ if (!check_all_coordinates(route_parameters.coordinates))
+ {
+ return 400;
+ }
+
+ std::vector<double> sub_trace_lengths;
+ 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())
+ {
+ return 400;
+ }
+
+ // enforce maximum number of locations for performance reasons
+ if (max_locations_map_matching > 0 &&
+ static_cast<int>(input_coords.size()) < max_locations_map_matching)
+ {
+ return 400;
+ }
+
+ const bool found_candidates =
+ getCandiates(input_coords, sub_trace_lengths, candidates_lists);
+ if (!found_candidates)
+ {
+ return 400;
+ }
+
+ // setup logging if enabled
+ if (osrm::json::Logger::get())
+ osrm::json::Logger::get()->initialize("matching");
+
+ // call the actual map matching
+ 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);
+
+ if (sub_matchings.empty())
+ {
+ return 400;
+ }
+
+ osrm::json::Array 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());
+ if (classification.first == ClassifierT::ClassLabel::POSITIVE)
+ {
+ sub.confidence = classification.second;
+ }
+ else
+ {
+ sub.confidence = 1 - classification.second;
+ }
+ }
+
+ BOOST_ASSERT(sub.nodes.size() > 1);
+
+ // 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)
+ {
+ 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<bool>(raw_route.segment_end_coordinates.size(), true), raw_route);
+
+ matchings.values.emplace_back(submatchingToJSON(sub, route_parameters, raw_route));
+ }
+
+ if (osrm::json::Logger::get())
+ osrm::json::Logger::get()->render("matching", json_result);
+ json_result.values["matchings"] = matchings;
+
+ return 200;
+ }
+
+ private:
+ std::string descriptor_string;
+ DataFacadeT *facade;
+ int max_locations_map_matching;
+ ClassifierT classifier;
+};
+
+#endif // MATCH_HPP
diff --git a/3party/osrm/osrm-backend/Plugins/NearestPlugin.h b/3party/osrm/osrm-backend/plugins/nearest.hpp
index e4fec91c19..bf4cff3a1d 100644..100755
--- a/3party/osrm/osrm-backend/Plugins/NearestPlugin.h
+++ b/3party/osrm/osrm-backend/plugins/nearest.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,13 +25,16 @@ 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 "BasePlugin.h"
-#include "../DataStructures/JSONContainer.h"
-#include "../DataStructures/PhantomNodes.h"
-#include "../DataStructures/Range.h"
+#include "plugin_base.hpp"
+
+#include "../data_structures/phantom_node.hpp"
+#include "../util/integer_range.hpp"
+#include "../util/json_renderer.hpp"
+
+#include <osrm/json_container.hpp>
#include <string>
@@ -44,68 +47,66 @@ template <class DataFacadeT> 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; }
- void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
+ int HandleRequest(const RouteParameters &route_parameters,
+ osrm::json::Object &json_result) override final
{
// check number of parameters
- if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().isValid())
+ 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<std::size_t>(route_parameters.num_results);
std::vector<PhantomNode> phantom_node_vector;
facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates.front(),
phantom_node_vector,
- route_parameters.zoom_level,
static_cast<int>(number_of_results));
- JSON::Object json_result;
- if (phantom_node_vector.empty() || !phantom_node_vector.front().isValid())
+ 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)
{
- JSON::Array results;
+ osrm::json::Array results;
auto vector_length = phantom_node_vector.size();
- for (const auto i : osrm::irange<std::size_t>(0, std::min(number_of_results, vector_length)))
+ for (const auto i :
+ osrm::irange<std::size_t>(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 /
COORDINATE_PRECISION);
result.values["mapped coordinate"] = json_coordinate;
- std::string temp_string;
- facade->GetName(phantom_node_vector.front().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;
}
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 /
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);
}
}
- JSON::render(reply.content, json_result);
+ return 200;
}
private:
@@ -113,4 +114,4 @@ template <class DataFacadeT> class NearestPlugin final : public BasePlugin
std::string descriptor_string;
};
-#endif /* NEAREST_PLUGIN_H */
+#endif /* NEAREST_HPP */
diff --git a/3party/osrm/osrm-backend/Plugins/BasePlugin.h b/3party/osrm/osrm-backend/plugins/plugin_base.hpp
index 11c6940bba..acc820432f 100644..100755
--- a/3party/osrm/osrm-backend/Plugins/BasePlugin.h
+++ b/3party/osrm/osrm-backend/plugins/plugin_base.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,15 +25,14 @@ 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 "../Util/StringUtil.h"
-
-#include <osrm/Coordinate.h>
-#include <osrm/Reply.h>
-#include <osrm/RouteParameters.h>
+#include <osrm/coordinate.hpp>
+#include <osrm/json_container.hpp>
+#include <osrm/route_parameters.hpp>
+#include <algorithm>
#include <string>
#include <vector>
@@ -44,7 +43,20 @@ 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 int HandleRequest(const RouteParameters &, osrm::json::Object &) = 0;
+ virtual bool
+ check_all_coordinates(const std::vector<FixedPointCoordinate> &coordinates) const final
+ {
+ if (2 > coordinates.size() || std::any_of(std::begin(coordinates), std::end(coordinates),
+ [](const FixedPointCoordinate &coordinate)
+ {
+ return !coordinate.is_valid();
+ }))
+ {
+ return false;
+ }
+ return true;
+ }
};
-#endif /* BASEPLUGIN_H_ */
+#endif /* BASE_PLUGIN_HPP */
diff --git a/3party/osrm/osrm-backend/Plugins/TimestampPlugin.h b/3party/osrm/osrm-backend/plugins/timestamp.hpp
index 0047db199b..8a5d208b79 100644..100755
--- a/3party/osrm/osrm-backend/Plugins/TimestampPlugin.h
+++ b/3party/osrm/osrm-backend/plugins/timestamp.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -28,8 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef TIMESTAMP_PLUGIN_H
#define TIMESTAMP_PLUGIN_H
-#include "../DataStructures/JSONContainer.h"
-#include "BasePlugin.h"
+#include "plugin_base.hpp"
+
+#include "../util/json_renderer.hpp"
+
+#include <osrm/json_container.hpp>
#include <string>
@@ -40,15 +43,14 @@ template <class DataFacadeT> class TimestampPlugin final : public BasePlugin
: facade(facade), descriptor_string("timestamp")
{
}
- const std::string GetDescriptor() const final { return descriptor_string; }
- void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
+ const std::string GetDescriptor() const override final { return descriptor_string; }
+ int HandleRequest(const RouteParameters &route_parameters,
+ osrm::json::Object &json_result) override 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/3party/osrm/osrm-backend/plugins/viaroute.hpp b/3party/osrm/osrm-backend/plugins/viaroute.hpp
new file mode 100755
index 0000000000..8eccc5af49
--- /dev/null
+++ b/3party/osrm/osrm-backend/plugins/viaroute.hpp
@@ -0,0 +1,192 @@
+/*
+
+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 VIA_ROUTE_HPP
+#define VIA_ROUTE_HPP
+
+#include "plugin_base.hpp"
+
+#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 "../util/integer_range.hpp"
+#include "../util/json_renderer.hpp"
+#include "../util/make_unique.hpp"
+#include "../util/simple_logger.hpp"
+
+#include <osrm/json_container.hpp>
+
+#include <cstdlib>
+
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <vector>
+
+template <class DataFacadeT> class ViaRoutePlugin final : public BasePlugin
+{
+ private:
+ DescriptorTable descriptor_table;
+ std::string descriptor_string;
+ std::unique_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
+ DataFacadeT *facade;
+
+ public:
+ explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade)
+ {
+ search_engine_ptr = osrm::make_unique<SearchEngine<DataFacadeT>>(facade);
+
+ descriptor_table.emplace("json", 0);
+ descriptor_table.emplace("gpx", 1);
+ // descriptor_table.emplace("geojson", 2);
+ }
+
+ virtual ~ViaRoutePlugin() {}
+
+ const std::string GetDescriptor() const override final { return descriptor_string; }
+
+ int HandleRequest(const RouteParameters &route_parameters,
+ osrm::json::Object &json_result) override final
+ {
+ if (!check_all_coordinates(route_parameters.coordinates))
+ {
+ return 400;
+ }
+
+ std::vector<phantom_node_pair> phantom_node_pair_list(route_parameters.coordinates.size());
+ const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());
+
+ for (const auto i : osrm::irange<std::size_t>(0, route_parameters.coordinates.size()))
+ {
+ if (checksum_OK && i < route_parameters.hints.size() &&
+ !route_parameters.hints[i].empty())
+ {
+ ObjectEncoder::DecodeFromBase64(route_parameters.hints[i],
+ phantom_node_pair_list[i]);
+ if (phantom_node_pair_list[i].first.is_valid(facade->GetNumberOfNodes()))
+ {
+ continue;
+ }
+ }
+ std::vector<PhantomNode> phantom_node_vector;
+ if (facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i],
+ phantom_node_vector, 1))
+ {
+ BOOST_ASSERT(!phantom_node_vector.empty());
+ phantom_node_pair_list[i].first = phantom_node_vector.front();
+ if (phantom_node_vector.size() > 1)
+ {
+ phantom_node_pair_list[i].second = phantom_node_vector.back();
+ }
+ }
+ }
+
+ auto check_component_id_is_tiny = [](const phantom_node_pair &phantom_pair)
+ {
+ return phantom_pair.first.component_id != 0;
+ };
+
+ const bool every_phantom_is_in_tiny_cc =
+ std::all_of(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list),
+ check_component_id_is_tiny);
+
+ // are all phantoms from a tiny cc?
+ const auto component_id = phantom_node_pair_list.front().first.component_id;
+
+ auto check_component_id_is_equal = [component_id](const phantom_node_pair &phantom_pair)
+ {
+ return component_id == phantom_pair.first.component_id;
+ };
+
+ const bool every_phantom_has_equal_id =
+ std::all_of(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list),
+ check_component_id_is_equal);
+
+ auto swap_phantom_from_big_cc_into_front = [](phantom_node_pair &phantom_pair)
+ {
+ if (0 != phantom_pair.first.component_id)
+ {
+ using namespace std;
+ swap(phantom_pair.first, phantom_pair.second);
+ }
+ };
+
+ // this case is true if we take phantoms from the big CC
+ if (!every_phantom_is_in_tiny_cc || !every_phantom_has_equal_id)
+ {
+ std::for_each(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list),
+ swap_phantom_from_big_cc_into_front);
+ }
+
+ InternalRouteResult raw_route;
+ auto build_phantom_pairs =
+ [&raw_route](const phantom_node_pair &first_pair, const phantom_node_pair &second_pair)
+ {
+ raw_route.segment_end_coordinates.emplace_back(
+ PhantomNodes{first_pair.first, second_pair.first});
+ };
+ osrm::for_each_pair(phantom_node_pair_list, build_phantom_pairs);
+
+ if (route_parameters.alternate_route && 1 == raw_route.segment_end_coordinates.size())
+ {
+ search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
+ raw_route);
+ }
+ else
+ {
+ search_engine_ptr->shortest_path(raw_route.segment_end_coordinates,
+ route_parameters.uturns, raw_route);
+ }
+
+ if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
+ {
+ SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
+ }
+
+ std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor;
+ switch (descriptor_table.get_id(route_parameters.output_format))
+ {
+ case 1:
+ descriptor = osrm::make_unique<GPXDescriptor<DataFacadeT>>(facade);
+ break;
+ // case 2:
+ // descriptor = osrm::make_unique<GEOJSONDescriptor<DataFacadeT>>();
+ // break;
+ default:
+ descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);
+ break;
+ }
+
+ descriptor->SetConfig(route_parameters);
+ descriptor->Run(raw_route, json_result);
+ return 200;
+ }
+};
+
+#endif // VIA_ROUTE_HPP
diff --git a/3party/osrm/osrm-backend/prepare.cpp b/3party/osrm/osrm-backend/prepare.cpp
index 3cf397d0fe..af10df0358 100644..100755
--- a/3party/osrm/osrm-backend/prepare.cpp
+++ b/3party/osrm/osrm-backend/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,
@@ -25,9 +25,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "Contractor/Prepare.h"
+#include "contractor/processing_chain.hpp"
+#include "util/simple_logger.hpp"
-#include <boost/program_options.hpp>
+#include <boost/program_options/errors.hpp>
+
+#include <exception>
+#include <ostream>
int main(int argc, char *argv[])
{
diff --git a/3party/osrm/osrm-backend/profile.lua b/3party/osrm/osrm-backend/profile.lua
index ad58cd86ef..813afd19c4 100644..100755
--- a/3party/osrm/osrm-backend/profile.lua
+++ b/3party/osrm/osrm-backend/profile.lua
@@ -1,9 +1,9 @@
-- 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_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" }
@@ -28,6 +28,7 @@ speed_profile = {
["service"] = 15,
-- ["track"] = 5,
["ferry"] = 5,
+ ["movable"] = 5,
["shuttle_train"] = 10,
["default"] = 10
}
@@ -103,6 +104,9 @@ maxspeed_table_default = {
-- List only exceptions
maxspeed_table = {
+ ["ch:rural"] = 80,
+ ["ch:trunk"] = 100,
+ ["ch:motorway"] = 120,
["de:living_street"] = 7,
["ru:living_street"] = 20,
["ru:urban"] = 60,
@@ -124,11 +128,11 @@ maxspeed_table = {
}
traffic_signal_penalty = 2
+use_turn_restrictions = true
local take_minimum_of_speeds = false
local obey_oneway = true
local obey_bollards = true
-local use_turn_restrictions = true
local ignore_areas = true -- future feature
local u_turn_penalty = 20
@@ -141,16 +145,16 @@ 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)
+local function find_access_tag(source, access_tags_hierachy)
for i,v in ipairs(access_tags_hierachy) do
- local has_tag = source.tags:Holds(v)
- if has_tag then
- return source.tags:Find(v)
+ local access_tag = source:get_value_by_key(v)
+ if access_tag and "" ~= access_tag then
+ return access_tag
end
end
- return nil
+ return ""
end
function get_exceptions(vector)
@@ -191,69 +195,64 @@ end
-- return penalty
-- end
-function node_function (node)
- local access = find_access_tag(node, access_tags_hierachy)
-
- --flag node if it carries a traffic light
- if node.tags:Holds("highway") then
- if node.tags:Find("highway") == "traffic_signals" then
- node.traffic_light = true;
- end
- end
-
+function node_function (node, result)
-- parse access and barrier tags
- if access and access ~= "" then
+ local access = find_access_tag(node, access_tags_hierachy)
+ if access ~= "" then
if access_tag_blacklist[access] then
- node.bollard = true
+ result.barrier = true
end
- elseif node.tags:Holds("barrier") then
- local barrier = node.tags:Find("barrier")
- if barrier_whitelist[barrier] then
- return
- else
- node.bollard = true
+ else
+ local barrier = node:get_value_by_key("barrier")
+ if barrier and "" ~= barrier then
+ if not barrier_whitelist[barrier] then
+ result.barrier = true
+ end
end
end
-end
-function way_function (way)
+ -- check if node is a traffic light
+ local tag = node:get_value_by_key("highway")
+ if tag and "traffic_signals" == tag then
+ result.traffic_lights = true;
+ end
+end
- local is_highway = way.tags:Holds("highway")
- local is_route = way.tags:Holds("route")
+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 (is_highway or is_route) then
+ if not ((highway and highway ~= "") or (route and route ~= "") or (bridge and bridge ~= "")) then
return
end
-- we dont route over areas
- local is_area = way.tags:Holds("area")
- if ignore_areas and is_area then
- local area = way.tags:Find("area")
- if "yes" == area then
- return
- end
+ local area = way:get_value_by_key("area")
+ if ignore_areas and area and "yes" == area then
+ return
end
-- check if oneway tag is unsupported
- local oneway = way.tags:Find("oneway")
- if "reversible" == oneway then
+ local oneway = way:get_value_by_key("oneway")
+ if oneway and "reversible" == oneway then
return
end
- local is_impassable = way.tags:Holds("impassable")
- if is_impassable then
- local impassable = way.tags:Find("impassable")
- if "yes" == impassable then
- return
- end
+ local impassable = way:get_value_by_key("impassable")
+ if impassable and "yes" == impassable then
+ return
end
- local is_status = way.tags:Holds("status")
- if is_status then
- local status = way.tags:Find("status")
- if "impassable" == status then
- return
- end
+ local status = way:get_value_by_key("status")
+ if status and "impassable" == status then
+ 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*"))
end
-- Check if we are allowed to access the way
@@ -262,22 +261,33 @@ function way_function (way)
return
end
- -- Second, parse the way according to these properties
- local highway = way.tags:Find("highway")
- local route = way.tags:Find("route")
-
- -- 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.tags:Find("duration")
- if durationIsValid(duration) then
- way.duration = max( parseDuration(duration), 1 );
+ local duration = way:get_value_by_key("duration")
+ if duration and durationIsValid(duration) then
+ result.duration = max( parseDuration(duration), 1 );
end
- way.forward_mode = mode_ferry
- way.backward_mode = mode_ferry
- way.forward_speed = route_speed
- way.backward_speed = route_speed
+ result.forward_mode = mode_ferry
+ result.backward_mode = mode_ferry
+ result.forward_speed = route_speed
+ result.backward_speed = route_speed
+ end
+
+ -- handling movable bridges
+ local bridge_speed = speed_profile[bridge]
+ 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
+ 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
@@ -285,122 +295,136 @@ function way_function (way)
return
end
- if way.forward_speed == -1 then
+ if result.forward_speed == -1 then
local highway_speed = speed_profile[highway]
- local max_speed = parse_maxspeed( way.tags:Find("maxspeed") )
+ local max_speed = parse_maxspeed( way:get_value_by_key("maxspeed") )
-- Set the avg speed on the way if it is accessible by road class
if highway_speed then
- if max_speed > highway_speed then
- way.forward_speed = max_speed
- way.backward_speed = max_speed
+ if max_speed and max_speed > highway_speed then
+ result.forward_speed = max_speed
+ result.backward_speed = max_speed
-- max_speed = math.huge
else
- way.forward_speed = highway_speed
- way.backward_speed = highway_speed
+ result.forward_speed = highway_speed
+ result.backward_speed = highway_speed
end
else
-- Set the avg speed on ways that are marked accessible
if access_tag_whitelist[access] then
- way.forward_speed = speed_profile["default"]
- way.backward_speed = speed_profile["default"]
+ result.forward_speed = speed_profile["default"]
+ result.backward_speed = speed_profile["default"]
end
end
if 0 == max_speed then
max_speed = math.huge
end
- way.forward_speed = min(way.forward_speed, max_speed)
- way.backward_speed = min(way.backward_speed, max_speed)
+ result.forward_speed = min(result.forward_speed, max_speed)
+ result.backward_speed = min(result.backward_speed, max_speed)
end
- if -1 == way.forward_speed and -1 == way.backward_speed then
+ if -1 == result.forward_speed and -1 == result.backward_speed then
return
end
-- reduce speed on bad surfaces
- local surface = way.tags:Find("surface")
- local tracktype = way.tags:Find("tracktype")
- local smoothness = way.tags:Find("smoothness")
+ local surface = way:get_value_by_key("surface")
+ local tracktype = way:get_value_by_key("tracktype")
+ local smoothness = way:get_value_by_key("smoothness")
if surface and surface_speeds[surface] then
- way.forward_speed = math.min(surface_speeds[surface], way.forward_speed)
- way.backward_speed = math.min(surface_speeds[surface], way.backward_speed)
+ result.forward_speed = math.min(surface_speeds[surface], result.forward_speed)
+ result.backward_speed = math.min(surface_speeds[surface], result.backward_speed)
end
if tracktype and tracktype_speeds[tracktype] then
- way.forward_speed = math.min(tracktype_speeds[tracktype], way.forward_speed)
- way.backward_speed = math.min(tracktype_speeds[tracktype], way.backward_speed)
+ result.forward_speed = math.min(tracktype_speeds[tracktype], result.forward_speed)
+ result.backward_speed = math.min(tracktype_speeds[tracktype], result.backward_speed)
end
if smoothness and smoothness_speeds[smoothness] then
- way.forward_speed = math.min(smoothness_speeds[smoothness], way.forward_speed)
- way.backward_speed = math.min(smoothness_speeds[smoothness], way.backward_speed)
+ result.forward_speed = math.min(smoothness_speeds[smoothness], result.forward_speed)
+ result.backward_speed = math.min(smoothness_speeds[smoothness], result.backward_speed)
end
-- parse the remaining tags
- local name = way.tags:Find("name")
- local ref = way.tags:Find("ref")
- local junction = way.tags:Find("junction")
- -- local barrier = way.tags:Find("barrier")
- -- local cycleway = way.tags:Find("cycleway")
- local service = way.tags:Find("service")
+ local name = way:get_value_by_key("name")
+ local ref = way:get_value_by_key("ref")
+ local junction = way:get_value_by_key("junction")
+ -- local barrier = way:get_value_by_key("barrier", "")
+ -- local cycleway = way:get_value_by_key("cycleway", "")
+ local service = way:get_value_by_key("service")
-- Set the name that will be used for instructions
- if "" ~= ref then
- way.name = ref
- elseif "" ~= name then
- way.name = name
+ if ref and "" ~= ref then
+ result.name = ref
+ elseif name and "" ~= name then
+ result.name = name
-- else
- -- way.name = highway -- if no name exists, use way type
+ -- result.name = highway -- if no name exists, use way type
end
- if "roundabout" == junction then
- way.roundabout = true;
+ if junction and "roundabout" == junction then
+ result.roundabout = true;
end
-- Set access restriction flag if access is allowed under certain restrictions only
if access ~= "" and access_tag_restricted[access] then
- way.is_access_restricted = true
+ result.is_access_restricted = true
end
-- Set access restriction flag if service is allowed under certain restrictions only
- if service ~= "" and service_tag_restricted[service] then
- way.is_access_restricted = true
+ if service and service ~= "" and service_tag_restricted[service] then
+ result.is_access_restricted = true
end
-- Set direction according to tags on way
- if obey_oneway then
+ if obey_oneway then
if oneway == "-1" then
- way.forward_mode = 0
+ result.forward_mode = 0
elseif oneway == "yes" or
oneway == "1" or
oneway == "true" or
junction == "roundabout" or
(highway == "motorway_link" and oneway ~="no") or
(highway == "motorway" and oneway ~= "no") then
- way.backward_mode = 0
+ result.backward_mode = 0
end
end
-- Override speed settings if explicit forward/backward maxspeeds are given
- local maxspeed_forward = parse_maxspeed(way.tags:Find( "maxspeed:forward"))
- local maxspeed_backward = parse_maxspeed(way.tags:Find( "maxspeed:backward"))
- if maxspeed_forward > 0 then
- if 0 ~= way.forward_mode and 0 ~= way.backward_mode then
- way.backward_speed = way.forward_speed
+ local maxspeed_forward = parse_maxspeed(way:get_value_by_key( "maxspeed:forward"))
+ local maxspeed_backward = parse_maxspeed(way:get_value_by_key( "maxspeed:backward"))
+ if maxspeed_forward and maxspeed_forward > 0 then
+ if 0 ~= result.forward_mode and 0 ~= result.backward_mode then
+ result.backward_speed = result.forward_speed
end
- way.forward_speed = maxspeed_forward
+ result.forward_speed = maxspeed_forward
end
- if maxspeed_backward > 0 then
- way.backward_speed = maxspeed_backward
+ if maxspeed_backward and maxspeed_backward > 0 then
+ result.backward_speed = maxspeed_backward
end
-- Override general direction settings of there is a specific one for our mode of travel
if ignore_in_grid[highway] then
- way.ignore_in_grid = true
+ result.ignore_in_grid = true
end
+
-- scale speeds to get better avg driving times
- way.forward_speed = way.forward_speed * speed_reduction
- if way.backward_speed > 0 then
- way.backward_speed = way.backward_speed*speed_reduction
+ if result.forward_speed > 0 then
+ local scaled_speed = result.forward_speed*speed_reduction + 11;
+ local penalized_speed = math.huge
+ if width <= 3 then
+ penalized_speed = result.forward_speed / 2;
+ end
+ result.forward_speed = math.min(penalized_speed, scaled_speed)
+ end
+
+ if result.backward_speed > 0 then
+ local scaled_speed = result.backward_speed*speed_reduction + 11;
+ local penalized_speed = math.huge
+ if width <= 3 then
+ penalized_speed = result.backward_speed / 2;
+ end
+ result.backward_speed = math.min(penalized_speed, scaled_speed)
end
end
diff --git a/3party/osrm/osrm-backend/profiles/bicycle.lua b/3party/osrm/osrm-backend/profiles/bicycle.lua
index 13bfd280db..497321ccf3 100644..100755
--- a/3party/osrm/osrm-backend/profiles/bicycle.lua
+++ b/3party/osrm/osrm-backend/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
@@ -125,48 +129,48 @@ function get_exceptions(vector)
end
end
-function node_function (node)
- local barrier = node.tags:Find ("barrier")
+function node_function (node, result)
+ local barrier = node:get_value_by_key("barrier")
local access = Access.find_access_tag(node, access_tags_hierachy)
- local traffic_signal = node.tags:Find("highway")
+ local traffic_signal = node:get_value_by_key("highway")
-- flag node if it carries a traffic light
- if traffic_signal == "traffic_signals" then
- node.traffic_light = true
+ if traffic_signal and traffic_signal == "traffic_signals" then
+ result.traffic_lights = true
end
-- parse access and barrier tags
if access and access ~= "" then
if access_tag_blacklist[access] then
- node.bollard = true
+ result.barrier = true
else
- node.bollard = false
+ result.barrier = false
end
elseif barrier and barrier ~= "" then
if barrier_whitelist[barrier] then
- node.bollard = false
+ result.barrier = false
else
- node.bollard = true
+ result.barrier = true
end
end
-
- -- return 1
end
-function way_function (way)
+function way_function (way, result)
-- initial routability check, filters out buildings, boundaries, etc
- local highway = way.tags:Find("highway")
- local route = way.tags:Find("route")
- local man_made = way.tags:Find("man_made")
- local railway = way.tags:Find("railway")
- local amenity = way.tags:Find("amenity")
- local public_transport = way.tags:Find("public_transport")
+ local highway = way:get_value_by_key("highway")
+ local route = way:get_value_by_key("route")
+ local man_made = way:get_value_by_key("man_made")
+ 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
@@ -178,117 +182,127 @@ function way_function (way)
-- access
local access = Access.find_access_tag(way, access_tags_hierachy)
- if access_tag_blacklist[access] then
+ if access and access_tag_blacklist[access] then
return
end
-- other tags
- local name = way.tags:Find("name")
- local ref = way.tags:Find("ref")
- local junction = way.tags:Find("junction")
- local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") )
- local maxspeed_forward = parse_maxspeed(way.tags:Find( "maxspeed:forward"))
- local maxspeed_backward = parse_maxspeed(way.tags:Find( "maxspeed:backward"))
- local barrier = way.tags:Find("barrier")
- local oneway = way.tags:Find("oneway")
- local onewayClass = way.tags:Find("oneway:bicycle")
- local cycleway = way.tags:Find("cycleway")
- local cycleway_left = way.tags:Find("cycleway:left")
- local cycleway_right = way.tags:Find("cycleway:right")
- local duration = way.tags:Find("duration")
- local service = way.tags:Find("service")
- local area = way.tags:Find("area")
- local foot = way.tags:Find("foot")
- local surface = way.tags:Find("surface")
- local bicycle = way.tags:Find("bicycle")
+ local name = way:get_value_by_key("name")
+ local ref = way:get_value_by_key("ref")
+ local junction = way:get_value_by_key("junction")
+ local maxspeed = parse_maxspeed(way:get_value_by_key ( "maxspeed") )
+ local maxspeed_forward = parse_maxspeed(way:get_value_by_key( "maxspeed:forward"))
+ local maxspeed_backward = parse_maxspeed(way:get_value_by_key( "maxspeed:backward"))
+ local barrier = way:get_value_by_key("barrier")
+ local oneway = way:get_value_by_key("oneway")
+ local onewayClass = way:get_value_by_key("oneway:bicycle")
+ local cycleway = way:get_value_by_key("cycleway")
+ local cycleway_left = way:get_value_by_key("cycleway:left")
+ local cycleway_right = way:get_value_by_key("cycleway:right")
+ local duration = way:get_value_by_key("duration")
+ local service = way:get_value_by_key("service")
+ local area = way:get_value_by_key("area")
+ local foot = way:get_value_by_key("foot")
+ local surface = way:get_value_by_key("surface")
+ local bicycle = way:get_value_by_key("bicycle")
-- name
- if "" ~= ref and "" ~= name then
- way.name = name .. ' / ' .. ref
- elseif "" ~= ref then
- way.name = ref
- elseif "" ~= name then
- way.name = name
- else
+ if ref and "" ~= ref and name and "" ~= name then
+ result.name = name .. ' / ' .. ref
+ elseif ref and "" ~= ref then
+ result.name = ref
+ elseif name and "" ~= name then
+ result.name = name
+ elseif highway then
-- if no name exists, use way type
-- this encoding scheme is excepted to be a temporary solution
- way.name = "{highway:"..highway.."}"
+ result.name = "{highway:"..highway.."}"
end
-- roundabout handling
- if "roundabout" == junction then
- way.roundabout = true;
+ if junction and "roundabout" == junction then
+ result.roundabout = true;
end
-- speed
- if route_speeds[route] then
+ local bridge_speed = bridge_speeds[bridge]
+ if (bridge_speed and bridge_speed > 0) then
+ highway = bridge;
+ if duration and durationIsValid(duration) then
+ result.duration = math.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)
- way.forward_mode = mode_ferry
- way.backward_mode = mode_ferry
- way.ignore_in_grid = true
- if durationIsValid(duration) then
- way.duration = math.max( 1, parseDuration(duration) )
+ result.forward_mode = mode_ferry
+ result.backward_mode = mode_ferry
+ result.ignore_in_grid = true
+ if duration and durationIsValid(duration) then
+ result.duration = math.max( 1, parseDuration(duration) )
else
- way.forward_speed = route_speeds[route]
- way.backward_speed = route_speeds[route]
+ result.forward_speed = route_speeds[route]
+ result.backward_speed = route_speeds[route]
end
elseif railway and platform_speeds[railway] then
-- railway platforms (old tagging scheme)
- way.forward_speed = platform_speeds[railway]
- way.backward_speed = platform_speeds[railway]
+ result.forward_speed = platform_speeds[railway]
+ result.backward_speed = platform_speeds[railway]
elseif platform_speeds[public_transport] then
-- public_transport platforms (new tagging platform)
- way.forward_speed = platform_speeds[public_transport]
- way.backward_speed = platform_speeds[public_transport]
+ result.forward_speed = platform_speeds[public_transport]
+ result.backward_speed = platform_speeds[public_transport]
elseif railway and railway_speeds[railway] then
- way.forward_mode = mode_train
- way.backward_mode = mode_train
+ result.forward_mode = mode_train
+ result.backward_mode = mode_train
-- railways
if access and access_tag_whitelist[access] then
- way.forward_speed = railway_speeds[railway]
- way.backward_speed = railway_speeds[railway]
+ result.forward_speed = railway_speeds[railway]
+ result.backward_speed = railway_speeds[railway]
end
elseif amenity and amenity_speeds[amenity] then
-- parking areas
- way.forward_speed = amenity_speeds[amenity]
- way.backward_speed = amenity_speeds[amenity]
+ result.forward_speed = amenity_speeds[amenity]
+ result.backward_speed = amenity_speeds[amenity]
elseif bicycle_speeds[highway] then
-- regular ways
- way.forward_speed = bicycle_speeds[highway]
- way.backward_speed = bicycle_speeds[highway]
+ result.forward_speed = bicycle_speeds[highway]
+ result.backward_speed = bicycle_speeds[highway]
elseif access and access_tag_whitelist[access] then
-- unknown way, but valid access tag
- way.forward_speed = default_speed
- way.backward_speed = default_speed
+ result.forward_speed = default_speed
+ result.backward_speed = default_speed
else
-- biking not allowed, maybe we can push our bike?
-- essentially requires pedestrian profiling, for example foot=no mean we can't push a bike
if foot ~= 'no' and junction ~= "roundabout" then
if pedestrian_speeds[highway] then
-- pedestrian-only ways and areas
- way.forward_speed = pedestrian_speeds[highway]
- way.backward_speed = pedestrian_speeds[highway]
- way.forward_mode = mode_pushing
- way.backward_mode = mode_pushing
+ result.forward_speed = pedestrian_speeds[highway]
+ result.backward_speed = pedestrian_speeds[highway]
+ result.forward_mode = mode_pushing
+ result.backward_mode = mode_pushing
elseif man_made and man_made_speeds[man_made] then
-- man made structures
- way.forward_speed = man_made_speeds[man_made]
- way.backward_speed = man_made_speeds[man_made]
- way.forward_mode = mode_pushing
- way.backward_mode = mode_pushing
+ result.forward_speed = man_made_speeds[man_made]
+ result.backward_speed = man_made_speeds[man_made]
+ result.forward_mode = mode_pushing
+ result.backward_mode = mode_pushing
elseif foot == 'yes' then
- way.forward_speed = walking_speed
- way.backward_speed = walking_speed
- way.forward_mode = mode_pushing
- way.backward_mode = mode_pushing
+ result.forward_speed = walking_speed
+ result.backward_speed = walking_speed
+ result.forward_mode = mode_pushing
+ result.backward_mode = mode_pushing
elseif foot_forward == 'yes' then
- way.forward_speed = walking_speed
- way.forward_mode = mode_pushing
- way.backward_mode = 0
+ result.forward_speed = walking_speed
+ result.forward_mode = mode_pushing
+ result.backward_mode = 0
elseif foot_backward == 'yes' then
- way.forward_speed = walking_speed
- way.forward_mode = 0
- way.backward_mode = mode_pushing
+ result.forward_speed = walking_speed
+ result.forward_mode = 0
+ result.backward_mode = mode_pushing
end
end
end
@@ -300,84 +314,84 @@ function way_function (way)
end
if onewayClass == "yes" or onewayClass == "1" or onewayClass == "true" then
- way.backward_mode = 0
+ result.backward_mode = 0
elseif onewayClass == "no" or onewayClass == "0" or onewayClass == "false" then
-- prevent implied oneway
elseif onewayClass == "-1" then
- way.forward_mode = 0
+ result.forward_mode = 0
elseif oneway == "no" or oneway == "0" or oneway == "false" then
-- prevent implied oneway
elseif cycleway and string.find(cycleway, "opposite") == 1 then
if impliedOneway then
- way.forward_mode = 0
- way.backward_mode = mode_normal
- way.backward_speed = bicycle_speeds["cycleway"]
+ result.forward_mode = 0
+ result.backward_mode = mode_normal
+ result.backward_speed = bicycle_speeds["cycleway"]
end
elseif cycleway_left and cycleway_tags[cycleway_left] and cycleway_right and cycleway_tags[cycleway_right] then
-- prevent implied
elseif cycleway_left and cycleway_tags[cycleway_left] then
if impliedOneway then
- way.forward_mode = 0
- way.backward_mode = mode_normal
- way.backward_speed = bicycle_speeds["cycleway"]
+ result.forward_mode = 0
+ result.backward_mode = mode_normal
+ result.backward_speed = bicycle_speeds["cycleway"]
end
elseif cycleway_right and cycleway_tags[cycleway_right] then
if impliedOneway then
- way.forward_mode = mode_normal
- way.backward_speed = bicycle_speeds["cycleway"]
- way.backward_mode = 0
+ result.forward_mode = mode_normal
+ result.backward_speed = bicycle_speeds["cycleway"]
+ result.backward_mode = 0
end
elseif oneway == "-1" then
- way.forward_mode = 0
+ result.forward_mode = 0
elseif oneway == "yes" or oneway == "1" or oneway == "true" or impliedOneway then
- way.backward_mode = 0
+ result.backward_mode = 0
end
-- pushing bikes
if bicycle_speeds[highway] or pedestrian_speeds[highway] then
if foot ~= "no" and junction ~= "roundabout" then
- if way.backward_mode == 0 then
- way.backward_speed = walking_speed
- way.backward_mode = mode_pushing
- elseif way.forward_mode == 0 then
- way.forward_speed = walking_speed
- way.forward_mode = mode_pushing
+ if result.backward_mode == 0 then
+ result.backward_speed = walking_speed
+ result.backward_mode = mode_pushing
+ elseif result.forward_mode == 0 then
+ result.forward_speed = walking_speed
+ result.forward_mode = mode_pushing
end
end
end
-- cycleways
if cycleway and cycleway_tags[cycleway] then
- way.forward_speed = bicycle_speeds["cycleway"]
+ result.forward_speed = bicycle_speeds["cycleway"]
elseif cycleway_left and cycleway_tags[cycleway_left] then
- way.forward_speed = bicycle_speeds["cycleway"]
+ result.forward_speed = bicycle_speeds["cycleway"]
elseif cycleway_right and cycleway_tags[cycleway_right] then
- way.forward_speed = bicycle_speeds["cycleway"]
+ result.forward_speed = bicycle_speeds["cycleway"]
end
-- dismount
if bicycle == "dismount" then
- way.forward_mode = mode_pushing
- way.backward_mode = mode_pushing
- way.forward_speed = walking_speed
- way.backward_speed = walking_speed
+ result.forward_mode = mode_pushing
+ result.backward_mode = mode_pushing
+ result.forward_speed = walking_speed
+ result.backward_speed = walking_speed
end
-- surfaces
if surface then
surface_speed = surface_speeds[surface]
if surface_speed then
- if way.forward_speed > 0 then
- way.forward_speed = surface_speed
+ if result.forward_speed > 0 then
+ result.forward_speed = surface_speed
end
- if way.backward_speed > 0 then
- way.backward_speed = surface_speed
+ if result.backward_speed > 0 then
+ result.backward_speed = surface_speed
end
end
end
-- maxspeed
- MaxSpeed.limit( way, maxspeed, maxspeed_forward, maxspeed_backward )
+ MaxSpeed.limit( result, maxspeed, maxspeed_forward, maxspeed_backward )
end
function turn_function (angle)
diff --git a/3party/osrm/osrm-backend/profiles/car.lua b/3party/osrm/osrm-backend/profiles/car.lua
index ad58cd86ef..813afd19c4 100644..100755
--- a/3party/osrm/osrm-backend/profiles/car.lua
+++ b/3party/osrm/osrm-backend/profiles/car.lua
@@ -1,9 +1,9 @@
-- 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_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" }
@@ -28,6 +28,7 @@ speed_profile = {
["service"] = 15,
-- ["track"] = 5,
["ferry"] = 5,
+ ["movable"] = 5,
["shuttle_train"] = 10,
["default"] = 10
}
@@ -103,6 +104,9 @@ maxspeed_table_default = {
-- List only exceptions
maxspeed_table = {
+ ["ch:rural"] = 80,
+ ["ch:trunk"] = 100,
+ ["ch:motorway"] = 120,
["de:living_street"] = 7,
["ru:living_street"] = 20,
["ru:urban"] = 60,
@@ -124,11 +128,11 @@ maxspeed_table = {
}
traffic_signal_penalty = 2
+use_turn_restrictions = true
local take_minimum_of_speeds = false
local obey_oneway = true
local obey_bollards = true
-local use_turn_restrictions = true
local ignore_areas = true -- future feature
local u_turn_penalty = 20
@@ -141,16 +145,16 @@ 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)
+local function find_access_tag(source, access_tags_hierachy)
for i,v in ipairs(access_tags_hierachy) do
- local has_tag = source.tags:Holds(v)
- if has_tag then
- return source.tags:Find(v)
+ local access_tag = source:get_value_by_key(v)
+ if access_tag and "" ~= access_tag then
+ return access_tag
end
end
- return nil
+ return ""
end
function get_exceptions(vector)
@@ -191,69 +195,64 @@ end
-- return penalty
-- end
-function node_function (node)
- local access = find_access_tag(node, access_tags_hierachy)
-
- --flag node if it carries a traffic light
- if node.tags:Holds("highway") then
- if node.tags:Find("highway") == "traffic_signals" then
- node.traffic_light = true;
- end
- end
-
+function node_function (node, result)
-- parse access and barrier tags
- if access and access ~= "" then
+ local access = find_access_tag(node, access_tags_hierachy)
+ if access ~= "" then
if access_tag_blacklist[access] then
- node.bollard = true
+ result.barrier = true
end
- elseif node.tags:Holds("barrier") then
- local barrier = node.tags:Find("barrier")
- if barrier_whitelist[barrier] then
- return
- else
- node.bollard = true
+ else
+ local barrier = node:get_value_by_key("barrier")
+ if barrier and "" ~= barrier then
+ if not barrier_whitelist[barrier] then
+ result.barrier = true
+ end
end
end
-end
-function way_function (way)
+ -- check if node is a traffic light
+ local tag = node:get_value_by_key("highway")
+ if tag and "traffic_signals" == tag then
+ result.traffic_lights = true;
+ end
+end
- local is_highway = way.tags:Holds("highway")
- local is_route = way.tags:Holds("route")
+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 (is_highway or is_route) then
+ if not ((highway and highway ~= "") or (route and route ~= "") or (bridge and bridge ~= "")) then
return
end
-- we dont route over areas
- local is_area = way.tags:Holds("area")
- if ignore_areas and is_area then
- local area = way.tags:Find("area")
- if "yes" == area then
- return
- end
+ local area = way:get_value_by_key("area")
+ if ignore_areas and area and "yes" == area then
+ return
end
-- check if oneway tag is unsupported
- local oneway = way.tags:Find("oneway")
- if "reversible" == oneway then
+ local oneway = way:get_value_by_key("oneway")
+ if oneway and "reversible" == oneway then
return
end
- local is_impassable = way.tags:Holds("impassable")
- if is_impassable then
- local impassable = way.tags:Find("impassable")
- if "yes" == impassable then
- return
- end
+ local impassable = way:get_value_by_key("impassable")
+ if impassable and "yes" == impassable then
+ return
end
- local is_status = way.tags:Holds("status")
- if is_status then
- local status = way.tags:Find("status")
- if "impassable" == status then
- return
- end
+ local status = way:get_value_by_key("status")
+ if status and "impassable" == status then
+ 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*"))
end
-- Check if we are allowed to access the way
@@ -262,22 +261,33 @@ function way_function (way)
return
end
- -- Second, parse the way according to these properties
- local highway = way.tags:Find("highway")
- local route = way.tags:Find("route")
-
- -- 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.tags:Find("duration")
- if durationIsValid(duration) then
- way.duration = max( parseDuration(duration), 1 );
+ local duration = way:get_value_by_key("duration")
+ if duration and durationIsValid(duration) then
+ result.duration = max( parseDuration(duration), 1 );
end
- way.forward_mode = mode_ferry
- way.backward_mode = mode_ferry
- way.forward_speed = route_speed
- way.backward_speed = route_speed
+ result.forward_mode = mode_ferry
+ result.backward_mode = mode_ferry
+ result.forward_speed = route_speed
+ result.backward_speed = route_speed
+ end
+
+ -- handling movable bridges
+ local bridge_speed = speed_profile[bridge]
+ 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
+ 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
@@ -285,122 +295,136 @@ function way_function (way)
return
end
- if way.forward_speed == -1 then
+ if result.forward_speed == -1 then
local highway_speed = speed_profile[highway]
- local max_speed = parse_maxspeed( way.tags:Find("maxspeed") )
+ local max_speed = parse_maxspeed( way:get_value_by_key("maxspeed") )
-- Set the avg speed on the way if it is accessible by road class
if highway_speed then
- if max_speed > highway_speed then
- way.forward_speed = max_speed
- way.backward_speed = max_speed
+ if max_speed and max_speed > highway_speed then
+ result.forward_speed = max_speed
+ result.backward_speed = max_speed
-- max_speed = math.huge
else
- way.forward_speed = highway_speed
- way.backward_speed = highway_speed
+ result.forward_speed = highway_speed
+ result.backward_speed = highway_speed
end
else
-- Set the avg speed on ways that are marked accessible
if access_tag_whitelist[access] then
- way.forward_speed = speed_profile["default"]
- way.backward_speed = speed_profile["default"]
+ result.forward_speed = speed_profile["default"]
+ result.backward_speed = speed_profile["default"]
end
end
if 0 == max_speed then
max_speed = math.huge
end
- way.forward_speed = min(way.forward_speed, max_speed)
- way.backward_speed = min(way.backward_speed, max_speed)
+ result.forward_speed = min(result.forward_speed, max_speed)
+ result.backward_speed = min(result.backward_speed, max_speed)
end
- if -1 == way.forward_speed and -1 == way.backward_speed then
+ if -1 == result.forward_speed and -1 == result.backward_speed then
return
end
-- reduce speed on bad surfaces
- local surface = way.tags:Find("surface")
- local tracktype = way.tags:Find("tracktype")
- local smoothness = way.tags:Find("smoothness")
+ local surface = way:get_value_by_key("surface")
+ local tracktype = way:get_value_by_key("tracktype")
+ local smoothness = way:get_value_by_key("smoothness")
if surface and surface_speeds[surface] then
- way.forward_speed = math.min(surface_speeds[surface], way.forward_speed)
- way.backward_speed = math.min(surface_speeds[surface], way.backward_speed)
+ result.forward_speed = math.min(surface_speeds[surface], result.forward_speed)
+ result.backward_speed = math.min(surface_speeds[surface], result.backward_speed)
end
if tracktype and tracktype_speeds[tracktype] then
- way.forward_speed = math.min(tracktype_speeds[tracktype], way.forward_speed)
- way.backward_speed = math.min(tracktype_speeds[tracktype], way.backward_speed)
+ result.forward_speed = math.min(tracktype_speeds[tracktype], result.forward_speed)
+ result.backward_speed = math.min(tracktype_speeds[tracktype], result.backward_speed)
end
if smoothness and smoothness_speeds[smoothness] then
- way.forward_speed = math.min(smoothness_speeds[smoothness], way.forward_speed)
- way.backward_speed = math.min(smoothness_speeds[smoothness], way.backward_speed)
+ result.forward_speed = math.min(smoothness_speeds[smoothness], result.forward_speed)
+ result.backward_speed = math.min(smoothness_speeds[smoothness], result.backward_speed)
end
-- parse the remaining tags
- local name = way.tags:Find("name")
- local ref = way.tags:Find("ref")
- local junction = way.tags:Find("junction")
- -- local barrier = way.tags:Find("barrier")
- -- local cycleway = way.tags:Find("cycleway")
- local service = way.tags:Find("service")
+ local name = way:get_value_by_key("name")
+ local ref = way:get_value_by_key("ref")
+ local junction = way:get_value_by_key("junction")
+ -- local barrier = way:get_value_by_key("barrier", "")
+ -- local cycleway = way:get_value_by_key("cycleway", "")
+ local service = way:get_value_by_key("service")
-- Set the name that will be used for instructions
- if "" ~= ref then
- way.name = ref
- elseif "" ~= name then
- way.name = name
+ if ref and "" ~= ref then
+ result.name = ref
+ elseif name and "" ~= name then
+ result.name = name
-- else
- -- way.name = highway -- if no name exists, use way type
+ -- result.name = highway -- if no name exists, use way type
end
- if "roundabout" == junction then
- way.roundabout = true;
+ if junction and "roundabout" == junction then
+ result.roundabout = true;
end
-- Set access restriction flag if access is allowed under certain restrictions only
if access ~= "" and access_tag_restricted[access] then
- way.is_access_restricted = true
+ result.is_access_restricted = true
end
-- Set access restriction flag if service is allowed under certain restrictions only
- if service ~= "" and service_tag_restricted[service] then
- way.is_access_restricted = true
+ if service and service ~= "" and service_tag_restricted[service] then
+ result.is_access_restricted = true
end
-- Set direction according to tags on way
- if obey_oneway then
+ if obey_oneway then
if oneway == "-1" then
- way.forward_mode = 0
+ result.forward_mode = 0
elseif oneway == "yes" or
oneway == "1" or
oneway == "true" or
junction == "roundabout" or
(highway == "motorway_link" and oneway ~="no") or
(highway == "motorway" and oneway ~= "no") then
- way.backward_mode = 0
+ result.backward_mode = 0
end
end
-- Override speed settings if explicit forward/backward maxspeeds are given
- local maxspeed_forward = parse_maxspeed(way.tags:Find( "maxspeed:forward"))
- local maxspeed_backward = parse_maxspeed(way.tags:Find( "maxspeed:backward"))
- if maxspeed_forward > 0 then
- if 0 ~= way.forward_mode and 0 ~= way.backward_mode then
- way.backward_speed = way.forward_speed
+ local maxspeed_forward = parse_maxspeed(way:get_value_by_key( "maxspeed:forward"))
+ local maxspeed_backward = parse_maxspeed(way:get_value_by_key( "maxspeed:backward"))
+ if maxspeed_forward and maxspeed_forward > 0 then
+ if 0 ~= result.forward_mode and 0 ~= result.backward_mode then
+ result.backward_speed = result.forward_speed
end
- way.forward_speed = maxspeed_forward
+ result.forward_speed = maxspeed_forward
end
- if maxspeed_backward > 0 then
- way.backward_speed = maxspeed_backward
+ if maxspeed_backward and maxspeed_backward > 0 then
+ result.backward_speed = maxspeed_backward
end
-- Override general direction settings of there is a specific one for our mode of travel
if ignore_in_grid[highway] then
- way.ignore_in_grid = true
+ result.ignore_in_grid = true
end
+
-- scale speeds to get better avg driving times
- way.forward_speed = way.forward_speed * speed_reduction
- if way.backward_speed > 0 then
- way.backward_speed = way.backward_speed*speed_reduction
+ if result.forward_speed > 0 then
+ local scaled_speed = result.forward_speed*speed_reduction + 11;
+ local penalized_speed = math.huge
+ if width <= 3 then
+ penalized_speed = result.forward_speed / 2;
+ end
+ result.forward_speed = math.min(penalized_speed, scaled_speed)
+ end
+
+ if result.backward_speed > 0 then
+ local scaled_speed = result.backward_speed*speed_reduction + 11;
+ local penalized_speed = math.huge
+ if width <= 3 then
+ penalized_speed = result.backward_speed / 2;
+ end
+ result.backward_speed = math.min(penalized_speed, scaled_speed)
end
end
diff --git a/3party/osrm/osrm-backend/profiles/examples/postgis.lua b/3party/osrm/osrm-backend/profiles/examples/postgis.lua
index b02a43d8a5..6e32e4c7f0 100644..100755
--- a/3party/osrm/osrm-backend/profiles/examples/postgis.lua
+++ b/3party/osrm/osrm-backend/profiles/examples/postgis.lua
@@ -53,8 +53,8 @@ function way_function (way)
end
-- Query PostGIS for industrial areas close to the way, then group by way and sum the areas.
- -- We take the square root of the area to get a estimate of the length of the side of the area,
- -- and thus a rough guess of how far we might be travelling along the area.
+ -- We take the square root of the area to get a estimate of the length of the side of the area,
+ -- and thus a rough guess of how far we might be travelling along the area.
local sql_query = " " ..
"SELECT SUM(SQRT(area.area)) AS val " ..
@@ -67,16 +67,16 @@ function way_function (way)
local row = cursor:fetch( {}, "a" ) -- fetch first (and only) row
way.forward_speed = 20.0 -- default speed
if row then
- local val = tonumber(row.val) -- read 'val' from row
+ local val = tonumber(row.val) -- read 'val' from row
if val > 10 then
- way.forward_speed = way.forward_speed / math.log10( val ) -- reduce speed by amount of industry close by
+ way.forward_speed = way.forward_speed / math.log10( val ) -- reduce speed by amount of industry close by
end
end
cursor:close() -- done with this query
-- set other required info for this way
way.name = way.tags:Find("name")
- way.direction = Way.bidirectional
+ way.direction = Way.bidirectional
way.type = 1
return 1
end
diff --git a/3party/osrm/osrm-backend/profiles/foot.lua b/3party/osrm/osrm-backend/profiles/foot.lua
index 7c366bf119..5a370971a5 100644..100755
--- a/3party/osrm/osrm-backend/profiles/foot.lua
+++ b/3party/osrm/osrm-backend/profiles/foot.lua
@@ -73,42 +73,42 @@ function get_exceptions(vector)
end
end
-function node_function (node)
- local barrier = node.tags:Find ("barrier")
+function node_function (node, result)
+ local barrier = node:get_value_by_key("barrier")
local access = Access.find_access_tag(node, access_tags_hierachy)
- local traffic_signal = node.tags:Find("highway")
+ local traffic_signal = node:get_value_by_key("highway")
-- flag node if it carries a traffic light
- if traffic_signal == "traffic_signals" then
- node.traffic_light = true
+ if traffic_signal and traffic_signal == "traffic_signals" then
+ result.traffic_light = true
end
-- parse access and barrier tags
if access and access ~= "" then
if access_tag_blacklist[access] then
- node.bollard = true
+ result.barrier = true
else
- node.bollard = false
+ result.barrier = false
end
elseif barrier and barrier ~= "" then
if barrier_whitelist[barrier] then
- node.bollard = false
+ result.barrier = false
else
- node.bollard = true
+ result.barrier = true
end
end
return 1
end
-function way_function (way)
+function way_function (way, result)
-- initial routability check, filters out buildings, boundaries, etc
- local highway = way.tags:Find("highway")
- local route = way.tags:Find("route")
- local man_made = way.tags:Find("man_made")
- local railway = way.tags:Find("railway")
- local amenity = way.tags:Find("amenity")
- local public_transport = way.tags:Find("public_transport")
+ local highway = way:get_value_by_key("highway")
+ local route = way:get_value_by_key("route")
+ local man_made = way:get_value_by_key("man_made")
+ 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")
if (not highway or highway == '') and
(not route or route == '') and
(not railway or railway=='') and
@@ -130,82 +130,82 @@ function way_function (way)
return
end
- local name = way.tags:Find("name")
- local ref = way.tags:Find("ref")
- local junction = way.tags:Find("junction")
- local onewayClass = way.tags:Find("oneway:foot")
- local duration = way.tags:Find("duration")
- local service = way.tags:Find("service")
- local area = way.tags:Find("area")
- local foot = way.tags:Find("foot")
- local surface = way.tags:Find("surface")
-
- -- name
- if "" ~= ref and "" ~= name then
- way.name = name .. ' / ' .. ref
- elseif "" ~= ref then
- way.name = ref
- elseif "" ~= name then
- way.name = name
- else
- way.name = "{highway:"..highway.."}" -- if no name exists, use way type
+ local name = way:get_value_by_key("name")
+ local ref = way:get_value_by_key("ref")
+ local junction = way:get_value_by_key("junction")
+ local onewayClass = way:get_value_by_key("oneway:foot")
+ local duration = way:get_value_by_key("duration")
+ local service = way:get_value_by_key("service")
+ local area = way:get_value_by_key("area")
+ local foot = way:get_value_by_key("foot")
+ local surface = way:get_value_by_key("surface")
+
+ -- name
+ if ref and "" ~= ref and name and "" ~= name then
+ result.name = name .. ' / ' .. ref
+ elseif ref and "" ~= ref then
+ result.name = ref
+ elseif name and "" ~= name then
+ result.name = name
+ elseif highway then
+ result.name = "{highway:"..highway.."}" -- if no name exists, use way type
-- this encoding scheme is excepted to be a temporary solution
end
-- roundabouts
if "roundabout" == junction then
- way.roundabout = true;
+ result.roundabout = true;
end
-- speed
if route_speeds[route] then
-- ferries (doesn't cover routes tagged using relations)
- way.ignore_in_grid = true
- if durationIsValid(duration) then
- way.duration = math.max( 1, parseDuration(duration) )
+ result.ignore_in_grid = true
+ if duration and durationIsValid(duration) then
+ result.duration = math.max( 1, parseDuration(duration) )
else
- way.forward_speed = route_speeds[route]
- way.backward_speed = route_speeds[route]
+ result.forward_speed = route_speeds[route]
+ result.backward_speed = route_speeds[route]
end
- way.forward_mode = mode_ferry
- way.backward_mode = mode_ferry
+ result.forward_mode = mode_ferry
+ result.backward_mode = mode_ferry
elseif railway and platform_speeds[railway] then
-- railway platforms (old tagging scheme)
- way.forward_speed = platform_speeds[railway]
- way.backward_speed = platform_speeds[railway]
+ result.forward_speed = platform_speeds[railway]
+ result.backward_speed = platform_speeds[railway]
elseif platform_speeds[public_transport] then
-- public_transport platforms (new tagging platform)
- way.forward_speed = platform_speeds[public_transport]
- way.backward_speed = platform_speeds[public_transport]
+ result.forward_speed = platform_speeds[public_transport]
+ result.backward_speed = platform_speeds[public_transport]
elseif amenity and amenity_speeds[amenity] then
-- parking areas
- way.forward_speed = amenity_speeds[amenity]
- way.backward_speed = amenity_speeds[amenity]
+ result.forward_speed = amenity_speeds[amenity]
+ result.backward_speed = amenity_speeds[amenity]
elseif speeds[highway] then
-- regular ways
- way.forward_speed = speeds[highway]
- way.backward_speed = speeds[highway]
+ result.forward_speed = speeds[highway]
+ result.backward_speed = speeds[highway]
elseif access and access_tag_whitelist[access] then
-- unknown way, but valid access tag
- way.forward_speed = walking_speed
- way.backward_speed = walking_speed
+ result.forward_speed = walking_speed
+ result.backward_speed = walking_speed
end
-- oneway
if onewayClass == "yes" or onewayClass == "1" or onewayClass == "true" then
- way.backward_mode = 0
+ result.backward_mode = 0
elseif onewayClass == "no" or onewayClass == "0" or onewayClass == "false" then
-- nothing to do
elseif onewayClass == "-1" then
- way.forward_mode = 0
+ result.forward_mode = 0
end
-- surfaces
if surface then
surface_speed = surface_speeds[surface]
if surface_speed then
- way.forward_speed = math.min(way.forward_speed, surface_speed)
- way.backward_speed = math.min(way.backward_speed, surface_speed)
+ result.forward_speed = math.min(result.forward_speed, surface_speed)
+ result.backward_speed = math.min(result.backward_speed, surface_speed)
end
end
end
diff --git a/3party/osrm/osrm-backend/profiles/lib/access.lua b/3party/osrm/osrm-backend/profiles/lib/access.lua
index 094db62907..76d2e2c897 100644..100755
--- a/3party/osrm/osrm-backend/profiles/lib/access.lua
+++ b/3party/osrm/osrm-backend/profiles/lib/access.lua
@@ -4,10 +4,10 @@ module "Access"
function find_access_tag(source,access_tags_hierachy)
for i,v in ipairs(access_tags_hierachy) do
- local tag = source.tags:Find(v)
- if tag ~= '' then
+ local tag = source:get_value_by_key(v)
+ if tag and tag ~= '' then
return tag
end
end
return nil
-end \ No newline at end of file
+end
diff --git a/3party/osrm/osrm-backend/profiles/lib/maxspeed.lua b/3party/osrm/osrm-backend/profiles/lib/maxspeed.lua
index aca344a796..aca344a796 100644..100755
--- a/3party/osrm/osrm-backend/profiles/lib/maxspeed.lua
+++ b/3party/osrm/osrm-backend/profiles/lib/maxspeed.lua
diff --git a/3party/osrm/osrm-backend/profiles/testbot.lua b/3party/osrm/osrm-backend/profiles/testbot.lua
index a0b06f56d2..7bd1416352 100644..100755
--- a/3party/osrm/osrm-backend/profiles/testbot.lua
+++ b/3party/osrm/osrm-backend/profiles/testbot.lua
@@ -45,46 +45,47 @@ function limit_speed(speed, limits)
return speed
end
-function node_function (node)
- local traffic_signal = node.tags:Find("highway")
+function node_function (node, result)
+ local traffic_signal = node:get_value_by_key("highway")
- if traffic_signal == "traffic_signals" then
- node.traffic_light = true;
+ if traffic_signal and traffic_signal == "traffic_signals" then
+ result.traffic_lights = true;
-- TODO: a way to set the penalty value
end
- return 1
end
-function way_function (way)
- local highway = way.tags:Find("highway")
- local name = way.tags:Find("name")
- local oneway = way.tags:Find("oneway")
- local route = way.tags:Find("route")
- local duration = way.tags:Find("duration")
- local maxspeed = tonumber(way.tags:Find ( "maxspeed"))
- local maxspeed_forward = tonumber(way.tags:Find( "maxspeed:forward"))
- local maxspeed_backward = tonumber(way.tags:Find( "maxspeed:backward"))
- local junction = way.tags:Find("junction")
-
- way.name = name
-
- if route ~= nil and durationIsValid(duration) then
- way.duration = math.max( 1, parseDuration(duration) )
- way.forward_mode = 2
- way.backward_mode = 2
+function way_function (way, result)
+ local highway = way:get_value_by_key("highway")
+ local name = way:get_value_by_key("name")
+ local oneway = way:get_value_by_key("oneway")
+ local route = way:get_value_by_key("route")
+ local duration = way:get_value_by_key("duration")
+ local maxspeed = tonumber(way:get_value_by_key ( "maxspeed"))
+ local maxspeed_forward = tonumber(way:get_value_by_key( "maxspeed:forward"))
+ local maxspeed_backward = tonumber(way:get_value_by_key( "maxspeed:backward"))
+ local junction = way:get_value_by_key("junction")
+
+ if name then
+ result.name = name
+ end
+
+ if duration and durationIsValid(duration) then
+ result.duration = math.max( 1, parseDuration(duration) )
+ result.forward_mode = 2
+ result.backward_mode = 2
else
local speed_forw = speed_profile[highway] or speed_profile['default']
local speed_back = speed_forw
if highway == "river" then
local temp_speed = speed_forw;
- way.forward_mode = 3
- way.backward_mode = 4
+ result.forward_mode = 3
+ result.backward_mode = 4
speed_forw = temp_speed*1.5
speed_back = temp_speed/1.5
elseif highway == "steps" then
- way.forward_mode = 5
- way.backward_mode = 6
+ result.forward_mode = 5
+ result.backward_mode = 6
end
if maxspeed_forward ~= nil and maxspeed_forward > 0 then
@@ -103,19 +104,19 @@ function way_function (way)
end
end
- way.forward_speed = speed_forw
- way.backward_speed = speed_back
+ result.forward_speed = speed_forw
+ result.backward_speed = speed_back
end
if oneway == "no" or oneway == "0" or oneway == "false" then
-- nothing to do
elseif oneway == "-1" then
- way.forward_mode = 0
+ result.forward_mode = 0
elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" then
- way.backward_mode = 0
+ result.backward_mode = 0
end
if junction == 'roundabout' then
- way.roundabout = true
+ result.roundabout = true
end
end
diff --git a/3party/osrm/osrm-backend/profiles/turnbot.lua b/3party/osrm/osrm-backend/profiles/turnbot.lua
index 4427ab7ddb..1a96966f13 100644..100755
--- a/3party/osrm/osrm-backend/profiles/turnbot.lua
+++ b/3party/osrm/osrm-backend/profiles/turnbot.lua
@@ -4,5 +4,5 @@
require 'testbot'
function turn_function (angle)
- return 200*math.abs(angle)/180 -- penalty
+ return 200*math.abs(angle)/180 -- penalty
end
diff --git a/3party/osrm/osrm-backend/routed.cpp b/3party/osrm/osrm-backend/routed.cpp
index a7ba54ab5f..8b0e2e88bf 100644..100755
--- a/3party/osrm/osrm-backend/routed.cpp
+++ b/3party/osrm/osrm-backend/routed.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,12 +25,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "Library/OSRM.h"
-#include "Server/Server.h"
-#include "Util/GitDescription.h"
-#include "Util/ProgramOptions.h"
-#include "Util/simple_logger.hpp"
-#include "Util/FingerPrint.h"
+#include "library/osrm.hpp"
+#include "server/server.hpp"
+#include "util/git_sha.hpp"
+#include "util/routed_options.hpp"
+#include "util/simple_logger.hpp"
#ifdef __linux__
#include <sys/mman.h>
@@ -41,7 +40,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <signal.h>
#include <chrono>
-#include <functional>
#include <future>
#include <iostream>
#include <thread>
@@ -71,20 +69,16 @@ 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;
- ServerPaths server_paths;
+ libosrm_config lib_config;
- const unsigned init_result = GenerateServerProgramOptions(argc,
- argv,
- server_paths,
- ip_address,
- ip_port,
- requested_thread_num,
- use_shared_memory,
- trial_run);
+ 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.max_locations_map_matching);
if (init_result == INIT_OK_DO_NOT_START_ENGINE)
{
return 0;
@@ -103,7 +97,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";
}
@@ -119,9 +113,8 @@ int main(int argc, const char *argv[])
pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask);
#endif
- OSRM osrm_lib(server_paths, use_shared_memory);
- auto routing_server =
- Server::CreateServer(ip_address, ip_port, requested_thread_num);
+ OSRM osrm_lib(lib_config);
+ auto routing_server = Server::CreateServer(ip_address, ip_port, requested_thread_num);
routing_server->GetRequestHandlerPtr().RegisterRoutingMachine(&osrm_lib);
@@ -131,7 +124,11 @@ int main(int argc, const char *argv[])
}
else
{
- std::packaged_task<int()> server_task([&]()->int{ routing_server->Run(); return 0; });
+ std::packaged_task<int()> server_task([&]() -> int
+ {
+ routing_server->Run();
+ return 0;
+ });
auto future = server_task.get_future();
std::thread server_thread(std::move(server_task));
@@ -160,7 +157,7 @@ int main(int argc, const char *argv[])
if (status == std::future_status::ready)
{
- server_thread.join();
+ server_thread.join();
}
else
{
diff --git a/3party/osrm/osrm-backend/RoutingAlgorithms/AlternativePathRouting.h b/3party/osrm/osrm-backend/routing_algorithms/alternative_path.hpp
index 83875f3d04..1dcc02096f 100644..100755
--- a/3party/osrm/osrm-backend/RoutingAlgorithms/AlternativePathRouting.h
+++ b/3party/osrm/osrm-backend/routing_algorithms/alternative_path.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,13 +25,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ALTERNATIVE_PATH_ROUTING_H
-#define ALTERNATIVE_PATH_ROUTING_H
+#ifndef ALTERNATIVE_PATH_ROUTING_HPP
+#define ALTERNATIVE_PATH_ROUTING_HPP
-#include "BasicRoutingInterface.h"
-#include "../DataStructures/Range.h"
-#include "../DataStructures/SearchEngineData.h"
-#include "../Util/container.hpp"
+#include "routing_base.hpp"
+#include "../data_structures/search_engine_data.hpp"
+#include "../util/integer_range.hpp"
+#include "../util/container.hpp"
#include <boost/assert.hpp>
@@ -44,9 +44,11 @@ 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 DataFacadeT> class AlternativeRouting final : private BasicRoutingInterface<DataFacadeT>
+template <class DataFacadeT>
+class AlternativeRouting final
+ : private BasicRoutingInterface<DataFacadeT, AlternativeRouting<DataFacadeT>>
{
- using super = BasicRoutingInterface<DataFacadeT>;
+ using super = BasicRoutingInterface<DataFacadeT, AlternativeRouting<DataFacadeT>>;
using EdgeData = typename DataFacadeT::EdgeData;
using QueryHeap = SearchEngineData::QueryHeap;
using SearchSpaceEdge = std::pair<NodeID, NodeID>;
@@ -78,7 +80,7 @@ template <class DataFacadeT> 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<NodeID> alternative_path;
std::vector<NodeID> via_node_candidate_list;
@@ -93,17 +95,16 @@ template <class DataFacadeT> class AlternativeRouting final : private BasicRouti
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;
- 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)
{
@@ -148,22 +149,16 @@ template <class DataFacadeT> class AlternativeRouting final : private BasicRouti
{
if (0 < forward_heap1.Size())
{
- AlternativeRoutingStep<true>(forward_heap1,
- reverse_heap1,
- &middle_node,
+ AlternativeRoutingStep<true>(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<false>(reverse_heap1,
- forward_heap1,
- &middle_node,
+ AlternativeRoutingStep<false>(forward_heap1, reverse_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 DataFacadeT> class AlternativeRouting final : private BasicRouti
std::vector<NodeID> &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<RankedCandidateNode> 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<int>(upper_bound_to_shortest_path_distance * VIAPATH_GAMMA);
if (sharing_of_via_path <= maximum_allowed_sharing &&
@@ -302,16 +294,10 @@ template <class DataFacadeT> 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 DataFacadeT> class AlternativeRouting final : private BasicRouti
{
std::vector<NodeID> 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 DataFacadeT> 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;
}
@@ -370,13 +351,13 @@ template <class DataFacadeT> class AlternativeRouting final : private BasicRouti
private:
// unpack alternate <s,..,v,..,t> 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<NodeID> &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<NodeID> &packed_path) const
{
// fetch packed path [s,v)
std::vector<NodeID> packed_v_t_path;
@@ -384,8 +365,8 @@ template <class DataFacadeT> 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());
}
@@ -394,19 +375,19 @@ template <class DataFacadeT> class AlternativeRouting final : private BasicRouti
// compute and unpack <s,..,v> and <v,..,t> 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<NodeID> &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<NodeID> &packed_shortest_path,
+ const EdgeWeight min_edge_offset)
{
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<NodeID> packed_s_v_path;
std::vector<NodeID> packed_v_t_path;
@@ -420,12 +401,8 @@ template <class DataFacadeT> class AlternativeRouting final : private BasicRouti
// compute path <s,..,v> 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 <v,..,t> by reusing backward search from node t
NodeID v_t_middle = SPECIAL_NODEID;
@@ -433,12 +410,8 @@ template <class DataFacadeT> 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 DataFacadeT> 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 DataFacadeT> 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 DataFacadeT> 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);
@@ -551,7 +522,7 @@ template <class DataFacadeT> class AlternativeRouting final : private BasicRouti
// variable
}
- // inline int approximateAmountOfSharing(
+ // int approximateAmountOfSharing(
// const NodeID alternate_path_middle_node_id,
// QueryHeap & forward_heap,
// QueryHeap & reverse_heap,
@@ -598,14 +569,17 @@ template <class DataFacadeT> class AlternativeRouting final : private BasicRouti
// todo: reorder parameters
template <bool is_forward_directed>
- inline void AlternativeRoutingStep(QueryHeap &forward_heap,
- QueryHeap &reverse_heap,
- NodeID *middle_node,
- int *upper_bound_to_shortest_path_distance,
- std::vector<NodeID> &search_space_intersection,
- std::vector<SearchSpaceEdge> &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<NodeID> &search_space_intersection,
+ std::vector<SearchSpaceEdge> &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;
@@ -674,16 +648,16 @@ template <class DataFacadeT> class AlternativeRouting final : private BasicRouti
}
// 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();
@@ -696,12 +670,8 @@ template <class DataFacadeT> 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 +685,8 @@ template <class DataFacadeT> 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 +697,11 @@ template <class DataFacadeT> 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 +781,7 @@ template <class DataFacadeT> 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<unsigned>(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]);
@@ -876,8 +841,8 @@ template <class DataFacadeT> class AlternativeRouting final : private BasicRouti
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;
@@ -888,17 +853,17 @@ template <class DataFacadeT> 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);
}
};
-#endif /* ALTERNATIVE_PATH_ROUTING_H */
+#endif /* ALTERNATIVE_PATH_ROUTING_HPP */
diff --git a/3party/osrm/osrm-backend/RoutingAlgorithms/ManyToManyRouting.h b/3party/osrm/osrm-backend/routing_algorithms/many_to_many.hpp
index ab73150738..2388804718 100644..100755
--- a/3party/osrm/osrm-backend/RoutingAlgorithms/ManyToManyRouting.h
+++ b/3party/osrm/osrm-backend/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,
@@ -25,11 +25,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef MANY_TO_MANY_ROUTING_H
-#define MANY_TO_MANY_ROUTING_H
+#ifndef MANY_TO_MANY_ROUTING_HPP
+#define MANY_TO_MANY_ROUTING_HPP
-#include "BasicRoutingInterface.h"
-#include "../DataStructures/SearchEngineData.h"
+#include "routing_base.hpp"
+#include "../data_structures/search_engine_data.hpp"
#include "../typedefs.h"
#include <boost/assert.hpp>
@@ -39,9 +39,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <unordered_map>
#include <vector>
-template <class DataFacadeT> class ManyToManyRouting final : public BasicRoutingInterface<DataFacadeT>
+template <class DataFacadeT>
+class ManyToManyRouting final
+ : public BasicRoutingInterface<DataFacadeT, ManyToManyRouting<DataFacadeT>>
{
- using super = BasicRoutingInterface<DataFacadeT>;
+ using super = BasicRoutingInterface<DataFacadeT, ManyToManyRouting<DataFacadeT>>;
using QueryHeap = SearchEngineData::QueryHeap;
SearchEngineData &engine_working_data;
@@ -64,10 +66,10 @@ template <class DataFacadeT> class ManyToManyRouting final : public BasicRouting
~ManyToManyRouting() {}
- std::shared_ptr<std::vector<EdgeWeight>> operator()(const PhantomNodeArray &phantom_nodes_array)
- const
+ std::shared_ptr<std::vector<EdgeWeight>>
+ operator()(const PhantomNodeArray &phantom_nodes_array) const
{
- const unsigned number_of_locations = static_cast<unsigned>(phantom_nodes_array.size());
+ const auto number_of_locations = phantom_nodes_array.size();
std::shared_ptr<std::vector<EdgeWeight>> result_table =
std::make_shared<std::vector<EdgeWeight>>(number_of_locations * number_of_locations,
std::numeric_limits<EdgeWeight>::max());
@@ -75,7 +77,7 @@ template <class DataFacadeT> class ManyToManyRouting final : public BasicRouting
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;
@@ -134,11 +136,8 @@ template <class DataFacadeT> 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;
@@ -209,7 +208,7 @@ template <class DataFacadeT> class ManyToManyRouting final : public BasicRouting
{
for (auto edge : super::facade->GetAdjacentEdgeRange(node))
{
- const auto &data = super::facade->GetEdgeData(edge, node);
+ const auto &data = super::facade->GetEdgeData(edge);
const bool direction_flag = (forward_direction ? data.forward : data.backward);
if (direction_flag)
{
@@ -237,12 +236,12 @@ template <class DataFacadeT> class ManyToManyRouting final : public BasicRouting
// Stalling
template <bool forward_direction>
- 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))
{
- const auto &data = super::facade->GetEdgeData(edge, node);
+ const auto &data = super::facade->GetEdgeData(edge);
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
if (reverse_flag)
{
diff --git a/3party/osrm/osrm-backend/routing_algorithms/map_matching.hpp b/3party/osrm/osrm-backend/routing_algorithms/map_matching.hpp
new file mode 100755
index 0000000000..737494b64d
--- /dev/null
+++ b/3party/osrm/osrm-backend/routing_algorithms/map_matching.hpp
@@ -0,0 +1,344 @@
+/*
+
+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 MAP_MATCHING_HPP
+#define MAP_MATCHING_HPP
+
+#include "routing_base.hpp"
+
+#include "../data_structures/coordinate_calculation.hpp"
+#include "../data_structures/hidden_markov_model.hpp"
+#include "../util/json_logger.hpp"
+#include "../util/matching_debug_info.hpp"
+
+#include <variant/variant.hpp>
+
+#include <algorithm>
+#include <iomanip>
+#include <numeric>
+
+namespace osrm
+{
+namespace matching
+{
+
+struct SubMatching
+{
+ std::vector<PhantomNode> nodes;
+ std::vector<unsigned> indices;
+ double length;
+ double confidence;
+};
+
+using CandidateList = std::vector<std::pair<PhantomNode, double>>;
+using CandidateLists = std::vector<CandidateList>;
+using HMM = HiddenMarkovModel<CandidateLists>;
+using SubMatchingList = std::vector<SubMatching>;
+
+constexpr static const unsigned MAX_BROKEN_STATES = 6;
+constexpr static const unsigned MAX_BROKEN_TIME = 60;
+
+constexpr static const unsigned MAX_DISTANCE_DELTA = 200;
+constexpr static const unsigned SUSPICIOUS_DISTANCE_DELTA = 100;
+
+constexpr static const double default_beta = 5.0;
+constexpr static const double default_sigma_z = 4.07;
+}
+}
+
+// implements a hidden markov model map matching algorithm
+template <class DataFacadeT>
+class MapMatching final : public BasicRoutingInterface<DataFacadeT, MapMatching<DataFacadeT>>
+{
+ using super = BasicRoutingInterface<DataFacadeT, MapMatching<DataFacadeT>>;
+ using QueryHeap = SearchEngineData::QueryHeap;
+ SearchEngineData &engine_working_data;
+
+ public:
+ MapMatching(DataFacadeT *facade, SearchEngineData &engine_working_data)
+ : super(facade), engine_working_data(engine_working_data)
+ {
+ }
+
+ void operator()(const osrm::matching::CandidateLists &candidates_list,
+ const std::vector<FixedPointCoordinate> &trace_coordinates,
+ const std::vector<unsigned> &trace_timestamps,
+ const double matching_beta,
+ const double gps_precision,
+ osrm::matching::SubMatchingList &sub_matchings) const
+ {
+ BOOST_ASSERT(!candidates_list.empty() && !trace_coordinates.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);
+ TransitionLogProbability transition_log_probability(
+ matching_beta > 0. ? matching_beta : osrm::matching::default_beta);
+
+ osrm::matching::HMM model(candidates_list, emission_log_probability);
+
+ std::size_t initial_timestamp = model.initialize(0);
+ if (initial_timestamp == osrm::matching::INVALID_STATE)
+ {
+ return;
+ }
+
+ MatchingDebugInfo matching_debug(osrm::json::Logger::get());
+ matching_debug.initialize(candidates_list);
+
+ std::size_t breakage_begin = osrm::matching::INVALID_STATE;
+ std::vector<std::size_t> split_points;
+ std::vector<std::size_t> 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)
+ {
+ // breakage recover has removed all previous good points
+ bool trace_split = prev_unbroken_timestamps.empty();
+
+ // use temporal information if available to determine a split
+ if (!trace_timestamps.empty())
+ {
+ trace_split =
+ trace_split ||
+ (trace_timestamps[t] - trace_timestamps[prev_unbroken_timestamps.back()] >
+ osrm::matching::MAX_BROKEN_TIME);
+ }
+ else
+ {
+ trace_split = trace_split || (t - prev_unbroken_timestamps.back() >
+ osrm::matching::MAX_BROKEN_STATES);
+ }
+
+ if (trace_split)
+ {
+ std::size_t split_index = t;
+ if (breakage_begin != osrm::matching::INVALID_STATE)
+ {
+ split_index = breakage_begin;
+ breakage_begin = osrm::matching::INVALID_STATE;
+ }
+ split_points.push_back(split_index);
+
+ // note: this preserves everything before split_index
+ model.clear(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!
+ // However since t > new_start >= breakge_begin
+ // we can only reset trace_coordindates.size() times.
+ t = new_start + 1;
+ }
+
+ BOOST_ASSERT(!prev_unbroken_timestamps.empty());
+ const std::size_t 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];
+
+ auto &current_viterbi = model.viterbi[t];
+ auto &current_pruned = model.pruned[t];
+ auto &current_suspicious = model.suspicious[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];
+
+ 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);
+
+ // compute d_t for this timestamp and the next one
+ for (const auto s : osrm::irange<std::size_t>(0u, prev_viterbi.size()))
+ {
+ if (prev_pruned[s])
+ {
+ continue;
+ }
+
+ for (const auto s_prime : osrm::irange<std::size_t>(0u, current_viterbi.size()))
+ {
+ // how likely is candidate s_prime at time t to be emitted?
+ const double emission_pr =
+ 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;
+ }
+
+ forward_heap.Clear();
+ reverse_heap.Clear();
+
+ // get distance diff between loc1/2 and locs/s_prime
+ 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);
+
+ const auto d_t = std::abs(network_distance - great_circle_distance);
+
+ // very low probability transition -> prune
+ if (d_t > osrm::matching::MAX_DISTANCE_DELTA)
+ {
+ continue;
+ }
+
+ const double transition_pr = transition_log_probability(d_t);
+ new_value += transition_pr;
+
+ matching_debug.add_transition_info(prev_unbroken_timestamp, t, s, s_prime,
+ prev_viterbi[s], emission_pr, transition_pr,
+ network_distance, great_circle_distance);
+
+ if (new_value > current_viterbi[s_prime])
+ {
+ current_viterbi[s_prime] = new_value;
+ current_parents[s_prime] = std::make_pair(prev_unbroken_timestamp, s);
+ current_lengths[s_prime] = network_distance;
+ current_pruned[s_prime] = false;
+ current_suspicious[s_prime] = d_t > osrm::matching::SUSPICIOUS_DISTANCE_DELTA;
+ model.breakage[t] = false;
+ }
+ }
+ }
+
+ if (model.breakage[t])
+ {
+ // 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();
+ }
+ else
+ {
+ prev_unbroken_timestamps.push_back(t);
+ }
+ }
+
+ matching_debug.set_viterbi(model.viterbi, model.pruned, model.suspicious);
+
+ if (!prev_unbroken_timestamps.empty())
+ {
+ split_points.push_back(prev_unbroken_timestamps.back() + 1);
+ }
+
+ std::size_t sub_matching_begin = initial_timestamp;
+ for (const auto sub_matching_end : split_points)
+ {
+ osrm::matching::SubMatching matching;
+
+ // find real end of trace
+ // not sure if this is really needed
+ std::size_t 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 (parent_timestamp_index - sub_matching_begin + 1 < 2)
+ {
+ sub_matching_begin = sub_matching_end;
+ continue;
+ }
+
+ // loop through the columns, and only compare the last entry
+ const auto max_element_iter =
+ std::max_element(model.viterbi[parent_timestamp_index].begin(),
+ model.viterbi[parent_timestamp_index].end());
+
+ std::size_t parent_candidate_index =
+ std::distance(model.viterbi[parent_timestamp_index].begin(), max_element_iter);
+
+ std::deque<std::pair<std::size_t, std::size_t>> reconstructed_indices;
+ while (parent_timestamp_index > sub_matching_begin)
+ {
+ if (model.breakage[parent_timestamp_index])
+ {
+ continue;
+ }
+
+ reconstructed_indices.emplace_front(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;
+ }
+ reconstructed_indices.emplace_front(parent_timestamp_index, parent_candidate_index);
+ if (reconstructed_indices.size() < 2)
+ {
+ sub_matching_begin = sub_matching_end;
+ continue;
+ }
+
+ matching.length = 0.0f;
+ matching.nodes.resize(reconstructed_indices.size());
+ matching.indices.resize(reconstructed_indices.size());
+ for (const auto i : osrm::irange<std::size_t>(0u, reconstructed_indices.size()))
+ {
+ 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;
+ matching.length += model.path_lengths[timestamp_index][location_index];
+
+ matching_debug.add_chosen(timestamp_index, location_index);
+ }
+
+ sub_matchings.push_back(matching);
+ sub_matching_begin = sub_matching_end;
+ }
+ matching_debug.add_breakage(model.breakage);
+ }
+};
+
+//[1] "Hidden Markov Map Matching Through Noise and Sparseness"; P. Newson and J. Krumm; 2009; ACM
+// GIS
+
+#endif /* MAP_MATCHING_HPP */
diff --git a/3party/osrm/osrm-backend/routing_algorithms/routing_base.hpp b/3party/osrm/osrm-backend/routing_algorithms/routing_base.hpp
new file mode 100755
index 0000000000..52c16a77ee
--- /dev/null
+++ b/3party/osrm/osrm-backend/routing_algorithms/routing_base.hpp
@@ -0,0 +1,494 @@
+/*
+
+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 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"
+// #include "../util/simple_logger.hpp"
+
+#include <boost/assert.hpp>
+
+#include <stack>
+
+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 DataFacadeT, class Derived> class BasicRoutingInterface
+{
+ private:
+ using EdgeData = typename DataFacadeT::EdgeData;
+
+ protected:
+ DataFacadeT *facade;
+
+ public:
+ BasicRoutingInterface() = delete;
+ BasicRoutingInterface(const BasicRoutingInterface &) = delete;
+ explicit BasicRoutingInterface(DataFacadeT *facade) : facade(facade) {}
+ ~BasicRoutingInterface() {}
+
+ 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);
+
+ // const NodeID parentnode = forward_heap.GetData(node).parent;
+ // SimpleLogger().Write() << (forward_direction ? "[fwd] " : "[rev] ") << "settled edge ("
+ // << parentnode << "," << node << "), dist: " << distance;
+
+ if (reverse_heap.WasInserted(node))
+ {
+ const int new_distance = reverse_heap.GetKey(node) + distance;
+ if (new_distance < *upper_bound)
+ {
+ if (new_distance >= 0)
+ {
+ *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;
+ }
+ }
+ }
+
+ if (distance + min_edge_offset > *upper_bound)
+ {
+ // SimpleLogger().Write() << "min_edge_offset: " << min_edge_offset;
+ forward_heap.DeleteAll();
+ return;
+ }
+
+ // Stalling
+ for (const auto edge : facade->GetAdjacentEdgeRange(node))
+ {
+ const EdgeData &data = facade->GetEdgeData(edge);
+ const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
+ if (reverse_flag)
+ {
+ const NodeID to = facade->GetTarget(edge);
+ const int edge_weight = data.distance;
+
+ BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
+
+ if (forward_heap.WasInserted(to))
+ {
+ if (forward_heap.GetKey(to) + edge_weight < distance)
+ {
+ return;
+ }
+ }
+ }
+ }
+
+ for (const auto edge : facade->GetAdjacentEdgeRange(node))
+ {
+ const EdgeData &data = facade->GetEdgeData(edge);
+ bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
+ if (forward_directionFlag)
+ {
+
+ const NodeID to = facade->GetTarget(edge);
+ const int edge_weight = data.distance;
+
+ BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
+ const int to_distance = distance + edge_weight;
+
+ // New Node discovered -> Add to Heap + Node Info Storage
+ if (!forward_heap.WasInserted(to))
+ {
+ forward_heap.Insert(to, to_distance, node);
+ }
+ // Found a shorter Path -> Update distance
+ else if (to_distance < forward_heap.GetKey(to))
+ {
+ // new parent
+ forward_heap.GetData(to).parent = node;
+ forward_heap.DecreaseKey(to, to_distance);
+ }
+ }
+ }
+ }
+
+ void UnpackPath(const std::vector<NodeID> &packed_path,
+ const PhantomNodes &phantom_node_pair,
+ std::vector<PathData> &unpacked_path) const
+ {
+ const bool start_traversed_in_reverse =
+ (packed_path.front() != phantom_node_pair.source_phantom.forward_node_id);
+ const bool target_traversed_in_reverse =
+ (packed_path.back() != phantom_node_pair.target_phantom.forward_node_id);
+
+ const unsigned packed_path_size = static_cast<unsigned>(packed_path.size());
+ std::stack<std::pair<NodeID, NodeID>> recursion_stack;
+
+ // We have to push the path in reverse order onto the stack because it's LIFO.
+ for (unsigned i = packed_path_size - 1; i > 0; --i)
+ {
+ recursion_stack.emplace(packed_path[i - 1], packed_path[i]);
+ }
+
+ std::pair<NodeID, NodeID> edge;
+ while (!recursion_stack.empty())
+ {
+ /*
+ Graphical representation of variables:
+
+ edge.first edge.second
+ *------------------>*
+ edge_id
+ */
+ edge = recursion_stack.top();
+ recursion_stack.pop();
+
+ // facade->FindEdge does not suffice here in case of shortcuts.
+ // The above explanation unclear? Think!
+ EdgeID smaller_edge_id = SPECIAL_EDGEID;
+ int edge_weight = std::numeric_limits<EdgeWeight>::max();
+ for (const auto edge_id : facade->GetAdjacentEdgeRange(edge.first))
+ {
+ const int weight = facade->GetEdgeData(edge_id).distance;
+ if ((facade->GetTarget(edge_id) == edge.second) && (weight < edge_weight) &&
+ facade->GetEdgeData(edge_id).forward)
+ {
+ smaller_edge_id = edge_id;
+ edge_weight = weight;
+ }
+ }
+
+ /*
+ Graphical representation of variables:
+
+ edge.first edge.second
+ *<------------------*
+ edge_id
+ */
+ if (SPECIAL_EDGEID == smaller_edge_id)
+ {
+ for (const auto edge_id : facade->GetAdjacentEdgeRange(edge.second))
+ {
+ const int weight = facade->GetEdgeData(edge_id).distance;
+ if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) &&
+ facade->GetEdgeData(edge_id).backward)
+ {
+ smaller_edge_id = edge_id;
+ edge_weight = weight;
+ }
+ }
+ }
+ BOOST_ASSERT_MSG(edge_weight != INVALID_EDGE_WEIGHT, "edge id invalid");
+
+ const EdgeData &ed = facade->GetEdgeData(smaller_edge_id);
+ if (ed.shortcut)
+ { // unpack
+ const NodeID middle_node_id = ed.id;
+ // again, we need to this in reversed order
+ recursion_stack.emplace(middle_node_id, edge.second);
+ recursion_stack.emplace(edge.first, middle_node_id);
+ }
+ else
+ {
+ BOOST_ASSERT_MSG(!ed.shortcut, "original edge flagged as shortcut");
+ unsigned name_index = facade->GetNameIndexFromEdgeID(ed.id);
+ 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);
+ }
+ else
+ {
+ std::vector<unsigned> id_vector;
+ facade->GetUncompressedGeometry(facade->GetGeometryIndexForEdgeID(ed.id),
+ id_vector);
+
+ const std::size_t start_index =
+ (unpacked_path.empty()
+ ? ((start_traversed_in_reverse)
+ ? id_vector.size() -
+ phantom_node_pair.source_phantom.fwd_segment_position - 1
+ : phantom_node_pair.source_phantom.fwd_segment_position)
+ : 0);
+ const std::size_t end_index = id_vector.size();
+
+ BOOST_ASSERT(start_index >= 0);
+ 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.back().turn_instruction = turn_instruction;
+ unpacked_path.back().segment_duration = ed.distance;
+ }
+ }
+ }
+ if (SPECIAL_EDGEID != phantom_node_pair.target_phantom.packed_geometry_id)
+ {
+ std::vector<unsigned> id_vector;
+ facade->GetUncompressedGeometry(phantom_node_pair.target_phantom.packed_geometry_id,
+ id_vector);
+ const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id ==
+ phantom_node_pair.target_phantom.packed_geometry_id) &&
+ unpacked_path.empty();
+
+ std::size_t start_index = 0;
+ if (is_local_path)
+ {
+ start_index = phantom_node_pair.source_phantom.fwd_segment_position;
+ if (target_traversed_in_reverse)
+ {
+ start_index =
+ id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position;
+ }
+ }
+
+ std::size_t end_index = phantom_node_pair.target_phantom.fwd_segment_position;
+ if (target_traversed_in_reverse)
+ {
+ std::reverse(id_vector.begin(), id_vector.end());
+ end_index =
+ id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
+ }
+
+ if (start_index > end_index)
+ {
+ 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});
+ }
+ }
+
+ // there is no equivalent to a node-based node in an edge-expanded graph.
+ // two equivalent routes may start (or end) at different node-based edges
+ // as they are added with the offset how much "distance" on the edge
+ // has already been traversed. Depending on offset one needs to remove
+ // the last node.
+ if (unpacked_path.size() > 1)
+ {
+ const std::size_t last_index = unpacked_path.size() - 1;
+ const std::size_t second_to_last_index = last_index - 1;
+
+ // looks like a trivially true check but tests for underflow
+ BOOST_ASSERT(last_index > second_to_last_index);
+
+ if (unpacked_path[last_index].node == unpacked_path[second_to_last_index].node)
+ {
+ unpacked_path.pop_back();
+ }
+ BOOST_ASSERT(!unpacked_path.empty());
+ }
+ }
+
+ void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> &unpacked_path) const
+ {
+ std::stack<std::pair<NodeID, NodeID>> recursion_stack;
+ recursion_stack.emplace(s, t);
+
+ std::pair<NodeID, NodeID> edge;
+ while (!recursion_stack.empty())
+ {
+ edge = recursion_stack.top();
+ recursion_stack.pop();
+
+ EdgeID smaller_edge_id = SPECIAL_EDGEID;
+ int edge_weight = std::numeric_limits<EdgeWeight>::max();
+ for (const auto edge_id : facade->GetAdjacentEdgeRange(edge.first))
+ {
+ const int weight = facade->GetEdgeData(edge_id).distance;
+ if ((facade->GetTarget(edge_id) == edge.second) && (weight < edge_weight) &&
+ facade->GetEdgeData(edge_id).forward)
+ {
+ smaller_edge_id = edge_id;
+ edge_weight = weight;
+ }
+ }
+
+ if (SPECIAL_EDGEID == smaller_edge_id)
+ {
+ for (const auto edge_id : facade->GetAdjacentEdgeRange(edge.second))
+ {
+ const int weight = facade->GetEdgeData(edge_id).distance;
+ if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) &&
+ facade->GetEdgeData(edge_id).backward)
+ {
+ smaller_edge_id = edge_id;
+ edge_weight = weight;
+ }
+ }
+ }
+ BOOST_ASSERT_MSG(edge_weight != std::numeric_limits<EdgeWeight>::max(),
+ "edge weight invalid");
+
+ const EdgeData &ed = facade->GetEdgeData(smaller_edge_id);
+ if (ed.shortcut)
+ { // unpack
+ const NodeID middle_node_id = ed.id;
+ // again, we need to this in reversed order
+ recursion_stack.emplace(middle_node_id, edge.second);
+ recursion_stack.emplace(edge.first, middle_node_id);
+ }
+ else
+ {
+ BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut");
+ unpacked_path.emplace_back(edge.first);
+ }
+ }
+ unpacked_path.emplace_back(t);
+ }
+
+ void RetrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap,
+ const SearchEngineData::QueryHeap &reverse_heap,
+ const NodeID middle_node_id,
+ std::vector<NodeID> &packed_path) const
+ {
+ RetrievePackedPathFromSingleHeap(forward_heap, middle_node_id, packed_path);
+ std::reverse(packed_path.begin(), packed_path.end());
+ packed_path.emplace_back(middle_node_id);
+ RetrievePackedPathFromSingleHeap(reverse_heap, middle_node_id, packed_path);
+ }
+
+ void RetrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap,
+ const NodeID middle_node_id,
+ std::vector<NodeID> &packed_path) const
+ {
+ NodeID current_node_id = middle_node_id;
+ while (current_node_id != search_heap.GetData(current_node_id).parent)
+ {
+ current_node_id = search_heap.GetData(current_node_id).parent;
+ 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<double>::max();
+ if (upper_bound != INVALID_EDGE_WEIGHT)
+ {
+ std::vector<NodeID> packed_leg;
+ RetrievePackedPathFromHeap(forward_heap, reverse_heap, middle_node, packed_leg);
+ std::vector<PathData> 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
diff --git a/3party/osrm/osrm-backend/RoutingAlgorithms/ShortestPathRouting.h b/3party/osrm/osrm-backend/routing_algorithms/shortest_path.hpp
index 4670eedf57..3dedc2b76a 100644..100755
--- a/3party/osrm/osrm-backend/RoutingAlgorithms/ShortestPathRouting.h
+++ b/3party/osrm/osrm-backend/routing_algorithms/shortest_path.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,19 +25,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SHORTEST_PATH_ROUTING_H
-#define SHORTEST_PATH_ROUTING_H
+#ifndef SHORTEST_PATH_HPP
+#define SHORTEST_PATH_HPP
#include <boost/assert.hpp>
-#include "BasicRoutingInterface.h"
-#include "../DataStructures/Range.h"
-#include "../DataStructures/SearchEngineData.h"
+#include "routing_base.hpp"
+#include "../data_structures/search_engine_data.hpp"
+#include "../util/integer_range.hpp"
#include "../typedefs.h"
-template <class DataFacadeT> class ShortestPathRouting final : public BasicRoutingInterface<DataFacadeT>
+template <class DataFacadeT>
+class ShortestPathRouting final
+ : public BasicRoutingInterface<DataFacadeT, ShortestPathRouting<DataFacadeT>>
{
- using super = BasicRoutingInterface<DataFacadeT>;
+ using super = BasicRoutingInterface<DataFacadeT, ShortestPathRouting<DataFacadeT>>;
using QueryHeap = SearchEngineData::QueryHeap;
SearchEngineData &engine_working_data;
@@ -51,7 +53,7 @@ template <class DataFacadeT> class ShortestPathRouting final : public BasicRouti
void operator()(const std::vector<PhantomNodes> &phantom_nodes_vector,
const std::vector<bool> &uturn_indicators,
- RawRouteData &raw_route_data) const
+ InternalRouteResult &raw_route_data) const
{
int distance1 = 0;
int distance2 = 0;
@@ -69,10 +71,10 @@ template <class DataFacadeT> class ShortestPathRouting final : public BasicRouti
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.
@@ -88,8 +90,11 @@ template <class DataFacadeT> 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];
- EdgeWeight min_edge_offset = 0;
+ const bool allow_u_turn = current_leg > 0 && uturn_indicators.size() > current_leg &&
+ uturn_indicators[current_leg - 1];
+ 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) &&
@@ -97,35 +102,32 @@ template <class DataFacadeT> 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(),
+ -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();
+ // SimpleLogger().Write(logDEBUG) << "fwd-a2 insert: " <<
+ // 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();
-
+ // SimpleLogger().Write(logDEBUG) << "fwd-b2 insert: " <<
+ // 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();
+ // SimpleLogger().Write(logDEBUG) << "fwd-a2 insert: " <<
+ // 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();
+ // SimpleLogger().Write(logDEBUG) << "fwd-b2 insert: " <<
+ // phantom_node_pair.source_phantom.reverse_node_id << ", w: " << -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset();
}
// insert new backward nodes into backward heap, unadjusted.
@@ -134,17 +136,17 @@ template <class DataFacadeT> 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 +154,13 @@ template <class DataFacadeT> 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 +170,13 @@ template <class DataFacadeT> 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,29 +202,31 @@ template <class DataFacadeT> 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<NodeID> temporary_packed_leg1;
std::vector<NodeID> 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)
{
- 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 +234,8 @@ template <class DataFacadeT> 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,8 +292,9 @@ template <class DataFacadeT> 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()) &&
- phantom_node_pair.target_phantom.isBidirected())
+ 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();
search_from_1st_node &=
@@ -298,8 +304,8 @@ template <class DataFacadeT> class ShortestPathRouting final : public BasicRouti
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;
}
@@ -324,12 +330,14 @@ template <class DataFacadeT> 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);
}
};
-#endif /* SHORTEST_PATH_ROUTING_H */
+#endif /* SHORTEST_PATH_HPP */
diff --git a/3party/osrm/osrm-backend/server/api_grammar.hpp b/3party/osrm/osrm-backend/server/api_grammar.hpp
new file mode 100755
index 0000000000..a629cfbf7b
--- /dev/null
+++ b/3party/osrm/osrm-backend/server/api_grammar.hpp
@@ -0,0 +1,101 @@
+/*
+
+Copyright (c) 2013, 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 API_GRAMMAR_HPP
+#define API_GRAMMAR_HPP
+
+#include <boost/bind.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+
+namespace qi = boost::spirit::qi;
+
+template <typename Iterator, class HandlerT> struct APIGrammar : qi::grammar<Iterator>
+{
+ 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 | timestamp | u | cmp |
+ 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)];
+ 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)];
+ 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") >> '=' >>
+ 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)];
+ 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_.-"));
+ 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<Iterator> api_call, query;
+ qi::rule<Iterator, std::string()> service, zoom, output, string, jsonp, checksum, location,
+ hint, timestamp, stringwithDot, stringwithPercent, language, instruction, geometry, cmp, alt_route, u,
+ uturns, old_API, num_results, matching_beta, gps_precision, classify;
+
+ HandlerT *handler;
+};
+
+#endif /* API_GRAMMAR_HPP */
diff --git a/3party/osrm/osrm-backend/Server/Connection.cpp b/3party/osrm/osrm-backend/server/connection.cpp
index 674fe62a5b..41b653e824 100644..100755
--- a/3party/osrm/osrm-backend/Server/Connection.cpp
+++ b/3party/osrm/osrm-backend/server/connection.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -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 <boost/assert.hpp>
#include <boost/bind.hpp>
@@ -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)));
}
@@ -66,19 +65,17 @@ 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) =
- request_parser.Parse(request,
- incoming_data_buffer.data(),
- incoming_data_buffer.data() + bytes_transferred,
- &compression_type);
+ compression_type compression_type(no_compression);
+ osrm::tribool result;
+ std::tie(result, compression_type) =
+ request_parser.parse(current_request, incoming_data_buffer.data(),
+ incoming_data_buffer.data() + bytes_transferred);
// 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);
+ current_request.endpoint = TCP_socket.remote_endpoint().address();
+ request_handler.handle_request(current_request, current_reply);
// Header compression_header;
std::vector<char> compressed_output;
@@ -87,52 +84,51 @@ 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"});
- CompressBufferCollection(reply.content, compression_type, compressed_output);
- reply.SetSize(static_cast<unsigned>(compressed_output.size()));
- output_buffer = reply.HeaderstoBuffers();
+ 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<unsigned>(compressed_output.size()));
+ output_buffer = current_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"});
- CompressBufferCollection(reply.content, compression_type, compressed_output);
- reply.SetSize(static_cast<unsigned>(compressed_output.size()));
- output_buffer = reply.HeaderstoBuffers();
+ 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<unsigned>(compressed_output.size()));
+ output_buffer = current_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();
+ 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)));
+ 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)
+ else if (result == osrm::tribool::no)
{ // request is not parseable
- reply = Reply::StockReply(Reply::badRequest);
+ current_reply = reply::stock_reply(reply::bad_request);
- 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, 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(),
+ strand.wrap(boost::bind(&Connection::handle_read, this->shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)));
}
@@ -149,26 +145,27 @@ void Connection::handle_write(const boost::system::error_code &error)
}
}
-void Connection::CompressBufferCollection(std::vector<char> uncompressed_data,
- CompressionType compression_type,
- std::vector<char> &compressed_data)
+std::vector<char> Connection::compress_buffers(const std::vector<char> &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 (deflateRFC1951 == compression_type)
+ if (deflate_rfc1951 == compression_type)
{
compression_parameters.noheader = true;
}
- BOOST_ASSERT(compressed_data.empty());
+ std::vector<char> 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/3party/osrm/osrm-backend/Server/Connection.h b/3party/osrm/osrm-backend/server/connection.hpp
index bc03c15884..9228a18a00 100644..100755
--- a/3party/osrm/osrm-backend/Server/Connection.h
+++ b/3party/osrm/osrm-backend/server/connection.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,45 +25,34 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef CONNECTION_H
-#define CONNECTION_H
+#ifndef CONNECTION_HPP
+#define CONNECTION_HPP
-#include "RequestParser.h"
-#include "Http/CompressionType.h"
-#include "Http/Request.h"
-
-#include <osrm/Reply.h>
+#include "http/compression_type.hpp"
+#include "http/reply.hpp"
+#include "http/request.hpp"
+#include "request_parser.hpp"
#include <boost/array.hpp>
#include <boost/asio.hpp>
#include <boost/config.hpp>
#include <boost/version.hpp>
- #include <memory>
- #include <string>
- #include <vector>
+#include <memory>
+#include <vector>
-//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<class T>
-const T* get_pointer(std::shared_ptr<T> const& p)
+namespace boost
{
- return p.get();
-}
+template <class T> const T *get_pointer(std::shared_ptr<T> const &p) { return p.get(); }
-template<class T>
-T* get_pointer(std::shared_ptr<T>& p)
-{
- return p.get();
-}
+template <class T> T *get_pointer(std::shared_ptr<T> &p) { return p.get(); }
} // namespace boost
#endif
-
-
class RequestHandler;
namespace http
@@ -88,19 +77,18 @@ class Connection : public std::enable_shared_from_this<Connection>
/// Handle completion of a write operation.
void handle_write(const boost::system::error_code &e);
- void CompressBufferCollection(std::vector<char> uncompressed_data,
- CompressionType compression_type,
- std::vector<char> &compressed_data);
+ std::vector<char> compress_buffers(const std::vector<char> &uncompressed_data,
+ const compression_type compression_type);
boost::asio::io_service::strand strand;
boost::asio::ip::tcp::socket TCP_socket;
RequestHandler &request_handler;
- boost::array<char, 8192> incoming_data_buffer;
- Request request;
RequestParser request_parser;
- Reply reply;
+ boost::array<char, 8192> incoming_data_buffer;
+ request current_request;
+ reply current_reply;
};
} // namespace http
-#endif // CONNECTION_H
+#endif // CONNECTION_HPP
diff --git a/3party/osrm/osrm-backend/Server/DataStructures/BaseDataFacade.h b/3party/osrm/osrm-backend/server/data_structures/datafacade_base.hpp
index b7a46083e3..20d0430576 100644..100755
--- a/3party/osrm/osrm-backend/Server/DataStructures/BaseDataFacade.h
+++ b/3party/osrm/osrm-backend/server/data_structures/datafacade_base.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,31 +25,31 @@ 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
-#include "../../DataStructures/EdgeBasedNode.h"
-#include "../../DataStructures/ImportNode.h"
-#include "../../DataStructures/PhantomNodes.h"
-#include "../../DataStructures/Range.h"
-#include "../../DataStructures/TurnInstructions.h"
-#include "../../Util/OSRMException.h"
-#include "../../Util/StringUtil.h"
+#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/osrm/Coordinate.h"
+#include <osrm/coordinate.hpp>
#include <string>
-typedef osrm::range<EdgeID> EdgeRange;
+using EdgeRange = osrm::range<EdgeID>;
template <class EdgeDataT> class BaseDataFacade
{
public:
- typedef EdgeBasedNode RTreeLeaf;
- typedef EdgeDataT EdgeData;
+ using RTreeLeaf = EdgeBasedNode;
+ using EdgeData = EdgeDataT;
BaseDataFacade() {}
virtual ~BaseDataFacade() {}
@@ -62,15 +62,7 @@ template <class EdgeDataT> class BaseDataFacade
virtual NodeID GetTarget(const EdgeID e) const = 0;
- //virtual EdgeDataT &GetEdgeData(const EdgeID e, NodeID node) { static EdgeDataT edge; return edge; }
-
- virtual EdgeDataT &GetEdgeData(const EdgeID e) const = 0;
-
- virtual EdgeDataT GetEdgeData(const EdgeID e, NodeID node)
- {
- EdgeDataT edge;
- return edge;
- }
+ virtual const EdgeDataT &GetEdgeData(const EdgeID e) const = 0;
virtual EdgeID BeginEdges(const NodeID n) const = 0;
@@ -104,30 +96,28 @@ template <class EdgeDataT> class BaseDataFacade
FixedPointCoordinate &result,
const unsigned zoom_level = 18) = 0;
- virtual bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
- PhantomNode &resulting_phantom_node,
- const unsigned zoom_level) = 0;
-
virtual bool
IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
std::vector<PhantomNode> &resulting_phantom_node_vector,
- const unsigned zoom_level,
const unsigned number_of_results) = 0;
+ virtual bool
+ IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
+ PhantomNode &resulting_phantom_node) = 0;
+ virtual bool IncrementalFindPhantomNodeForCoordinateWithMaxDistance(
+ const FixedPointCoordinate &input_coordinate,
+ std::vector<std::pair<PhantomNode, double>> &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;
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;
};
-#endif // BASE_DATA_FACADE_H
+#endif // DATAFACADE_BASE_HPP
diff --git a/3party/osrm/osrm-backend/Server/DataStructures/InternalDataFacade.h b/3party/osrm/osrm-backend/server/data_structures/internal_datafacade.hpp
index 93c212d004..823ac3329b 100644..100755
--- a/3party/osrm/osrm-backend/Server/DataStructures/InternalDataFacade.h
+++ b/3party/osrm/osrm-backend/server/data_structures/internal_datafacade.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,35 +25,37 @@ 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 "../../DataStructures/OriginalEdgeData.h"
-#include "../../DataStructures/QueryNode.h"
-#include "../../DataStructures/QueryEdge.h"
-#include "../../DataStructures/SharedMemoryVectorWrapper.h"
-#include "../../DataStructures/StaticGraph.h"
-#include "../../DataStructures/StaticRTree.h"
-#include "../../DataStructures/RangeTable.h"
-#include "../../Util/BoostFileSystemFix.h"
-#include "../../Util/GraphLoader.h"
-#include "../../Util/ProgramOptions.h"
-#include "../../Util/simple_logger.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 <osrm/Coordinate.h>
+#include <osrm/coordinate.hpp>
+#include <osrm/server_paths.hpp>
-template <class EdgeDataT> class InternalDataFacade : public BaseDataFacade<EdgeDataT>
+#include <limits>
+
+template <class EdgeDataT> class InternalDataFacade final : public BaseDataFacade<EdgeDataT>
{
private:
- typedef BaseDataFacade<EdgeDataT> super;
- typedef StaticGraph<typename super::EdgeData> QueryGraph;
- typedef typename QueryGraph::InputEdge InputEdge;
- typedef typename super::RTreeLeaf RTreeLeaf;
+ using super = BaseDataFacade<EdgeDataT>;
+ using QueryGraph = StaticGraph<typename super::EdgeData>;
+ using InputEdge = typename QueryGraph::InputEdge;
+ using RTreeLeaf = typename super::RTreeLeaf;
InternalDataFacade() {}
@@ -126,14 +128,14 @@ template <class EdgeDataT> class InternalDataFacade : public BaseDataFacade<Edge
{
boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary);
- NodeInfo current_node;
+ QueryNode current_node;
unsigned number_of_coordinates = 0;
nodes_input_stream.read((char *)&number_of_coordinates, sizeof(unsigned));
m_coordinate_list =
std::make_shared<std::vector<FixedPointCoordinate>>(number_of_coordinates);
for (unsigned i = 0; i < number_of_coordinates; ++i)
{
- nodes_input_stream.read((char *)&current_node, sizeof(NodeInfo));
+ nodes_input_stream.read((char *)&current_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);
@@ -235,31 +237,31 @@ template <class EdgeDataT> class InternalDataFacade : public BaseDataFacade<Edge
// generate paths of data files
if (server_paths.find("hsgrdata") == server_paths.end())
{
- throw OSRMException("no hsgr file given in ini file");
+ throw osrm::exception("no hsgr file given in ini file");
}
if (server_paths.find("ramindex") == server_paths.end())
{
- throw OSRMException("no ram index file given in ini file");
+ throw osrm::exception("no ram index file given in ini file");
}
if (server_paths.find("fileindex") == server_paths.end())
{
- throw OSRMException("no leaf index file given in ini file");
+ throw osrm::exception("no leaf index file given in ini file");
}
if (server_paths.find("geometries") == server_paths.end())
{
- throw OSRMException("no geometries file given in ini file");
+ throw osrm::exception("no geometries file given in ini file");
}
if (server_paths.find("nodesdata") == server_paths.end())
{
- throw OSRMException("no nodes file given in ini file");
+ throw osrm::exception("no nodes file given in ini file");
}
if (server_paths.find("edgesdata") == server_paths.end())
{
- throw OSRMException("no edges file given in ini file");
+ throw osrm::exception("no edges file given in ini file");
}
if (server_paths.find("namesdata") == server_paths.end())
{
- throw OSRMException("no names file given in ini file");
+ throw osrm::exception("no names file given in ini file");
}
ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata");
@@ -309,92 +311,101 @@ template <class EdgeDataT> class InternalDataFacade : public BaseDataFacade<Edge
}
// search graph access
- unsigned GetNumberOfNodes() const final { return m_query_graph->GetNumberOfNodes(); }
-
- unsigned GetNumberOfEdges() const final { return m_query_graph->GetNumberOfEdges(); }
+ unsigned GetNumberOfNodes() const override final { return m_query_graph->GetNumberOfNodes(); }
- unsigned GetOutDegree(const NodeID n) const final { return m_query_graph->GetOutDegree(n); }
+ unsigned GetNumberOfEdges() const override final { return m_query_graph->GetNumberOfEdges(); }
- NodeID GetTarget(const EdgeID e) const final { return m_query_graph->GetTarget(e); }
+ unsigned GetOutDegree(const NodeID n) const override final
+ {
+ return m_query_graph->GetOutDegree(n);
+ }
- // EdgeDataT &GetEdgeData(const EdgeID e) final { return m_query_graph->GetEdgeData(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 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); }
+ bool EdgeIsCompressed(const unsigned id) const override final
+ {
+ 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);
}
- TravelMode GetTravelModeForEdgeID(const unsigned id) const
+ TravelMode GetTravelModeForEdgeID(const unsigned id) const override final
{
- return m_travel_mode_list.at(id);
+ return m_travel_mode_list.at(id);
}
bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
FixedPointCoordinate &result,
- const unsigned zoom_level = 18) final
+ const unsigned zoom_level = 18) override final
{
if (!m_static_rtree.get())
{
LoadRTree();
}
- return m_static_rtree->LocateClosestEndPointForCoordinate(
- input_coordinate, result, zoom_level);
+ return m_static_rtree->LocateClosestEndPointForCoordinate(input_coordinate, result,
+ zoom_level);
}
- bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
- PhantomNode &resulting_phantom_node,
- const unsigned zoom_level) final
+ bool IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
+ PhantomNode &resulting_phantom_node) override final
{
- if (!m_static_rtree.get())
+ std::vector<PhantomNode> resulting_phantom_node_vector;
+ auto result = IncrementalFindPhantomNodeForCoordinate(input_coordinate,
+ resulting_phantom_node_vector, 1);
+ if (result)
{
- LoadRTree();
+ BOOST_ASSERT(!resulting_phantom_node_vector.empty());
+ resulting_phantom_node = resulting_phantom_node_vector.front();
}
- return m_static_rtree->FindPhantomNodeForCoordinate(
- input_coordinate, resulting_phantom_node, zoom_level);
+ return result;
}
bool
IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
std::vector<PhantomNode> &resulting_phantom_node_vector,
- const unsigned zoom_level,
- const unsigned number_of_results) final
+ const unsigned number_of_results) override final
{
if (!m_static_rtree.get())
{
@@ -402,52 +413,69 @@ template <class EdgeDataT> class InternalDataFacade : public BaseDataFacade<Edge
}
return m_static_rtree->IncrementalFindPhantomNodeForCoordinate(
- input_coordinate, resulting_phantom_node_vector, zoom_level, number_of_results);
+ input_coordinate, resulting_phantom_node_vector, number_of_results);
}
- unsigned GetCheckSum() const final { return m_check_sum; }
+ bool IncrementalFindPhantomNodeForCoordinateWithMaxDistance(
+ const FixedPointCoordinate &input_coordinate,
+ std::vector<std::pair<PhantomNode, double>> &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())
+ {
+ LoadRTree();
+ }
- unsigned GetNameIndexFromEdgeID(const unsigned id) const final
+ return m_static_rtree->IncrementalFindPhantomNodeForCoordinateWithDistance(
+ 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; }
+
+ 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 final
+ std::string get_name_for_id(const unsigned name_id) const override final
{
- if (UINT_MAX == name_id)
+ if (std::numeric_limits<unsigned>::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());
+ m_names_char_list.begin() + range.back() + 1, result.begin());
}
+ return result;
}
- virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const final
+ virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const override final
{
return m_via_node_list.at(id);
}
virtual void GetUncompressedGeometry(const unsigned id,
- std::vector<unsigned> &result_nodes) const final
+ std::vector<unsigned> &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);
+ result_nodes.insert(result_nodes.begin(), m_geometry_list.begin() + begin,
+ m_geometry_list.begin() + end);
}
- std::string GetTimestamp() const final { return m_timestamp; }
+ std::string GetTimestamp() const override final { return m_timestamp; }
};
-#endif // INTERNAL_DATA_FACADE
+#endif // INTERNAL_DATAFACADE_HPP
diff --git a/3party/osrm/osrm-backend/Server/DataStructures/SharedBarriers.h b/3party/osrm/osrm-backend/server/data_structures/shared_barriers.hpp
index 36ba08b1f7..e6f1234ca8 100644..100755
--- a/3party/osrm/osrm-backend/Server/DataStructures/SharedBarriers.h
+++ b/3party/osrm/osrm-backend/server/data_structures/shared_barriers.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SHARED_BARRIER_H
-#define SHARED_BARRIER_H
+#ifndef SHARED_BARRIERS_HPP
+#define SHARED_BARRIERS_HPP
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/sync/named_condition.hpp>
@@ -57,4 +57,4 @@ struct SharedBarriers
int number_of_queries;
};
-#endif // SHARED_BARRIER_H
+#endif // SHARED_BARRIERS_HPP
diff --git a/3party/osrm/osrm-backend/Server/DataStructures/SharedDataFacade.h b/3party/osrm/osrm-backend/server/data_structures/shared_datafacade.hpp
index 835a50f273..b156423160 100644..100755
--- a/3party/osrm/osrm-backend/Server/DataStructures/SharedDataFacade.h
+++ b/3party/osrm/osrm-backend/server/data_structures/shared_datafacade.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,37 +25,37 @@ 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 "../../DataStructures/RangeTable.h"
-#include "../../DataStructures/StaticGraph.h"
-#include "../../DataStructures/StaticRTree.h"
-#include "../../Util/BoostFileSystemFix.h"
-#include "../../Util/ProgramOptions.h"
-#include "../../Util/make_unique.hpp"
-#include "../../Util/simple_logger.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 <algorithm>
+#include <limits>
#include <memory>
-template <class EdgeDataT> class SharedDataFacade : public BaseDataFacade<EdgeDataT>
+template <class EdgeDataT> class SharedDataFacade final : public BaseDataFacade<EdgeDataT>
{
private:
- typedef EdgeDataT EdgeData;
- typedef BaseDataFacade<EdgeData> super;
- typedef StaticGraph<EdgeData, true> QueryGraph;
- typedef typename StaticGraph<EdgeData, true>::NodeArrayEntry GraphNode;
- typedef typename StaticGraph<EdgeData, true>::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<EdgeData>;
+ using QueryGraph = StaticGraph<EdgeData, true>;
+ using GraphNode = typename StaticGraph<EdgeData, true>::NodeArrayEntry;
+ using GraphEdge = typename StaticGraph<EdgeData, true>::EdgeArrayEntry;
+ using NameIndexBlock = typename RangeTable<16, true>::BlockT;
+ using InputEdge = typename QueryGraph::InputEdge;
+ using RTreeLeaf = typename super::RTreeLeaf;
using SharedRTree = StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>;
using TimeStampedRTreePair = std::pair<unsigned, std::shared_ptr<SharedRTree>>;
using RTreeNode = typename SharedRTree::TreeNode;
@@ -113,12 +113,11 @@ template <class EdgeDataT> class SharedDataFacade : public BaseDataFacade<EdgeDa
RTreeNode *tree_ptr =
data_layout->GetBlockPtr<RTreeNode>(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<SharedRTree>(
- 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()
@@ -144,11 +143,10 @@ template <class EdgeDataT> class SharedDataFacade : public BaseDataFacade<EdgeDa
m_coordinate_list = osrm::make_unique<ShM<FixedPointCoordinate, true>::vector>(
coordinate_list_ptr, data_layout->num_entries[SharedDataLayout::COORDINATE_LIST]);
- TravelMode *travel_mode_list_ptr = data_layout->GetBlockPtr<TravelMode>(
- shared_memory, SharedDataLayout::TRAVEL_MODE);
+ TravelMode *travel_mode_list_ptr =
+ data_layout->GetBlockPtr<TravelMode>(shared_memory, SharedDataLayout::TRAVEL_MODE);
typename ShM<TravelMode, true>::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<TurnInstruction>(
@@ -259,8 +257,8 @@ template <class EdgeDataT> class SharedDataFacade : public BaseDataFacade<EdgeDa
if (!boost::filesystem::exists(file_index_path))
{
SimpleLogger().Write(logDEBUG) << "Leaf file name " << file_index_path.string();
- throw OSRMException("Could not load leaf index file."
- "Is any data loaded into shared memory?");
+ throw osrm::exception("Could not load leaf index file."
+ "Is any data loaded into shared memory?");
}
LoadGraph();
@@ -276,7 +274,7 @@ template <class EdgeDataT> class SharedDataFacade : public BaseDataFacade<EdgeDa
SimpleLogger().Write() << "number of geometries: " << m_coordinate_list->size();
for (unsigned i = 0; i < m_coordinate_list->size(); ++i)
{
- if (!GetCoordinateOfNode(i).isValid())
+ if (!GetCoordinateOfNode(i).is_valid())
{
SimpleLogger().Write() << "coordinate " << i << " not valid";
}
@@ -285,109 +283,117 @@ template <class EdgeDataT> class SharedDataFacade : public BaseDataFacade<EdgeDa
}
// search graph access
- unsigned GetNumberOfNodes() const final { return m_query_graph->GetNumberOfNodes(); }
+ 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<unsigned> &result_nodes) const final
+ std::vector<unsigned> &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);
+ result_nodes.insert(result_nodes.begin(), m_geometry_list.begin() + begin,
+ m_geometry_list.begin() + end);
}
- virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const final
+ virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const override final
{
return m_via_node_list.at(id);
}
- TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const final
+ TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const override final
{
return m_turn_instruction_list.at(id);
}
- TravelMode GetTravelModeForEdgeID(const unsigned id) const
+ TravelMode GetTravelModeForEdgeID(const unsigned id) const override final
{
return m_travel_mode_list.at(id);
}
bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
FixedPointCoordinate &result,
- const unsigned zoom_level = 18) final
+ 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);
+ return m_static_rtree->second->LocateClosestEndPointForCoordinate(input_coordinate, result,
+ zoom_level);
}
- bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
- PhantomNode &resulting_phantom_node,
- const unsigned zoom_level) final
+ bool IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
+ PhantomNode &resulting_phantom_node) override final
{
- if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
+ std::vector<PhantomNode> resulting_phantom_node_vector;
+ auto result = IncrementalFindPhantomNodeForCoordinate(input_coordinate,
+ resulting_phantom_node_vector, 1);
+ if (result)
{
- LoadRTree();
+ BOOST_ASSERT(!resulting_phantom_node_vector.empty());
+ resulting_phantom_node = resulting_phantom_node_vector.front();
}
- return m_static_rtree->second->FindPhantomNodeForCoordinate(
- input_coordinate, resulting_phantom_node, zoom_level);
+ return result;
}
bool
IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
std::vector<PhantomNode> &resulting_phantom_node_vector,
- const unsigned zoom_level,
- const unsigned number_of_results) final
+ const unsigned number_of_results) override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
@@ -395,36 +401,53 @@ template <class EdgeDataT> class SharedDataFacade : public BaseDataFacade<EdgeDa
}
return m_static_rtree->second->IncrementalFindPhantomNodeForCoordinate(
- input_coordinate, resulting_phantom_node_vector, zoom_level, number_of_results);
+ input_coordinate, resulting_phantom_node_vector, number_of_results);
+ }
+
+ bool IncrementalFindPhantomNodeForCoordinateWithMaxDistance(
+ const FixedPointCoordinate &input_coordinate,
+ std::vector<std::pair<PhantomNode, double>> &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)
+ {
+ LoadRTree();
+ }
+
+ return m_static_rtree->second->IncrementalFindPhantomNodeForCoordinateWithDistance(
+ input_coordinate, resulting_phantom_node_vector, max_distance,
+ min_number_of_phantom_nodes, max_number_of_phantom_nodes);
}
- unsigned GetCheckSum() const final { return m_check_sum; }
+ unsigned GetCheckSum() const override final { return m_check_sum; }
- unsigned GetNameIndexFromEdgeID(const unsigned id) const final
+ 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 final
+ std::string get_name_for_id(const unsigned name_id) const override final
{
- if (UINT_MAX == name_id)
+ if (std::numeric_limits<unsigned>::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());
+ m_names_char_list.begin() + range.back() + 1, result.begin());
}
+ return result;
}
- std::string GetTimestamp() const final { return m_timestamp; }
+ std::string GetTimestamp() const override final { return m_timestamp; }
};
-#endif // SHARED_DATA_FACADE_H
+#endif // SHARED_DATAFACADE_HPP
diff --git a/3party/osrm/osrm-backend/Server/DataStructures/SharedDataType.h b/3party/osrm/osrm-backend/server/data_structures/shared_datatype.hpp
index 5f07f131fc..326157389b 100644..100755
--- a/3party/osrm/osrm-backend/Server/DataStructures/SharedDataType.h
+++ b/3party/osrm/osrm-backend/server/data_structures/shared_datatype.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,22 +25,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SHARED_DATA_TYPE_H_
-#define SHARED_DATA_TYPE_H_
+#ifndef SHARED_DATA_TYPE_HPP
+#define SHARED_DATA_TYPE_HPP
-#include "../../Util/OSRMException.h"
-#include "../../Util/simple_logger.hpp"
+#include "../../util/osrm_exception.hpp"
+#include "../../util/simple_logger.hpp"
#include <cstdint>
#include <array>
+namespace
+{
// Added at the start and end of each block as sanity check
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<uint64_t, NUM_BLOCKS> num_entries;
std::array<uint64_t, NUM_BLOCKS> 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) << "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)
+ << "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<typename T>
- inline void SetBlockSize(BlockID bid, uint64_t entries)
+ template <typename T> 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,35 +170,35 @@ 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<typename T, bool WRITE_CANARY=false>
- inline T* GetBlockPtr(char* shared_memory, BlockID bid)
+ template <typename T, bool WRITE_CANARY = false>
+ 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)
{
- throw OSRMException("Start canary of block corrupted.");
+ throw osrm::exception("Start canary of block corrupted.");
}
if (!end_canary_alive)
{
- throw OSRMException("End canary of block corrupted.");
+ throw osrm::exception("End canary of block corrupted.");
}
}
@@ -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/3party/osrm/osrm-backend/Server/Http/CompressionType.h b/3party/osrm/osrm-backend/server/http/compression_type.hpp
index 74d0b629b9..f0dc692fa6 100644..100755
--- a/3party/osrm/osrm-backend/Server/Http/CompressionType.h
+++ b/3party/osrm/osrm-backend/server/http/compression_type.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -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 };
-
-} // namespace http
+enum compression_type
+{
+ no_compression,
+ gzip_rfc1952,
+ deflate_rfc1951
+};
+}
-#endif // COMPRESSION_TYPE_H
+#endif // COMPRESSION_TYPE_HPP
diff --git a/3party/osrm/osrm-backend/Include/osrm/Header.h b/3party/osrm/osrm-backend/server/http/header.hpp
index d126c4c989..08d2476b18 100644..100755
--- a/3party/osrm/osrm-backend/Include/osrm/Header.h
+++ b/3party/osrm/osrm-backend/server/http/header.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,21 +25,22 @@ 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 <string>
#include <algorithm>
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)) {}
+ // 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()
+ void clear()
{
name.clear();
value.clear();
@@ -50,4 +51,4 @@ struct Header
};
}
-#endif // HTTP_HEADER_H
+#endif // HEADER_HPP
diff --git a/3party/osrm/osrm-backend/Server/Http/Reply.cpp b/3party/osrm/osrm-backend/server/http/reply.cpp
index e2cf0aecf8..036d1ae05f 100644..100755
--- a/3party/osrm/osrm-backend/Server/Http/Reply.cpp
+++ b/3party/osrm/osrm-backend/server/http/reply.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,16 +25,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <osrm/Reply.h>
+#include "reply.hpp"
-#include "../../Util/cast.hpp"
+#include "../../util/cast.hpp"
namespace http
{
-void Reply::SetSize(const unsigned size)
+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)
+ 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<unsigned>(content.size())); }
+void reply::set_uncompressed_size() { set_size(content.size()); }
-std::vector<boost::asio::const_buffer> Reply::ToBuffers()
+std::vector<boost::asio::const_buffer> reply::to_buffers()
{
std::vector<boost::asio::const_buffer> 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<boost::asio::const_buffer> Reply::ToBuffers()
return buffers;
}
-std::vector<boost::asio::const_buffer> Reply::HeaderstoBuffers()
+std::vector<boost::asio::const_buffer> reply::headers_to_buffers()
{
std::vector<boost::asio::const_buffer> 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 &current_header : headers)
{
- Header &current_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<boost::asio::const_buffer> 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;
+ return ok_html;
}
- if (Reply::badRequest == status)
+ if (reply::bad_request == status)
{
- return badRequestHTML;
+ return bad_request_html;
}
- return internalServerErrorHTML;
+ return internal_server_error_html;
}
-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);
+ return boost::asio::buffer(http_ok_string);
}
- if (Reply::internalServerError == status)
+ 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) {}
+reply::reply() : status(ok) {}
}
diff --git a/3party/osrm/osrm-backend/server/http/reply.hpp b/3party/osrm/osrm-backend/server/http/reply.hpp
new file mode 100755
index 0000000000..733818c2c9
--- /dev/null
+++ b/3party/osrm/osrm-backend/server/http/reply.hpp
@@ -0,0 +1,65 @@
+/*
+
+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 REPLY_HPP
+#define REPLY_HPP
+
+#include "header.hpp"
+
+#include <boost/asio.hpp>
+
+#include <vector>
+
+namespace http
+{
+class reply
+{
+ public:
+ enum status_type
+ {
+ ok = 200,
+ bad_request = 400,
+ internal_server_error = 500
+ } status;
+
+ std::vector<header> headers;
+ std::vector<boost::asio::const_buffer> to_buffers();
+ std::vector<boost::asio::const_buffer> headers_to_buffers();
+ std::vector<char> 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/3party/osrm/osrm-backend/Server/Http/Request.h b/3party/osrm/osrm-backend/server/http/request.hpp
index 4746a5ec2a..c487fba65a 100644..100755
--- a/3party/osrm/osrm-backend/Server/Http/Request.h
+++ b/3party/osrm/osrm-backend/server/http/request.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -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 <boost/asio.hpp>
@@ -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
diff --git a/3party/osrm/osrm-backend/server/request_handler.cpp b/3party/osrm/osrm-backend/server/request_handler.cpp
new file mode 100755
index 0000000000..d1c6e6265c
--- /dev/null
+++ b/3party/osrm/osrm-backend/server/request_handler.cpp
@@ -0,0 +1,175 @@
+/*
+
+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 "request_handler.hpp"
+
+#include "api_grammar.hpp"
+#include "http/reply.hpp"
+#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 "../typedefs.h"
+
+#include <osrm/route_parameters.hpp>
+#include <osrm/json_container.hpp>
+
+#include <ctime>
+
+#include <algorithm>
+#include <iostream>
+
+RequestHandler::RequestHandler() : routing_machine(nullptr) {}
+
+void RequestHandler::handle_request(const http::request &current_request,
+ http::reply &current_reply)
+{
+ // parse command
+ try
+ {
+ 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") <<
+ // " " << 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;
+
+ ltime = time(nullptr);
+ time_stamp = localtime(&ltime);
+
+ // 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 << " " << 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_string.begin();
+ const bool result =
+ boost::spirit::qi::parse(api_iterator, request_string.end(), api_parser);
+
+ osrm::json::Object json_result;
+ // check if the was an error with the request
+ if (!result || (api_iterator != request_string.end()))
+ {
+ 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;
+ osrm::json::render(current_reply.content, json_result);
+ return;
+ }
+
+ // parsing done, lets call the right plugin to handle the request
+ BOOST_ASSERT_MSG(routing_machine != nullptr, "pointer not init'ed");
+
+ if (!route_parameters.jsonp_parameter.empty())
+ { // prepend response with jsonp parameter
+ const std::string json_p = (route_parameters.jsonp_parameter + "(");
+ 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)
+ {
+ 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;
+ 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, Content-Type");
+
+ // set headers
+ current_reply.headers.emplace_back("Content-Length",
+ cast::integral_to_string(current_reply.content.size()));
+ if ("gpx" == route_parameters.output_format)
+ { // gpx file
+ 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",
+ "attachment; filename=\"route.gpx\"");
+ }
+ else if (route_parameters.jsonp_parameter.empty())
+ { // json file
+ 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
+ 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\"");
+ }
+ if (!route_parameters.jsonp_parameter.empty())
+ { // append brace to jsonp response
+ current_reply.content.push_back(')');
+ }
+ }
+ catch (const std::exception &e)
+ {
+ current_reply = http::reply::stock_reply(http::reply::internal_server_error);
+ SimpleLogger().Write(logWARNING) << "[server error] code: " << e.what()
+ << ", uri: " << current_request.uri;
+ return;
+ }
+}
+
+void RequestHandler::RegisterRoutingMachine(OSRM *osrm) { routing_machine = osrm; }
diff --git a/3party/osrm/osrm-backend/Server/RequestHandler.h b/3party/osrm/osrm-backend/server/request_handler.hpp
index 7263dad4ef..b4019db7d8 100644..100755
--- a/3party/osrm/osrm-backend/Server/RequestHandler.h
+++ b/3party/osrm/osrm-backend/server/request_handler.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -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 <string>
@@ -36,8 +36,8 @@ class OSRM;
namespace http
{
-class Reply;
-struct Request;
+class reply;
+struct request;
}
class RequestHandler
@@ -49,11 +49,11 @@ class RequestHandler
RequestHandler();
RequestHandler(const RequestHandler &) = delete;
- void handle_request(const http::Request &req, http::Reply &rep);
+ void handle_request(const http::request &current_request, http::reply &current_reply);
void RegisterRoutingMachine(OSRM *osrm);
private:
OSRM *routing_machine;
};
-#endif // REQUEST_HANDLER_H
+#endif // REQUEST_HANDLER_HPP
diff --git a/3party/osrm/osrm-backend/server/request_parser.cpp b/3party/osrm/osrm-backend/server/request_parser.cpp
new file mode 100755
index 0000000000..584dcbeeb1
--- /dev/null
+++ b/3party/osrm/osrm-backend/server/request_parser.cpp
@@ -0,0 +1,323 @@
+/*
+
+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 "request_parser.hpp"
+
+#include "http/compression_type.hpp"
+#include "http/header.hpp"
+#include "http/request.hpp"
+
+#include "../data_structures/tribool.hpp"
+
+#include <boost/algorithm/string/predicate.hpp>
+
+#include <string>
+
+namespace http
+{
+
+RequestParser::RequestParser()
+ : state(internal_state::method_start), current_header({"", ""}),
+ selected_compression(no_compression)
+{
+}
+
+std::tuple<osrm::tribool, compression_type>
+RequestParser::parse(request &current_request, char *begin, char *end)
+{
+ while (begin != end)
+ {
+ osrm::tribool result = consume(current_request, *begin++);
+ if (result != osrm::tribool::indeterminate)
+ {
+ return std::make_tuple(result, selected_compression);
+ }
+ }
+ osrm::tribool result = osrm::tribool::indeterminate;
+ return std::make_tuple(result, selected_compression);
+}
+
+osrm::tribool RequestParser::consume(request &current_request, const char input)
+{
+ switch (state)
+ {
+ case internal_state::method_start:
+ if (!is_char(input) || is_CTL(input) || is_special(input))
+ {
+ return osrm::tribool::no;
+ }
+ state = internal_state::method;
+ return osrm::tribool::indeterminate;
+ case internal_state::method:
+ if (input == ' ')
+ {
+ state = internal_state::uri;
+ return osrm::tribool::indeterminate;
+ }
+ if (!is_char(input) || is_CTL(input) || is_special(input))
+ {
+ return osrm::tribool::no;
+ }
+ return osrm::tribool::indeterminate;
+ case internal_state::uri_start:
+ if (is_CTL(input))
+ {
+ return osrm::tribool::no;
+ }
+ state = internal_state::uri;
+ current_request.uri.push_back(input);
+ return osrm::tribool::indeterminate;
+ case internal_state::uri:
+ if (input == ' ')
+ {
+ state = internal_state::http_version_h;
+ return osrm::tribool::indeterminate;
+ }
+ if (is_CTL(input))
+ {
+ return osrm::tribool::no;
+ }
+ current_request.uri.push_back(input);
+ return osrm::tribool::indeterminate;
+ case internal_state::http_version_h:
+ if (input == 'H')
+ {
+ state = internal_state::http_version_t_1;
+ return osrm::tribool::indeterminate;
+ }
+ return osrm::tribool::no;
+ case internal_state::http_version_t_1:
+ if (input == 'T')
+ {
+ state = internal_state::http_version_t_2;
+ return osrm::tribool::indeterminate;
+ }
+ return osrm::tribool::no;
+ case internal_state::http_version_t_2:
+ if (input == 'T')
+ {
+ state = internal_state::http_version_p;
+ return osrm::tribool::indeterminate;
+ }
+ return osrm::tribool::no;
+ case internal_state::http_version_p:
+ if (input == 'P')
+ {
+ state = internal_state::http_version_slash;
+ return osrm::tribool::indeterminate;
+ }
+ return osrm::tribool::no;
+ case internal_state::http_version_slash:
+ if (input == '/')
+ {
+ state = internal_state::http_version_major_start;
+ return osrm::tribool::indeterminate;
+ }
+ return osrm::tribool::no;
+ case internal_state::http_version_major_start:
+ if (is_digit(input))
+ {
+ state = internal_state::http_version_major;
+ return osrm::tribool::indeterminate;
+ }
+ return osrm::tribool::no;
+ case internal_state::http_version_major:
+ if (input == '.')
+ {
+ state = internal_state::http_version_minor_start;
+ return osrm::tribool::indeterminate;
+ }
+ if (is_digit(input))
+ {
+ return osrm::tribool::indeterminate;
+ }
+ return osrm::tribool::no;
+ case internal_state::http_version_minor_start:
+ if (is_digit(input))
+ {
+ state = internal_state::http_version_minor;
+ return osrm::tribool::indeterminate;
+ }
+ return osrm::tribool::no;
+ case internal_state::http_version_minor:
+ if (input == '\r')
+ {
+ state = internal_state::expecting_newline_1;
+ return osrm::tribool::indeterminate;
+ }
+ if (is_digit(input))
+ {
+ return osrm::tribool::indeterminate;
+ }
+ return osrm::tribool::no;
+ case internal_state::expecting_newline_1:
+ if (input == '\n')
+ {
+ state = internal_state::header_line_start;
+ return osrm::tribool::indeterminate;
+ }
+ return osrm::tribool::no;
+ case internal_state::header_line_start:
+ if (boost::iequals(current_header.name, "Accept-Encoding"))
+ {
+ /* giving gzip precedence over deflate */
+ if (boost::icontains(current_header.value, "deflate"))
+ {
+ selected_compression = deflate_rfc1951;
+ }
+ if (boost::icontains(current_header.value, "gzip"))
+ {
+ selected_compression = gzip_rfc1952;
+ }
+ }
+
+ if (boost::iequals(current_header.name, "Referer"))
+ {
+ current_request.referrer = current_header.value;
+ }
+
+ if (boost::iequals(current_header.name, "User-Agent"))
+ {
+ current_request.agent = current_header.value;
+ }
+
+ if (input == '\r')
+ {
+ state = internal_state::expecting_newline_3;
+ return osrm::tribool::indeterminate;
+ }
+ if (!is_char(input) || is_CTL(input) || is_special(input))
+ {
+ return osrm::tribool::no;
+ }
+ state = internal_state::header_name;
+ current_header.clear();
+ current_header.name.push_back(input);
+ return osrm::tribool::indeterminate;
+ case internal_state::header_lws:
+ if (input == '\r')
+ {
+ state = internal_state::expecting_newline_2;
+ return osrm::tribool::indeterminate;
+ }
+ if (input == ' ' || input == '\t')
+ {
+ return osrm::tribool::indeterminate;
+ }
+ if (is_CTL(input))
+ {
+ return osrm::tribool::no;
+ }
+ state = internal_state::header_value;
+ return osrm::tribool::indeterminate;
+ case internal_state::header_name:
+ if (input == ':')
+ {
+ state = internal_state::space_before_header_value;
+ return osrm::tribool::indeterminate;
+ }
+ if (!is_char(input) || is_CTL(input) || is_special(input))
+ {
+ return osrm::tribool::no;
+ }
+ current_header.name.push_back(input);
+ return osrm::tribool::indeterminate;
+ case internal_state::space_before_header_value:
+ if (input == ' ')
+ {
+ state = internal_state::header_value;
+ return osrm::tribool::indeterminate;
+ }
+ return osrm::tribool::no;
+ case internal_state::header_value:
+ if (input == '\r')
+ {
+ state = internal_state::expecting_newline_2;
+ return osrm::tribool::indeterminate;
+ }
+ if (is_CTL(input))
+ {
+ return osrm::tribool::no;
+ }
+ current_header.value.push_back(input);
+ return osrm::tribool::indeterminate;
+ case internal_state::expecting_newline_2:
+ if (input == '\n')
+ {
+ 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;
+ }
+}
+
+bool RequestParser::is_char(const int character) const
+{
+ return character >= 0 && character <= 127;
+}
+
+bool RequestParser::is_CTL(const int character) const
+{
+ return (character >= 0 && character <= 31) || (character == 127);
+}
+
+bool RequestParser::is_special(const int character) const
+{
+ switch (character)
+ {
+ case '(':
+ case ')':
+ case '<':
+ case '>':
+ case '@':
+ case ',':
+ case ';':
+ case ':':
+ case '\\':
+ case '"':
+ case '/':
+ case '[':
+ case ']':
+ case '?':
+ case '=':
+ case '{':
+ case '}':
+ case ' ':
+ case '\t':
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool RequestParser::is_digit(const int character) const
+{
+ return character >= '0' && character <= '9';
+}
+}
diff --git a/3party/osrm/osrm-backend/Server/RequestParser.h b/3party/osrm/osrm-backend/server/request_parser.hpp
index 4b74d83b9c..2b6bf69447 100644..100755
--- a/3party/osrm/osrm-backend/Server/RequestParser.h
+++ b/3party/osrm/osrm-backend/server/request_parser.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,66 +25,68 @@ 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/CompressionType.h"
-#include <osrm/Header.h>
+#include "http/compression_type.hpp"
+#include "http/header.hpp"
+#include "../data_structures/tribool.hpp"
-#include <boost/logic/tribool.hpp>
-#include <boost/tuple/tuple.hpp>
+#include <tuple>
namespace http
{
-struct Request;
+struct request;
class RequestParser
{
public:
RequestParser();
- void Reset();
- boost::tuple<boost::tribool, char *>
- Parse(Request &req, char *begin, char *end, CompressionType *compressionType);
+ std::tuple<osrm::tribool, compression_type>
+ parse(request &current_request, char *begin, char *end);
private:
- boost::tribool consume(Request &req, char input, CompressionType *compressionType);
-
- inline bool isChar(int c);
-
- inline bool isCTL(int c);
-
- inline bool isTSpecial(int c);
-
- 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_;
-
- Header header;
+ osrm::tribool consume(request &current_request, const char input);
+
+ bool is_char(const int character) const;
+
+ bool is_CTL(const int character) const;
+
+ bool is_special(const int character) const;
+
+ bool is_digit(const int character) const;
+
+ enum class internal_state : unsigned char
+ {
+ 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 current_header;
+ compression_type selected_compression;
};
} // namespace http
-#endif // REQUEST_PARSER_H
+#endif // REQUEST_PARSER_HPP
diff --git a/3party/osrm/osrm-backend/Server/Server.h b/3party/osrm/osrm-backend/server/server.hpp
index 8e0b101302..0ec316379e 100644..100755
--- a/3party/osrm/osrm-backend/Server/Server.h
+++ b/3party/osrm/osrm-backend/server/server.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,15 +25,15 @@ 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/make_unique.hpp"
-#include "../Util/simple_logger.hpp"
+#include "../util/cast.hpp"
+#include "../util/integer_range.hpp"
+#include "../util/simple_logger.hpp"
#include <boost/asio.hpp>
#include <boost/bind.hpp>
@@ -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<Server> CreateServer(std::string &ip_address, int ip_port, unsigned requested_num_threads)
+ static std::shared_ptr<Server>
+ 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<http::Connection>(io_service, request_handler)), request_handler()
+ new_connection(std::make_shared<http::Connection>(io_service, request_handler))
{
const std::string port_string = cast::integral_to_string(port);
@@ -116,4 +116,4 @@ class Server
RequestHandler request_handler;
};
-#endif // SERVER_H
+#endif // SERVER_HPP
diff --git a/3party/osrm/osrm-backend/taginfo.json b/3party/osrm/osrm-backend/taginfo.json
index 17a4f8f24e..17a4f8f24e 100644..100755
--- a/3party/osrm/osrm-backend/taginfo.json
+++ b/3party/osrm/osrm-backend/taginfo.json
diff --git a/3party/osrm/osrm-backend/test/.gitignore b/3party/osrm/osrm-backend/test/.gitignore
index ea5e38ea80..ea5e38ea80 100644..100755
--- a/3party/osrm/osrm-backend/test/.gitignore
+++ b/3party/osrm/osrm-backend/test/.gitignore
diff --git a/3party/osrm/osrm-backend/test/.stxxl b/3party/osrm/osrm-backend/test/.stxxl
index b1765e2c08..b1765e2c08 100644..100755
--- a/3party/osrm/osrm-backend/test/.stxxl
+++ b/3party/osrm/osrm-backend/test/.stxxl
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/.gitignore b/3party/osrm/osrm-backend/third_party/libosmium/.gitignore
new file mode 100755
index 0000000000..50139035b7
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/.gitignore
@@ -0,0 +1,2 @@
+*.swp
+.ycm_extra_conf.pyc
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/.travis.yml b/3party/osrm/osrm-backend/third_party/libosmium/.travis.yml
new file mode 100755
index 0000000000..73dff72a1a
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/.travis.yml
@@ -0,0 +1,51 @@
+#-----------------------------------------------------------------------------
+#
+# 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
+ - 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
+ - sudo rm /usr/bin/cpp
+ - sudo ln -s /usr/bin/cpp-4.8 /usr/bin/cpp
+ # upgrade libosmium dependencies
+ - sudo apt-get install --yes make libboost-dev libboost-program-options-dev libsparsehash-dev libprotobuf-dev protobuf-compiler libgeos++-dev libproj-dev libgdal1h libgdal-dev
+ - git clone https://github.com/osmcode/osm-testdata.git
+ # OSMPBF is too old, install from git
+ #- sudo apt-get install --yes libosmpbf-dev
+ - git clone https://github.com/scrosby/OSM-binary.git
+ - cd OSM-binary/src
+ - make
+ - sudo make install
+ - cd ../..
+ - cd libosmium
+
+before_script:
+ - true
+
+script:
+ - if [ "${CXX}" = 'g++' ]; then export CXX=g++-4.8; fi;
+ - mkdir build
+ - cd build
+ - cmake -LA -DCMAKE_BUILD_TYPE=${CONFIGURATION} ..
+ - make VERBOSE=1
+ - ctest --output-on-failure
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/.ycm_extra_conf.py b/3party/osrm/osrm-backend/third_party/libosmium/.ycm_extra_conf.py
new file mode 100755
index 0000000000..2b8730616a
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/.ycm_extra_conf.py
@@ -0,0 +1,48 @@
+#-----------------------------------------------------------------------------
+#
+# Configuration for YouCompleteMe Vim plugin
+#
+# http://valloric.github.io/YouCompleteMe/
+#
+#-----------------------------------------------------------------------------
+
+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
+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
+'-I%s/include' % basedir,
+'-I%s/test/include' % basedir,
+'-I%s/test/data-test/include' % basedir,
+
+# 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/3party/osrm/osrm-backend/third_party/libosmium/CHANGELOG.md b/3party/osrm/osrm-backend/third_party/libosmium/CHANGELOG.md
new file mode 100755
index 0000000000..4c345a4981
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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/3party/osrm/osrm-backend/third_party/libosmium/CMakeLists.txt b/3party/osrm/osrm-backend/third_party/libosmium/CMakeLists.txt
new file mode 100755
index 0000000000..5e70a9935a
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/CMakeLists.txt
@@ -0,0 +1,333 @@
+#-----------------------------------------------------------------------------
+#
+# CMake Config
+#
+# Libosmium
+#
+#-----------------------------------------------------------------------------
+
+cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
+
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+
+
+#-----------------------------------------------------------------------------
+#
+# Project version
+#
+#-----------------------------------------------------------------------------
+
+set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel;Dev"
+ CACHE STRING
+ "List of available configuration types"
+ FORCE)
+
+project(libosmium)
+
+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})
+
+
+#-----------------------------------------------------------------------------
+#
+# Build options
+#
+# (Change with -DOPTION=VALUE on cmake command line.)
+#
+#-----------------------------------------------------------------------------
+
+if(CMAKE_BUILD_TYPE STREQUAL "Dev")
+ set(dev_build ON)
+else()
+ 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
+#
+#-----------------------------------------------------------------------------
+
+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)
+
+
+#-----------------------------------------------------------------------------
+#
+# Decide which C++ version to use (Minimum/default: 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()
+
+
+#-----------------------------------------------------------------------------
+#
+# 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)
+mark_as_advanced(
+ CMAKE_CXX_FLAGS_DEV
+ CMAKE_EXE_LINKER_FLAGS_DEV
+)
+
+set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${USUAL_COMPILE_OPTIONS}"
+ CACHE STRING "Flags used by the compiler during RELWITHDEBINFO builds."
+ FORCE)
+
+
+#-----------------------------------------------------------------------------
+#
+# Build Type
+#
+#-----------------------------------------------------------------------------
+# 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)
+ set(build_type ${CMAKE_BUILD_TYPE})
+else()
+ set(build_type "RelWithDebInfo")
+endif()
+
+set(CMAKE_BUILD_TYPE ${build_type}
+ CACHE STRING
+ "Choose the type of build, options are: ${CMAKE_CONFIGURATION_TYPES}."
+ FORCE)
+
+
+#-----------------------------------------------------------------------------
+#
+# Unit and data tests
+#
+#-----------------------------------------------------------------------------
+enable_testing()
+
+if(BUILD_TESTING OR BUILD_DATA_TESTS)
+ 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")
+endif()
+
+if(BUILD_TESTING)
+ add_subdirectory(test)
+endif()
+
+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)
+
+ # 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/data-tests/*.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 " Build target 'cppcheck' will not be available.")
+endif(CPPCHECK)
+
+
+#-----------------------------------------------------------------------------
+#
+# Examples, benchmarks and documentation
+#
+#-----------------------------------------------------------------------------
+
+if(BUILD_EXAMPLES)
+ add_subdirectory(examples)
+endif()
+
+if(BUILD_BENCHMARKS)
+ add_subdirectory(benchmarks)
+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)
+
+ 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} STATIC ${DUMMYCPP} include/${hpp})
+
+ #### this is better but only supported from cmake 3.0:
+ ###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)
+
+
+#-----------------------------------------------------------------------------
+#
+# 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/3party/osrm/osrm-backend/third_party/libosmium/CONTRIBUTING.md b/3party/osrm/osrm-backend/third_party/libosmium/CONTRIBUTING.md
new file mode 100755
index 0000000000..323c84744d
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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
+<http://code.google.com/p/include-what-you-use/>.
+
+
+## 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/3party/osrm/osrm-backend/third_party/libosmium/LICENSE.txt b/3party/osrm/osrm-backend/third_party/libosmium/LICENSE.txt
new file mode 100755
index 0000000000..36b7cd93cd
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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/3party/osrm/osrm-backend/third_party/libosmium/README.md b/3party/osrm/osrm-backend/third_party/libosmium/README.md
new file mode 100755
index 0000000000..503440e8ed
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/README.md
@@ -0,0 +1,104 @@
+# Libosmium
+
+http://osmcode.org/libosmium
+
+A fast and flexible C++ library for working with OpenStreetMap data.
+
+[![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 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 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 your programs.
+
+For details see the
+[list of dependencies](https://github.com/osmcode/libosmium/wiki/Libosmium-dependencies).
+
+
+## Directories
+
+* benchmarks: Some benchmarks checking different parts of Libosmium.
+
+* cmake: CMake configuration scripts.
+
+* doc: Config for documentation.
+
+* examples: Osmium example applications.
+
+* include: C/C++ include files. All of Libosmium is in those header files
+ which are needed for building Osmium applications.
+
+* test: Tests (see below).
+
+
+## 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.
+
+For more see the
+[Libosmium Wiki](https://github.com/osmcode/libosmium/wiki/Building-Libosmium).
+
+
+## Testing
+
+See the
+[Libosmium Wiki](https://github.com/osmcode/libosmium/wiki/Testing-Libosmium)
+for instructions.
+
+
+## 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
+
+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
+
+Libosmium is available under the Boost Software License. See LICENSE.txt.
+
+
+## Authors
+
+Libosmium was mainly written and is maintained by Jochen Topf
+(jochen@topf.org). See the git commit log for other authors.
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/appveyor.yml b/3party/osrm/osrm-backend/third_party/libosmium/appveyor.yml
new file mode 100755
index 0000000000..06c8e69749
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/appveyor.yml
@@ -0,0 +1,77 @@
+#-----------------------------------------------------------------------------
+#
+# Configuration for continuous integration service at appveyor.com
+#
+#-----------------------------------------------------------------------------
+
+environment:
+ matrix:
+ - config: Dev
+ - config: RelWithDebInfo
+
+# branches to build
+branches:
+ # whitelist
+ only:
+ - master
+
+# Operating system (build VM template)
+os: Visual Studio 2014 CTP4
+
+# scripts that are called at very beginning, before repo cloning
+init:
+
+# clone directory
+clone_folder: c:\projects\libosmium
+
+platform: x64
+
+install:
+ # 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 | %windir%\system32\find "ing archive"
+ - 7z x lodeps.7z | %windir%\system32\find "ing archive"
+ - echo %LODEPSDIR%
+ - dir %LODEPSDIR%
+ - echo our own cmake
+ - cmake -version
+ - cd c:\projects
+ - git clone https://github.com/osmcode/osm-testdata.git
+
+build_script:
+ - cd c:\projects\libosmium
+ - mkdir build
+ - cd build
+ - echo %config%
+ - cmake .. -LA -G "Visual Studio 14 Win64" -DOsmium_DEBUG=TRUE -DCMAKE_BUILD_TYPE=%config% -DBUILD_BENCHMARKS=OFF -DBOOST_ROOT=%LODEPSDIR%\boost -DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_57.lib -DOSMPBF_LIBRARY=%LODEPSDIR%\osmpbf\lib\osmpbf.lib -DOSMPBF_INCLUDE_DIR=%LODEPSDIR%\osmpbf\include -DPROTOBUF_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf.lib -DPROTOBUF_LITE_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf-lite.lib -DPROTOBUF_INCLUDE_DIR=%LODEPSDIR%\protobuf\include -DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib -DZLIB_INCLUDE_DIR=%LODEPSDIR%\zlib\include -DEXPAT_LIBRARY=%LODEPSDIR%\expat\lib\libexpat.lib -DEXPAT_INCLUDE_DIR=%LODEPSDIR%\expat\include -DBZIP2_LIBRARIES=%LIBBZIP2% -DBZIP2_INCLUDE_DIR=%LODEPSDIR%\bzip2\include -DGDAL_LIBRARY=%LODEPSDIR%\gdal\lib\gdal_i.lib -DGDAL_INCLUDE_DIR=%LODEPSDIR%\gdal\include -DGEOS_LIBRARY=%LODEPSDIR%\geos\lib\geos.lib -DGEOS_INCLUDE_DIR=%LODEPSDIR%\geos\include -DPROJ_LIBRARY=%LODEPSDIR%\proj\lib\proj.lib -DPROJ_INCLUDE_DIR=%LODEPSDIR%\proj\include -DSPARSEHASH_INCLUDE_DIR=%LODEPSDIR%\sparsehash\include -DGETOPT_LIBRARY=%LODEPSDIR%\wingetopt\lib\wingetopt.lib -DGETOPT_INCLUDE_DIR=%LODEPSDIR%\wingetopt\include
+ - 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:
+ # -LE fails_on_windows exempts tests we know will fail
+ - ctest --output-on-failure -C %config% -LE fails_on_windows
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/CMakeLists.txt b/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/CMakeLists.txt
new file mode 100755
index 0000000000..6a4ca162db
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/README.md b/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/README.md
new file mode 100755
index 0000000000..f10045ca0a
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/download_data.sh b/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/download_data.sh
new file mode 100755
index 0000000000..8a6a8ff50d
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/osmium_benchmark_count.cpp b/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/osmium_benchmark_count.cpp
new file mode 100755
index 0000000000..701d6faec8
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/osmium_benchmark_count.cpp
@@ -0,0 +1,54 @@
+/*
+
+ The code in this file is released into the Public Domain.
+
+*/
+
+#include <iostream>
+
+#include <osmium/io/any_input.hpp>
+#include <osmium/handler.hpp>
+#include <osmium/visitor.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/osmium_benchmark_count_tag.cpp b/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/osmium_benchmark_count_tag.cpp
new file mode 100755
index 0000000000..4a77c34529
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/osmium_benchmark_count_tag.cpp
@@ -0,0 +1,55 @@
+/*
+
+ The code in this file is released into the Public Domain.
+
+*/
+
+#include <iostream>
+
+#include <osmium/io/any_input.hpp>
+#include <osmium/handler.hpp>
+#include <osmium/visitor.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/osmium_benchmark_index_map.cpp b/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/osmium_benchmark_index_map.cpp
new file mode 100755
index 0000000000..fa75fb2b86
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/osmium_benchmark_index_map.cpp
@@ -0,0 +1,41 @@
+/*
+
+ The code in this file is released into the Public Domain.
+
+*/
+
+#include <iostream>
+
+#include <osmium/index/map/all.hpp>
+#include <osmium/handler/node_locations_for_ways.hpp>
+#include <osmium/visitor.hpp>
+
+#include <osmium/io/any_input.hpp>
+#include <osmium/handler.hpp>
+
+typedef osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location> index_type;
+
+typedef osmium::handler::NodeLocationsForWays<index_type> 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<osmium::unsigned_object_id_type, osmium::Location>::instance();
+ std::unique_ptr<index_type> 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/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/osmium_benchmark_static_vs_dynamic_index.cpp b/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/osmium_benchmark_static_vs_dynamic_index.cpp
new file mode 100755
index 0000000000..9c47c84499
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 <algorithm>
+#include <chrono>
+#include <cmath>
+#include <iostream>
+#include <limits>
+
+#include <osmium/index/map/all.hpp>
+#include <osmium/handler/node_locations_for_ways.hpp>
+#include <osmium/visitor.hpp>
+
+#include <osmium/io/any_input.hpp>
+#include <osmium/handler.hpp>
+
+typedef osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location> static_index_type;
+const std::string location_store="sparse_mem_array";
+
+typedef osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location> dynamic_index_type;
+
+typedef osmium::handler::NodeLocationsForWays<static_index_type> static_location_handler_type;
+typedef osmium::handler::NodeLocationsForWays<dynamic_index_type> 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<osmium::unsigned_object_id_type, osmium::Location>::instance();
+
+ const auto buffer_size = buffer.committed() / (1024*1024); // buffer size in MBytes
+ const int runs = std::max(10, static_cast<int>(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<double>::max();
+ double static_sum = 0;
+ double static_max = 0;
+
+ double dynamic_min = std::numeric_limits<double>::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<double, std::milli>(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<dynamic_index_type> 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<double, std::milli>(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/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/run_benchmark_count.sh b/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/run_benchmark_count.sh
new file mode 100755
index 0000000000..d71508f764
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/run_benchmark_count_tag.sh b/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/run_benchmark_count_tag.sh
new file mode 100755
index 0000000000..4fa6a1068f
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/run_benchmark_index_map.sh b/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/run_benchmark_index_map.sh
new file mode 100755
index 0000000000..30984d4603
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/run_benchmark_static_vs_dynamic_index.sh b/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/run_benchmark_static_vs_dynamic_index.sh
new file mode 100755
index 0000000000..05e32f1260
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/run_benchmarks.sh b/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/run_benchmarks.sh
new file mode 100755
index 0000000000..6a20c02141
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/setup.sh b/3party/osrm/osrm-backend/third_party/libosmium/benchmarks/setup.sh
new file mode 100755
index 0000000000..9733bfe1bd
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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/3party/osrm/osrm-backend/third_party/libosmium/cmake/FindGem.cmake b/3party/osrm/osrm-backend/third_party/libosmium/cmake/FindGem.cmake
new file mode 100755
index 0000000000..f5389d1e83
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 <gem-name>` 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/3party/osrm/osrm-backend/third_party/libosmium/cmake/FindOSMPBF.cmake b/3party/osrm/osrm-backend/third_party/libosmium/cmake/FindOSMPBF.cmake
new file mode 100755
index 0000000000..deeebd8b6c
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 <osmpbf/osmpbf.h>
+# and not
+# #include <osmpbf.h>
+#
+
+find_path(OSMPBF_INCLUDE_DIR osmpbf/osmpbf.h
+ HINTS $ENV{OSMPBF_DIR}
+ PATH_SUFFIXES include
+ PATHS
+ ~/Library/Frameworks
+ /Library/Frameworks
+ /usr/local
+ /usr
+ /opt/local # DarwinPorts
+ /opt
+)
+
+find_library(OSMPBF_LIBRARY
+ NAMES osmpbf
+ HINTS $ENV{OSMPBF_DIR}
+ PATH_SUFFIXES lib64 lib
+ PATHS
+ ~/Library/Frameworks
+ /Library/Frameworks
+ /usr/local
+ /usr
+ /opt/local
+ /opt
+)
+
+# Handle the QUIETLY and REQUIRED arguments and set OSMPBF_FOUND to TRUE if
+# all listed variables are TRUE.
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(OSMPBF DEFAULT_MSG OSMPBF_LIBRARY OSMPBF_INCLUDE_DIR)
+
+# Copy the results to the output variables.
+if(OSMPBF_FOUND)
+ set(OSMPBF_INCLUDE_DIRS ${OSMPBF_INCLUDE_DIR})
+ set(OSMPBF_LIBRARIES ${OSMPBF_LIBRARY})
+endif()
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/cmake/FindOsmium.cmake b/3party/osrm/osrm-backend/third_party/libosmium/cmake/FindOsmium.cmake
new file mode 100755
index 0000000000..1de41a0226
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/cmake/FindOsmium.cmake
@@ -0,0 +1,340 @@
+#----------------------------------------------------------------------
+#
+# FindOsmium.cmake
+#
+# Find the Libosmium headers and, optionally, several components needed for
+# different Libosmium functions.
+#
+#----------------------------------------------------------------------
+#
+# Usage:
+#
+# 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:
+#
+# find_package(Osmium REQUIRED COMPONENTS <XXX>)
+# include_directories(${OSMIUM_INCLUDE_DIRS})
+#
+# For the <XXX> 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})
+else()
+ set(OSMIUM_INCLUDE_DIRS "")
+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)
+ # 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++.
+ include(CheckTypeSize)
+ set(CMAKE_REQUIRED_INCLUDES ${SPARSEHASH_INCLUDE_DIR})
+ set(CMAKE_EXTRA_INCLUDE_FILES "google/sparsetable")
+ check_type_size("google::sparsetable<int>::size_type" SPARSETABLE_SIZE_TYPE LANGUAGE CXX)
+ set(CMAKE_EXTRA_INCLUDE_FILES)
+ set(CMAKE_REQUIRED_INCLUDES)
+
+ # Falling back to checking size_t if google::sparsetable<int>::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})
+ 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.")
+ endif()
+endif()
+
+#----------------------------------------------------------------------
+
+list(REMOVE_DUPLICATES OSMIUM_INCLUDE_DIRS)
+
+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()
+
+#----------------------------------------------------------------------
+#
+# 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)
+
+ # 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()
+
+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.
+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")
+
+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/3party/osrm/osrm-backend/third_party/libosmium/cmake/README b/3party/osrm/osrm-backend/third_party/libosmium/cmake/README
new file mode 100755
index 0000000000..4a035f7b21
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/cmake/README
@@ -0,0 +1,3 @@
+
+FindGem.cmake from https://github.com/rock-core/base-cmake
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/cmake/build.bat b/3party/osrm/osrm-backend/third_party/libosmium/cmake/build.bat
new file mode 100755
index 0000000000..5ffab124eb
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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/3party/osrm/osrm-backend/third_party/libosmium/cmake/iwyu.sh b/3party/osrm/osrm-backend/third_party/libosmium/cmake/iwyu.sh
new file mode 100755
index 0000000000..d203844915
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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/3party/osrm/osrm-backend/third_party/libosmium/doc/CMakeLists.txt b/3party/osrm/osrm-backend/third_party/libosmium/doc/CMakeLists.txt
new file mode 100755
index 0000000000..9d69a16bd9
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/doc/CMakeLists.txt
@@ -0,0 +1,35 @@
+#-----------------------------------------------------------------------------
+#
+# 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(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}
+ ${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/3party/osrm/osrm-backend/third_party/libosmium/doc/Doxyfile.in b/3party/osrm/osrm-backend/third_party/libosmium/doc/Doxyfile.in
new file mode 100755
index 0000000000..c03e255e9e
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 = "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
+# 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 = @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
+# 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 <section_label> ... \endif and \cond <section_label>
+# ... \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 = 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
+# 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:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> 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 = "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
+# 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 = 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
+# 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 = 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
+# 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 = "@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
+# 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 <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX 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: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
+# replace them by respectively the title of the page, the current date and time,
+# only the current date, the version number of doxygen, the project name (see
+# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF 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: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = YES
+
+# The XML_OUTPUT tag is used to specify where the XML pages 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: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages 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: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED = __linux__
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: YES.
+
+HAVE_DOT = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font n the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
+# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
+# gif:cairo:gd, gif:gd, gif:gd:gd and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/doc/README.md b/3party/osrm/osrm-backend/third_party/libosmium/doc/README.md
new file mode 100755
index 0000000000..7ca8e7cf73
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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/3party/osrm/osrm-backend/third_party/libosmium/doc/doc.txt b/3party/osrm/osrm-backend/third_party/libosmium/doc/doc.txt
new file mode 100755
index 0000000000..1f06f4f3ce
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/doc/doc.txt
@@ -0,0 +1,26 @@
+
+/**
+ * @mainpage
+ *
+ * Osmium is a fast and flexible C++ library for working with OpenStreetMap
+ * data.
+ *
+ * This is the API documentation that was automatically created from the
+ * source code. For more information about the Osmium Library see
+ * http://osmcode.org/libosmium .
+ *
+ * Osmium is free software and available under the Boost Software License.
+ * The source code is available at https://github.com/osmcode/libosmium .
+ *
+ * Osmium is a header-only library. You do not need to compile and link it,
+ * just include the headers you need.
+ *
+ * Everything in namespaces called "detail" is for internal Osmium use only,
+ * do not depend on it in your code. Do not include any include files in
+ * directories named "detail" directly. Include files in directories called
+ * "experimental" and everything in namespaces called "experimental" is
+ * unsupported and may change at any time regardless of the status of the rest
+ * of the library.
+ *
+ */
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/doc/header.html b/3party/osrm/osrm-backend/third_party/libosmium/doc/header.html
new file mode 100755
index 0000000000..495d50024e
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/doc/header.html
@@ -0,0 +1,56 @@
+<!-- HTML header for doxygen 1.8.8-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<meta name="generator" content="Doxygen $doxygenversion"/>
+<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
+<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
+<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="$relpath^jquery.js"></script>
+<script type="text/javascript" src="$relpath^dynsections.js"></script>
+$treeview
+$search
+$mathjax
+<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
+$extrastylesheet
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+
+<!--BEGIN TITLEAREA-->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <!--BEGIN PROJECT_LOGO-->
+ <td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
+ <!--END PROJECT_LOGO-->
+ <!--BEGIN PROJECT_NAME-->
+ <td style="padding-left: 0.5em;">
+ <div id="projectname">$projectname
+ <!--BEGIN PROJECT_NUMBER-->&#160;<span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER-->
+ </div>
+ <!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
+ </td>
+ <!--END PROJECT_NAME-->
+ <!--BEGIN !PROJECT_NAME-->
+ <!--BEGIN PROJECT_BRIEF-->
+ <td style="padding-left: 0.5em;">
+ <div id="projectbrief">$projectbrief</div>
+ </td>
+ <!--END PROJECT_BRIEF-->
+ <!--END !PROJECT_NAME-->
+ <!--BEGIN DISABLE_INDEX-->
+ <!--BEGIN SEARCHENGINE-->
+ <td>$searchbox</td>
+ <!--END SEARCHENGINE-->
+ <!--END DISABLE_INDEX-->
+ </tr>
+ </tbody>
+</table>
+</div>
+<!--END TITLEAREA-->
+<!-- end header part -->
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/doc/osmium.css b/3party/osrm/osrm-backend/third_party/libosmium/doc/osmium.css
new file mode 100755
index 0000000000..6256e845ed
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/doc/osmium.css
@@ -0,0 +1,22 @@
+
+body {
+ font-family: "Droid Sans",Helvetica,Arial,sans-serif;
+ background-color: #ffffff;
+ color: #202060;
+}
+
+.tabs, .tabs2, .tabs3, .navpath ul, .tablist li {
+ background-image: none;
+}
+
+.tabs, .tabs2, .tabs3 {
+ border-top: 1px solid #202060;
+}
+
+div.contents {
+ margin: 0px;
+ padding-top: 10px;
+ padding-left: 12px;
+ padding-right: 8px;
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/examples/CMakeLists.txt b/3party/osrm/osrm-backend/third_party/libosmium/examples/CMakeLists.txt
new file mode 100755
index 0000000000..c9f59603dc
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/examples/CMakeLists.txt
@@ -0,0 +1,115 @@
+#-----------------------------------------------------------------------------
+#
+# CMake Config
+#
+# Libosmium examples
+#
+#-----------------------------------------------------------------------------
+
+message(STATUS "Configuring examples")
+
+set(EXAMPLES
+ area_test
+ convert
+ count
+ create_node_cache
+ debug
+ index
+ read
+ serdump
+ toogr
+ toogr2
+ toogr2_exp
+ use_node_cache
+ CACHE STRING "Example programs"
+)
+
+
+#-----------------------------------------------------------------------------
+#
+# 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(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()
+
+
+#-----------------------------------------------------------------------------
+#
+# 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()
+
+
+#-----------------------------------------------------------------------------
+#
+# 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)
+ list(APPEND EXAMPLE_LIBS_index ${Boost_PROGRAM_OPTIONS_LIBRARY})
+else()
+ list(REMOVE_ITEM EXAMPLES index)
+ message(STATUS "Configuring examples - Skipping examples because Boost program_options not found:")
+ message(STATUS " - osmium_index")
+endif()
+
+
+#-----------------------------------------------------------------------------
+#
+# 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})
+ list(APPEND EXAMPLE_LIBS_${example} ${GDAL_LIBRARIES})
+ list(APPEND EXAMPLE_LIBS_${example} ${PROJ_LIBRARIES})
+ endforeach()
+else()
+ 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/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_area_test.cpp b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_area_test.cpp
new file mode 100755
index 0000000000..ee2ba12964
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_area_test.cpp
@@ -0,0 +1,138 @@
+/*
+
+ This is an example tool that creates multipolygons from OSM data
+ and dumps them to stdout.
+
+ The code in this example file is released into the Public Domain.
+
+*/
+
+#include <iostream>
+
+#include <getopt.h>
+
+#include <osmium/area/assembler.hpp>
+#include <osmium/area/multipolygon_collector.hpp>
+#include <osmium/dynamic_handler.hpp>
+#include <osmium/geom/wkt.hpp>
+#include <osmium/handler/dump.hpp>
+#include <osmium/handler/node_locations_for_ways.hpp>
+#include <osmium/index/map/dummy.hpp>
+#include <osmium/index/map/sparse_mem_array.hpp>
+#include <osmium/io/any_input.hpp>
+#include <osmium/visitor.hpp>
+
+typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
+typedef osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
+typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
+
+class WKTDump : public osmium::handler::Handler {
+
+ osmium::geom::WKTFactory<> m_factory ;
+
+ std::ostream& m_out;
+
+public:
+
+ WKTDump(std::ostream& out) :
+ m_out(out) {
+ }
+
+ void area(const osmium::Area& area) {
+ try {
+ m_out << m_factory.create_multipolygon(area) << "\n";
+ } catch (osmium::geometry_error& e) {
+ m_out << "GEOMETRY ERROR: " << e.what() << "\n";
+ }
+ }
+
+}; // class WKTDump
+
+void print_help() {
+ std::cout << "osmium_area_test [OPTIONS] OSMFILE\n\n"
+ << "Read OSMFILE and build multipolygons from it.\n"
+ << "\nOptions:\n"
+ << " -h, --help This help message\n"
+ << " -w, --dump-wkt Dump area geometries as WKT\n"
+ << " -o, --dump-objects Dump area objects\n";
+}
+
+int main(int argc, char* argv[]) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"dump-wkt", no_argument, 0, 'w'},
+ {"dump-objects", no_argument, 0, 'o'},
+ {0, 0, 0, 0}
+ };
+
+ osmium::handler::DynamicHandler handler;
+
+ while (true) {
+ int c = getopt_long(argc, argv, "hwo", long_options, 0);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'h':
+ print_help();
+ exit(0);
+ case 'w':
+ handler.set<WKTDump>(std::cout);
+ break;
+ case 'o':
+ handler.set<osmium::handler::Dump>(std::cout);
+ break;
+ default:
+ exit(1);
+ }
+ }
+
+ int remaining_args = argc - optind;
+ if (remaining_args != 1) {
+ std::cerr << "Usage: " << argv[0] << " [OPTIONS] OSMFILE\n";
+ exit(1);
+ }
+
+ osmium::io::File infile(argv[optind]);
+
+ osmium::area::Assembler::config_type assembler_config;
+ osmium::area::MultipolygonCollector<osmium::area::Assembler> collector(assembler_config);
+
+ std::cout << "Pass 1...\n";
+ osmium::io::Reader reader1(infile, osmium::osm_entity_bits::relation);
+ collector.read_relations(reader1);
+ reader1.close();
+ std::cout << "Pass 1 done\n";
+
+ std::cout << "Memory:\n";
+ collector.used_memory();
+
+ index_pos_type index_pos;
+ index_neg_type index_neg;
+ location_handler_type location_handler(index_pos, index_neg);
+ location_handler.ignore_errors(); // XXX
+
+ std::cout << "Pass 2...\n";
+ osmium::io::Reader reader2(infile);
+ osmium::apply(reader2, location_handler, collector.handler([&handler](osmium::memory::Buffer&& buffer) {
+ osmium::apply(buffer, handler);
+ }));
+ reader2.close();
+ std::cout << "Pass 2 done\n";
+
+ std::cout << "Memory:\n";
+ collector.used_memory();
+
+ std::vector<const osmium::Relation*> incomplete_relations = collector.get_incomplete_relations();
+ if (!incomplete_relations.empty()) {
+ std::cerr << "Warning! Some member ways missing for these multipolygon relations:";
+ for (const auto* relation : incomplete_relations) {
+ std::cerr << " " << relation->id();
+ }
+ std::cerr << "\n";
+ }
+
+ google::protobuf::ShutdownProtobufLibrary();
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_convert.cpp b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_convert.cpp
new file mode 100755
index 0000000000..7956e1181c
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_convert.cpp
@@ -0,0 +1,112 @@
+/*
+
+ Convert OSM files from one format into another.
+
+ The code in this example file is released into the Public Domain.
+
+*/
+
+#include <iostream>
+#include <getopt.h>
+
+#include <osmium/io/any_input.hpp>
+
+#include <osmium/io/any_output.hpp>
+
+void print_help() {
+ std::cout << "osmium_convert [OPTIONS] [INFILE [OUTFILE]]\n\n" \
+ << "If INFILE or OUTFILE is not given stdin/stdout is assumed.\n" \
+ << "File format is autodetected from file name suffix.\n" \
+ << "Use -f and -t options to force file format.\n" \
+ << "\nFile types:\n" \
+ << " osm normal OSM file\n" \
+ << " osc OSM change file\n" \
+ << " osh OSM file with history information\n" \
+ << "\nFile format:\n" \
+ << " (default) XML encoding\n" \
+ << " pbf binary PBF encoding\n" \
+ << " opl OPL encoding\n" \
+ << "\nFile compression\n" \
+ << " gz compressed with gzip\n" \
+ << " bz2 compressed with bzip2\n" \
+ << "\nOptions:\n" \
+ << " -h, --help This help message\n" \
+ << " -f, --from-format=FORMAT Input format\n" \
+ << " -t, --to-format=FORMAT Output format\n";
+}
+
+int main(int argc, char* argv[]) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"from-format", required_argument, 0, 'f'},
+ {"to-format", required_argument, 0, 't'},
+ {0, 0, 0, 0}
+ };
+
+ std::string input_format;
+ std::string output_format;
+
+ while (true) {
+ int c = getopt_long(argc, argv, "dhf:t:", long_options, 0);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'h':
+ print_help();
+ exit(0);
+ case 'f':
+ input_format = optarg;
+ break;
+ case 't':
+ output_format = optarg;
+ break;
+ default:
+ exit(1);
+ }
+ }
+
+ std::string input;
+ std::string output;
+ int remaining_args = argc - optind;
+ if (remaining_args > 2) {
+ std::cerr << "Usage: " << argv[0] << " [OPTIONS] [INFILE [OUTFILE]]" << std::endl;
+ exit(1);
+ } else if (remaining_args == 2) {
+ input = argv[optind];
+ output = argv[optind+1];
+ } else if (remaining_args == 1) {
+ input = argv[optind];
+ }
+
+ osmium::io::File infile(input, input_format);
+
+ osmium::io::File outfile(output, output_format);
+
+ if (infile.has_multiple_object_versions() && !outfile.has_multiple_object_versions()) {
+ std::cerr << "Warning! You are converting from an OSM file with (potentially) several versions of the same object to one that is not marked as such.\n";
+ }
+
+ int exit_code = 0;
+
+ try {
+ osmium::io::Reader reader(infile);
+ osmium::io::Header header = reader.header();
+ header.set("generator", "osmium_convert");
+
+ osmium::io::Writer writer(outfile, header, osmium::io::overwrite::allow);
+ while (osmium::memory::Buffer buffer = reader.read()) {
+ writer(std::move(buffer));
+ }
+ writer.close();
+ reader.close();
+ } catch (std::exception& e) {
+ std::cerr << e.what() << "\n";
+ exit_code = 1;
+ }
+
+ google::protobuf::ShutdownProtobufLibrary();
+ return exit_code;
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_count.cpp b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_count.cpp
new file mode 100755
index 0000000000..dca18bfdc0
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_count.cpp
@@ -0,0 +1,57 @@
+/*
+
+ This is a small tool that counts the number of nodes, ways, and relations in
+ the input file.
+
+ The code in this example file is released into the Public Domain.
+
+*/
+
+#include <iostream>
+
+#include <osmium/io/any_input.hpp>
+#include <osmium/handler.hpp>
+#include <osmium/visitor.hpp>
+
+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);
+ }
+
+ osmium::io::File infile(argv[1]);
+ osmium::io::Reader reader(infile);
+
+ 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/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_create_node_cache.cpp b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_create_node_cache.cpp
new file mode 100755
index 0000000000..74f7596fe7
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_create_node_cache.cpp
@@ -0,0 +1,58 @@
+/*
+
+ This reads an OSM file and writes out the node locations to a cache
+ file.
+
+ The code in this example file is released into the Public Domain.
+
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <iostream>
+
+#include <osmium/io/pbf_input.hpp>
+#include <osmium/io/xml_input.hpp>
+
+#include <osmium/index/map/dummy.hpp>
+#include <osmium/index/map/dense_mmap_array.hpp>
+#include <osmium/index/map/dense_file_array.hpp>
+
+#include <osmium/handler/node_locations_for_ways.hpp>
+#include <osmium/visitor.hpp>
+
+typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
+//typedef osmium::index::map::DenseMmapArray<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
+typedef osmium::index::map::DenseFileArray<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
+
+typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
+
+int main(int argc, char* argv[]) {
+ if (argc != 3) {
+ std::cerr << "Usage: " << argv[0] << " OSM_FILE CACHE_FILE\n";
+ return 1;
+ }
+
+ std::string input_filename(argv[1]);
+ osmium::io::Reader reader(input_filename, osmium::osm_entity_bits::node);
+
+ int fd = open(argv[2], O_RDWR | O_CREAT, 0666);
+ if (fd == -1) {
+ std::cerr << "Can not open node cache file '" << argv[2] << "': " << strerror(errno) << "\n";
+ return 1;
+ }
+
+ index_pos_type index_pos {fd};
+ index_neg_type index_neg;
+ location_handler_type location_handler(index_pos, index_neg);
+ location_handler.ignore_errors();
+
+ osmium::apply(reader, location_handler);
+ reader.close();
+
+ google::protobuf::ShutdownProtobufLibrary();
+
+ return 0;
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_debug.cpp b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_debug.cpp
new file mode 100755
index 0000000000..6878ed1e8d
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_debug.cpp
@@ -0,0 +1,52 @@
+/*
+
+ This is a small tool to dump the contents of the input file.
+
+ The code in this example file is released into the Public Domain.
+
+*/
+
+#include <iostream>
+
+#include <osmium/handler/dump.hpp>
+#include <osmium/io/any_input.hpp>
+
+int main(int argc, char* argv[]) {
+ std::ios_base::sync_with_stdio(false);
+
+ if (argc < 2 || argc > 3) {
+ std::cerr << "Usage: " << argv[0] << " OSMFILE [TYPES]\n";
+ std::cerr << "TYPES can be any combination of 'n', 'w', 'r', and 'c' to indicate what types of OSM entities you want (default: all).\n";
+ exit(1);
+ }
+
+ osmium::osm_entity_bits::type read_types = osmium::osm_entity_bits::all;
+
+ if (argc == 3) {
+ read_types = osmium::osm_entity_bits::nothing;
+ std::string types = argv[2];
+ if (types.find('n') != std::string::npos) read_types |= osmium::osm_entity_bits::node;
+ if (types.find('w') != std::string::npos) read_types |= osmium::osm_entity_bits::way;
+ if (types.find('r') != std::string::npos) read_types |= osmium::osm_entity_bits::relation;
+ if (types.find('c') != std::string::npos) read_types |= osmium::osm_entity_bits::changeset;
+ }
+
+ osmium::io::Reader reader(argv[1], read_types);
+ osmium::io::Header header = reader.header();
+
+ std::cout << "HEADER:\n generator=" << header.get("generator") << "\n";
+
+ for (auto& bbox : header.boxes()) {
+ std::cout << " bbox=" << bbox << "\n";
+ }
+
+ osmium::handler::Dump dump(std::cout);
+ while (osmium::memory::Buffer buffer = reader.read()) {
+ osmium::apply(buffer, dump);
+ }
+
+ reader.close();
+
+ google::protobuf::ShutdownProtobufLibrary();
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_index.cpp b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_index.cpp
new file mode 100755
index 0000000000..b61214097b
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_index.cpp
@@ -0,0 +1,237 @@
+/*
+
+ Example program to look at Osmium indexes on disk.
+
+ The code in this example file is released into the Public Domain.
+
+*/
+
+#include <fcntl.h>
+#include <iomanip>
+#include <iostream>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <boost/program_options.hpp>
+
+#include <osmium/index/map/dense_file_array.hpp>
+#include <osmium/index/map/sparse_file_array.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/types.hpp>
+
+template <typename TKey, typename TValue>
+class IndexSearch {
+
+ typedef typename osmium::index::map::DenseFileArray<TKey, TValue> dense_index_type;
+ typedef typename osmium::index::map::SparseFileArray<TKey, TValue> sparse_index_type;
+
+ int m_fd;
+ bool m_dense_format;
+
+ void dump_dense() {
+ dense_index_type index(m_fd);
+
+ for (size_t i = 0; i < index.size(); ++i) {
+ if (index.get(i) != TValue()) {
+ std::cout << i << " " << index.get(i) << "\n";
+ }
+ }
+ }
+
+ void dump_sparse() {
+ sparse_index_type index(m_fd);
+
+ for (auto& element : index) {
+ std::cout << element.first << " " << element.second << "\n";
+ }
+ }
+
+ bool search_dense(TKey key) {
+ dense_index_type index(m_fd);
+
+ try {
+ TValue value = index.get(key);
+ std::cout << key << " " << value << std::endl;
+ } catch (...) {
+ std::cout << key << " not found" << std::endl;
+ return false;
+ }
+
+ return true;
+ }
+
+ bool search_sparse(TKey key) {
+ typedef typename sparse_index_type::element_type element_type;
+ sparse_index_type index(m_fd);
+
+ element_type elem {key, TValue()};
+ auto positions = std::equal_range(index.begin(), index.end(), elem, [](const element_type& lhs, const element_type& rhs) {
+ return lhs.first < rhs.first;
+ });
+ if (positions.first == positions.second) {
+ std::cout << key << " not found" << std::endl;
+ return false;
+ }
+
+ for (auto& it = positions.first; it != positions.second; ++it) {
+ std::cout << it->first << " " << it->second << "\n";
+ }
+
+ return true;
+ }
+
+public:
+
+ IndexSearch(int fd, bool dense_format) :
+ m_fd(fd),
+ m_dense_format(dense_format) {
+ }
+
+ void dump() {
+ if (m_dense_format) {
+ dump_dense();
+ } else {
+ dump_sparse();
+ }
+ }
+
+ bool search(TKey key) {
+ if (m_dense_format) {
+ return search_dense(key);
+ } else {
+ return search_sparse(key);
+ }
+ }
+
+ bool search(std::vector<TKey> keys) {
+ bool found_all = true;
+
+ for (const auto key : keys) {
+ if (!search(key)) {
+ found_all = false;
+ }
+ }
+
+ return found_all;
+ }
+
+}; // class IndexSearch
+
+enum return_code : int {
+ okay = 0,
+ not_found = 1,
+ error = 2,
+ fatal = 3
+};
+
+namespace po = boost::program_options;
+
+class Options {
+
+ po::variables_map vm;
+
+public:
+
+ Options(int argc, char* argv[]) {
+ try {
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help,h", "Print this help message")
+ ("array,a", po::value<std::string>(), "Read given index file in array format")
+ ("list,l", po::value<std::string>(), "Read given index file in list format")
+ ("dump,d", "Dump contents of index file to STDOUT")
+ ("search,s", po::value<std::vector<osmium::unsigned_object_id_type>>(), "Search for given id (Option can appear multiple times)")
+ ("type,t", po::value<std::string>(), "Type of value ('location' or 'offset')")
+ ;
+
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help")) {
+ std::cout << desc << "\n";
+ exit(return_code::okay);
+ }
+
+ if (vm.count("array") && vm.count("list")) {
+ std::cerr << "Only option --array or --list allowed." << std::endl;
+ exit(return_code::fatal);
+ }
+
+ if (!vm.count("array") && !vm.count("list")) {
+ std::cerr << "Need one of option --array or --list." << std::endl;
+ exit(return_code::fatal);
+ }
+
+ if (!vm.count("type")) {
+ std::cerr << "Need --type argument." << std::endl;
+ exit(return_code::fatal);
+ }
+
+ const std::string& type = vm["type"].as<std::string>();
+ if (type != "location" && type != "offset") {
+ std::cerr << "Unknown type '" << type << "'. Must be 'location' or 'offset'." << std::endl;
+ exit(return_code::fatal);
+ }
+ } catch (boost::program_options::error& e) {
+ std::cerr << "Error parsing command line: " << e.what() << std::endl;
+ exit(return_code::fatal);
+ }
+ }
+
+ const std::string& filename() const {
+ if (vm.count("array")) {
+ return vm["array"].as<std::string>();
+ } else {
+ return vm["list"].as<std::string>();
+ }
+ }
+
+ bool dense_format() const {
+ return vm.count("array") != 0;
+ }
+
+ bool do_dump() const {
+ return vm.count("dump") != 0;
+ }
+
+ std::vector<osmium::unsigned_object_id_type> search_keys() const {
+ return vm["search"].as<std::vector<osmium::unsigned_object_id_type>>();
+ }
+
+ bool type_is(const char* type) const {
+ return vm["type"].as<std::string>() == type;
+ }
+
+}; // class Options
+
+int main(int argc, char* argv[]) {
+ std::ios_base::sync_with_stdio(false);
+
+ Options options(argc, argv);
+
+ std::cout << std::fixed << std::setprecision(7);
+ int fd = open(options.filename().c_str(), O_RDWR);
+
+ bool result_okay = true;
+
+ if (options.type_is("location")) {
+ IndexSearch<osmium::unsigned_object_id_type, osmium::Location> is(fd, options.dense_format());
+
+ if (options.do_dump()) {
+ is.dump();
+ } else {
+ result_okay = is.search(options.search_keys());
+ }
+ } else {
+ IndexSearch<osmium::unsigned_object_id_type, size_t> is(fd, options.dense_format());
+
+ if (options.do_dump()) {
+ is.dump();
+ } else {
+ result_okay = is.search(options.search_keys());
+ }
+ }
+
+ exit(result_okay ? return_code::okay : return_code::not_found);
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_read.cpp b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_read.cpp
new file mode 100755
index 0000000000..1bb0299662
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_read.cpp
@@ -0,0 +1,32 @@
+/*
+
+ This is a small tool that reads and discards the contents of the input file.
+ (Used for timing.)
+
+ The code in this example file is released into the Public Domain.
+
+*/
+
+#include <iostream>
+
+#include <osmium/io/any_input.hpp>
+
+int main(int argc, char* argv[]) {
+
+ if (argc != 2) {
+ std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
+ exit(1);
+ }
+
+ osmium::io::File infile(argv[1]);
+ osmium::io::Reader reader(infile);
+
+ while (osmium::memory::Buffer buffer = reader.read()) {
+ // do nothing
+ }
+
+ reader.close();
+
+ google::protobuf::ShutdownProtobufLibrary();
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_serdump.cpp b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_serdump.cpp
new file mode 100755
index 0000000000..a774a8dbd3
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_serdump.cpp
@@ -0,0 +1,209 @@
+/*
+
+ This is a small tool to dump the contents of the input file
+ in serialized format to stdout.
+
+ The code in this example file is released into the Public Domain.
+
+*/
+
+#include <cerrno>
+#include <cstring>
+#include <getopt.h>
+#include <iostream>
+#include <string>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#ifdef _MSC_VER
+# include <direct.h>
+#endif
+
+#include <osmium/io/pbf_input.hpp>
+#include <osmium/io/xml_input.hpp>
+#include <osmium/handler/disk_store.hpp>
+#include <osmium/handler/object_relations.hpp>
+
+#include <osmium/index/map/sparse_mem_array.hpp>
+#include <osmium/index/multimap/sparse_mem_multimap.hpp>
+#include <osmium/index/multimap/sparse_mem_array.hpp>
+#include <osmium/index/multimap/hybrid.hpp>
+
+// ==============================================================================
+// Choose the following depending on the size of the input OSM files:
+// ==============================================================================
+// for smaller OSM files (extracts)
+typedef osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, size_t> offset_index_type;
+//typedef osmium::index::map::SparseMapMmap<osmium::unsigned_object_id_type, size_t> offset_index_type;
+//typedef osmium::index::map::SparseMapFile<osmium::unsigned_object_id_type, size_t> offset_index_type;
+
+typedef osmium::index::multimap::SparseMemArray<osmium::unsigned_object_id_type, osmium::unsigned_object_id_type> map_type;
+//typedef osmium::index::multimap::SparseMemMultimap<osmium::unsigned_object_id_type, osmium::unsigned_object_id_type> map_type;
+//typedef osmium::index::multimap::Hybrid<osmium::unsigned_object_id_type, osmium::unsigned_object_id_type> map_type;
+
+// ==============================================================================
+// for very large OSM files (planet)
+//typedef osmium::index::map::DenseMmapArray<osmium::unsigned_object_id_type, size_t> offset_index_type;
+// ==============================================================================
+
+void print_help() {
+ std::cout << "osmium_serdump OSMFILE DIR\n" \
+ << "Serialize content of OSMFILE into data file in DIR.\n" \
+ << "\nOptions:\n" \
+ << " -h, --help This help message\n";
+}
+
+int main(int argc, char* argv[]) {
+ std::ios_base::sync_with_stdio(false);
+
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0}
+ };
+
+ while (true) {
+ int c = getopt_long(argc, argv, "h", long_options, 0);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'h':
+ print_help();
+ exit(0);
+ default:
+ exit(2);
+ }
+ }
+
+ int remaining_args = argc - optind;
+
+ if (remaining_args != 2) {
+ std::cerr << "Usage: " << argv[0] << " OSMFILE DIR\n";
+ exit(2);
+ }
+
+ std::string dir(argv[optind+1]);
+#ifndef _WIN32
+ int result = ::mkdir(dir.c_str(), 0777);
+#else
+ int result = mkdir(dir.c_str());
+#endif
+ if (result == -1 && errno != EEXIST) {
+ std::cerr << "Problem creating directory '" << dir << "': " << strerror(errno) << "\n";
+ exit(2);
+ }
+
+ std::string data_file(dir + "/data.osm.ser");
+ int data_fd = ::open(data_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (data_fd < 0) {
+ std::cerr << "Can't open data file '" << data_file << "': " << strerror(errno) << "\n";
+ exit(2);
+ }
+
+ offset_index_type node_index;
+ offset_index_type way_index;
+ offset_index_type relation_index;
+
+ osmium::handler::DiskStore disk_store_handler(data_fd, node_index, way_index, relation_index);
+
+ map_type map_node2way;
+ map_type map_node2relation;
+ map_type map_way2relation;
+ map_type map_relation2relation;
+
+ osmium::handler::ObjectRelations object_relations_handler(map_node2way, map_node2relation, map_way2relation, map_relation2relation);
+
+ osmium::io::Reader reader(argv[1]);
+
+ while (osmium::memory::Buffer buffer = reader.read()) {
+ disk_store_handler(buffer); // XXX
+ osmium::apply(buffer, object_relations_handler);
+ }
+
+ reader.close();
+
+ {
+ std::string index_file(dir + "/nodes.idx");
+ int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0) {
+ std::cerr << "Can't open nodes index file '" << index_file << "': " << strerror(errno) << "\n";
+ exit(2);
+ }
+ node_index.dump_as_list(fd);
+ close(fd);
+ }
+
+ {
+ std::string index_file(dir + "/ways.idx");
+ int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0) {
+ std::cerr << "Can't open ways index file '" << index_file << "': " << strerror(errno) << "\n";
+ exit(2);
+ }
+ way_index.dump_as_list(fd);
+ close(fd);
+ }
+
+ {
+ std::string index_file(dir + "/relations.idx");
+ int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0) {
+ std::cerr << "Can't open relations index file '" << index_file << "': " << strerror(errno) << "\n";
+ exit(2);
+ }
+ relation_index.dump_as_list(fd);
+ close(fd);
+ }
+
+ {
+ map_node2way.sort();
+ std::string index_file(dir + "/node2way.map");
+ int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0) {
+ std::cerr << "Can't open node->way map file '" << index_file << "': " << strerror(errno) << "\n";
+ exit(2);
+ }
+ map_node2way.dump_as_list(fd);
+ close(fd);
+ }
+
+ {
+ map_node2relation.sort();
+ std::string index_file(dir + "/node2rel.map");
+ int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0) {
+ std::cerr << "Can't open node->rel map file '" << index_file << "': " << strerror(errno) << "\n";
+ exit(2);
+ }
+ map_node2relation.dump_as_list(fd);
+ close(fd);
+ }
+
+ {
+ map_way2relation.sort();
+ std::string index_file(dir + "/way2rel.map");
+ int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0) {
+ std::cerr << "Can't open way->rel map file '" << index_file << "': " << strerror(errno) << "\n";
+ exit(2);
+ }
+ map_way2relation.dump_as_list(fd);
+ close(fd);
+ }
+
+ {
+ map_relation2relation.sort();
+ std::string index_file(dir + "/rel2rel.map");
+ int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0) {
+ std::cerr << "Can't open rel->rel map file '" << index_file << "': " << strerror(errno) << "\n";
+ exit(2);
+ }
+ map_relation2relation.dump_as_list(fd);
+ close(fd);
+ }
+
+ google::protobuf::ShutdownProtobufLibrary();
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_toogr.cpp b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_toogr.cpp
new file mode 100755
index 0000000000..6d8ab8d940
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_toogr.cpp
@@ -0,0 +1,246 @@
+/*
+
+ This is an example tool that converts OSM data to some output format
+ like Spatialite or Shapefiles using the OGR library.
+
+ The code in this example file is released into the Public Domain.
+
+*/
+
+#include <iostream>
+#include <getopt.h>
+
+#include <osmium/index/map/all.hpp>
+#include <osmium/handler/node_locations_for_ways.hpp>
+#include <osmium/visitor.hpp>
+
+#include <osmium/geom/ogr.hpp>
+#include <osmium/io/any_input.hpp>
+#include <osmium/handler.hpp>
+
+typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
+typedef osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
+
+typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
+
+class MyOGRHandler : public osmium::handler::Handler {
+
+ OGRDataSource* m_data_source;
+ OGRLayer* m_layer_point;
+ OGRLayer* m_layer_linestring;
+
+ osmium::geom::OGRFactory<> m_factory;
+
+public:
+
+ MyOGRHandler(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<char**>(options));
+ if (!m_data_source) {
+ std::cerr << "Creation of output file failed.\n";
+ exit(1);
+ }
+
+ OGRSpatialReference sparef;
+ sparef.SetWellKnownGeogCS("WGS84");
+ m_layer_point = m_data_source->CreateLayer("postboxes", &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_operator("operator", OFTString);
+ layer_point_field_operator.SetWidth(30);
+
+ if (m_layer_point->CreateField(&layer_point_field_operator) != OGRERR_NONE) {
+ std::cerr << "Creating operator field failed.\n";
+ exit(1);
+ }
+
+ /* Transactions might make things faster, then again they might not.
+ Feel free to experiment and benchmark and report back. */
+ m_layer_point->StartTransaction();
+
+ m_layer_linestring = m_data_source->CreateLayer("roads", &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_linestring->StartTransaction();
+ }
+
+ ~MyOGRHandler() {
+ m_layer_linestring->CommitTransaction();
+ m_layer_point->CommitTransaction();
+ OGRDataSource::DestroyDataSource(m_data_source);
+ OGRCleanupAll();
+ }
+
+ void node(const osmium::Node& node) {
+ const char* amenity = node.tags().get_value_by_key("amenity");
+ if (amenity && !strcmp(amenity, "post_box")) {
+ OGRFeature* feature = OGRFeature::CreateFeature(m_layer_point->GetLayerDefn());
+ std::unique_ptr<OGRPoint> ogr_point = m_factory.create_point(node);
+ feature->SetGeometry(ogr_point.get());
+ feature->SetField("id", static_cast<double>(node.id()));
+ feature->SetField("operator", node.tags().get_value_by_key("operator"));
+
+ 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) {
+ const char* highway = way.tags().get_value_by_key("highway");
+ if (highway) {
+ try {
+ std::unique_ptr<OGRLineString> ogr_linestring = m_factory.create_linestring(way);
+ OGRFeature* feature = OGRFeature::CreateFeature(m_layer_linestring->GetLayerDefn());
+ feature->SetGeometry(ogr_linestring.get());
+ feature->SetField("id", static_cast<double>(way.id()));
+ feature->SetField("type", highway);
+
+ 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 print_help() {
+ std::cout << "osmium_toogr [OPTIONS] [INFILE [OUTFILE]]\n\n" \
+ << "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" \
+ << " -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<osmium::unsigned_object_id_type, osmium::Location>::instance();
+
+ static struct option long_options[] = {
+ {"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 location_store { "sparse_mem_array" };
+
+ while (true) {
+ int c = getopt_long(argc, argv, "hf:l:L", long_options, 0);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'h':
+ print_help();
+ exit(0);
+ 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);
+ }
+ }
+
+ std::string input_filename;
+ std::string output_filename("ogr_out");
+ int remaining_args = argc - optind;
+ if (remaining_args > 2) {
+ std::cerr << "Usage: " << argv[0] << " [OPTIONS] [INFILE [OUTFILE]]" << std::endl;
+ exit(1);
+ } else if (remaining_args == 2) {
+ input_filename = argv[optind];
+ output_filename = argv[optind+1];
+ } else if (remaining_args == 1) {
+ input_filename = argv[optind];
+ } else {
+ input_filename = "-";
+ }
+
+ osmium::io::Reader reader(input_filename);
+
+ std::unique_ptr<index_pos_type> index_pos = map_factory.create_map(location_store);
+ index_neg_type index_neg;
+ location_handler_type location_handler(*index_pos, index_neg);
+ location_handler.ignore_errors();
+
+ MyOGRHandler ogr_handler(output_format, output_filename);
+
+ osmium::apply(reader, location_handler, ogr_handler);
+ reader.close();
+
+ google::protobuf::ShutdownProtobufLibrary();
+
+ int locations_fd = open("locations.dump", O_WRONLY | O_CREAT, 0644);
+ if (locations_fd < 0) {
+ throw std::system_error(errno, std::system_category(), "Open failed");
+ }
+ index_pos->dump_as_list(locations_fd);
+ close(locations_fd);
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_toogr2.cpp b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_toogr2.cpp
new file mode 100755
index 0000000000..a966c5edcc
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_toogr2.cpp
@@ -0,0 +1,333 @@
+/*
+
+ This is an example tool that converts OSM data to some output format
+ like Spatialite or Shapefiles using the OGR library.
+
+ This version does multipolygon handling (in contrast to the osmium_toogr
+ example which doesn't).
+
+ The code in this example file is released into the Public Domain.
+
+*/
+
+#include <iostream>
+#include <getopt.h>
+
+// usually you only need one or two of these
+#include <osmium/index/map/dummy.hpp>
+#include <osmium/index/map/sparse_mem_array.hpp>
+
+#include <osmium/handler/node_locations_for_ways.hpp>
+#include <osmium/visitor.hpp>
+#include <osmium/area/multipolygon_collector.hpp>
+#include <osmium/area/assembler.hpp>
+
+#include <osmium/geom/mercator_projection.hpp>
+//#include <osmium/geom/projection.hpp>
+#include <osmium/geom/ogr.hpp>
+#include <osmium/io/any_input.hpp>
+#include <osmium/handler.hpp>
+
+typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
+
+typedef osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
+
+typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
+
+class MyOGRHandler : public osmium::handler::Handler {
+
+ OGRDataSource* m_data_source;
+ OGRLayer* m_layer_point;
+ OGRLayer* m_layer_linestring;
+ OGRLayer* m_layer_polygon;
+
+ // Choose one of the following:
+
+ // 1. Use WGS84, do not project coordinates.
+ //osmium::geom::OGRFactory<> m_factory {};
+
+ // 2. Project coordinates into "Web Mercator".
+ osmium::geom::OGRFactory<osmium::geom::MercatorProjection> m_factory;
+
+ // 3. Use any projection that the proj library can handle.
+ // (Initialize projection with EPSG code or proj string).
+ // In addition you need to link with "-lproj" and add
+ // #include <osmium/geom/projection.hpp>.
+ //osmium::geom::OGRFactory<osmium::geom::Projection> m_factory {osmium::geom::Projection(3857)};
+
+public:
+
+ MyOGRHandler(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<char**>(options));
+ if (!m_data_source) {
+ std::cerr << "Creation of output file failed.\n";
+ exit(1);
+ }
+
+ OGRSpatialReference sparef;
+ sparef.importFromProj4(m_factory.proj_string().c_str());
+
+ m_layer_point = m_data_source->CreateLayer("postboxes", &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_operator("operator", OFTString);
+ layer_point_field_operator.SetWidth(30);
+
+ if (m_layer_point->CreateField(&layer_point_field_operator) != OGRERR_NONE) {
+ std::cerr << "Creating operator field failed.\n";
+ exit(1);
+ }
+
+ /* Transactions might make things faster, then again they might not.
+ Feel free to experiment and benchmark and report back. */
+ m_layer_point->StartTransaction();
+
+ m_layer_linestring = m_data_source->CreateLayer("roads", &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_linestring->StartTransaction();
+
+ m_layer_polygon = m_data_source->CreateLayer("buildings", &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_type("type", OFTString);
+ layer_polygon_field_type.SetWidth(30);
+
+ if (m_layer_polygon->CreateField(&layer_polygon_field_type) != OGRERR_NONE) {
+ std::cerr << "Creating type field failed.\n";
+ exit(1);
+ }
+
+ m_layer_polygon->StartTransaction();
+ }
+
+ ~MyOGRHandler() {
+ m_layer_polygon->CommitTransaction();
+ m_layer_linestring->CommitTransaction();
+ m_layer_point->CommitTransaction();
+ OGRDataSource::DestroyDataSource(m_data_source);
+ OGRCleanupAll();
+ }
+
+ void node(const osmium::Node& node) {
+ const char* amenity = node.tags()["amenity"];
+ if (amenity && !strcmp(amenity, "post_box")) {
+ OGRFeature* feature = OGRFeature::CreateFeature(m_layer_point->GetLayerDefn());
+ std::unique_ptr<OGRPoint> ogr_point = m_factory.create_point(node);
+ feature->SetGeometry(ogr_point.get());
+ feature->SetField("id", static_cast<double>(node.id()));
+ feature->SetField("operator", node.tags()["operator"]);
+
+ 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) {
+ const char* highway = way.tags()["highway"];
+ if (highway) {
+ try {
+ std::unique_ptr<OGRLineString> ogr_linestring = m_factory.create_linestring(way);
+ OGRFeature* feature = OGRFeature::CreateFeature(m_layer_linestring->GetLayerDefn());
+ feature->SetGeometry(ogr_linestring.get());
+ feature->SetField("id", static_cast<double>(way.id()));
+ feature->SetField("type", highway);
+
+ 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) {
+ const char* building = area.tags()["building"];
+ if (building) {
+ try {
+ std::unique_ptr<OGRMultiPolygon> ogr_polygon = m_factory.create_multipolygon(area);
+ OGRFeature* feature = OGRFeature::CreateFeature(m_layer_polygon->GetLayerDefn());
+ feature->SetGeometry(ogr_polygon.get());
+ feature->SetField("id", static_cast<int>(area.id()));
+ feature->SetField("type", building);
+
+ std::string type = "";
+ if (area.from_way()) {
+ type += "w";
+ } else {
+ type += "r";
+ }
+ feature->SetField("type", 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";
+ }
+ }
+ }
+
+};
+
+/* ================================================== */
+
+void print_help() {
+ std::cout << "osmium_toogr [OPTIONS] [INFILE [OUTFILE]]\n\n" \
+ << "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" \
+ << " -d, --debug Enable debug output\n" \
+ << " -f, --format=FORMAT Output OGR format (Default: 'SQLite')\n";
+}
+
+int main(int argc, char* argv[]) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"debug", no_argument, 0, 'd'},
+ {"format", required_argument, 0, 'f'},
+ {0, 0, 0, 0}
+ };
+
+ std::string output_format("SQLite");
+ bool debug = false;
+
+ while (true) {
+ int c = getopt_long(argc, argv, "hdf:", long_options, 0);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'h':
+ print_help();
+ exit(0);
+ case 'd':
+ debug = true;
+ break;
+ case 'f':
+ output_format = optarg;
+ break;
+ default:
+ exit(1);
+ }
+ }
+
+ std::string input_filename;
+ std::string output_filename("ogr_out");
+ int remaining_args = argc - optind;
+ if (remaining_args > 2) {
+ std::cerr << "Usage: " << argv[0] << " [OPTIONS] [INFILE [OUTFILE]]" << std::endl;
+ exit(1);
+ } else if (remaining_args == 2) {
+ input_filename = argv[optind];
+ output_filename = argv[optind+1];
+ } else if (remaining_args == 1) {
+ input_filename = argv[optind];
+ } else {
+ input_filename = "-";
+ }
+
+ osmium::area::Assembler::config_type assembler_config;
+ assembler_config.enable_debug_output(debug);
+ osmium::area::MultipolygonCollector<osmium::area::Assembler> 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_pos_type index_pos;
+ index_neg_type index_neg;
+ location_handler_type location_handler(index_pos, index_neg);
+ location_handler.ignore_errors();
+
+ MyOGRHandler ogr_handler(output_format, output_filename);
+
+ std::cerr << "Pass 2...\n";
+ osmium::io::Reader reader2(input_filename);
+
+ osmium::apply(reader2, location_handler, ogr_handler, collector.handler([&ogr_handler](const osmium::memory::Buffer& area_buffer) {
+ osmium::apply(area_buffer, ogr_handler);
+ }));
+
+ reader2.close();
+ std::cerr << "Pass 2 done\n";
+
+ std::vector<const osmium::Relation*> incomplete_relations = collector.get_incomplete_relations();
+ if (!incomplete_relations.empty()) {
+ std::cerr << "Warning! Some member ways missing for these multipolygon relations:";
+ for (const auto* relation : incomplete_relations) {
+ std::cerr << " " << relation->id();
+ }
+ std::cerr << "\n";
+ }
+
+ google::protobuf::ShutdownProtobufLibrary();
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_toogr2_exp.cpp b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_toogr2_exp.cpp
new file mode 100755
index 0000000000..474da96d01
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_toogr2_exp.cpp
@@ -0,0 +1,307 @@
+/*
+
+ This is an example tool that converts OSM data to some output format
+ like Spatialite or Shapefiles using the OGR library.
+
+ This version does multipolygon handling (in contrast to the osmium_toogr
+ example which doesn't).
+
+ This version (..._exp) uses a new experimental unsupported interface.
+
+ The code in this example file is released into the Public Domain.
+
+*/
+
+#include <iostream>
+#include <getopt.h>
+
+#include <osmium/index/map/sparse_mem_array.hpp>
+
+#include <osmium/visitor.hpp>
+
+#include <osmium/geom/mercator_projection.hpp>
+//#include <osmium/geom/projection.hpp>
+#include <osmium/geom/ogr.hpp>
+#include <osmium/io/any_input.hpp>
+#include <osmium/handler.hpp>
+#include <osmium/experimental/flex_reader.hpp>
+
+typedef osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location> index_type;
+typedef osmium::handler::NodeLocationsForWays<index_type> location_handler_type;
+
+class MyOGRHandler : public osmium::handler::Handler {
+
+ OGRDataSource* m_data_source;
+ OGRLayer* m_layer_point;
+ OGRLayer* m_layer_linestring;
+ OGRLayer* m_layer_polygon;
+
+ // Choose one of the following:
+
+ // 1. Use WGS84, do not project coordinates.
+ //osmium::geom::OGRFactory<> m_factory {};
+
+ // 2. Project coordinates into "Web Mercator".
+ osmium::geom::OGRFactory<osmium::geom::MercatorProjection> m_factory;
+
+ // 3. Use any projection that the proj library can handle.
+ // (Initialize projection with EPSG code or proj string).
+ // In addition you need to link with "-lproj" and add
+ // #include <osmium/geom/projection.hpp>.
+ //osmium::geom::OGRFactory<osmium::geom::Projection> m_factory {osmium::geom::Projection(3857)};
+
+public:
+
+ MyOGRHandler(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<char**>(options));
+ if (!m_data_source) {
+ std::cerr << "Creation of output file failed.\n";
+ exit(1);
+ }
+
+ OGRSpatialReference sparef;
+ sparef.importFromProj4(m_factory.proj_string().c_str());
+
+ m_layer_point = m_data_source->CreateLayer("postboxes", &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_operator("operator", OFTString);
+ layer_point_field_operator.SetWidth(30);
+
+ if (m_layer_point->CreateField(&layer_point_field_operator) != OGRERR_NONE) {
+ std::cerr << "Creating operator field failed.\n";
+ exit(1);
+ }
+
+ /* Transactions might make things faster, then again they might not.
+ Feel free to experiment and benchmark and report back. */
+ m_layer_point->StartTransaction();
+
+ m_layer_linestring = m_data_source->CreateLayer("roads", &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_linestring->StartTransaction();
+
+ m_layer_polygon = m_data_source->CreateLayer("buildings", &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_type("type", OFTString);
+ layer_polygon_field_type.SetWidth(30);
+
+ if (m_layer_polygon->CreateField(&layer_polygon_field_type) != OGRERR_NONE) {
+ std::cerr << "Creating type field failed.\n";
+ exit(1);
+ }
+
+ m_layer_polygon->StartTransaction();
+ }
+
+ ~MyOGRHandler() {
+ m_layer_polygon->CommitTransaction();
+ m_layer_linestring->CommitTransaction();
+ m_layer_point->CommitTransaction();
+ OGRDataSource::DestroyDataSource(m_data_source);
+ OGRCleanupAll();
+ }
+
+ void node(const osmium::Node& node) {
+ const char* amenity = node.tags()["amenity"];
+ if (amenity && !strcmp(amenity, "post_box")) {
+ OGRFeature* feature = OGRFeature::CreateFeature(m_layer_point->GetLayerDefn());
+ std::unique_ptr<OGRPoint> ogr_point = m_factory.create_point(node);
+ feature->SetGeometry(ogr_point.get());
+ feature->SetField("id", static_cast<double>(node.id()));
+ feature->SetField("operator", node.tags()["operator"]);
+
+ 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) {
+ const char* highway = way.tags()["highway"];
+ if (highway) {
+ try {
+ std::unique_ptr<OGRLineString> ogr_linestring = m_factory.create_linestring(way);
+ OGRFeature* feature = OGRFeature::CreateFeature(m_layer_linestring->GetLayerDefn());
+ feature->SetGeometry(ogr_linestring.get());
+ feature->SetField("id", static_cast<double>(way.id()));
+ feature->SetField("type", highway);
+
+ 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) {
+ const char* building = area.tags()["building"];
+ if (building) {
+ try {
+ std::unique_ptr<OGRMultiPolygon> ogr_polygon = m_factory.create_multipolygon(area);
+ OGRFeature* feature = OGRFeature::CreateFeature(m_layer_polygon->GetLayerDefn());
+ feature->SetGeometry(ogr_polygon.get());
+ feature->SetField("id", static_cast<int>(area.id()));
+ feature->SetField("type", building);
+
+ std::string type = "";
+ if (area.from_way()) {
+ type += "w";
+ } else {
+ type += "r";
+ }
+ feature->SetField("type", 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";
+ }
+ }
+ }
+
+};
+
+/* ================================================== */
+
+void print_help() {
+ std::cout << "osmium_toogr [OPTIONS] [INFILE [OUTFILE]]\n\n" \
+ << "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";
+}
+
+int main(int argc, char* argv[]) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"format", required_argument, 0, 'f'},
+ {0, 0, 0, 0}
+ };
+
+ std::string output_format("SQLite");
+
+ while (true) {
+ int c = getopt_long(argc, argv, "hf:", long_options, 0);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'h':
+ print_help();
+ exit(0);
+ case 'f':
+ output_format = optarg;
+ break;
+ default:
+ exit(1);
+ }
+ }
+
+ std::string input_filename;
+ std::string output_filename("ogr_out");
+ int remaining_args = argc - optind;
+ if (remaining_args > 2) {
+ std::cerr << "Usage: " << argv[0] << " [OPTIONS] [INFILE [OUTFILE]]" << std::endl;
+ exit(1);
+ } else if (remaining_args == 2) {
+ input_filename = argv[optind];
+ output_filename = argv[optind+1];
+ } else if (remaining_args == 1) {
+ input_filename = argv[optind];
+ } else {
+ input_filename = "-";
+ }
+
+ index_type index_pos;
+ location_handler_type location_handler(index_pos);
+ osmium::experimental::FlexReader<location_handler_type> exr(input_filename, location_handler, osmium::osm_entity_bits::object);
+
+ MyOGRHandler ogr_handler(output_format, output_filename);
+
+ while (auto buffer = exr.read()) {
+ osmium::apply(buffer, ogr_handler);
+ }
+
+ exr.close();
+
+ std::vector<const osmium::Relation*> incomplete_relations = exr.collector().get_incomplete_relations();
+ if (!incomplete_relations.empty()) {
+ std::cerr << "Warning! Some member ways missing for these multipolygon relations:";
+ for (const auto* relation : incomplete_relations) {
+ std::cerr << " " << relation->id();
+ }
+ std::cerr << "\n";
+ }
+
+ google::protobuf::ShutdownProtobufLibrary();
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_use_node_cache.cpp b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_use_node_cache.cpp
new file mode 100755
index 0000000000..6b8f964aba
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/examples/osmium_use_node_cache.cpp
@@ -0,0 +1,71 @@
+/*
+
+ This reads ways from an OSM file and writes out the node locations
+ it got from a node cache generated with osmium_create_node_cache.
+
+ The code in this example file is released into the Public Domain.
+
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <iostream>
+
+#include <osmium/io/pbf_input.hpp>
+#include <osmium/io/xml_input.hpp>
+
+#include <osmium/index/map/dummy.hpp>
+#include <osmium/index/map/dense_file_array.hpp>
+#include <osmium/index/map/dense_mmap_array.hpp>
+
+#include <osmium/handler/node_locations_for_ways.hpp>
+#include <osmium/visitor.hpp>
+
+typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
+//typedef osmium::index::map::DenseMmapArray<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
+typedef osmium::index::map::DenseFileArray<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
+
+typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
+
+class MyHandler : public osmium::handler::Handler {
+
+public:
+
+ void way(osmium::Way& way) {
+ for (auto& nr : way.nodes()) {
+ std::cout << nr << "\n";
+ }
+ }
+
+}; // class MyHandler
+
+int main(int argc, char* argv[]) {
+ if (argc != 3) {
+ std::cerr << "Usage: " << argv[0] << " OSM_FILE CACHE_FILE\n";
+ return 1;
+ }
+
+ std::string input_filename(argv[1]);
+ osmium::io::Reader reader(input_filename, osmium::osm_entity_bits::way);
+
+ int fd = open(argv[2], O_RDWR);
+ if (fd == -1) {
+ std::cerr << "Can not open node cache file '" << argv[2] << "': " << strerror(errno) << "\n";
+ return 1;
+ }
+
+ index_pos_type index_pos {fd};
+ index_neg_type index_neg;
+ location_handler_type location_handler(index_pos, index_neg);
+ location_handler.ignore_errors();
+
+ MyHandler handler;
+ osmium::apply(reader, location_handler, handler);
+ reader.close();
+
+ google::protobuf::ShutdownProtobufLibrary();
+
+ return 0;
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/boost_unicode_iterator.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/boost_unicode_iterator.hpp
new file mode 100755
index 0000000000..3a7b68fbe7
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/boost_unicode_iterator.hpp
@@ -0,0 +1,776 @@
+/*
+ *
+ * Copyright (c) 2004
+ * John Maddock
+ *
+ * Use, modification and distribution are subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+ /*
+ * LOCATION: see http://www.boost.org for most recent version.
+ * FILE unicode_iterator.hpp
+ * VERSION see <boost/version.hpp>
+ * DESCRIPTION: Iterator adapters for converting between different Unicode encodings.
+ */
+
+/****************************************************************************
+
+Contents:
+~~~~~~~~~
+
+1) Read Only, Input Adapters:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+template <class BaseIterator, class U8Type = ::boost::uint8_t>
+class u32_to_u8_iterator;
+
+Adapts sequence of UTF-32 code points to "look like" a sequence of UTF-8.
+
+template <class BaseIterator, class U32Type = ::boost::uint32_t>
+class u8_to_u32_iterator;
+
+Adapts sequence of UTF-8 code points to "look like" a sequence of UTF-32.
+
+template <class BaseIterator, class U16Type = ::boost::uint16_t>
+class u32_to_u16_iterator;
+
+Adapts sequence of UTF-32 code points to "look like" a sequence of UTF-16.
+
+template <class BaseIterator, class U32Type = ::boost::uint32_t>
+class u16_to_u32_iterator;
+
+Adapts sequence of UTF-16 code points to "look like" a sequence of UTF-32.
+
+2) Single pass output iterator adapters:
+
+template <class BaseIterator>
+class utf8_output_iterator;
+
+Accepts UTF-32 code points and forwards them on as UTF-8 code points.
+
+template <class BaseIterator>
+class utf16_output_iterator;
+
+Accepts UTF-32 code points and forwards them on as UTF-16 code points.
+
+****************************************************************************/
+
+#ifndef BOOST_REGEX_UNICODE_ITERATOR_HPP
+#define BOOST_REGEX_UNICODE_ITERATOR_HPP
+#include <boost/cstdint.hpp>
+#include <boost/assert.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/throw_exception.hpp>
+#include <stdexcept>
+#ifndef BOOST_NO_STD_LOCALE
+#include <sstream>
+#include <ios>
+#endif
+#include <limits.h> // CHAR_BIT
+
+namespace boost{
+
+namespace detail{
+
+static const ::boost::uint16_t high_surrogate_base = 0xD7C0u;
+static const ::boost::uint16_t low_surrogate_base = 0xDC00u;
+static const ::boost::uint32_t ten_bit_mask = 0x3FFu;
+
+inline bool is_high_surrogate(::boost::uint16_t v)
+{
+ return (v & 0xFFFFFC00u) == 0xd800u;
+}
+inline bool is_low_surrogate(::boost::uint16_t v)
+{
+ return (v & 0xFFFFFC00u) == 0xdc00u;
+}
+template <class T>
+inline bool is_surrogate(T v)
+{
+ return (v & 0xFFFFF800u) == 0xd800;
+}
+
+inline unsigned utf8_byte_count(boost::uint8_t c)
+{
+ // if the most significant bit with a zero in it is in position
+ // 8-N then there are N bytes in this UTF-8 sequence:
+ boost::uint8_t mask = 0x80u;
+ unsigned result = 0;
+ while(c & mask)
+ {
+ ++result;
+ mask >>= 1;
+ }
+ return (result == 0) ? 1 : ((result > 4) ? 4 : result);
+}
+
+inline unsigned utf8_trailing_byte_count(boost::uint8_t c)
+{
+ return utf8_byte_count(c) - 1;
+}
+
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4100)
+#endif
+inline void invalid_utf32_code_point(::boost::uint32_t val)
+{
+#ifndef BOOST_NO_STD_LOCALE
+ std::stringstream ss;
+ ss << "Invalid UTF-32 code point U+" << std::showbase << std::hex << val << " encountered while trying to encode UTF-16 sequence";
+ std::out_of_range e(ss.str());
+#else
+ std::out_of_range e("Invalid UTF-32 code point encountered while trying to encode UTF-16 sequence");
+#endif
+ boost::throw_exception(e);
+}
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+
+} // namespace detail
+
+template <class BaseIterator, class U16Type = ::boost::uint16_t>
+class u32_to_u16_iterator
+ : public boost::iterator_facade<u32_to_u16_iterator<BaseIterator, U16Type>, U16Type, std::bidirectional_iterator_tag, const U16Type>
+{
+ typedef boost::iterator_facade<u32_to_u16_iterator<BaseIterator, U16Type>, U16Type, std::bidirectional_iterator_tag, const U16Type> base_type;
+
+#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+ typedef typename std::iterator_traits<BaseIterator>::value_type base_value_type;
+
+ BOOST_STATIC_ASSERT(sizeof(base_value_type)*CHAR_BIT == 32);
+ BOOST_STATIC_ASSERT(sizeof(U16Type)*CHAR_BIT == 16);
+#endif
+
+public:
+ typename base_type::reference
+ dereference()const
+ {
+ if(m_current == 2)
+ extract_current();
+ return m_values[m_current];
+ }
+ bool equal(const u32_to_u16_iterator& that)const
+ {
+ if(m_position == that.m_position)
+ {
+ // Both m_currents must be equal, or both even
+ // this is the same as saying their sum must be even:
+ return (m_current + that.m_current) & 1u ? false : true;
+ }
+ return false;
+ }
+ void increment()
+ {
+ // if we have a pending read then read now, so that we know whether
+ // to skip a position, or move to a low-surrogate:
+ if(m_current == 2)
+ {
+ // pending read:
+ extract_current();
+ }
+ // move to the next surrogate position:
+ ++m_current;
+ // if we've reached the end skip a position:
+ if(m_values[m_current] == 0)
+ {
+ m_current = 2;
+ ++m_position;
+ }
+ }
+ void decrement()
+ {
+ if(m_current != 1)
+ {
+ // decrementing an iterator always leads to a valid position:
+ --m_position;
+ extract_current();
+ m_current = m_values[1] ? 1 : 0;
+ }
+ else
+ {
+ m_current = 0;
+ }
+ }
+ BaseIterator base()const
+ {
+ return m_position;
+ }
+ // construct:
+ u32_to_u16_iterator() : m_position(), m_current(0)
+ {
+ m_values[0] = 0;
+ m_values[1] = 0;
+ m_values[2] = 0;
+ }
+ u32_to_u16_iterator(BaseIterator b) : m_position(b), m_current(2)
+ {
+ m_values[0] = 0;
+ m_values[1] = 0;
+ m_values[2] = 0;
+ }
+private:
+
+ void extract_current()const
+ {
+ // begin by checking for a code point out of range:
+ ::boost::uint32_t v = *m_position;
+ if(v >= 0x10000u)
+ {
+ if(v > 0x10FFFFu)
+ detail::invalid_utf32_code_point(*m_position);
+ // split into two surrogates:
+ m_values[0] = static_cast<U16Type>(v >> 10) + detail::high_surrogate_base;
+ m_values[1] = static_cast<U16Type>(v & detail::ten_bit_mask) + detail::low_surrogate_base;
+ m_current = 0;
+ BOOST_ASSERT(detail::is_high_surrogate(m_values[0]));
+ BOOST_ASSERT(detail::is_low_surrogate(m_values[1]));
+ }
+ else
+ {
+ // 16-bit code point:
+ m_values[0] = static_cast<U16Type>(*m_position);
+ m_values[1] = 0;
+ m_current = 0;
+ // value must not be a surrogate:
+ if(detail::is_surrogate(m_values[0]))
+ detail::invalid_utf32_code_point(*m_position);
+ }
+ }
+ BaseIterator m_position;
+ mutable U16Type m_values[3];
+ mutable unsigned m_current;
+};
+
+template <class BaseIterator, class U32Type = ::boost::uint32_t>
+class u16_to_u32_iterator
+ : public boost::iterator_facade<u16_to_u32_iterator<BaseIterator, U32Type>, U32Type, std::bidirectional_iterator_tag, const U32Type>
+{
+ typedef boost::iterator_facade<u16_to_u32_iterator<BaseIterator, U32Type>, U32Type, std::bidirectional_iterator_tag, const U32Type> base_type;
+ // special values for pending iterator reads:
+ BOOST_STATIC_CONSTANT(U32Type, pending_read = 0xffffffffu);
+
+#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+ typedef typename std::iterator_traits<BaseIterator>::value_type base_value_type;
+
+ BOOST_STATIC_ASSERT(sizeof(base_value_type)*CHAR_BIT == 16);
+ BOOST_STATIC_ASSERT(sizeof(U32Type)*CHAR_BIT == 32);
+#endif
+
+public:
+ typename base_type::reference
+ dereference()const
+ {
+ if(m_value == pending_read)
+ extract_current();
+ return m_value;
+ }
+ bool equal(const u16_to_u32_iterator& that)const
+ {
+ return m_position == that.m_position;
+ }
+ void increment()
+ {
+ // skip high surrogate first if there is one:
+ if(detail::is_high_surrogate(*m_position)) ++m_position;
+ ++m_position;
+ m_value = pending_read;
+ }
+ void decrement()
+ {
+ --m_position;
+ // if we have a low surrogate then go back one more:
+ if(detail::is_low_surrogate(*m_position))
+ --m_position;
+ m_value = pending_read;
+ }
+ BaseIterator base()const
+ {
+ return m_position;
+ }
+ // construct:
+ u16_to_u32_iterator() : m_position()
+ {
+ m_value = pending_read;
+ }
+ u16_to_u32_iterator(BaseIterator b) : m_position(b)
+ {
+ m_value = pending_read;
+ }
+ //
+ // Range checked version:
+ //
+ u16_to_u32_iterator(BaseIterator b, BaseIterator start, BaseIterator end) : m_position(b)
+ {
+ m_value = pending_read;
+ //
+ // The range must not start with a low surrogate, or end in a high surrogate,
+ // otherwise we run the risk of running outside the underlying input range.
+ // Likewise b must not be located at a low surrogate.
+ //
+ boost::uint16_t val;
+ if(start != end)
+ {
+ if((b != start) && (b != end))
+ {
+ val = *b;
+ if(detail::is_surrogate(val) && ((val & 0xFC00u) == 0xDC00u))
+ invalid_code_point(val);
+ }
+ val = *start;
+ if(detail::is_surrogate(val) && ((val & 0xFC00u) == 0xDC00u))
+ invalid_code_point(val);
+ val = *--end;
+ if(detail::is_high_surrogate(val))
+ invalid_code_point(val);
+ }
+ }
+private:
+ static void invalid_code_point(::boost::uint16_t val)
+ {
+#ifndef BOOST_NO_STD_LOCALE
+ std::stringstream ss;
+ ss << "Misplaced UTF-16 surrogate U+" << std::showbase << std::hex << val << " encountered while trying to encode UTF-32 sequence";
+ std::out_of_range e(ss.str());
+#else
+ std::out_of_range e("Misplaced UTF-16 surrogate encountered while trying to encode UTF-32 sequence");
+#endif
+ boost::throw_exception(e);
+ }
+ void extract_current()const
+ {
+ m_value = static_cast<U32Type>(static_cast< ::boost::uint16_t>(*m_position));
+ // if the last value is a high surrogate then adjust m_position and m_value as needed:
+ if(detail::is_high_surrogate(*m_position))
+ {
+ // precondition; next value must have be a low-surrogate:
+ BaseIterator next(m_position);
+ ::boost::uint16_t t = *++next;
+ if((t & 0xFC00u) != 0xDC00u)
+ invalid_code_point(t);
+ m_value = (m_value - detail::high_surrogate_base) << 10;
+ m_value |= (static_cast<U32Type>(static_cast< ::boost::uint16_t>(t)) & detail::ten_bit_mask);
+ }
+ // postcondition; result must not be a surrogate:
+ if(detail::is_surrogate(m_value))
+ invalid_code_point(static_cast< ::boost::uint16_t>(m_value));
+ }
+ BaseIterator m_position;
+ mutable U32Type m_value;
+};
+
+template <class BaseIterator, class U8Type = ::boost::uint8_t>
+class u32_to_u8_iterator
+ : public boost::iterator_facade<u32_to_u8_iterator<BaseIterator, U8Type>, U8Type, std::bidirectional_iterator_tag, const U8Type>
+{
+ typedef boost::iterator_facade<u32_to_u8_iterator<BaseIterator, U8Type>, U8Type, std::bidirectional_iterator_tag, const U8Type> base_type;
+
+#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+ typedef typename std::iterator_traits<BaseIterator>::value_type base_value_type;
+
+ BOOST_STATIC_ASSERT(sizeof(base_value_type)*CHAR_BIT == 32);
+ BOOST_STATIC_ASSERT(sizeof(U8Type)*CHAR_BIT == 8);
+#endif
+
+public:
+ typename base_type::reference
+ dereference()const
+ {
+ if(m_current == 4)
+ extract_current();
+ return m_values[m_current];
+ }
+ bool equal(const u32_to_u8_iterator& that)const
+ {
+ if(m_position == that.m_position)
+ {
+ // either the m_current's must be equal, or one must be 0 and
+ // the other 4: which means neither must have bits 1 or 2 set:
+ return (m_current == that.m_current)
+ || (((m_current | that.m_current) & 3) == 0);
+ }
+ return false;
+ }
+ void increment()
+ {
+ // if we have a pending read then read now, so that we know whether
+ // to skip a position, or move to a low-surrogate:
+ if(m_current == 4)
+ {
+ // pending read:
+ extract_current();
+ }
+ // move to the next surrogate position:
+ ++m_current;
+ // if we've reached the end skip a position:
+ if(m_values[m_current] == 0)
+ {
+ m_current = 4;
+ ++m_position;
+ }
+ }
+ void decrement()
+ {
+ if((m_current & 3) == 0)
+ {
+ --m_position;
+ extract_current();
+ m_current = 3;
+ while(m_current && (m_values[m_current] == 0))
+ --m_current;
+ }
+ else
+ --m_current;
+ }
+ BaseIterator base()const
+ {
+ return m_position;
+ }
+ // construct:
+ u32_to_u8_iterator() : m_position(), m_current(0)
+ {
+ m_values[0] = 0;
+ m_values[1] = 0;
+ m_values[2] = 0;
+ m_values[3] = 0;
+ m_values[4] = 0;
+ }
+ u32_to_u8_iterator(BaseIterator b) : m_position(b), m_current(4)
+ {
+ m_values[0] = 0;
+ m_values[1] = 0;
+ m_values[2] = 0;
+ m_values[3] = 0;
+ m_values[4] = 0;
+ }
+private:
+
+ void extract_current()const
+ {
+ boost::uint32_t c = *m_position;
+ if(c > 0x10FFFFu)
+ detail::invalid_utf32_code_point(c);
+ if(c < 0x80u)
+ {
+ m_values[0] = static_cast<unsigned char>(c);
+ m_values[1] = static_cast<unsigned char>(0u);
+ m_values[2] = static_cast<unsigned char>(0u);
+ m_values[3] = static_cast<unsigned char>(0u);
+ }
+ else if(c < 0x800u)
+ {
+ m_values[0] = static_cast<unsigned char>(0xC0u + (c >> 6));
+ m_values[1] = static_cast<unsigned char>(0x80u + (c & 0x3Fu));
+ m_values[2] = static_cast<unsigned char>(0u);
+ m_values[3] = static_cast<unsigned char>(0u);
+ }
+ else if(c < 0x10000u)
+ {
+ m_values[0] = static_cast<unsigned char>(0xE0u + (c >> 12));
+ m_values[1] = static_cast<unsigned char>(0x80u + ((c >> 6) & 0x3Fu));
+ m_values[2] = static_cast<unsigned char>(0x80u + (c & 0x3Fu));
+ m_values[3] = static_cast<unsigned char>(0u);
+ }
+ else
+ {
+ m_values[0] = static_cast<unsigned char>(0xF0u + (c >> 18));
+ m_values[1] = static_cast<unsigned char>(0x80u + ((c >> 12) & 0x3Fu));
+ m_values[2] = static_cast<unsigned char>(0x80u + ((c >> 6) & 0x3Fu));
+ m_values[3] = static_cast<unsigned char>(0x80u + (c & 0x3Fu));
+ }
+ m_current= 0;
+ }
+ BaseIterator m_position;
+ mutable U8Type m_values[5];
+ mutable unsigned m_current;
+};
+
+template <class BaseIterator, class U32Type = ::boost::uint32_t>
+class u8_to_u32_iterator
+ : public boost::iterator_facade<u8_to_u32_iterator<BaseIterator, U32Type>, U32Type, std::bidirectional_iterator_tag, const U32Type>
+{
+ typedef boost::iterator_facade<u8_to_u32_iterator<BaseIterator, U32Type>, U32Type, std::bidirectional_iterator_tag, const U32Type> base_type;
+ // special values for pending iterator reads:
+ BOOST_STATIC_CONSTANT(U32Type, pending_read = 0xffffffffu);
+
+#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+ typedef typename std::iterator_traits<BaseIterator>::value_type base_value_type;
+
+ BOOST_STATIC_ASSERT(sizeof(base_value_type)*CHAR_BIT == 8);
+ BOOST_STATIC_ASSERT(sizeof(U32Type)*CHAR_BIT == 32);
+#endif
+
+public:
+ typename base_type::reference
+ dereference()const
+ {
+ if(m_value == pending_read)
+ extract_current();
+ return m_value;
+ }
+ bool equal(const u8_to_u32_iterator& that)const
+ {
+ return m_position == that.m_position;
+ }
+ void increment()
+ {
+ // We must not start with a continuation character:
+ if((static_cast<boost::uint8_t>(*m_position) & 0xC0) == 0x80)
+ invalid_sequence();
+ // skip high surrogate first if there is one:
+ unsigned c = detail::utf8_byte_count(*m_position);
+ if(m_value == pending_read)
+ {
+ // Since we haven't read in a value, we need to validate the code points:
+ for(unsigned i = 0; i < c; ++i)
+ {
+ ++m_position;
+ // We must have a continuation byte:
+ if((i != c - 1) && ((static_cast<boost::uint8_t>(*m_position) & 0xC0) != 0x80))
+ invalid_sequence();
+ }
+ }
+ else
+ {
+ std::advance(m_position, c);
+ }
+ m_value = pending_read;
+ }
+ void decrement()
+ {
+ // Keep backtracking until we don't have a trailing character:
+ unsigned count = 0;
+ while((*--m_position & 0xC0u) == 0x80u) ++count;
+ // now check that the sequence was valid:
+ if(count != detail::utf8_trailing_byte_count(*m_position))
+ invalid_sequence();
+ m_value = pending_read;
+ }
+ BaseIterator base()const
+ {
+ return m_position;
+ }
+ // construct:
+ u8_to_u32_iterator() : m_position()
+ {
+ m_value = pending_read;
+ }
+ u8_to_u32_iterator(BaseIterator b) : m_position(b)
+ {
+ m_value = pending_read;
+ }
+ //
+ // Checked constructor:
+ //
+ u8_to_u32_iterator(BaseIterator b, BaseIterator start, BaseIterator end) : m_position(b)
+ {
+ m_value = pending_read;
+ //
+ // We must not start with a continuation character, or end with a
+ // truncated UTF-8 sequence otherwise we run the risk of going past
+ // the start/end of the underlying sequence:
+ //
+ if(start != end)
+ {
+ unsigned char v = *start;
+ if((v & 0xC0u) == 0x80u)
+ invalid_sequence();
+ if((b != start) && (b != end) && ((*b & 0xC0u) == 0x80u))
+ invalid_sequence();
+ BaseIterator pos = end;
+ do
+ {
+ v = *--pos;
+ }
+ while((start != pos) && ((v & 0xC0u) == 0x80u));
+ std::ptrdiff_t extra = detail::utf8_byte_count(v);
+ if(std::distance(pos, end) < extra)
+ invalid_sequence();
+ }
+ }
+private:
+ static void invalid_sequence()
+ {
+ std::out_of_range e("Invalid UTF-8 sequence encountered while trying to encode UTF-32 character");
+ boost::throw_exception(e);
+ }
+ void extract_current()const
+ {
+ m_value = static_cast<U32Type>(static_cast< ::boost::uint8_t>(*m_position));
+ // we must not have a continuation character:
+ if((m_value & 0xC0u) == 0x80u)
+ invalid_sequence();
+ // see how many extra bytes we have:
+ unsigned extra = detail::utf8_trailing_byte_count(*m_position);
+ // extract the extra bits, 6 from each extra byte:
+ BaseIterator next(m_position);
+ for(unsigned c = 0; c < extra; ++c)
+ {
+ ++next;
+ m_value <<= 6;
+ // We must have a continuation byte:
+ if((static_cast<boost::uint8_t>(*next) & 0xC0) != 0x80)
+ invalid_sequence();
+ m_value += static_cast<boost::uint8_t>(*next) & 0x3Fu;
+ }
+ // we now need to remove a few of the leftmost bits, but how many depends
+ // upon how many extra bytes we've extracted:
+ static const boost::uint32_t masks[4] =
+ {
+ 0x7Fu,
+ 0x7FFu,
+ 0xFFFFu,
+ 0x1FFFFFu,
+ };
+ m_value &= masks[extra];
+ // check the result:
+ if(m_value > static_cast<U32Type>(0x10FFFFu))
+ invalid_sequence();
+ }
+ BaseIterator m_position;
+ mutable U32Type m_value;
+};
+
+template <class BaseIterator>
+class utf16_output_iterator
+{
+public:
+ typedef void difference_type;
+ typedef void value_type;
+ typedef boost::uint32_t* pointer;
+ typedef boost::uint32_t& reference;
+ typedef std::output_iterator_tag iterator_category;
+
+ utf16_output_iterator(const BaseIterator& b)
+ : m_position(b){}
+ utf16_output_iterator(const utf16_output_iterator& that)
+ : m_position(that.m_position){}
+ utf16_output_iterator& operator=(const utf16_output_iterator& that)
+ {
+ m_position = that.m_position;
+ return *this;
+ }
+ const utf16_output_iterator& operator*()const
+ {
+ return *this;
+ }
+ void operator=(boost::uint32_t val)const
+ {
+ push(val);
+ }
+ utf16_output_iterator& operator++()
+ {
+ return *this;
+ }
+ utf16_output_iterator& operator++(int)
+ {
+ return *this;
+ }
+ BaseIterator base()const
+ {
+ return m_position;
+ }
+private:
+ void push(boost::uint32_t v)const
+ {
+ if(v >= 0x10000u)
+ {
+ // begin by checking for a code point out of range:
+ if(v > 0x10FFFFu)
+ detail::invalid_utf32_code_point(v);
+ // split into two surrogates:
+ *m_position++ = static_cast<boost::uint16_t>(v >> 10) + detail::high_surrogate_base;
+ *m_position++ = static_cast<boost::uint16_t>(v & detail::ten_bit_mask) + detail::low_surrogate_base;
+ }
+ else
+ {
+ // 16-bit code point:
+ // value must not be a surrogate:
+ if(detail::is_surrogate(v))
+ detail::invalid_utf32_code_point(v);
+ *m_position++ = static_cast<boost::uint16_t>(v);
+ }
+ }
+ mutable BaseIterator m_position;
+};
+
+template <class BaseIterator>
+class utf8_output_iterator
+{
+public:
+ typedef void difference_type;
+ typedef void value_type;
+ typedef boost::uint32_t* pointer;
+ typedef boost::uint32_t& reference;
+ typedef std::output_iterator_tag iterator_category;
+
+ utf8_output_iterator(const BaseIterator& b)
+ : m_position(b){}
+ utf8_output_iterator(const utf8_output_iterator& that)
+ : m_position(that.m_position){}
+ utf8_output_iterator& operator=(const utf8_output_iterator& that)
+ {
+ m_position = that.m_position;
+ return *this;
+ }
+ const utf8_output_iterator& operator*()const
+ {
+ return *this;
+ }
+ void operator=(boost::uint32_t val)const
+ {
+ push(val);
+ }
+ utf8_output_iterator& operator++()
+ {
+ return *this;
+ }
+ utf8_output_iterator& operator++(int)
+ {
+ return *this;
+ }
+ BaseIterator base()const
+ {
+ return m_position;
+ }
+private:
+ void push(boost::uint32_t c)const
+ {
+ if(c > 0x10FFFFu)
+ detail::invalid_utf32_code_point(c);
+ if(c < 0x80u)
+ {
+ *m_position++ = static_cast<unsigned char>(c);
+ }
+ else if(c < 0x800u)
+ {
+ *m_position++ = static_cast<unsigned char>(0xC0u + (c >> 6));
+ *m_position++ = static_cast<unsigned char>(0x80u + (c & 0x3Fu));
+ }
+ else if(c < 0x10000u)
+ {
+ *m_position++ = static_cast<unsigned char>(0xE0u + (c >> 12));
+ *m_position++ = static_cast<unsigned char>(0x80u + ((c >> 6) & 0x3Fu));
+ *m_position++ = static_cast<unsigned char>(0x80u + (c & 0x3Fu));
+ }
+ else
+ {
+ *m_position++ = static_cast<unsigned char>(0xF0u + (c >> 18));
+ *m_position++ = static_cast<unsigned char>(0x80u + ((c >> 12) & 0x3Fu));
+ *m_position++ = static_cast<unsigned char>(0x80u + ((c >> 6) & 0x3Fu));
+ *m_position++ = static_cast<unsigned char>(0x80u + (c & 0x3Fu));
+ }
+ }
+ mutable BaseIterator m_position;
+};
+
+} // namespace boost
+
+#endif // BOOST_REGEX_UNICODE_ITERATOR_HPP
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/mmap_for_windows.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/mmap_for_windows.hpp
new file mode 100755
index 0000000000..abe62d6403
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/mmap_for_windows.hpp
@@ -0,0 +1,103 @@
+#ifndef MMAP_FOR_WINDOWS_HPP
+#define MMAP_FOR_WINDOWS_HPP
+
+/* mmap() replacement for Windows
+ *
+ * Author: Mike Frysinger <vapier@gentoo.org>
+ * Placed into the public domain
+ */
+
+/* References:
+ * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx
+ * CloseHandle: http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx
+ * MapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx
+ * UnmapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx
+ */
+
+#include <io.h>
+#include <windows.h>
+#include <sys/types.h>
+
+#define PROT_READ 0x1
+#define PROT_WRITE 0x2
+/* This flag is only available in WinXP+ */
+#ifdef FILE_MAP_EXECUTE
+#define PROT_EXEC 0x4
+#else
+#define PROT_EXEC 0x0
+#define FILE_MAP_EXECUTE 0
+#endif
+
+#define MAP_SHARED 0x01
+#define MAP_PRIVATE 0x02
+#define MAP_ANONYMOUS 0x20
+#define MAP_ANON MAP_ANONYMOUS
+#define MAP_FAILED ((void *) -1)
+
+static DWORD dword_hi(uint64_t x) {
+ return static_cast<DWORD>(x >> 32);
+}
+
+static DWORD dword_lo(uint64_t x) {
+ return static_cast<DWORD>(x & 0xffffffff);
+}
+
+static void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
+{
+ if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
+ return MAP_FAILED;
+ if (fd == -1) {
+ if (!(flags & MAP_ANON) || offset)
+ return MAP_FAILED;
+ } else if (flags & MAP_ANON)
+ return MAP_FAILED;
+
+ DWORD flProtect;
+ if (prot & PROT_WRITE) {
+ if (prot & PROT_EXEC)
+ flProtect = PAGE_EXECUTE_READWRITE;
+ else
+ flProtect = PAGE_READWRITE;
+ } else if (prot & PROT_EXEC) {
+ if (prot & PROT_READ)
+ flProtect = PAGE_EXECUTE_READ;
+ else if (prot & PROT_EXEC)
+ flProtect = PAGE_EXECUTE;
+ } else
+ flProtect = PAGE_READONLY;
+
+ uint64_t end = static_cast<uint64_t>(length) + offset;
+ HANDLE mmap_fd;
+ if (fd == -1)
+ mmap_fd = INVALID_HANDLE_VALUE;
+ else
+ mmap_fd = (HANDLE)_get_osfhandle(fd);
+
+ HANDLE h = CreateFileMapping(mmap_fd, NULL, flProtect, dword_hi(end), dword_lo(end), NULL);
+ if (h == NULL)
+ return MAP_FAILED;
+
+ DWORD dwDesiredAccess;
+ if (prot & PROT_WRITE)
+ dwDesiredAccess = FILE_MAP_WRITE;
+ else
+ dwDesiredAccess = FILE_MAP_READ;
+ if (prot & PROT_EXEC)
+ dwDesiredAccess |= FILE_MAP_EXECUTE;
+ if (flags & MAP_PRIVATE)
+ dwDesiredAccess |= FILE_MAP_COPY;
+ void *ret = MapViewOfFile(h, dwDesiredAccess, dword_hi(offset), dword_lo(offset), length);
+ if (ret == NULL) {
+ CloseHandle(h);
+ ret = MAP_FAILED;
+ }
+ return ret;
+}
+
+static int munmap(void *addr, size_t length)
+{
+ return UnmapViewOfFile(addr) ? 0 : -1;
+ /* ruh-ro, we leaked handle from CreateFileMapping() ... */
+}
+
+#endif
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/assembler.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/assembler.hpp
new file mode 100755
index 0000000000..0a5f12323e
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/assembler.hpp
@@ -0,0 +1,783 @@
+#ifndef OSMIUM_AREA_ASSEMBLER_HPP
+#define OSMIUM_AREA_ASSEMBLER_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#include <list>
+#include <map>
+#include <vector>
+
+#include <osmium/builder/osm_object_builder.hpp>
+#include <osmium/memory/buffer.hpp>
+#include <osmium/osm/area.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/relation.hpp>
+#include <osmium/tags/filter.hpp>
+
+#include <osmium/area/detail/proto_ring.hpp>
+#include <osmium/area/detail/node_ref_segment.hpp>
+#include <osmium/area/detail/segment_list.hpp>
+#include <osmium/area/problem_reporter.hpp>
+
+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<ProtoRing> m_rings;
+
+ std::vector<ProtoRing*> m_outer_rings;
+ std::vector<ProtoRing*> 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<const osmium::Way*>& ways) const {
+ std::map<std::string, size_t> counter;
+ for (const osmium::Way* way : ways) {
+ for (const auto& tag : way->tags()) {
+ std::string kv {tag.key()};
+ kv.append(1, '\0');
+ kv.append(tag.value());
+ ++counter[kv];
+ }
+ }
+
+ 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<const osmium::Way*> 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<size_t>& 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<osmium::Area>(area_offset).tags(); // tags of the area we just built
+
+ // Find all closed ways that are inner rings and check their
+ // tags. If they are not the same as the tags of the area we
+ // just built, add them to a list and later build areas for
+ // them, too.
+ std::vector<const osmium::Way*> ways_that_should_be_areas;
+ if (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<const osmium::Way>(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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/detail/node_ref_segment.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/detail/node_ref_segment.hpp
new file mode 100755
index 0000000000..43569a8657
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/detail/node_ref_segment.hpp
@@ -0,0 +1,262 @@
+#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 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <cstdint>
+#include <cstring>
+#include <iosfwd>
+#include <utility>
+
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/node_ref.hpp>
+
+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<osmium::Location, osmium::Location> 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 <typename TChar, typename TTraits>
+ inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& 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<int64_t>(s2.second().y()) - static_cast<int64_t>(s2.first().y())) *
+ (static_cast<int64_t>(s1.second().x()) - static_cast<int64_t>(s1.first().x())) -
+ (static_cast<int64_t>(s2.second().x()) - static_cast<int64_t>(s2.first().x())) *
+ (static_cast<int64_t>(s1.second().y()) - static_cast<int64_t>(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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/detail/proto_ring.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/detail/proto_ring.hpp
new file mode 100755
index 0000000000..c0f545c98b
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/detail/proto_ring.hpp
@@ -0,0 +1,274 @@
+#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 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <cassert>
+#include <iostream>
+#include <list>
+#include <set>
+#include <vector>
+
+#include <osmium/osm/node_ref.hpp>
+#include <osmium/area/detail/node_ref_segment.hpp>
+
+namespace osmium {
+
+ namespace area {
+
+ namespace detail {
+
+ /**
+ * A ring in the process of being built by the Assembler object.
+ */
+ class ProtoRing {
+
+ public:
+
+ typedef std::vector<NodeRefSegment> 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<ProtoRing*> 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<size_t>(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<int64_t>(segment.first().location().x()) * static_cast<int64_t>(segment.second().location().y()) -
+ static_cast<int64_t>(segment.second().location().x()) * static_cast<int64_t>(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<ProtoRing*>& 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<segments_type::difference_type>(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<const osmium::Way*>& 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 <typename TChar, typename TTraits>
+ inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/detail/segment_list.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/detail/segment_list.hpp
new file mode 100755
index 0000000000..ca6071edea
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/detail/segment_list.hpp
@@ -0,0 +1,216 @@
+#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 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <cassert>
+#include <iostream>
+#include <vector>
+
+#include <osmium/area/problem_reporter.hpp>
+#include <osmium/area/detail/node_ref_segment.hpp>
+#include <osmium/memory/buffer.hpp>
+#include <osmium/osm/relation.hpp>
+#include <osmium/osm/way.hpp>
+
+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<NodeRefSegment> 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<size_t>& 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<const osmium::Way>(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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/multipolygon_collector.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/multipolygon_collector.hpp
new file mode 100755
index 0000000000..84a52622b4
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/multipolygon_collector.hpp
@@ -0,0 +1,212 @@
+#ifndef OSMIUM_AREA_MULTIPOLYGON_COLLECTOR_HPP
+#define OSMIUM_AREA_MULTIPOLYGON_COLLECTOR_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <vector>
+
+#include <osmium/memory/buffer.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/relation.hpp>
+#include <osmium/osm/tag.hpp>
+#include <osmium/osm/way.hpp>
+#include <osmium/relations/collector.hpp>
+#include <osmium/relations/detail/member_meta.hpp>
+
+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 TAssembler>
+ class MultipolygonCollector : public osmium::relations::Collector<MultipolygonCollector<TAssembler>, false, true, false> {
+
+ typedef typename osmium::relations::Collector<MultipolygonCollector<TAssembler>, 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.nodes().size() > 3 && way.ends_have_same_location()) {
+ // 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<size_t> 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/problem_reporter.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/problem_reporter.hpp
new file mode 100755
index 0000000000..4ae4bb23d1
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/problem_reporter.hpp
@@ -0,0 +1,149 @@
+#ifndef OSMIUM_AREA_PROBLEM_REPORTER_HPP
+#define OSMIUM_AREA_PROBLEM_REPORTER_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/types.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/problem_reporter_exception.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/problem_reporter_exception.hpp
new file mode 100755
index 0000000000..5e743c6d85
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/problem_reporter_exception.hpp
@@ -0,0 +1,96 @@
+#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 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <sstream>
+#include <stdexcept>
+
+#include <osmium/area/problem_reporter_stream.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/types.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/problem_reporter_ogr.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/problem_reporter_ogr.hpp
new file mode 100755
index 0000000000..c437a3f57a
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/problem_reporter_ogr.hpp
@@ -0,0 +1,223 @@
+#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 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+/**
+ * @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 <ogr_api.h>
+#include <ogrsf_frmts.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#else
+# pragma GCC diagnostic pop
+#endif
+
+#include <memory>
+#include <stdexcept>
+
+#include <osmium/area/problem_reporter.hpp>
+#include <osmium/geom/ogr.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/types.hpp>
+
+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<OGRPoint> ogr_point = m_ogr_factory.create_point(location);
+ feature->SetGeometry(ogr_point.get());
+ feature->SetField("id1", static_cast<double>(id1));
+ feature->SetField("id2", static_cast<double>(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<OGRPoint> ogr_point1 = m_ogr_factory.create_point(loc1);
+ std::unique_ptr<OGRPoint> ogr_point2 = m_ogr_factory.create_point(loc2);
+ std::unique_ptr<OGRLineString> ogr_linestring = std::unique_ptr<OGRLineString>(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<double>(id1));
+ feature->SetField("id2", static_cast<double>(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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/problem_reporter_stream.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/problem_reporter_stream.hpp
new file mode 100755
index 0000000000..ddcb343e82
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/area/problem_reporter_stream.hpp
@@ -0,0 +1,96 @@
+#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 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <ostream>
+
+#include <osmium/area/problem_reporter.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/types.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/builder/builder.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/builder/builder.hpp
new file mode 100755
index 0000000000..dcb95e2ac3
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/builder/builder.hpp
@@ -0,0 +1,223 @@
+#ifndef OSMIUM_BUILDER_BUILDER_HPP
+#define OSMIUM_BUILDER_BUILDER_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <new>
+#include <string>
+#include <type_traits>
+
+#include <osmium/memory/buffer.hpp>
+#include <osmium/memory/item.hpp>
+#include <osmium/osm/types.hpp>
+#include <osmium/util/cast.hpp>
+
+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<osmium::memory::Item*>(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::fill_n(m_buffer.reserve_space(padding), padding, 0);
+ 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) {
+ unsigned char* target = m_buffer.reserve_space(item->padded_size());
+ std::copy_n(reinterpret_cast<const unsigned char*>(item), item->padded_size(), target);
+ add_size(item->padded_size());
+ }
+
+ /**
+ * Reserve space for an object of class T in buffer and return
+ * pointer to it.
+ */
+ template <class T>
+ T* reserve_space_for() {
+ assert(m_buffer.is_aligned());
+ return reinterpret_cast<T*>(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) {
+ unsigned char* target = m_buffer.reserve_space(length);
+ std::copy_n(reinterpret_cast<const unsigned char*>(data), length, target);
+ return length;
+ }
+
+ /**
+ * Append \0-terminated string to buffer.
+ */
+ osmium::memory::item_size_type append(const char* str) {
+ return append(str, static_cast<osmium::memory::item_size_type>(std::strlen(str) + 1));
+ }
+
+ /// Return the buffer this builder is using.
+ osmium::memory::Buffer& buffer() noexcept {
+ return m_buffer;
+ }
+
+ }; // class Builder
+
+ template <class TItem>
+ class ObjectBuilder : public Builder {
+
+ static_assert(std::is_base_of<osmium::memory::Item, TItem>::value, "ObjectBuilder can only build objects derived from osmium::memory::Item");
+
+ public:
+
+ explicit ObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
+ Builder(buffer, parent, sizeof(TItem)) {
+ new (&item()) TItem();
+ }
+
+ TItem& object() noexcept {
+ return static_cast<TItem&>(item());
+ }
+
+ /**
+ * Add user name to buffer.
+ *
+ * @param user Pointer to user name.
+ * @param length Length of user name 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<string_size_type>(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<string_size_type>(user.size() + 1));
+ }
+
+ }; // class ObjectBuilder
+
+ } // namespace builder
+
+} // namespace osmium
+
+#endif // OSMIUM_BUILDER_BUILDER_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/builder/builder_helper.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/builder/builder_helper.hpp
new file mode 100755
index 0000000000..eebdf338c4
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/builder/builder_helper.hpp
@@ -0,0 +1,103 @@
+#ifndef OSMIUM_BUILDER_BUILDER_HELPER_HPP
+#define OSMIUM_BUILDER_BUILDER_HELPER_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstddef>
+#include <initializer_list>
+#include <functional>
+#include <map>
+#include <utility>
+
+#include <osmium/builder/osm_object_builder.hpp>
+#include <osmium/memory/buffer.hpp>
+
+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<osmium::NodeRef>& 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<const osmium::WayNodeList>(pos);
+ }
+
+ inline const osmium::TagList& build_tag_list(osmium::memory::Buffer& buffer, const std::initializer_list<std::pair<const char*, const char*>>& 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<const osmium::TagList>(pos);
+ }
+
+ inline const osmium::TagList& build_tag_list_from_map(osmium::memory::Buffer& buffer, const std::map<const char*, const char*>& 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<const osmium::TagList>(pos);
+ }
+
+ inline const osmium::TagList& build_tag_list_from_func(osmium::memory::Buffer& buffer, std::function<void(osmium::builder::TagListBuilder&)> func) {
+ size_t pos = buffer.committed();
+ {
+ osmium::builder::TagListBuilder tl_builder(buffer);
+ func(tl_builder);
+ }
+ buffer.commit();
+ return buffer.get<const osmium::TagList>(pos);
+ }
+
+ } // namespace builder
+
+} // namespace osmium
+
+#endif // OSMIUM_BUILDER_BUILDER_HELPER_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/builder/osm_object_builder.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/builder/osm_object_builder.hpp
new file mode 100755
index 0000000000..058f89e8eb
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/builder/osm_object_builder.hpp
@@ -0,0 +1,284 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstring>
+#include <initializer_list>
+#include <new>
+#include <string>
+#include <utility>
+
+#include <osmium/builder/builder.hpp>
+#include <osmium/osm.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/node_ref.hpp>
+#include <osmium/osm/object.hpp>
+#include <osmium/osm/tag.hpp>
+#include <osmium/osm/types.hpp>
+#include <osmium/util/cast.hpp>
+
+namespace osmium {
+
+ namespace memory {
+ class Buffer;
+ }
+
+ namespace builder {
+
+ class TagListBuilder : public ObjectBuilder<TagList> {
+
+ public:
+
+ explicit TagListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
+ ObjectBuilder<TagList>(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<string_size_type>(key.size() + 1)) +
+ append(value.data(), static_cast_with_assert<string_size_type>(value.size() + 1)));
+ }
+
+ }; // class TagListBuilder
+
+ template <class T>
+ class NodeRefListBuilder : public ObjectBuilder<T> {
+
+ public:
+
+ explicit NodeRefListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
+ ObjectBuilder<T>(buffer, parent) {
+ }
+
+ ~NodeRefListBuilder() {
+ static_cast<Builder*>(this)->add_padding();
+ }
+
+ void add_node_ref(const NodeRef& node_ref) {
+ new (static_cast<Builder*>(this)->reserve_space_for<osmium::NodeRef>()) osmium::NodeRef(node_ref);
+ static_cast<Builder*>(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<WayNodeList> WayNodeListBuilder;
+ typedef NodeRefListBuilder<OuterRing> OuterRingBuilder;
+ typedef NodeRefListBuilder<InnerRing> InnerRingBuilder;
+
+ class RelationMemberListBuilder : public ObjectBuilder<RelationMemberList> {
+
+ /**
+ * 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<string_size_type>(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<string_size_type>(role.size() + 1));
+ }
+
+ public:
+
+ explicit RelationMemberListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
+ ObjectBuilder<RelationMemberList>(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<osmium::RelationMember>();
+ new (member) osmium::RelationMember(ref, type, full_member != nullptr);
+ add_size(sizeof(RelationMember));
+ add_role(*member, role);
+ if (full_member) {
+ add_item(full_member);
+ }
+ }
+
+ /**
+ * Add 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<osmium::RelationMember>();
+ new (member) osmium::RelationMember(ref, type, full_member != nullptr);
+ add_size(sizeof(RelationMember));
+ add_role(*member, role);
+ if (full_member) {
+ add_item(full_member);
+ }
+ }
+
+ }; // class RelationMemberListBuilder
+
+ template <class T>
+ class OSMObjectBuilder : public ObjectBuilder<T> {
+
+ public:
+
+ explicit OSMObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
+ ObjectBuilder<T>(buffer, parent) {
+ static_cast<Builder*>(this)->reserve_space_for<string_size_type>();
+ static_cast<Builder*>(this)->add_size(sizeof(string_size_type));
+ }
+
+ void add_tags(const std::initializer_list<std::pair<const char*, const char*>>& tags) {
+ osmium::builder::TagListBuilder tl_builder(static_cast<Builder*>(this)->buffer(), this);
+ for (const auto& p : tags) {
+ tl_builder.add_tag(p.first, p.second);
+ }
+ }
+
+ }; // class OSMObjectBuilder
+
+ typedef OSMObjectBuilder<osmium::Node> NodeBuilder;
+ typedef OSMObjectBuilder<osmium::Relation> RelationBuilder;
+
+ class WayBuilder : public OSMObjectBuilder<osmium::Way> {
+
+ public:
+
+ explicit WayBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
+ OSMObjectBuilder<osmium::Way>(buffer, parent) {
+ }
+
+ void add_node_refs(const std::initializer_list<osmium::NodeRef>& 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<osmium::Area> {
+
+ public:
+
+ explicit AreaBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
+ OSMObjectBuilder<osmium::Area>(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<osmium::Changeset> ChangesetBuilder;
+
+ } // namespace builder
+
+} // namespace osmium
+
+#endif // OSMIUM_BUILDER_OSM_OBJECT_BUILDER_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/diff_handler.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/diff_handler.hpp
new file mode 100755
index 0000000000..4f9b3a1a0b
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/diff_handler.hpp
@@ -0,0 +1,67 @@
+#ifndef OSMIUM_DIFF_HANDLER_HPP
+#define OSMIUM_DIFF_HANDLER_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/osm/diff_object.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/diff_iterator.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/diff_iterator.hpp
new file mode 100755
index 0000000000..0ddf7ff7a3
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/diff_iterator.hpp
@@ -0,0 +1,129 @@
+#ifndef OSMIUM_DIFF_ITERATOR_HPP
+#define OSMIUM_DIFF_ITERATOR_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cassert>
+#include <iterator>
+#include <type_traits>
+
+#include <osmium/osm/diff_object.hpp>
+
+namespace osmium {
+
+ class OSMObject;
+
+ template <class TBasicIterator>
+ class DiffIterator : public std::iterator<std::input_iterator_tag, const osmium::DiffObject> {
+
+ static_assert(std::is_base_of<osmium::OSMObject, typename TBasicIterator::value_type>::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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/diff_visitor.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/diff_visitor.hpp
new file mode 100755
index 0000000000..5e72a7bb74
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/diff_visitor.hpp
@@ -0,0 +1,104 @@
+#ifndef OSMIUM_DIFF_VISITOR_HPP
+#define OSMIUM_DIFF_VISITOR_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/diff_iterator.hpp>
+#include <osmium/io/input_iterator.hpp>
+#include <osmium/memory/buffer.hpp>
+#include <osmium/osm/diff_object.hpp>
+#include <osmium/osm/item_type.hpp>
+
+namespace osmium {
+
+ namespace detail {
+
+ template <class THandler>
+ inline void apply_diff_iterator_recurse(const osmium::DiffObject& diff, THandler& handler) {
+ switch (diff.type()) {
+ case osmium::item_type::node:
+ handler.node(static_cast<const osmium::DiffNode&>(diff));
+ break;
+ case osmium::item_type::way:
+ handler.way(static_cast<const osmium::DiffWay&>(diff));
+ break;
+ case osmium::item_type::relation:
+ handler.relation(static_cast<const osmium::DiffRelation&>(diff));
+ break;
+ default:
+ throw osmium::unknown_type();
+ }
+ }
+
+ template <class THandler, class ...TRest>
+ 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 <class TIterator, class ...THandlers>
+ inline void apply_diff(TIterator it, TIterator end, THandlers&... handlers) {
+ typedef osmium::DiffIterator<TIterator> 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 <class TSource, class ...THandlers>
+ inline void apply_diff(TSource& source, THandlers&... handlers) {
+ apply_diff(osmium::io::InputIterator<TSource, osmium::OSMObject> {source},
+ osmium::io::InputIterator<TSource, osmium::OSMObject> {},
+ handlers...);
+ }
+
+ template <class ...THandlers>
+ inline void apply_diff(osmium::memory::Buffer& buffer, THandlers&... handlers) {
+ apply_diff(buffer.begin(), buffer.end(), handlers...);
+ }
+
+ template <class ...THandlers>
+ 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/dynamic_handler.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/dynamic_handler.hpp
new file mode 100755
index 0000000000..9d0bd66f58
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/dynamic_handler.hpp
@@ -0,0 +1,195 @@
+#ifndef OSMIUM_DYNAMIC_HANDLER_HPP
+#define OSMIUM_DYNAMIC_HANDLER_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <memory>
+#include <utility>
+
+#include <osmium/handler.hpp>
+
+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 <class THandler> \
+auto _name_##_dispatch(THandler& handler, const osmium::_type_& object, int) -> decltype(handler._name_(object), void()) { \
+ handler._name_(object); \
+} \
+template <class THandler> \
+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 <class THandler>
+ auto flush_dispatch(THandler& handler, int) -> decltype(handler.flush(), void()) {
+ handler.flush();
+ }
+
+ template <class THandler>
+ void flush_dispatch(THandler&, long) {}
+
+ template <class THandler>
+ class HandlerWrapper : public HandlerWrapperBase {
+
+ THandler m_handler;
+
+ public:
+
+ template <class... TArgs>
+ HandlerWrapper(TArgs&&... args) :
+ m_handler(std::forward<TArgs>(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<osmium::handler::detail::HandlerWrapperBase> impl_ptr;
+ impl_ptr m_impl;
+
+ public:
+
+ DynamicHandler() :
+ m_impl(impl_ptr(new osmium::handler::detail::HandlerWrapperBase)) {
+ }
+
+ template <class THandler, class... TArgs>
+ void set(TArgs&&... args) {
+ m_impl = impl_ptr(new osmium::handler::detail::HandlerWrapper<THandler>(std::forward<TArgs>(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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/experimental/flex_reader.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/experimental/flex_reader.hpp
new file mode 100755
index 0000000000..f00a5ecafe
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/experimental/flex_reader.hpp
@@ -0,0 +1,129 @@
+#ifndef OSMIUM_EXPERIMENTAL_FLEX_READER_HPP
+#define OSMIUM_EXPERIMENTAL_FLEX_READER_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/handler/node_locations_for_ways.hpp>
+#include <osmium/visitor.hpp>
+#include <osmium/area/multipolygon_collector.hpp>
+#include <osmium/area/assembler.hpp>
+
+namespace osmium {
+
+ /**
+ * @brief Experimental code that is not "officially" supported.
+ */
+ namespace experimental {
+
+ template <class TLocationHandler>
+ class FlexReader {
+
+ bool m_with_areas;
+ osmium::osm_entity_bits::type m_entities;
+
+ TLocationHandler& m_location_handler;
+
+ osmium::io::Reader m_reader;
+ osmium::area::Assembler::config_type m_assembler_config;
+ osmium::area::MultipolygonCollector<osmium::area::Assembler> m_collector;
+
+ public:
+
+ 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_location_handler(location_handler),
+ 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, 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, 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() {
+ osmium::memory::Buffer buffer = m_reader.read();
+
+ if (buffer) {
+ if (m_with_areas) {
+ std::vector<osmium::memory::Buffer> 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));
+ }));
+ for (const osmium::memory::Buffer& b : area_buffers) {
+ buffer.add_buffer(b);
+ buffer.commit();
+ }
+ } else if (m_entities & (osmium::osm_entity_bits::node | osmium::osm_entity_bits::way)) {
+ osmium::apply(buffer, m_location_handler);
+ }
+ }
+
+ return buffer;
+ }
+
+ 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<osmium::area::Assembler>& collector() const {
+ return m_collector;
+ }
+
+ }; // class FlexReader
+
+ } // namespace experimental
+
+} // namespace osmium
+
+#endif // OSMIUM_EXPERIMENTAL_FLEX_READER_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/coordinates.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/coordinates.hpp
new file mode 100755
index 0000000000..2bad57e0d0
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/coordinates.hpp
@@ -0,0 +1,97 @@
+#ifndef OSMIUM_GEOM_COORDINATES_HPP
+#define OSMIUM_GEOM_COORDINATES_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstddef>
+#include <iosfwd>
+#include <string>
+
+#include <osmium/osm/location.hpp>
+#include <osmium/util/double.hpp>
+
+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 <typename TChar, typename TTraits>
+ inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const Coordinates& c) {
+ return out << '(' << c.x << ',' << c.y << ')';
+ }
+
+ } // namespace geom
+
+} // namespace osmium
+
+#endif // OSMIUM_GEOM_COORDINATES_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/factory.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/factory.hpp
new file mode 100755
index 0000000000..518cbfbc26
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/factory.hpp
@@ -0,0 +1,328 @@
+#ifndef OSMIUM_GEOM_FACTORY_HPP
+#define OSMIUM_GEOM_FACTORY_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstddef>
+#include <stdexcept>
+#include <string>
+#include <utility>
+
+#include <osmium/geom/coordinates.hpp>
+#include <osmium/memory/collection.hpp>
+#include <osmium/memory/item.hpp>
+#include <osmium/osm/area.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/node.hpp>
+#include <osmium/osm/node_ref.hpp>
+#include <osmium/osm/way.hpp>
+
+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 TGeomImpl, class TProjection = IdentityProjection>
+ 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 <class... TArgs>
+ GeometryFactory<TGeomImpl, TProjection>(TArgs&&... args) :
+ m_projection(),
+ m_impl(std::forward<TArgs>(args)...) {
+ }
+
+ /**
+ * Constructor for explicitly initialized projection. Note that the
+ * projection is moved into the GeometryFactory.
+ */
+ template <class... TArgs>
+ GeometryFactory<TGeomImpl, TProjection>(TProjection&& projection, TArgs&&... args) :
+ m_projection(std::move(projection)),
+ m_impl(std::forward<TArgs>(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 <class TIter>
+ 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 <class TIter>
+ 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 <class TIter>
+ 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 <class TIter>
+ 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<const osmium::OuterRing&>(*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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/geojson.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/geojson.hpp
new file mode 100755
index 0000000000..7d59535352
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/geojson.hpp
@@ -0,0 +1,154 @@
+#ifndef OSMIUM_GEOM_GEOJSON_HPP
+#define OSMIUM_GEOM_GEOJSON_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cassert>
+#include <string>
+#include <utility>
+
+#include <osmium/geom/coordinates.hpp>
+#include <osmium/geom/factory.hpp>
+
+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());
+ std::string str;
+ std::swap(str, m_str);
+ str.back() = ']';
+ str += "}";
+ return str;
+ }
+
+ }; // class GeoJSONFactoryImpl
+
+ } // namespace detail
+
+ template <class TProjection = IdentityProjection>
+ using GeoJSONFactory = GeometryFactory<osmium::geom::detail::GeoJSONFactoryImpl, TProjection>;
+
+ } // namespace geom
+
+} // namespace osmium
+
+#endif // OSMIUM_GEOM_GEOJSON_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/geos.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/geos.hpp
new file mode 100755
index 0000000000..3c73637be0
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/geos.hpp
@@ -0,0 +1,230 @@
+#ifndef OSMIUM_GEOM_GEOS_HPP
+#define OSMIUM_GEOM_GEOS_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+/**
+ * @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 <utility>
+
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/CoordinateSequence.h>
+#include <geos/geom/CoordinateSequenceFactory.h>
+#include <geos/geom/GeometryFactory.h>
+#include <geos/geom/LinearRing.h>
+#include <geos/geom/MultiPolygon.h>
+#include <geos/geom/Point.h>
+#include <geos/geom/Polygon.h>
+#include <geos/geom/PrecisionModel.h>
+#include <geos/util/GEOSException.h>
+
+#include <osmium/geom/factory.hpp>
+#include <osmium/geom/coordinates.hpp>
+
+// 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<geos::geom::CoordinateSequence> m_coordinate_sequence;
+ std::vector<std::unique_ptr<geos::geom::LinearRing>> m_rings;
+ std::vector<std::unique_ptr<geos::geom::Polygon>> m_polygons;
+
+ public:
+
+ typedef std::unique_ptr<geos::geom::Point> point_type;
+ typedef std::unique_ptr<geos::geom::LineString> linestring_type;
+ typedef std::unique_ptr<geos::geom::Polygon> polygon_type;
+ typedef std::unique_ptr<geos::geom::MultiPolygon> multipolygon_type;
+ typedef std::unique_ptr<geos::geom::LinearRing> 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<size_t>(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<geos::geom::Geometry*>;
+ std::transform(std::next(m_rings.begin(), 1), m_rings.end(), std::back_inserter(*inner_rings), [](std::unique_ptr<geos::geom::LinearRing>& r) {
+ return r.release();
+ });
+ m_polygons.emplace_back(m_geos_factory.createPolygon(m_rings[0].release(), inner_rings));
+ m_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<size_t>(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<size_t>(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<geos::geom::Geometry*>;
+ std::transform(m_polygons.begin(), m_polygons.end(), std::back_inserter(*polygons), [](std::unique_ptr<geos::geom::Polygon>& 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 <class TProjection = IdentityProjection>
+ using GEOSFactory = GeometryFactory<osmium::geom::detail::GEOSFactoryImpl, TProjection>;
+
+ } // namespace geom
+
+} // namespace osmium
+
+#undef THROW
+
+#endif // OSMIUM_GEOM_GEOS_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/haversine.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/haversine.hpp
new file mode 100755
index 0000000000..e62a31b03e
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/haversine.hpp
@@ -0,0 +1,94 @@
+#ifndef OSMIUM_GEOM_HAVERSINE_HPP
+#define OSMIUM_GEOM_HAVERSINE_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cmath>
+#include <iterator>
+
+#include <osmium/geom/coordinates.hpp>
+#include <osmium/geom/util.hpp>
+#include <osmium/osm/node_ref.hpp>
+#include <osmium/osm/way.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/mercator_projection.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/mercator_projection.hpp
new file mode 100755
index 0000000000..a6d1d5742c
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/mercator_projection.hpp
@@ -0,0 +1,109 @@
+#ifndef OSMIUM_GEOM_MERCATOR_PROJECTION_HPP
+#define OSMIUM_GEOM_MERCATOR_PROJECTION_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cmath>
+#include <string>
+
+#include <osmium/geom/coordinates.hpp>
+#include <osmium/geom/util.hpp>
+#include <osmium/osm/location.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/ogr.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/ogr.hpp
new file mode 100755
index 0000000000..f33971c7db
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/ogr.hpp
@@ -0,0 +1,206 @@
+#ifndef OSMIUM_GEOM_OGR_HPP
+#define OSMIUM_GEOM_OGR_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+/**
+ * @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 <cassert>
+#include <cstddef>
+#include <memory>
+#include <utility>
+
+#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 <ogr_geometry.h>
+#include <ogr_api.h>
+#include <ogrsf_frmts.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#else
+# pragma GCC diagnostic pop
+#endif
+
+#include <osmium/geom/coordinates.hpp>
+#include <osmium/geom/factory.hpp>
+
+namespace osmium {
+
+ namespace geom {
+
+ namespace detail {
+
+ class OGRFactoryImpl {
+
+ public:
+
+ typedef std::unique_ptr<OGRPoint> point_type;
+ typedef std::unique_ptr<OGRLineString> linestring_type;
+ typedef std::unique_ptr<OGRPolygon> polygon_type;
+ typedef std::unique_ptr<OGRMultiPolygon> multipolygon_type;
+ typedef std::unique_ptr<OGRLinearRing> 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<OGRLineString>(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<OGRLinearRing>(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<OGRPolygon> polygon = std::unique_ptr<OGRPolygon>(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 <class TProjection = IdentityProjection>
+ using OGRFactory = GeometryFactory<osmium::geom::detail::OGRFactoryImpl, TProjection>;
+
+ } // namespace geom
+
+} // namespace osmium
+
+#endif // OSMIUM_GEOM_OGR_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/projection.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/projection.hpp
new file mode 100755
index 0000000000..6419101f81
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/projection.hpp
@@ -0,0 +1,167 @@
+#ifndef OSMIUM_GEOM_PROJECTION_HPP
+#define OSMIUM_GEOM_PROJECTION_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+/**
+ * @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 <memory>
+#include <string>
+
+#include <proj_api.h>
+
+#include <osmium/geom/coordinates.hpp>
+#include <osmium/geom/util.hpp>
+#include <osmium/osm/location.hpp>
+
+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<void, ProjCRSDeleter> 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()) != 0;
+ }
+
+ bool is_geocent() const {
+ return pj_is_geocent(m_crs.get()) != 0;
+ }
+
+ /**
+ * 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) 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 {
+ Coordinates c {location.lon(), location.lat()};
+
+ if (m_epsg != 4326) {
+ c = transform(m_crs_wgs84, m_crs_user, Coordinates(deg_to_rad(location.lon()), deg_to_rad(location.lat())));
+ 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/relations.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/relations.hpp
new file mode 100755
index 0000000000..e9e2aa4209
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/relations.hpp
@@ -0,0 +1,57 @@
+#ifndef OSMIUM_GEOM_RELATIONS_HPP
+#define OSMIUM_GEOM_RELATIONS_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/osm/box.hpp>
+#include <osmium/osm/location.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/util.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/util.hpp
new file mode 100755
index 0000000000..5e9f8228c4
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/util.hpp
@@ -0,0 +1,75 @@
+#ifndef OSMIUM_GEOM_UTIL_HPP
+#define OSMIUM_GEOM_UTIL_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <stdexcept>
+#include <string>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/wkb.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/wkb.hpp
new file mode 100755
index 0000000000..2f32fe33be
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/wkb.hpp
@@ -0,0 +1,277 @@
+#ifndef OSMIUM_GEOM_WKB_HPP
+#define OSMIUM_GEOM_WKB_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstddef>
+#include <cstdint>
+#include <string>
+
+// Windows is only available for little endian architectures
+// http://stackoverflow.com/questions/6449468/can-i-safely-assume-that-windows-installations-will-always-be-little-endian
+#if !defined(_WIN32) && !defined(__APPLE__)
+# include <endian.h>
+#else
+# define __LITTLE_ENDIAN 1234
+# define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
+
+#include <osmium/geom/coordinates.hpp>
+#include <osmium/geom/factory.hpp>
+#include <osmium/util/cast.hpp>
+
+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 <typename T>
+ inline void str_push(std::string& str, T data) {
+ size_t size = str.size();
+ str.resize(size + sizeof(T));
+ std::copy_n(reinterpret_cast<char*>(&data), sizeof(T), &str[size]);
+ }
+
+ inline std::string convert_to_hex(const 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<uint32_t>(0));
+ }
+ return offset;
+ }
+
+ void set_size(const size_t offset, const size_t size) {
+ *reinterpret_cast<uint32_t*>(&m_data[offset]) = static_cast_with_assert<uint32_t>(size);
+ }
+
+ 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<uint32_t>(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<uint32_t>(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 <class TProjection = IdentityProjection>
+ using WKBFactory = GeometryFactory<osmium::geom::detail::WKBFactoryImpl, TProjection>;
+
+ } // namespace geom
+
+} // namespace osmium
+
+#endif // OSMIUM_GEOM_WKB_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/wkt.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/wkt.hpp
new file mode 100755
index 0000000000..4fea96baa7
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/geom/wkt.hpp
@@ -0,0 +1,150 @@
+#ifndef OSMIUM_GEOM_WKT_HPP
+#define OSMIUM_GEOM_WKT_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cassert>
+#include <cstddef>
+#include <string>
+#include <utility>
+
+#include <osmium/geom/coordinates.hpp>
+#include <osmium/geom/factory.hpp>
+
+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());
+ std::string str;
+ std::swap(str, m_str);
+ str.back() = ')';
+ return str;
+ }
+
+ }; // class WKTFactoryImpl
+
+ } // namespace detail
+
+ template <class TProjection = IdentityProjection>
+ using WKTFactory = GeometryFactory<osmium::geom::detail::WKTFactoryImpl, TProjection>;
+
+ } // namespace geom
+
+} // namespace osmium
+
+#endif // OSMIUM_GEOM_WKT_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler.hpp
new file mode 100755
index 0000000000..34d8785113
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler.hpp
@@ -0,0 +1,101 @@
+#ifndef OSMIUM_HANDLER_HPP
+#define OSMIUM_HANDLER_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/chain.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/chain.hpp
new file mode 100755
index 0000000000..1af3962fd1
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/chain.hpp
@@ -0,0 +1,128 @@
+#ifndef OSMIUM_HANDLER_CHAIN_HPP
+#define OSMIUM_HANDLER_CHAIN_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <tuple>
+
+#include <osmium/handler.hpp>
+
+#define OSMIUM_CHAIN_HANDLER_CALL(_func_, _type_) \
+ template <int N, int SIZE, class THandlers> \
+ struct call_ ## _func_ { \
+ void operator()(THandlers& handlers, osmium::_type_& object) { \
+ std::get<N>(handlers)._func_(object); \
+ call_ ## _func_<N+1, SIZE, THandlers>()(handlers, object); \
+ } \
+ }; \
+ template <int SIZE, class THandlers> \
+ struct call_ ## _func_<SIZE, SIZE, THandlers> { \
+ 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 ...THandler>
+ class ChainHandler : public osmium::handler::Handler {
+
+ typedef std::tuple<THandler&...> handlers_type;
+ handlers_type m_handlers;
+
+ template <int N, int SIZE, class THandlers>
+ struct call_flush {
+ void operator()(THandlers& handlers) {
+ std::get<N>(handlers).flush();
+ call_flush<N+1, SIZE, THandlers>()(handlers);
+ }
+ }; // struct call_flush
+
+ template <int SIZE, class THandlers>
+ struct call_flush<SIZE, SIZE, THandlers> {
+ 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/disk_store.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/disk_store.hpp
new file mode 100755
index 0000000000..ccae5962a9
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/disk_store.hpp
@@ -0,0 +1,111 @@
+#ifndef OSMIUM_HANDLER_DISK_STORE_HPP
+#define OSMIUM_HANDLER_DISK_STORE_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstddef>
+
+#include <osmium/handler.hpp>
+#include <osmium/index/map.hpp>
+#include <osmium/io/detail/read_write.hpp>
+#include <osmium/memory/buffer.hpp>
+#include <osmium/memory/item_iterator.hpp>
+#include <osmium/osm/node.hpp>
+#include <osmium/osm/relation.hpp>
+#include <osmium/osm/types.hpp>
+#include <osmium/osm/way.hpp>
+#include <osmium/visitor.hpp>
+
+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<unsigned_object_id_type, size_t> 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/dump.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/dump.hpp
new file mode 100755
index 0000000000..a23236e102
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/dump.hpp
@@ -0,0 +1,294 @@
+#ifndef OSMIUM_HANDLER_DUMP_HPP
+#define OSMIUM_HANDLER_DUMP_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <iomanip>
+#include <iostream>
+#include <string>
+
+#include <osmium/handler.hpp>
+#include <osmium/memory/collection.hpp>
+#include <osmium/memory/item.hpp>
+#include <osmium/osm/area.hpp>
+#include <osmium/osm/box.hpp>
+#include <osmium/osm/changeset.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/node.hpp>
+#include <osmium/osm/node_ref.hpp>
+#include <osmium/osm/object.hpp>
+#include <osmium/osm/relation.hpp>
+#include <osmium/osm/tag.hpp>
+#include <osmium/osm/timestamp.hpp>
+#include <osmium/osm/way.hpp>
+#include <osmium/visitor.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/node_locations_for_ways.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/node_locations_for_ways.hpp
new file mode 100755
index 0000000000..9b9fcbf3f3
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/node_locations_for_ways.hpp
@@ -0,0 +1,180 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <type_traits>
+
+#include <osmium/handler.hpp>
+#include <osmium/index/index.hpp>
+#include <osmium/index/map/dummy.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/node.hpp>
+#include <osmium/osm/node_ref.hpp>
+#include <osmium/osm/types.hpp>
+#include <osmium/osm/way.hpp>
+
+#include <osmium/index/node_locations_map.hpp>
+
+namespace osmium {
+
+ namespace handler {
+
+ typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> 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 TStoragePosIDs, class TStorageNegIDs = dummy_type>
+ class NodeLocationsForWays : public osmium::handler::Handler {
+
+ static_assert(std::is_base_of<osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>, TStoragePosIDs>::value, "Index class must be derived from osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>");
+
+ static_assert(std::is_base_of<osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>, TStorageNegIDs>::value, "Index class must be derived from osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>");
+
+ 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(NodeLocationsForWays&&) = default;
+ NodeLocationsForWays& operator=(NodeLocationsForWays&&) = default;
+
+ ~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<osmium::unsigned_object_id_type>( id), node.location());
+ } else {
+ m_storage_neg.set(static_cast<osmium::unsigned_object_id_type>(-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<osmium::unsigned_object_id_type>( id));
+ } else {
+ return m_storage_neg.get(static_cast<osmium::unsigned_object_id_type>(-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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/object_relations.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/object_relations.hpp
new file mode 100755
index 0000000000..dc4aa45d87
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/handler/object_relations.hpp
@@ -0,0 +1,106 @@
+#ifndef OSMIUM_HANDLER_OBJECT_RELATIONS_HPP
+#define OSMIUM_HANDLER_OBJECT_RELATIONS_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/handler.hpp>
+#include <osmium/index/multimap.hpp>
+#include <osmium/osm/node_ref.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/relation.hpp>
+#include <osmium/osm/types.hpp>
+#include <osmium/osm/way.hpp>
+
+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<unsigned_object_id_type, unsigned_object_id_type> 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/create_map_with_fd.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/create_map_with_fd.hpp
new file mode 100755
index 0000000000..29dc1dc675
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cassert>
+#include <cerrno>
+#include <cstring>
+#include <fcntl.h>
+#include <stdexcept>
+#include <string>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <vector>
+
+namespace osmium {
+
+ namespace index {
+
+ namespace detail {
+
+ template <class T>
+ inline T* create_map_with_fd(const std::vector<std::string>& 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/mmap_vector_anon.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/mmap_vector_anon.hpp
new file mode 100755
index 0000000000..0ea4f9db65
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/mmap_vector_anon.hpp
@@ -0,0 +1,78 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#ifdef __linux__
+
+#include <cstddef>
+
+#include <osmium/index/detail/typed_mmap.hpp>
+#include <osmium/index/detail/mmap_vector_base.hpp>
+
+namespace osmium {
+
+ namespace detail {
+
+ /**
+ * This class looks and behaves like STL vector, but uses mmap internally.
+ */
+ template <typename T>
+ class mmap_vector_anon : public mmap_vector_base<T, mmap_vector_anon> {
+
+ public:
+
+ mmap_vector_anon() :
+ mmap_vector_base<T, osmium::detail::mmap_vector_anon>(
+ -1,
+ osmium::detail::mmap_vector_size_increment,
+ 0,
+ osmium::detail::typed_mmap<T>::map(osmium::detail::mmap_vector_size_increment)) {
+ }
+
+ void reserve(size_t new_capacity) {
+ if (new_capacity > this->capacity()) {
+ this->data(osmium::detail::typed_mmap<T>::remap(this->data(), this->capacity(), new_capacity));
+ this->m_capacity = new_capacity;
+ }
+ }
+
+ }; // class mmap_vector_anon
+
+ } // namespace detail
+
+} // namespace osmium
+
+#endif // __linux__
+
+#endif // OSMIUM_INDEX_DETAIL_MMAP_VECTOR_ANON_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/mmap_vector_base.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/mmap_vector_base.hpp
new file mode 100755
index 0000000000..3aff26d410
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/mmap_vector_base.hpp
@@ -0,0 +1,184 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstddef>
+#include <new>
+#include <stdexcept>
+
+#include <osmium/index/detail/typed_mmap.hpp>
+#include <osmium/util/compatibility.hpp>
+
+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 <typename T, template <typename> 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<T>::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<T>::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<TDerived<T>*>(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_INDEX_DETAIL_MMAP_VECTOR_BASE_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/mmap_vector_file.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/mmap_vector_file.hpp
new file mode 100755
index 0000000000..55077d18d4
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/mmap_vector_file.hpp
@@ -0,0 +1,85 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstddef>
+
+#include <osmium/index/detail/typed_mmap.hpp>
+#include <osmium/index/detail/mmap_vector_base.hpp>
+#include <osmium/index/detail/tmpfile.hpp>
+
+namespace osmium {
+
+ namespace detail {
+
+ /**
+ * This class looks and behaves like STL vector, but mmap's a file
+ * internally.
+ */
+ template <typename T>
+ class mmap_vector_file : public mmap_vector_base<T, mmap_vector_file> {
+
+ public:
+
+ explicit mmap_vector_file() :
+ mmap_vector_base<T, osmium::detail::mmap_vector_file>(
+ osmium::detail::create_tmp_file(),
+ osmium::detail::mmap_vector_size_increment,
+ 0) {
+ }
+
+ explicit mmap_vector_file(int fd) :
+ mmap_vector_base<T, osmium::detail::mmap_vector_file>(
+ fd,
+ osmium::detail::typed_mmap<T>::file_size(fd) == 0 ?
+ osmium::detail::mmap_vector_size_increment :
+ osmium::detail::typed_mmap<T>::file_size(fd),
+ osmium::detail::typed_mmap<T>::file_size(fd)) {
+ }
+
+ void reserve(size_t new_capacity) {
+ if (new_capacity > this->capacity()) {
+ typed_mmap<T>::unmap(this->data(), this->capacity());
+ this->data(typed_mmap<T>::grow_and_map(new_capacity, this->m_fd));
+ this->m_capacity = new_capacity;
+ }
+ }
+
+ }; // class mmap_vector_file
+
+ } // namespace detail
+
+} // namespace osmium
+
+#endif // OSMIUM_INDEX_DETAIL_MMAP_VECTOR_FILE_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/tmpfile.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/tmpfile.hpp
new file mode 100755
index 0000000000..06cab6544b
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/tmpfile.hpp
@@ -0,0 +1,62 @@
+#ifndef OSMIUM_INDEX_DETAIL_TMPFILE_HPP
+#define OSMIUM_INDEX_DETAIL_TMPFILE_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cerrno>
+#include <cstdio>
+#include <system_error>
+
+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_INDEX_DETAIL_TMPFILE_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/typed_mmap.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/typed_mmap.hpp
new file mode 100755
index 0000000000..77b065e8e9
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/typed_mmap.hpp
@@ -0,0 +1,229 @@
+#ifndef OSMIUM_INDEX_DETAIL_TYPED_MMAP_HPP
+#define OSMIUM_INDEX_DETAIL_TYPED_MMAP_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cerrno>
+#include <cstddef>
+#include <stdexcept>
+#include <system_error>
+
+#include <sys/stat.h>
+
+#ifndef _WIN32
+# include <sys/mman.h>
+#else
+# include <mmap_for_windows.hpp>
+#endif
+
+#ifndef _MSC_VER
+# include <unistd.h>
+#else
+# define ftruncate _chsize
+#endif
+
+// for bsd systems
+#ifndef MAP_ANONYMOUS
+# define MAP_ANONYMOUS MAP_ANON
+#endif
+
+#include <osmium/util/cast.hpp>
+
+namespace osmium {
+
+ /**
+ * @brief Namespace for Osmium internal use
+ */
+ namespace detail {
+
+ /**
+ * This is a helper class for working with memory mapped files and
+ * anonymous shared memory. It wraps the necessary system calls
+ * adding:
+ * - error checking: all functions throw exceptions where needed
+ * - internal casts and size calculations allow use with user defined
+ * type T instead of void*
+ *
+ * This class only contains static functions. It should never be
+ * instantiated.
+ *
+ * @tparam T Type of objects we want to store.
+ */
+ template <typename T>
+ class typed_mmap {
+
+ public:
+
+ /**
+ * Create anonymous private memory mapping with enough space for size
+ * objects of type T.
+ *
+ * Note that no constructor is called for any of the objects in this memory!
+ *
+ * @param size Number of objects of type T that should fit into this memory
+ * @returns Pointer to mapped memory
+ * @throws std::system_error If mmap(2) failed
+ */
+ static T* map(size_t size) {
+ void* addr = ::mmap(nullptr, sizeof(T) * size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+ if (addr == MAP_FAILED) {
+ throw std::system_error(errno, std::system_category(), "mmap failed");
+ }
+#pragma GCC diagnostic pop
+ return reinterpret_cast<T*>(addr);
+ }
+
+ /**
+ * Create shared memory mapping of a file with enough space for size
+ * objects of type T. The file must already have at least the
+ * required size.
+ *
+ * Note that no constructor is called for any of the objects in this memory!
+ *
+ * @param size Number of objects of type T that should fit into this memory
+ * @param fd File descriptor
+ * @param write True if data should be writable
+ * @returns Pointer to mapped memory
+ * @throws std::system_error If mmap(2) failed
+ */
+ static T* map(size_t size, int fd, bool write = false) {
+ int prot = PROT_READ;
+ if (write) {
+ prot |= PROT_WRITE;
+ }
+ void* addr = ::mmap(nullptr, sizeof(T) * size, prot, MAP_SHARED, fd, 0);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+ if (addr == MAP_FAILED) {
+ throw std::system_error(errno, std::system_category(), "mmap failed");
+ }
+#pragma GCC diagnostic pop
+ return reinterpret_cast<T*>(addr);
+ }
+
+// mremap(2) is only available on linux systems
+#ifdef __linux__
+ /**
+ * Grow memory mapping created with map().
+ *
+ * Note that no constructor is called for any of the objects in this memory!
+ *
+ * @param data Pointer to current mapping (as returned by typed_mmap())
+ * @param old_size Number of objects currently stored in this memory
+ * @param new_size Number of objects we want to have space for
+ * @throws std::system_error If mremap(2) call failed
+ */
+ static T* remap(T* data, size_t old_size, size_t new_size) {
+ void* addr = ::mremap(reinterpret_cast<void*>(data), sizeof(T) * old_size, sizeof(T) * new_size, MREMAP_MAYMOVE);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+ if (addr == MAP_FAILED) {
+ throw std::system_error(errno, std::system_category(), "mremap failed");
+ }
+#pragma GCC diagnostic pop
+ return reinterpret_cast<T*>(addr);
+ }
+#endif
+
+ /**
+ * Release memory from map() call.
+ *
+ * Note that no destructor is called for the objects in this memory!
+ *
+ * @param data Pointer to the data
+ * @param size Number of objects of type T stored
+ * @throws std::system_error If munmap(2) call failed
+ */
+ static void unmap(T* data, size_t size) {
+ if (::munmap(reinterpret_cast<void*>(data), sizeof(T) * size) != 0) {
+ throw std::system_error(errno, std::system_category(), "munmap failed");
+ }
+ }
+
+ /**
+ * Get number of objects of type T that would fit into a file.
+ *
+ * @param fd File descriptor
+ * @returns Number of objects of type T in this file
+ * @throws std::system_error If fstat(2) call failed
+ * @throws std::length_error If size of the file isn't a multiple of sizeof(T)
+ */
+ static size_t file_size(int fd) {
+ struct stat s;
+ if (fstat(fd, &s) < 0) {
+ throw std::system_error(errno, std::system_category(), "fstat failed");
+ }
+ if (static_cast<size_t>(s.st_size) % sizeof(T) != 0) {
+ throw std::length_error("file size has to be multiple of object size");
+ }
+ return static_cast<size_t>(s.st_size) / sizeof(T);
+ }
+
+ /**
+ * Grow file so there is enough space for at least new_size objects
+ * of type T. If the file is large enough already, nothing is done.
+ * The file is never shrunk.
+ *
+ * @param new_size Number of objects of type T that should fit into this file
+ * @param fd File descriptor
+ * @throws std::system_error If ftruncate(2) call failed
+ */
+ static void grow_file(size_t new_size, int fd) {
+ if (file_size(fd) < new_size) {
+ if (::ftruncate(fd, static_cast_with_assert<off_t>(sizeof(T) * new_size)) < 0) {
+ throw std::system_error(errno, std::system_category(), "ftruncate failed");
+ }
+ }
+ }
+
+ /**
+ * Grow file to given size (if it is smaller) and mmap it.
+ *
+ * @param size Number of objects of type T that should fit into this file
+ * @param fd File descriptor
+ * @throws Errors thrown by grow_file() or map()
+ */
+ static T* grow_and_map(size_t size, int fd) {
+ grow_file(size, fd);
+ return map(size, fd, true);
+ }
+
+ }; // class typed_mmap
+
+ } // namespace detail
+
+} // namespace osmium
+
+#endif // OSMIUM_INDEX_DETAIL_TYPED_MMAP_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/vector_map.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/vector_map.hpp
new file mode 100755
index 0000000000..73c5a37a57
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/vector_map.hpp
@@ -0,0 +1,238 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <cstddef>
+#include <stdexcept>
+#include <utility>
+
+#include <osmium/index/index.hpp>
+#include <osmium/index/map.hpp>
+#include <osmium/io/detail/read_write.hpp>
+
+namespace osmium {
+
+ namespace index {
+
+ namespace map {
+
+ template <class TVector, typename TId, typename TValue>
+ class VectorBasedDenseMap : public Map<TId, TValue> {
+
+ TVector m_vector;
+
+ public:
+
+ typedef TValue element_type;
+ typedef TVector vector_type;
+ typedef typename vector_type::iterator iterator;
+ typedef typename vector_type::const_iterator const_iterator;
+
+ 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<TValue>()) {
+ 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();
+ }
+
+ 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 VectorBasedDenseMap
+
+
+ template <typename TId, typename TValue, template<typename...> class TVector>
+ class VectorBasedSparseMap : public Map<TId, TValue> {
+
+ public:
+
+ typedef typename std::pair<TId, TValue> element_type;
+ typedef TVector<element_type> 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<TValue>()
+ };
+ 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(const int fd) override final {
+ osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(m_vector.data()), byte_size());
+ }
+
+ iterator begin() {
+ return m_vector.begin();
+ }
+
+ 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_DETAIL_VECTOR_MAP_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/vector_multimap.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/vector_multimap.hpp
new file mode 100755
index 0000000000..c2b2e1f291
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/detail/vector_multimap.hpp
@@ -0,0 +1,152 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <cstddef>
+#include <utility>
+
+#include <osmium/index/index.hpp>
+#include <osmium/index/multimap.hpp>
+#include <osmium/io/detail/read_write.hpp>
+
+namespace osmium {
+
+ namespace index {
+
+ namespace multimap {
+
+ template <typename TId, typename TValue, template<typename...> class TVector>
+ class VectorBasedSparseMultimap : public Multimap<TId, TValue> {
+
+ public:
+
+ typedef typename std::pair<TId, TValue> element_type;
+ typedef TVector<element_type> 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<TValue>();
+ }
+
+ 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<iterator, iterator> get_all(const TId id) {
+ const element_type element {
+ id,
+ osmium::index::empty_value<TValue>()
+ };
+ 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<const_iterator, const_iterator> get_all(const TId id) const {
+ const element_type element {
+ id,
+ osmium::index::empty_value<TValue>()
+ };
+ 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(const int fd) override final {
+ osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(m_vector.data()), byte_size());
+ }
+
+ }; // class VectorBasedSparseMultimap
+
+ } // namespace multimap
+
+ } // namespace index
+
+} // namespace osmium
+
+#endif // OSMIUM_INDEX_DETAIL_VECTOR_MULTIMAP_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/index.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/index.hpp
new file mode 100755
index 0000000000..b73b319e87
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/index.hpp
@@ -0,0 +1,100 @@
+#ifndef OSMIUM_INDEX_INDEX_HPP
+#define OSMIUM_INDEX_INDEX_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstddef>
+#include <limits>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+
+#include <osmium/util/compatibility.hpp>
+
+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 <typename TKey>
+ 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 <typename T>
+ 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<size_t>() {
+ return std::numeric_limits<size_t>::max();
+ }
+
+ } // namespace index
+
+} // namespace osmium
+
+#endif // OSMIUM_INDEX_INDEX_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map.hpp
new file mode 100755
index 0000000000..7b44b8e337
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map.hpp
@@ -0,0 +1,254 @@
+#ifndef OSMIUM_INDEX_MAP_HPP
+#define OSMIUM_INDEX_MAP_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <cstddef>
+#include <functional>
+#include <map>
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include <osmium/util/compatibility.hpp>
+#include <osmium/util/string.hpp>
+
+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 <typename TId, typename TValue>
+ class Map {
+
+ static_assert(std::is_integral<TId>::value && std::is_unsigned<TId>::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(const int /*fd*/) {
+ std::runtime_error("can't dump as list");
+ }
+
+ }; // class Map
+
+ } // namespace map
+
+ template <typename TId, typename TValue>
+ class MapFactory {
+
+ public:
+
+ typedef TId id_type;
+ typedef TValue value_type;
+ typedef osmium::index::map::Map<id_type, value_type> map_type;
+ typedef std::function<map_type*(const std::vector<std::string>&)> create_map_func;
+
+ private:
+
+ std::map<const std::string, create_map_func> 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<id_type, value_type>& instance() {
+ static MapFactory<id_type, value_type> 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<std::string> map_types() const {
+ std::vector<std::string> result;
+
+ for (const auto& cb : m_callbacks) {
+ result.push_back(cb.first);
+ }
+
+ std::sort(result.begin(), result.end());
+
+ return result;
+ }
+
+ std::unique_ptr<map_type> create_map(const std::string& config_string) const {
+ std::vector<std::string> 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<map_type>((it->second)(config));
+ }
+
+ error(config[0]);
+ }
+
+ }; // class MapFactory
+
+ namespace map {
+
+ template <typename TId, typename TValue, template<typename, typename> class TMap>
+ struct create_map {
+ TMap<TId, TValue>* operator()(const std::vector<std::string>&) {
+ return new TMap<TId, TValue>();
+ }
+ };
+
+ } // namespace map
+
+ template <typename TId, typename TValue, template<typename, typename> class TMap>
+ inline bool register_map(const std::string& name) {
+ return osmium::index::MapFactory<TId, TValue>::instance().register_map(name, [](const std::vector<std::string>& config) {
+ return map::create_map<TId, TValue, TMap>()(config);
+ });
+ }
+
+#define REGISTER_MAP(id, value, klass, name) \
+namespace { \
+ const bool registered_index_map_##name = osmium::index::register_map<id, value, klass>(#name); \
+}
+
+ } // namespace index
+
+} // namespace osmium
+
+#endif // OSMIUM_INDEX_MAP_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/all.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/all.hpp
new file mode 100755
index 0000000000..9ffadc0ded
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/index/map/dense_file_array.hpp> // IWYU pragma: keep
+#include <osmium/index/map/dense_mem_array.hpp> // IWYU pragma: keep
+#include <osmium/index/map/dense_mmap_array.hpp> // IWYU pragma: keep
+#include <osmium/index/map/dummy.hpp> // IWYU pragma: keep
+#include <osmium/index/map/sparse_file_array.hpp> // IWYU pragma: keep
+#include <osmium/index/map/sparse_mem_array.hpp> // IWYU pragma: keep
+#include <osmium/index/map/sparse_mem_map.hpp> // IWYU pragma: keep
+#include <osmium/index/map/sparse_mem_table.hpp> // IWYU pragma: keep
+#include <osmium/index/map/sparse_mmap_array.hpp> // IWYU pragma: keep
+
+#endif // OSMIUM_INDEX_MAP_ALL_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/dense_file_array.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/dense_file_array.hpp
new file mode 100755
index 0000000000..d209a875c2
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <string>
+#include <vector>
+
+#include <osmium/index/detail/mmap_vector_file.hpp>
+#include <osmium/index/detail/vector_map.hpp>
+#include <osmium/index/detail/create_map_with_fd.hpp>
+
+#define OSMIUM_HAS_INDEX_MAP_DENSE_FILE_ARRAY
+
+namespace osmium {
+
+ namespace index {
+
+ namespace map {
+
+ template <typename TId, typename TValue>
+ using DenseFileArray = VectorBasedDenseMap<osmium::detail::mmap_vector_file<TValue>, TId, TValue>;
+
+ template <typename TId, typename TValue>
+ struct create_map<TId, TValue, DenseFileArray> {
+ DenseFileArray<TId, TValue>* operator()(const std::vector<std::string>& config) {
+ return osmium::index::detail::create_map_with_fd<DenseFileArray<TId, TValue>>(config);
+ }
+ };
+
+ } // namespace map
+
+ } // namespace index
+
+} // namespace osmium
+
+#endif // OSMIUM_INDEX_MAP_DENSE_FILE_ARRAY_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/dense_mem_array.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/dense_mem_array.hpp
new file mode 100755
index 0000000000..b45eec4588
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <vector>
+
+#include <osmium/index/detail/vector_map.hpp>
+
+#define OSMIUM_HAS_INDEX_MAP_DENSE_MEM_ARRAY
+
+namespace osmium {
+
+ namespace index {
+
+ namespace map {
+
+ template <typename TId, typename TValue>
+ using DenseMemArray = VectorBasedDenseMap<std::vector<TValue>, TId, TValue>;
+
+ } // namespace map
+
+ } // namespace index
+
+} // namespace osmium
+
+#endif // OSMIUM_INDEX_MAP_DENSE_MEM_ARRAY_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/dense_mmap_array.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/dense_mmap_array.hpp
new file mode 100755
index 0000000000..fc60a1ef21
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/dense_mmap_array.hpp
@@ -0,0 +1,60 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#ifdef __linux__
+
+#include <osmium/index/detail/mmap_vector_anon.hpp>
+#include <osmium/index/detail/vector_map.hpp>
+
+#define OSMIUM_HAS_INDEX_MAP_DENSE_MMAP_ARRAY
+
+namespace osmium {
+
+ namespace index {
+
+ namespace map {
+
+ template <typename TId, typename TValue>
+ using DenseMmapArray = VectorBasedDenseMap<osmium::detail::mmap_vector_anon<TValue>, TId, TValue>;
+
+ } // namespace map
+
+ } // namespace index
+
+} // namespace osmium
+
+#endif // __linux__
+
+#endif // OSMIUM_INDEX_MAP_DENSE_MMAP_ARRAY_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/dummy.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/dummy.hpp
new file mode 100755
index 0000000000..de05d1d697
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/dummy.hpp
@@ -0,0 +1,88 @@
+#ifndef OSMIUM_INDEX_MAP_DUMMY_HPP
+#define OSMIUM_INDEX_MAP_DUMMY_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstddef>
+
+#include <osmium/index/index.hpp>
+#include <osmium/index/map.hpp>
+
+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 <typename TId, typename TValue>
+ class Dummy : public osmium::index::map::Map<TId, TValue> {
+
+ 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_file_array.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_file_array.hpp
new file mode 100755
index 0000000000..2ba9315dde
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <string>
+#include <vector>
+
+#include <osmium/index/detail/mmap_vector_file.hpp>
+#include <osmium/index/detail/vector_map.hpp>
+#include <osmium/index/detail/create_map_with_fd.hpp>
+
+#define OSMIUM_HAS_INDEX_MAP_SPARSE_FILE_ARRAY
+
+namespace osmium {
+
+ namespace index {
+
+ namespace map {
+
+ template <typename TId, typename TValue>
+ using SparseFileArray = VectorBasedSparseMap<TId, TValue, osmium::detail::mmap_vector_file>;
+
+ template <typename TId, typename TValue>
+ struct create_map<TId, TValue, SparseFileArray> {
+ SparseFileArray<TId, TValue>* operator()(const std::vector<std::string>& config) {
+ return osmium::index::detail::create_map_with_fd<SparseFileArray<TId, TValue>>(config);
+ }
+ };
+
+ } // namespace map
+
+ } // namespace index
+
+} // namespace osmium
+
+#endif // OSMIUM_INDEX_MAP_SPARSE_FILE_ARRAY_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_mem_array.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_mem_array.hpp
new file mode 100755
index 0000000000..9adf41f0a5
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_mem_array.hpp
@@ -0,0 +1,60 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <vector>
+
+#include <osmium/index/detail/vector_map.hpp>
+
+#define OSMIUM_HAS_INDEX_MAP_SPARSE_MEM_ARRAY
+
+namespace osmium {
+
+ namespace index {
+
+ namespace map {
+
+ template <typename T>
+ using StdVectorWrap = std::vector<T>;
+
+ template <typename TId, typename TValue>
+ using SparseMemArray = VectorBasedSparseMap<TId, TValue, StdVectorWrap>;
+
+ } // namespace map
+
+ } // namespace index
+
+} // namespace osmium
+
+#endif // OSMIUM_INDEX_MAP_SPARSE_MEM_ARRAY_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_mem_map.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_mem_map.hpp
new file mode 100755
index 0000000000..d053155f05
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_mem_map.hpp
@@ -0,0 +1,115 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <cstddef>
+#include <iterator>
+#include <map>
+#include <stdexcept>
+#include <vector>
+
+#include <osmium/index/map.hpp>
+#include <osmium/index/index.hpp>
+#include <osmium/io/detail/read_write.hpp>
+
+#define OSMIUM_HAS_INDEX_MAP_SPARSE_MEM_MAP
+
+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 <typename TId, typename TValue>
+ class SparseMemMap : public osmium::index::map::Map<TId, TValue> {
+
+ // 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<TId, TValue> m_elements;
+
+ public:
+
+ SparseMemMap() = default;
+
+ ~SparseMemMap() 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) override final {
+ typedef typename std::map<TId, TValue>::value_type t;
+ std::vector<t> v;
+ std::copy(m_elements.begin(), m_elements.end(), std::back_inserter(v));
+ osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(v.data()), sizeof(t) * v.size());
+ }
+
+ }; // class SparseMemMap
+
+ } // namespace map
+
+ } // namespace index
+
+} // namespace osmium
+
+#endif // OSMIUM_INDEX_MAP_SPARSE_MEM_MAP_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_mem_table.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_mem_table.hpp
new file mode 100755
index 0000000000..09ee81bbc0
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_mem_table.hpp
@@ -0,0 +1,146 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#ifdef OSMIUM_WITH_SPARSEHASH
+
+#include <cstddef>
+#include <utility>
+#include <vector>
+
+#include <google/sparsetable>
+
+#include <osmium/index/index.hpp>
+#include <osmium/index/map.hpp>
+#include <osmium/io/detail/read_write.hpp>
+
+#define OSMIUM_HAS_INDEX_MAP_SPARSE_MEM_TABLE
+
+namespace osmium {
+
+ namespace index {
+
+ namespace map {
+
+ /**
+ * The SparseMemTable index stores elements in a Google sparsetable,
+ * a data structure that can hold sparsly filled tables in a
+ * 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 <typename TId, typename TValue>
+ class SparseMemTable : public osmium::index::map::Map<TId, TValue> {
+
+ TId m_grow_size;
+
+ google::sparsetable<TValue> m_elements;
+
+ static_assert(sizeof(typename google::sparsetable<TValue>::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 SparseMemTable(const TId grow_size = 10000) :
+ m_grow_size(grow_size),
+ m_elements(grow_size) {
+ }
+
+ ~SparseMemTable() 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<TValue>()) {
+ 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) override final {
+ std::vector<std::pair<TId, TValue>> v;
+ int n = 0;
+ for (const TValue value : m_elements) {
+ if (value != osmium::index::empty_value<TValue>()) {
+ v.emplace_back(n, value);
+ }
+ ++n;
+ }
+ osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(v.data()), sizeof(std::pair<TId, TValue>) * v.size());
+ }
+
+ }; // class SparseMemTable
+
+ } // namespace map
+
+ } // namespace index
+
+} // namespace osmium
+
+#endif // OSMIUM_WITH_SPARSEHASH
+
+#endif // OSMIUM_INDEX_BYID_SPARSE_MEM_TABLE_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_mmap_array.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_mmap_array.hpp
new file mode 100755
index 0000000000..c85e2c9383
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/map/sparse_mmap_array.hpp
@@ -0,0 +1,60 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#ifdef __linux__
+
+#include <osmium/index/detail/mmap_vector_anon.hpp>
+#include <osmium/index/detail/vector_map.hpp>
+
+#define OSMIUM_HAS_INDEX_MAP_SPARSE_MMAP_ARRAY
+
+namespace osmium {
+
+ namespace index {
+
+ namespace map {
+
+ template <typename TId, typename TValue>
+ using SparseMmapArray = VectorBasedSparseMap<TId, TValue, osmium::detail::mmap_vector_anon>;
+
+ } // namespace map
+
+ } // namespace index
+
+} // namespace osmium
+
+#endif // __linux__
+
+#endif // OSMIUM_INDEX_MAP_SPARSE_MMAP_ARRAY_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap.hpp
new file mode 100755
index 0000000000..c817b6fb6b
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap.hpp
@@ -0,0 +1,127 @@
+#ifndef OSMIUM_INDEX_MULTIMAP_HPP
+#define OSMIUM_INDEX_MULTIMAP_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstddef>
+#include <stdexcept>
+#include <type_traits>
+#include <utility>
+
+namespace osmium {
+
+ namespace index {
+
+ /**
+ * @brief Key-value containers with multiple values for an integer key
+ */
+ namespace multimap {
+
+ template <typename TId, typename TValue>
+ class Multimap {
+
+ static_assert(std::is_integral<TId>::value && std::is_unsigned<TId>::value, "TId template parameter for class Multimap must be unsigned integral type");
+
+ typedef typename std::pair<TId, TValue> 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<iterator, iterator> 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(const int /*fd*/) {
+ std::runtime_error("can't dump as list");
+ }
+
+ }; // class Multimap
+
+ } // namespace map
+
+ } // namespace index
+
+} // namespace osmium
+
+#endif // OSMIUM_INDEX_MULTIMAP_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/all.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/all.hpp
new file mode 100755
index 0000000000..8b0ae99f90
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/index/multimap/sparse_file_array.hpp> // IWYU pragma: keep
+#include <osmium/index/multimap/sparse_mem_array.hpp> // IWYU pragma: keep
+#include <osmium/index/multimap/sparse_mem_multimap.hpp> // IWYU pragma: keep
+#include <osmium/index/multimap/sparse_mmap_array.hpp> // IWYU pragma: keep
+
+#endif // OSMIUM_INDEX_MULTIMAP_ALL_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/hybrid.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/hybrid.hpp
new file mode 100755
index 0000000000..ac2d964524
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/hybrid.hpp
@@ -0,0 +1,200 @@
+#ifndef OSMIUM_INDEX_MULTIMAP_HYBRID_HPP
+#define OSMIUM_INDEX_MULTIMAP_HYBRID_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstddef>
+#include <utility>
+
+#include <osmium/index/index.hpp>
+#include <osmium/index/multimap.hpp>
+#include <osmium/index/multimap/sparse_mem_array.hpp>
+#include <osmium/index/multimap/sparse_mem_multimap.hpp>
+
+namespace osmium {
+
+ namespace index {
+
+ namespace multimap {
+
+ template <typename TId, typename TValue>
+ class HybridIterator {
+
+ typedef SparseMemArray<TId, TValue> main_map_type;
+ typedef SparseMemMultimap<TId, TValue> extra_map_type;
+
+ typedef typename std::pair<TId, TValue> 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<TValue>()) { // ignore removed elements
+ ++m_begin_main;
+ }
+ }
+ return *this;
+ }
+
+ HybridIterator<TId, TValue> 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 <typename TId, typename TValue>
+ class Hybrid : public Multimap<TId, TValue> {
+
+ typedef SparseMemArray<TId, TValue> main_map_type;
+ typedef SparseMemMultimap<TId, TValue> extra_map_type;
+
+ main_map_type m_main;
+ extra_map_type m_extra;
+
+ public:
+
+ typedef HybridIterator<TId, TValue> iterator;
+ typedef const HybridIterator<TId, TValue> 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<iterator, iterator> 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(const 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/sparse_file_array.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/sparse_file_array.hpp
new file mode 100755
index 0000000000..0b9ae92c55
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/sparse_file_array.hpp
@@ -0,0 +1,54 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/index/detail/mmap_vector_file.hpp>
+#include <osmium/index/detail/vector_multimap.hpp>
+
+namespace osmium {
+
+ namespace index {
+
+ namespace multimap {
+
+ template <typename TId, typename TValue>
+ using SparseFileArray = VectorBasedSparseMultimap<TId, TValue, osmium::detail::mmap_vector_file>;
+
+ } // namespace multimap
+
+ } // namespace index
+
+} // namespace osmium
+
+#endif // OSMIUM_INDEX_MULTIMAP_SPARSE_FILE_ARRAY_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/sparse_mem_array.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/sparse_mem_array.hpp
new file mode 100755
index 0000000000..c4140cba0a
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/sparse_mem_array.hpp
@@ -0,0 +1,58 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <vector>
+
+#include <osmium/index/detail/vector_multimap.hpp>
+
+namespace osmium {
+
+ namespace index {
+
+ namespace multimap {
+
+ template <typename T>
+ using StdVectorWrap = std::vector<T>;
+
+ template <typename TId, typename TValue>
+ using SparseMemArray = VectorBasedSparseMultimap<TId, TValue, StdVectorWrap>;
+
+ } // namespace multimap
+
+ } // namespace index
+
+} // namespace osmium
+
+#endif // OSMIUM_INDEX_MULTIMAP_SPARSE_MEM_ARRAY_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/sparse_mem_multimap.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/sparse_mem_multimap.hpp
new file mode 100755
index 0000000000..5b4715279b
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/sparse_mem_multimap.hpp
@@ -0,0 +1,151 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <cstddef>
+#include <map>
+#include <utility>
+#include <vector>
+
+#include <osmium/index/multimap.hpp>
+#include <osmium/io/detail/read_write.hpp>
+
+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 <typename TId, typename TValue>
+ class SparseMemMultimap : public osmium::index::multimap::Multimap<TId, TValue> {
+
+ // 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<const TId, TValue> 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<TId, TValue> element_type;
+
+ private:
+
+ collection_type m_elements;
+
+ public:
+
+ SparseMemMultimap() = default;
+
+ ~SparseMemMultimap() 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<iterator, iterator> get_all(const TId id) {
+ return m_elements.equal_range(id);
+ }
+
+ std::pair<const_iterator, const_iterator> get_all(const TId id) const {
+ return m_elements.equal_range(id);
+ }
+
+ void remove(const TId id, const TValue value) {
+ std::pair<iterator, iterator> 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) override final {
+ std::vector<element_type> 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<const char*>(v.data()), sizeof(element_type) * v.size());
+ }
+
+ }; // class SparseMemMultimap
+
+ } // namespace multimap
+
+ } // namespace index
+
+} // namespace osmium
+
+#endif // OSMIUM_INDEX_MULTIMAP_SPARSE_MEM_MULTIMAP_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/sparse_mmap_array.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/sparse_mmap_array.hpp
new file mode 100755
index 0000000000..9f92555f68
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/multimap/sparse_mmap_array.hpp
@@ -0,0 +1,58 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#ifdef __linux__
+
+#include <osmium/index/detail/mmap_vector_anon.hpp>
+#include <osmium/index/detail/vector_multimap.hpp>
+
+namespace osmium {
+
+ namespace index {
+
+ namespace multimap {
+
+ template <typename TId, typename TValue>
+ using SparseMmapArray = VectorBasedSparseMultimap<TId, TValue, osmium::detail::mmap_vector_anon>;
+
+ } // namespace multimap
+
+ } // namespace index
+
+} // namespace osmium
+
+#endif // __linux__
+
+#endif // OSMIUM_INDEX_MULTIMAP_SPARSE_MMAP_ARRAY_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/node_locations_map.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/index/node_locations_map.hpp
new file mode 100755
index 0000000000..ca4b1361e1
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/index/map.hpp> // 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/any_compression.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/any_compression.hpp
new file mode 100755
index 0000000000..00e8ee2be1
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/any_compression.hpp
@@ -0,0 +1,48 @@
+#ifndef OSMIUM_IO_ANY_COMPRESSION_HPP
+#define OSMIUM_IO_ANY_COMPRESSION_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+/**
+ * @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 <osmium/io/bzip2_compression.hpp> // IWYU pragma: export
+#include <osmium/io/gzip_compression.hpp> // IWYU pragma: export
+
+#endif // OSMIUM_IO_ANY_COMPRESSION_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/any_input.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/any_input.hpp
new file mode 100755
index 0000000000..633fab3139
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/any_input.hpp
@@ -0,0 +1,51 @@
+#ifndef OSMIUM_IO_ANY_INPUT_HPP
+#define OSMIUM_IO_ANY_INPUT_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+/**
+ * @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 <osmium/io/any_compression.hpp> // IWYU pragma: export
+
+#include <osmium/io/pbf_input.hpp> // IWYU pragma: export
+#include <osmium/io/xml_input.hpp> // IWYU pragma: export
+
+#endif // OSMIUM_IO_ANY_INPUT_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/any_output.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/any_output.hpp
new file mode 100755
index 0000000000..63de3ff2eb
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/any_output.hpp
@@ -0,0 +1,52 @@
+#ifndef OSMIUM_IO_ANY_OUTPUT_HPP
+#define OSMIUM_IO_ANY_OUTPUT_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+/**
+ * @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 <osmium/io/any_compression.hpp> // IWYU pragma: export
+
+#include <osmium/io/opl_output.hpp> // IWYU pragma: export
+#include <osmium/io/pbf_output.hpp> // IWYU pragma: export
+#include <osmium/io/xml_output.hpp> // IWYU pragma: export
+
+#endif // OSMIUM_IO_ANY_OUTPUT_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/bzip2_compression.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/bzip2_compression.hpp
new file mode 100755
index 0000000000..7e86c15435
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/bzip2_compression.hpp
@@ -0,0 +1,289 @@
+#ifndef OSMIUM_IO_BZIP2_COMPRESSION_HPP
+#define OSMIUM_IO_BZIP2_COMPRESSION_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+/**
+ * @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 <cerrno>
+#include <cstddef>
+#include <cstdio>
+#include <stdexcept>
+#include <string>
+
+#include <bzlib.h>
+
+#ifndef _MSC_VER
+# include <unistd.h>
+#endif
+
+#include <osmium/io/compression.hpp>
+#include <osmium/io/file_compression.hpp>
+#include <osmium/util/cast.hpp>
+#include <osmium/util/compatibility.hpp>
+
+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<char*>(data.data()), static_cast_with_assert<int>(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 {
+ std::string buffer;
+
+ if (!m_stream_end) {
+ buffer.resize(osmium::io::Decompressor::input_buffer_size);
+ int error;
+ int nread = ::BZ2_bzRead(&error, m_bzfile, const_cast<char*>(buffer.data()), static_cast_with_assert<int>(buffer.size()));
+ 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<const char*>(unused), static_cast<std::string::size_type>(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<void*>(static_cast<const void*>(unused_data.data())), static_cast_with_assert<int>(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<std::string::size_type>(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<char*>(buffer);
+ m_bzstream.avail_in = static_cast_with_assert<unsigned int>(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 {
+ std::string output;
+
+ if (m_buffer) {
+ const size_t buffer_size = 10240;
+ output.resize(buffer_size);
+ m_bzstream.next_out = const_cast<char*>(output.data());
+ m_bzstream.avail_out = buffer_size;
+ int result = BZ2_bzDecompress(&m_bzstream);
+
+ 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<unsigned long>(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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/compression.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/compression.hpp
new file mode 100755
index 0000000000..c1f8de2e71
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/compression.hpp
@@ -0,0 +1,281 @@
+#ifndef OSMIUM_IO_COMPRESSION_HPP
+#define OSMIUM_IO_COMPRESSION_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cerrno>
+#include <functional>
+#include <map>
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <system_error>
+#include <utility>
+
+#ifndef _MSC_VER
+# include <unistd.h>
+#else
+# include <io.h>
+#endif
+
+#include <osmium/io/detail/read_write.hpp>
+#include <osmium/io/file_compression.hpp>
+#include <osmium/util/compatibility.hpp>
+
+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 unsigned int input_buffer_size = 1024 * 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<osmium::io::Compressor*(int)> create_compressor_type;
+ typedef std::function<osmium::io::Decompressor*(int)> create_decompressor_type_fd;
+ typedef std::function<osmium::io::Decompressor*(const char*, size_t)> create_decompressor_type_buffer;
+
+ private:
+
+ typedef std::map<const osmium::io::file_compression, std::tuple<create_compressor_type, create_decompressor_type_fd, create_decompressor_type_buffer>> 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<osmium::io::Compressor> create_compressor(osmium::io::file_compression compression, int fd) {
+ auto it = m_callbacks.find(compression);
+
+ if (it != m_callbacks.end()) {
+ return std::unique_ptr<osmium::io::Compressor>(std::get<0>(it->second)(fd));
+ }
+
+ error(compression);
+ }
+
+ std::unique_ptr<osmium::io::Decompressor> create_decompressor(osmium::io::file_compression compression, int fd) {
+ auto it = m_callbacks.find(compression);
+
+ if (it != m_callbacks.end()) {
+ return std::unique_ptr<osmium::io::Decompressor>(std::get<1>(it->second)(fd));
+ }
+
+ error(compression);
+ }
+
+ std::unique_ptr<osmium::io::Decompressor> 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<osmium::io::Decompressor>(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 {
+ std::string buffer;
+
+ if (m_buffer) {
+ if (m_buffer_size != 0) {
+ size_t size = m_buffer_size;
+ m_buffer_size = 0;
+ buffer.append(m_buffer, size);
+ }
+ } else {
+ buffer.resize(osmium::io::Decompressor::input_buffer_size);
+ auto nread = ::read(m_fd, const_cast<char*>(buffer.data()), osmium::io::Decompressor::input_buffer_size);
+ if (nread < 0) {
+ throw std::system_error(errno, std::system_category(), "Read failed");
+ }
+ buffer.resize(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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/input_format.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/input_format.hpp
new file mode 100755
index 0000000000..03e1190c32
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/input_format.hpp
@@ -0,0 +1,158 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <functional>
+#include <map>
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <utility>
+
+#include <osmium/io/file.hpp>
+#include <osmium/io/file_format.hpp>
+#include <osmium/io/header.hpp>
+#include <osmium/memory/buffer.hpp>
+#include <osmium/osm/entity_bits.hpp>
+
+namespace osmium {
+
+ namespace thread {
+ template <typename T> 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::io::Header m_header;
+
+ explicit InputFormat(const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities) :
+ m_file(file),
+ m_read_which_entities(read_which_entities) {
+ 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<osmium::io::detail::InputFormat*(const osmium::io::File&, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue<std::string>&)> create_input_type;
+
+ private:
+
+ typedef std::map<osmium::io::file_format, create_input_type> 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<osmium::io::detail::InputFormat> create_input(const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue<std::string>& input_queue) {
+ file.check();
+
+ auto it = m_callbacks.find(file.format());
+ if (it != m_callbacks.end()) {
+ return std::unique_ptr<osmium::io::detail::InputFormat>((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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/opl_output_format.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/opl_output_format.hpp
new file mode 100755
index 0000000000..cf92e1382d
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/opl_output_format.hpp
@@ -0,0 +1,317 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <chrono>
+#include <cinttypes>
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <future>
+#include <iterator>
+#include <memory>
+#include <ratio>
+#include <string>
+#include <thread>
+#include <utility>
+
+#include <boost/version.hpp>
+
+#ifdef __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wmissing-noreturn"
+# pragma clang diagnostic ignored "-Wsign-conversion"
+#endif
+
+#if BOOST_VERSION >= 104800
+# include <boost/regex/pending/unicode_iterator.hpp>
+#else
+# include <boost_unicode_iterator.hpp>
+#endif
+
+#ifdef __clang__
+# pragma clang diagnostic pop
+#endif
+
+#include <osmium/handler.hpp>
+#include <osmium/io/detail/output_format.hpp>
+#include <osmium/io/file_format.hpp>
+#include <osmium/memory/buffer.hpp>
+#include <osmium/memory/collection.hpp>
+#include <osmium/osm/box.hpp>
+#include <osmium/osm/changeset.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/node.hpp>
+#include <osmium/osm/object.hpp>
+#include <osmium/osm/relation.hpp>
+#include <osmium/osm/tag.hpp>
+#include <osmium/osm/timestamp.hpp>
+#include <osmium/osm/way.hpp>
+#include <osmium/thread/pool.hpp>
+#include <osmium/visitor.hpp>
+
+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;
+
+ std::shared_ptr<osmium::memory::Buffer> m_input_buffer;
+
+ std::shared_ptr<std::string> m_out;
+
+ char m_tmp_buffer[tmp_buffer_size+1];
+
+ template <typename... TArgs>
+ void output_formatted(const char* format, TArgs&&... args) {
+#ifndef NDEBUG
+ int len =
+#endif
+#ifndef _MSC_VER
+ snprintf(m_tmp_buffer, tmp_buffer_size, format, std::forward<TArgs>(args)...);
+#else
+ _snprintf(m_tmp_buffer, tmp_buffer_size, format, std::forward<TArgs>(args)...);
+#endif
+ assert(len > 0 && static_cast<size_t>(len) < tmp_buffer_size);
+ *m_out += m_tmp_buffer;
+ }
+
+ void append_encoded_string(const std::string& data) {
+ boost::u8_to_u32_iterator<std::string::const_iterator> it(data.cbegin(), data.cbegin(), data.cend());
+ boost::u8_to_u32_iterator<std::string::const_iterator> end(data.cend(), data.cend(), data.cend());
+ boost::utf8_output_iterator<std::back_insert_iterator<std::string>> oit(std::back_inserter(*m_out));
+
+ 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::make_shared<osmium::memory::Buffer>(std::move(buffer))),
+ m_out(std::make_shared<std::string>()),
+ m_tmp_buffer() {
+ }
+
+ OPLOutputBlock(const OPLOutputBlock&) = default;
+ OPLOutputBlock& operator=(const OPLOutputBlock&) = default;
+
+ OPLOutputBlock(OPLOutputBlock&&) = default;
+ OPLOutputBlock& operator=(OPLOutputBlock&&) = default;
+
+ ~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<std::string> 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/output_format.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/output_format.hpp
new file mode 100755
index 0000000000..529a1890fb
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/output_format.hpp
@@ -0,0 +1,156 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <functional>
+#include <future>
+#include <map>
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <utility>
+
+#include <osmium/io/file.hpp>
+#include <osmium/io/file_format.hpp>
+#include <osmium/io/header.hpp>
+#include <osmium/thread/queue.hpp>
+
+namespace osmium {
+
+ namespace memory {
+ class Buffer;
+ }
+
+ namespace io {
+
+ namespace detail {
+
+ typedef osmium::thread::Queue<std::future<std::string>> 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<osmium::io::detail::OutputFormat*(const osmium::io::File&, data_queue_type&)> create_output_type;
+
+ private:
+
+ typedef std::map<osmium::io::file_format, create_output_type> 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<osmium::io::detail::OutputFormat> 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<osmium::io::detail::OutputFormat>((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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf.hpp
new file mode 100755
index 0000000000..e64e51a57c
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf.hpp
@@ -0,0 +1,98 @@
+#ifndef OSMIUM_IO_DETAIL_PBF_HPP
+#define OSMIUM_IO_DETAIL_PBF_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <stdexcept>
+
+#include <osmpbf/osmpbf.h>
+
+// needed for htonl and ntohl
+#ifndef _WIN32
+# include <netinet/in.h>
+#else
+# include <winsock2.h>
+#endif
+
+#include <osmium/io/error.hpp>
+#include <osmium/osm/item_type.hpp>
+
+namespace osmium {
+
+// avoid g++ false positive
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wreturn-type"
+ inline item_type osmpbf_membertype_to_item_type(const OSMPBF::Relation::MemberType mt) {
+ switch (mt) {
+ case OSMPBF::Relation::NODE:
+ return item_type::node;
+ case OSMPBF::Relation::WAY:
+ return item_type::way;
+ case OSMPBF::Relation::RELATION:
+ return item_type::relation;
+ }
+ }
+#pragma GCC diagnostic pop
+
+ inline OSMPBF::Relation::MemberType item_type_to_osmpbf_membertype(const item_type type) {
+ switch (type) {
+ case item_type::node:
+ return OSMPBF::Relation::NODE;
+ case item_type::way:
+ return OSMPBF::Relation::WAY;
+ case item_type::relation:
+ return OSMPBF::Relation::RELATION;
+ default:
+ throw std::runtime_error("Unknown relation member type");
+ }
+ }
+
+ /**
+ * Exception thrown when there was a problem with parsing the PBF format of
+ * a file.
+ */
+ 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf_input_format.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf_input_format.hpp
new file mode 100755
index 0000000000..ba8fb42a2e
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf_input_format.hpp
@@ -0,0 +1,262 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <atomic>
+#include <cassert>
+#include <chrono>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <future>
+#include <memory>
+#include <ratio>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include <thread>
+#include <type_traits>
+
+#include <osmium/io/detail/input_format.hpp>
+#include <osmium/io/detail/pbf.hpp> // IWYU pragma: export
+#include <osmium/io/detail/pbf_parser.hpp>
+#include <osmium/io/error.hpp>
+#include <osmium/io/file.hpp>
+#include <osmium/io/file_format.hpp>
+#include <osmium/memory/buffer.hpp>
+#include <osmium/osm.hpp>
+#include <osmium/osm/box.hpp>
+#include <osmium/osm/entity_bits.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/object.hpp>
+#include <osmium/osm/timestamp.hpp>
+#include <osmium/thread/pool.hpp>
+#include <osmium/thread/queue.hpp>
+#include <osmium/thread/util.hpp>
+#include <osmium/util/cast.hpp>
+#include <osmium/util/config.hpp>
+
+namespace osmium {
+
+ namespace io {
+
+ class File;
+
+ namespace detail {
+
+ typedef osmium::thread::Queue<std::future<osmium::memory::Buffer>> queue_type;
+
+ /**
+ * Class for parsing PBF files.
+ */
+ class PBFInputFormat : public osmium::io::detail::InputFormat {
+
+ bool m_use_thread_pool;
+ bool m_eof { false };
+ queue_type m_queue;
+ std::atomic<bool> m_quit_input_thread;
+ std::thread m_reader;
+ osmium::thread::Queue<std::string>& 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<const uint32_t*>(input_data.data());
+ } catch (osmium::pbf_error&) {
+ return 0; // EOF
+ }
+
+ uint32_t size = ntohl(size_in_network_byte_order);
+ if (size > static_cast<uint32_t>(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<size_t>(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<osmium::memory::Buffer> 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_quit_input_thread) {
+ return;
+ }
+ }
+
+ // Send an empty buffer to signal the reader that we are
+ // done.
+ std::promise<osmium::memory::Buffer> 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:
+
+ /**
+ * 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<std::string>& input_queue) :
+ 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_quit_input_thread(false),
+ m_input_queue(input_queue),
+ m_input_buffer() {
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ // handle OSMHeader
+ auto size = read_blob_header("OSMHeader");
+ m_header = parse_header_blob(read_from_input_queue(size));
+
+ if (m_read_which_entities != osmium::osm_entity_bits::nothing) {
+ m_reader = std::thread(&PBFInputFormat::parse_osm_data, this, m_read_which_entities);
+ }
+ }
+
+ ~PBFInputFormat() {
+ 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 an empty buffer at end of input.
+ */
+ osmium::memory::Buffer read() override {
+ osmium::memory::Buffer buffer;
+ if (m_eof) {
+ return buffer;
+ }
+
+ std::future<osmium::memory::Buffer> 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
+
+ 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<std::string>& 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf_output_format.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf_output_format.hpp
new file mode 100755
index 0000000000..288008f6ad
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf_output_format.hpp
@@ -0,0 +1,972 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+/*
+
+About the .osm.pbf file format
+This is an excerpt of <http://wiki.openstreetmap.org/wiki/PBF_Format>
+
+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:
+ <https://github.com/MaZderMind/OSM-binary/tree/osmpbf-outline>
+*/
+
+#include <algorithm>
+#include <chrono>
+#include <cmath>
+#include <cstdint>
+#include <cstdlib>
+#include <future>
+#include <iostream>
+#include <memory>
+#include <ratio>
+#include <string>
+#include <thread>
+#include <time.h>
+#include <utility>
+
+#include <osmium/handler.hpp>
+#include <osmium/io/detail/output_format.hpp>
+#include <osmium/io/detail/pbf.hpp> // IWYU pragma: export
+#include <osmium/io/detail/pbf_stringtable.hpp>
+#include <osmium/io/detail/zlib.hpp>
+#include <osmium/io/file.hpp>
+#include <osmium/io/file_format.hpp>
+#include <osmium/io/header.hpp>
+#include <osmium/memory/buffer.hpp>
+#include <osmium/memory/collection.hpp>
+#include <osmium/osm/box.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/node.hpp>
+#include <osmium/osm/object.hpp>
+#include <osmium/osm/relation.hpp>
+#include <osmium/osm/tag.hpp>
+#include <osmium/osm/timestamp.hpp>
+#include <osmium/osm/way.hpp>
+#include <osmium/util/cast.hpp>
+#include <osmium/visitor.hpp>
+
+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<uint32_t>(blob_header_data.size()));
+
+ // write to output: the 4-byte BlobHeader-Size followed by the BlobHeader followed by the Blob
+ std::string output;
+ output.reserve(sizeof(sz) + blob_header_data.size() + blob_data.size());
+ output.append(reinterpret_cast<const char*>(&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 <typename T>
+ 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};
+
+ /**
+ * 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.
+ */
+ 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<int64_t> m_delta_id;
+ Delta<int64_t> m_delta_lat;
+ Delta<int64_t> m_delta_lon;
+ Delta<int64_t> m_delta_timestamp;
+ Delta<int64_t> m_delta_changeset;
+ Delta<int64_t> m_delta_uid;
+ Delta<::google::protobuf::int32> m_delta_user_sid;
+
+ bool debug;
+
+ bool has_debug_level(int) {
+ return false;
+ }
+
+ ///// 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(); i<l; ++i) {
+ auto user_sid = denseinfo->user_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.
+ *
+ * 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(); i<l; ++i) {
+ map_common_string_ids(pbf_nodes->mutable_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<l; ++i) {
+ // map interim string-ids > 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<l; ++i) {
+ // map interim string-ids > 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(); i<l; ++i) {
+ map_common_string_ids(pbf_ways->mutable_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(); i<l; ++i) {
+ // get a pointer to the relation
+ OSMPBF::Relation* relation = pbf_relations->mutable_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 <class TPBFObject>
+ 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(); i<l; ++i) {
+ in->set_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<int64_t>(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<int64_t>(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 <class TPBFObject>
+ 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<std::string> 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());
+
+ string_table.store_stringtable(pbf_primitive_block.mutable_stringtable(), m_sort_stringtables);
+
+ if (m_sort_stringtables) {
+ map_string_ids();
+ } else {
+ delta_encode_string_ids();
+ }
+
+ std::promise<std::string> 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<float>(primitive_block_size) / static_cast<float>(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<int64_t> 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<int64_t> 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_sort_stringtables") == "false") {
+ m_sort_stringtables = 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<std::string> 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf_parser.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf_parser.hpp
new file mode 100755
index 0000000000..65a11e1558
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf_parser.hpp
@@ -0,0 +1,455 @@
+#ifndef OSMIUM_IO_DETAIL_PBF_PRIMITIVE_BLOCK_PARSER_HPP
+#define OSMIUM_IO_DETAIL_PBF_PRIMITIVE_BLOCK_PARSER_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <algorithm>
+
+#include <osmpbf/osmpbf.h>
+
+#include <osmium/builder/osm_object_builder.hpp>
+#include <osmium/io/detail/pbf.hpp> // IWYU pragma: export
+#include <osmium/io/detail/zlib.hpp>
+#include <osmium/io/header.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/node.hpp>
+#include <osmium/osm/types.hpp>
+#include <osmium/memory/buffer.hpp>
+#include <osmium/osm/entity_bits.hpp>
+#include <osmium/util/cast.hpp>
+
+namespace osmium {
+
+ namespace io {
+
+ namespace detail {
+
+ class PBFPrimitiveBlockParser {
+
+ static constexpr size_t initial_buffer_size = 2 * 1024 * 1024;
+
+ const std::string& m_data;
+
+ const OSMPBF::StringTable* m_stringtable;
+ int64_t m_lon_offset;
+ int64_t m_lat_offset;
+ int64_t m_date_factor;
+ int32_t m_granularity;
+
+ osmium::osm_entity_bits::type m_read_types;
+
+ osmium::memory::Buffer m_buffer;
+
+ PBFPrimitiveBlockParser(const PBFPrimitiveBlockParser&) = delete;
+ PBFPrimitiveBlockParser(PBFPrimitiveBlockParser&&) = delete;
+
+ PBFPrimitiveBlockParser& operator=(const PBFPrimitiveBlockParser&) = delete;
+ PBFPrimitiveBlockParser& operator=(PBFPrimitiveBlockParser&&) = delete;
+
+ public:
+
+ explicit PBFPrimitiveBlockParser(const std::string& data, osmium::osm_entity_bits::type read_types) :
+ m_data(data),
+ m_stringtable(nullptr),
+ m_lon_offset(0),
+ m_lat_offset(0),
+ m_date_factor(1000),
+ m_granularity(100),
+ m_read_types(read_types),
+ m_buffer(initial_buffer_size) {
+ }
+
+ ~PBFPrimitiveBlockParser() = default;
+
+ osmium::memory::Buffer operator()() {
+ OSMPBF::PrimitiveBlock pbf_primitive_block;
+ if (!pbf_primitive_block.ParseFromString(m_data)) {
+ throw osmium::pbf_error("failed to parse PrimitiveBlock");
+ }
+
+ m_stringtable = &pbf_primitive_block.stringtable();
+ m_lon_offset = pbf_primitive_block.lon_offset();
+ m_lat_offset = pbf_primitive_block.lat_offset();
+ m_date_factor = pbf_primitive_block.date_granularity() / 1000;
+ m_granularity = pbf_primitive_block.granularity();
+
+ for (int i = 0; i < pbf_primitive_block.primitivegroup_size(); ++i) {
+ const OSMPBF::PrimitiveGroup& group = pbf_primitive_block.primitivegroup(i);
+
+ if (group.has_dense()) {
+ if (m_read_types & osmium::osm_entity_bits::node) parse_dense_node_group(group);
+ } else if (group.ways_size() != 0) {
+ if (m_read_types & osmium::osm_entity_bits::way) parse_way_group(group);
+ } else if (group.relations_size() != 0) {
+ if (m_read_types & osmium::osm_entity_bits::relation) parse_relation_group(group);
+ } else if (group.nodes_size() != 0) {
+ if (m_read_types & osmium::osm_entity_bits::node) parse_node_group(group);
+ } else {
+ throw osmium::pbf_error("group of unknown type");
+ }
+ }
+
+ return std::move(m_buffer);
+ }
+
+ private:
+
+ template <class TBuilder, class TPBFObject>
+ void parse_attributes(TBuilder& builder, const TPBFObject& pbf_object) {
+ auto& object = builder.object();
+
+ object.set_id(pbf_object.id());
+
+ if (pbf_object.has_info()) {
+ object.set_version(static_cast_with_assert<object_version_type>(pbf_object.info().version()))
+ .set_changeset(static_cast_with_assert<changeset_id_type>(pbf_object.info().changeset()))
+ .set_timestamp(pbf_object.info().timestamp() * m_date_factor)
+ .set_uid_from_signed(pbf_object.info().uid());
+ if (pbf_object.info().has_visible()) {
+ object.set_visible(pbf_object.info().visible());
+ }
+ builder.add_user(m_stringtable->s(static_cast_with_assert<int>(pbf_object.info().user_sid())));
+ } else {
+ builder.add_user("", 1);
+ }
+ }
+
+ void parse_node_group(const OSMPBF::PrimitiveGroup& group) {
+ for (int i = 0; i < group.nodes_size(); ++i) {
+ osmium::builder::NodeBuilder builder(m_buffer);
+ const OSMPBF::Node& pbf_node = group.nodes(i);
+ parse_attributes(builder, pbf_node);
+
+ if (builder.object().visible()) {
+ builder.object().set_location(osmium::Location(
+ (pbf_node.lon() * m_granularity + m_lon_offset) / (OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision),
+ (pbf_node.lat() * m_granularity + m_lat_offset) / (OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision)));
+ }
+
+ if (pbf_node.keys_size() > 0) {
+ osmium::builder::TagListBuilder tl_builder(m_buffer, &builder);
+ for (int tag = 0; tag < pbf_node.keys_size(); ++tag) {
+ tl_builder.add_tag(m_stringtable->s(static_cast<int>(pbf_node.keys(tag))),
+ m_stringtable->s(static_cast<int>(pbf_node.vals(tag))));
+ }
+ }
+
+ m_buffer.commit();
+ }
+ }
+
+ void parse_way_group(const OSMPBF::PrimitiveGroup& group) {
+ for (int i = 0; i < group.ways_size(); ++i) {
+ osmium::builder::WayBuilder builder(m_buffer);
+ const OSMPBF::Way& pbf_way = group.ways(i);
+ parse_attributes(builder, pbf_way);
+
+ if (pbf_way.refs_size() > 0) {
+ osmium::builder::WayNodeListBuilder wnl_builder(m_buffer, &builder);
+ int64_t ref = 0;
+ for (int n = 0; n < pbf_way.refs_size(); ++n) {
+ ref += pbf_way.refs(n);
+ wnl_builder.add_node_ref(ref);
+ }
+ }
+
+ if (pbf_way.keys_size() > 0) {
+ osmium::builder::TagListBuilder tl_builder(m_buffer, &builder);
+ for (int tag = 0; tag < pbf_way.keys_size(); ++tag) {
+ tl_builder.add_tag(m_stringtable->s(static_cast<int>(pbf_way.keys(tag))),
+ m_stringtable->s(static_cast<int>(pbf_way.vals(tag))));
+ }
+ }
+
+ m_buffer.commit();
+ }
+ }
+
+ void parse_relation_group(const OSMPBF::PrimitiveGroup& group) {
+ for (int i = 0; i < group.relations_size(); ++i) {
+ osmium::builder::RelationBuilder builder(m_buffer);
+ const OSMPBF::Relation& pbf_relation = group.relations(i);
+ parse_attributes(builder, pbf_relation);
+
+ if (pbf_relation.types_size() > 0) {
+ osmium::builder::RelationMemberListBuilder rml_builder(m_buffer, &builder);
+ int64_t ref = 0;
+ for (int n = 0; n < pbf_relation.types_size(); ++n) {
+ ref += pbf_relation.memids(n);
+ rml_builder.add_member(osmpbf_membertype_to_item_type(pbf_relation.types(n)), ref, m_stringtable->s(pbf_relation.roles_sid(n)));
+ }
+ }
+
+ if (pbf_relation.keys_size() > 0) {
+ osmium::builder::TagListBuilder tl_builder(m_buffer, &builder);
+ for (int tag = 0; tag < pbf_relation.keys_size(); ++tag) {
+ tl_builder.add_tag(m_stringtable->s(static_cast<int>(pbf_relation.keys(tag))),
+ m_stringtable->s(static_cast<int>(pbf_relation.vals(tag))));
+ }
+ }
+
+ m_buffer.commit();
+ }
+ }
+
+ int add_tags(const OSMPBF::DenseNodes& dense, int n, osmium::builder::NodeBuilder* builder) {
+ if (n >= dense.keys_vals_size()) {
+ return n;
+ }
+
+ if (dense.keys_vals(n) == 0) {
+ return n+1;
+ }
+
+ osmium::builder::TagListBuilder tl_builder(m_buffer, builder);
+
+ while (n < dense.keys_vals_size()) {
+ int tag_key_pos = dense.keys_vals(n++);
+
+ if (tag_key_pos == 0) {
+ break;
+ }
+
+ tl_builder.add_tag(m_stringtable->s(tag_key_pos),
+ m_stringtable->s(dense.keys_vals(n)));
+
+ ++n;
+ }
+
+ return n;
+ }
+
+ void parse_dense_node_group(const OSMPBF::PrimitiveGroup& group) {
+ int64_t last_dense_id = 0;
+ int64_t last_dense_latitude = 0;
+ int64_t last_dense_longitude = 0;
+ int64_t last_dense_uid = 0;
+ int64_t last_dense_user_sid = 0;
+ int64_t last_dense_changeset = 0;
+ int64_t last_dense_timestamp = 0;
+ int last_dense_tag = 0;
+
+ const OSMPBF::DenseNodes& dense = group.dense();
+
+ for (int i = 0; i < dense.id_size(); ++i) {
+ bool visible = true;
+
+ last_dense_id += dense.id(i);
+ last_dense_latitude += dense.lat(i);
+ last_dense_longitude += dense.lon(i);
+
+ if (dense.has_denseinfo()) {
+ last_dense_changeset += dense.denseinfo().changeset(i);
+ last_dense_timestamp += dense.denseinfo().timestamp(i);
+ last_dense_uid += dense.denseinfo().uid(i);
+ last_dense_user_sid += dense.denseinfo().user_sid(i);
+ if (dense.denseinfo().visible_size() > 0) {
+ visible = dense.denseinfo().visible(i);
+ }
+ assert(last_dense_changeset >= 0);
+ assert(last_dense_timestamp >= 0);
+ assert(last_dense_uid >= -1);
+ assert(last_dense_user_sid >= 0);
+ }
+
+ osmium::builder::NodeBuilder builder(m_buffer);
+ osmium::Node& node = builder.object();
+
+ node.set_id(last_dense_id);
+
+ if (dense.has_denseinfo()) {
+ auto v = dense.denseinfo().version(i);
+ assert(v > 0);
+ node.set_version(static_cast<osmium::object_version_type>(v));
+ node.set_changeset(static_cast<osmium::changeset_id_type>(last_dense_changeset));
+ node.set_timestamp(last_dense_timestamp * m_date_factor);
+ node.set_uid_from_signed(static_cast<osmium::signed_user_id_type>(last_dense_uid));
+ node.set_visible(visible);
+ builder.add_user(m_stringtable->s(static_cast<int>(last_dense_user_sid)));
+ } else {
+ builder.add_user("", 1);
+ }
+
+ if (visible) {
+ builder.object().set_location(osmium::Location(
+ (last_dense_longitude * m_granularity + m_lon_offset) / (OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision),
+ (last_dense_latitude * m_granularity + m_lat_offset) / (OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision)));
+ }
+
+ last_dense_tag = add_tags(dense, last_dense_tag, &builder);
+ m_buffer.commit();
+ }
+ }
+
+ }; // class PBFPrimitiveBlockParser
+
+ /**
+ * PBF blobs can optionally be packed with the zlib algorithm.
+ * This function returns the raw data (if it was unpacked) or
+ * the unpacked data (if it was packed).
+ *
+ * @param input_data Reference to input data.
+ * @returns Unpacked data
+ * @throws osmium::pbf_error If there was a problem parsing the PBF
+ */
+ inline std::unique_ptr<const std::string> unpack_blob(const std::string& input_data) {
+ OSMPBF::Blob pbf_blob;
+ if (!pbf_blob.ParseFromString(input_data)) {
+ throw osmium::pbf_error("failed to parse blob");
+ }
+
+ if (pbf_blob.has_raw()) {
+ return std::unique_ptr<std::string>(pbf_blob.release_raw());
+ } else if (pbf_blob.has_zlib_data()) {
+ auto raw_size = pbf_blob.raw_size();
+ assert(raw_size >= 0);
+ assert(raw_size <= OSMPBF::max_uncompressed_blob_size);
+ return osmium::io::detail::zlib_uncompress(pbf_blob.zlib_data(), static_cast<unsigned long>(raw_size));
+ } else if (pbf_blob.has_lzma_data()) {
+ throw osmium::pbf_error("lzma blobs not implemented");
+ } else {
+ throw osmium::pbf_error("blob contains no data");
+ }
+ }
+
+ /**
+ * Parse blob as a HeaderBlock.
+ *
+ * @param input_buffer Blob data
+ * @returns Header object
+ * @throws osmium::pbf_error If there was a parsing error
+ */
+ inline osmium::io::Header parse_header_blob(const std::string& input_buffer) {
+ const std::unique_ptr<const std::string> data = unpack_blob(input_buffer);
+
+ OSMPBF::HeaderBlock pbf_header_block;
+ if (!pbf_header_block.ParseFromString(*data)) {
+ throw osmium::pbf_error("failed to parse HeaderBlock");
+ }
+
+ osmium::io::Header header;
+ for (int i = 0; i < pbf_header_block.required_features_size(); ++i) {
+ const std::string& feature = pbf_header_block.required_features(i);
+
+ if (feature == "OsmSchema-V0.6") continue;
+ if (feature == "DenseNodes") {
+ header.set("pbf_dense_nodes", true);
+ continue;
+ }
+ if (feature == "HistoricalInformation") {
+ header.set_has_multiple_object_versions(true);
+ continue;
+ }
+
+ throw osmium::pbf_error(std::string("required feature not supported: ") + feature);
+ }
+
+ for (int i = 0; i < pbf_header_block.optional_features_size(); ++i) {
+ const std::string& feature = pbf_header_block.optional_features(i);
+ header.set("pbf_optional_feature_" + std::to_string(i), feature);
+ }
+
+ if (pbf_header_block.has_writingprogram()) {
+ header.set("generator", pbf_header_block.writingprogram());
+ }
+
+ if (pbf_header_block.has_bbox()) {
+ const OSMPBF::HeaderBBox& pbf_bbox = pbf_header_block.bbox();
+ const int64_t resolution_convert = OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision;
+ osmium::Box box;
+ box.extend(osmium::Location(pbf_bbox.left() / resolution_convert, pbf_bbox.bottom() / resolution_convert));
+ box.extend(osmium::Location(pbf_bbox.right() / resolution_convert, pbf_bbox.top() / resolution_convert));
+ header.add_box(box);
+ }
+
+ if (pbf_header_block.has_osmosis_replication_timestamp()) {
+ header.set("osmosis_replication_timestamp", osmium::Timestamp(pbf_header_block.osmosis_replication_timestamp()).to_iso());
+ }
+
+ if (pbf_header_block.has_osmosis_replication_sequence_number()) {
+ header.set("osmosis_replication_sequence_number", std::to_string(pbf_header_block.osmosis_replication_sequence_number()));
+ }
+
+ if (pbf_header_block.has_osmosis_replication_base_url()) {
+ header.set("osmosis_replication_base_url", pbf_header_block.osmosis_replication_base_url());
+ }
+
+ return header;
+ }
+
+ class DataBlobParser {
+
+ std::shared_ptr<std::string> m_input_buffer;
+ osmium::osm_entity_bits::type m_read_types;
+
+ public:
+
+ DataBlobParser(std::string&& input_buffer, osmium::osm_entity_bits::type read_types) :
+ m_input_buffer(std::make_shared<std::string>(std::move(input_buffer))),
+ m_read_types(read_types) {
+ if (input_buffer.size() > OSMPBF::max_uncompressed_blob_size) {
+ throw osmium::pbf_error(std::string("invalid blob size: " + std::to_string(input_buffer.size())));
+ }
+ }
+/*
+ DataBlobParser(const DataBlobParser& other) :
+ m_input_buffer(std::move(other.m_input_buffer)),
+ m_read_types(other.m_read_types) {
+ }*/
+
+ DataBlobParser(const DataBlobParser&) = default;
+ DataBlobParser& operator=(const DataBlobParser&) = default;
+
+ DataBlobParser(DataBlobParser&&) = default;
+ DataBlobParser& operator=(DataBlobParser&&) = default;
+
+ ~DataBlobParser() = default;
+
+ osmium::memory::Buffer operator()() {
+ const std::unique_ptr<const std::string> data = unpack_blob(*m_input_buffer);
+ PBFPrimitiveBlockParser parser(*data, m_read_types);
+ return parser();
+ }
+
+ }; // class DataBlobParser
+
+ } // namespace detail
+
+ } // namespace io
+
+} // namespace osmium
+
+#endif // OSMIUM_IO_DETAIL_PBF_PRIMITIVE_BLOCK_PARSER_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf_stringtable.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf_stringtable.hpp
new file mode 100755
index 0000000000..5f540f1271
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/pbf_stringtable.hpp
@@ -0,0 +1,218 @@
+#ifndef OSMIUM_IO_DETAIL_PBF_STRINGTABLE_HPP
+#define OSMIUM_IO_DETAIL_PBF_STRINGTABLE_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <cstdint>
+#include <iterator>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <osmpbf/osmpbf.h>
+
+#include <osmium/util/cast.hpp>
+
+namespace osmium {
+
+ namespace io {
+
+ namespace detail {
+
+ /**
+ * StringTable management for PBF writer
+ *
+ * All strings are stored as indexes to rows in a StringTable. The StringTable contains
+ * one row for each used string, so strings that are used multiple times need to be
+ * stored only once. The StringTable is sorted by usage-count, so the most often used
+ * string is stored at index 1.
+ */
+ class StringTable {
+
+ public:
+
+ /// type for string IDs (interim and final)
+ typedef uint16_t string_id_type;
+
+ private:
+
+ /**
+ * this is the struct used to build the StringTable. It is stored as
+ * the value-part in the strings-map.
+ *
+ * when a new string is added to the map, its count is set to 0 and
+ * the interim_id is set to the current size of the map. This interim_id
+ * is then stored into the pbf-objects.
+ *
+ * before the PrimitiveBlock is serialized, the map is sorted by count
+ * and stored into the pbf-StringTable. Afterwards the interim-ids are
+ * mapped to the "real" id in the StringTable.
+ *
+ * this way often used strings get lower ids in the StringTable. As the
+ * protobuf-serializer stores numbers in variable bit-lengths, lower
+ * IDs means less used space in the resulting file.
+ */
+ struct string_info {
+
+ /// number of occurrences of this string
+ uint16_t count;
+
+ /// an intermediate-id
+ string_id_type interim_id;
+
+ }; // struct string_info
+
+ /**
+ * Interim StringTable, storing all strings that should be written to
+ * the StringTable once the block is written to disk.
+ */
+ typedef std::map<std::string, string_info> string2string_info_type;
+ string2string_info_type m_strings;
+
+ /**
+ * This vector is used to map the interim IDs to real StringTable IDs after
+ * writing all strings to the StringTable.
+ */
+ typedef std::vector<string_id_type> interim_id2id_type;
+ interim_id2id_type m_id2id_map;
+
+ size_t m_size = 0;
+
+ public:
+
+ StringTable() {
+ }
+
+ friend bool operator<(const string_info& lhs, const string_info& rhs) {
+ return lhs.count > rhs.count;
+ }
+
+ /**
+ * record a string in the interim StringTable if it's missing, otherwise just increase its counter,
+ * return the interim-id assigned to the string.
+ */
+ string_id_type record_string(const std::string& string) {
+ string_info& info = m_strings[string];
+ if (info.interim_id == 0) {
+ ++m_size;
+ info.interim_id = static_cast_with_assert<string_id_type>(m_size);
+ } else {
+ info.count++;
+ }
+ return info.interim_id;
+ }
+
+ /**
+ * Sort the interim StringTable and store it to the real protobuf StringTable.
+ * while storing to the real table, this function fills the id2id_map with
+ * pairs, mapping the interim-ids to final and real StringTable ids.
+ *
+ * Note that the m_strings table is a std::map and as such is sorted lexicographically.
+ * When the transformation into the sortedby multimap is done, it gets sorted by
+ * the count. The end result (at least with the glibc standard container/algorithm
+ * implementation) is that the string table is sorted first by reverse count (ie descending)
+ * and then by reverse lexicographic order.
+ */
+ void store_stringtable(OSMPBF::StringTable* st, bool sort) {
+ // add empty StringTable entry at index 0
+ // StringTable index 0 is reserved as delimiter in the densenodes key/value list
+ // this line also ensures that there's always a valid StringTable
+ st->add_s("");
+
+ if (sort) {
+ std::multimap<string_info, std::string> sortedbycount;
+
+ m_id2id_map.resize(m_size+1);
+
+ std::transform(m_strings.begin(), m_strings.end(),
+ std::inserter(sortedbycount, sortedbycount.begin()),
+ [](const std::pair<std::string, string_info>& p) {
+ return std::pair<string_info, std::string>(p.second, p.first);
+ });
+
+ string_id_type n = 0;
+
+ for (const auto& mapping : sortedbycount) {
+ // add the string of the current item to the pbf StringTable
+ st->add_s(mapping.second);
+
+ // store the mapping from the interim-id to the real id
+ m_id2id_map[mapping.first.interim_id] = ++n;
+ }
+ } else {
+ std::vector<std::pair<string_id_type, const char*>> sortedbyid;
+ sortedbyid.reserve(m_strings.size());
+
+ for (const auto& p : m_strings) {
+ sortedbyid.emplace_back(p.second.interim_id, p.first.c_str());
+ }
+
+ std::sort(sortedbyid.begin(), sortedbyid.end());
+ for (const auto& mapping : sortedbyid) {
+ st->add_s(mapping.second);
+ }
+ }
+ }
+
+ /**
+ * Map from an interim ID to a real string ID.
+ */
+ string_id_type map_string_id(const string_id_type interim_id) const {
+ return m_id2id_map[interim_id];
+ }
+
+ template <typename T>
+ string_id_type map_string_id(const T interim_id) const {
+ return map_string_id(static_cast_with_assert<string_id_type>(interim_id));
+ }
+
+ /**
+ * Clear the stringtable, preparing for the next block.
+ */
+ void clear() {
+ m_strings.clear();
+ m_id2id_map.clear();
+ m_size = 0;
+ }
+
+ }; // class StringTable
+
+ } // namespace detail
+
+ } // namespace io
+
+} // namespace osmium
+
+#endif // OSMIUM_IO_DETAIL_PBF_STRINGTABLE_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/read_thread.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/read_thread.hpp
new file mode 100755
index 0000000000..bce4f55078
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/read_thread.hpp
@@ -0,0 +1,106 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <atomic>
+#include <chrono>
+#include <ratio>
+#include <string>
+#include <thread>
+#include <utility>
+
+#include <osmium/io/compression.hpp>
+#include <osmium/thread/queue.hpp>
+#include <osmium/thread/util.hpp>
+
+namespace osmium {
+
+ namespace io {
+
+ namespace detail {
+
+ class ReadThread {
+
+ osmium::thread::Queue<std::string>& 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<bool>& m_done;
+
+ public:
+
+ explicit ReadThread(osmium::thread::Queue<std::string>& queue, osmium::io::Decompressor* decompressor, std::atomic<bool>& 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/read_write.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/read_write.hpp
new file mode 100755
index 0000000000..6651cced9b
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/read_write.hpp
@@ -0,0 +1,160 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cerrno>
+#include <cstddef>
+#include <fcntl.h>
+#include <string>
+#include <system_error>
+
+#ifndef _MSC_VER
+# include <unistd.h>
+#else
+# include <io.h>
+#endif
+
+#include <osmium/io/overwrite.hpp>
+
+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) {
+ constexpr size_t max_write = 100 * 1024 * 1024; // Max 100 MByte per write
+ size_t offset = 0;
+ do {
+ auto write_count = size - offset;
+ if (write_count > max_write) {
+ write_count = max_write;
+ }
+ auto length = ::write(fd, output_buffer + offset, static_cast<unsigned int>(write_count));
+ if (length < 0) {
+ throw std::system_error(errno, std::system_category(), "Write failed");
+ }
+ offset += static_cast<size_t>(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<const unsigned char*>(output_buffer), size);
+ }
+
+ } // namespace detail
+
+ } // namespace io
+
+} // namespace osmium
+
+#endif // OSMIUM_IO_DETAIL_READ_WRITE_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/write_thread.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/write_thread.hpp
new file mode 100755
index 0000000000..fad22ed69e
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/write_thread.hpp
@@ -0,0 +1,86 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <future>
+#include <string>
+
+#include <osmium/io/compression.hpp>
+#include <osmium/io/detail/output_format.hpp>
+#include <osmium/thread/util.hpp>
+
+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<std::string> 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/xml_input_format.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/xml_input_format.hpp
new file mode 100755
index 0000000000..c03f84d9b4
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/xml_input_format.hpp
@@ -0,0 +1,738 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <atomic>
+#include <cassert>
+#include <chrono>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <exception>
+#include <future>
+#include <iostream>
+#include <memory>
+#include <ratio>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include <thread>
+#include <utility>
+
+#include <expat.h>
+
+#include <osmium/builder/builder.hpp>
+#include <osmium/builder/osm_object_builder.hpp>
+#include <osmium/io/detail/input_format.hpp>
+#include <osmium/io/error.hpp>
+#include <osmium/io/file_format.hpp>
+#include <osmium/io/header.hpp>
+#include <osmium/memory/buffer.hpp>
+#include <osmium/osm.hpp>
+#include <osmium/osm/box.hpp>
+#include <osmium/osm/entity_bits.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/object.hpp>
+#include <osmium/osm/types.hpp>
+#include <osmium/thread/queue.hpp>
+#include <osmium/thread/util.hpp>
+#include <osmium/util/cast.hpp>
+
+namespace osmium {
+
+ /**
+ * Exception thrown when the XML parser failed. The exception contains
+ * (if available) 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;
+
+ explicit 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)) {
+ }
+
+ 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;
+
+ 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<osmium::builder::NodeBuilder> m_node_builder;
+ std::unique_ptr<osmium::builder::WayBuilder> m_way_builder;
+ std::unique_ptr<osmium::builder::RelationBuilder> m_relation_builder;
+ std::unique_ptr<osmium::builder::ChangesetBuilder> m_changeset_builder;
+
+ std::unique_ptr<osmium::builder::TagListBuilder> m_tl_builder;
+ std::unique_ptr<osmium::builder::WayNodeListBuilder> m_wnl_builder;
+ std::unique_ptr<osmium::builder::RelationMemberListBuilder> m_rml_builder;
+
+ osmium::thread::Queue<std::string>& m_input_queue;
+ osmium::thread::Queue<osmium::memory::Buffer>& m_queue;
+ std::promise<osmium::io::Header>& m_header_promise;
+
+ osmium::osm_entity_bits::type m_read_types;
+
+ std::atomic<bool>& m_done;
+
+ /**
+ * A C++ wrapper for the Expat parser that makes sure no memory is leaked.
+ */
+ template <class T>
+ class ExpatXMLParser {
+
+ XML_Parser m_parser;
+
+ static void XMLCALL start_element_wrapper(void* data, const XML_Char* element, const XML_Char** attrs) {
+ static_cast<XMLParser*>(data)->start_element(element, attrs);
+ }
+
+ static void XMLCALL end_element_wrapper(void* data, const XML_Char* element) {
+ static_cast<XMLParser*>(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<int>(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 T>
+ class PromiseKeeper {
+
+ T& m_data;
+ std::promise<T>& m_promise;
+
+ public:
+
+ PromiseKeeper(T& data, std::promise<T>& promise) :
+ m_data(data),
+ m_promise(promise) {
+ }
+
+ ~PromiseKeeper() {
+ m_promise.set_value(m_data);
+ }
+
+ }; // class PromiseKeeper
+
+ public:
+
+ explicit XMLParser(osmium::thread::Queue<std::string>& input_queue, osmium::thread::Queue<osmium::memory::Buffer>& queue, std::promise<osmium::io::Header>& header_promise, osmium::osm_entity_bits::type read_types, std::atomic<bool>& 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<XMLParser> parser(this);
+ PromiseKeeper<osmium::io::Header> 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<osmium::Node&>(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<osmium::builder::TagListBuilder>(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();
+ }
+ } else {
+ throw osmium::xml_error(std::string("Unknown top-level element: ") + element);
+ }
+ 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<osmium::builder::NodeBuilder>(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<osmium::builder::WayBuilder>(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<osmium::builder::RelationBuilder>(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<osmium::builder::ChangesetBuilder>(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<osmium::builder::WayNodeListBuilder>(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<osmium::builder::RelationMemberListBuilder>(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<char>(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<const char*>(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<osmium::memory::Buffer> m_queue;
+ std::atomic<bool> m_done;
+ std::promise<osmium::io::Header> m_header_promise;
+ std::future<bool> 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<std::string>& input_queue) :
+ osmium::io::detail::InputFormat(file, read_which_entities),
+ 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() override {
+ 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<std::string>& 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/xml_output_format.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/xml_output_format.hpp
new file mode 100755
index 0000000000..65ba171b8b
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/xml_output_format.hpp
@@ -0,0 +1,484 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cassert>
+#include <chrono>
+#include <cinttypes>
+#include <cstddef>
+#include <cstdio>
+#include <future>
+#include <iterator>
+#include <memory>
+#include <ratio>
+#include <string>
+#include <thread>
+#include <utility>
+
+#include <osmium/handler.hpp>
+#include <osmium/io/detail/output_format.hpp>
+#include <osmium/io/file.hpp>
+#include <osmium/io/file_format.hpp>
+#include <osmium/io/header.hpp>
+#include <osmium/memory/buffer.hpp>
+#include <osmium/memory/collection.hpp>
+#include <osmium/osm/box.hpp>
+#include <osmium/osm/changeset.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/node.hpp>
+#include <osmium/osm/object.hpp>
+#include <osmium/osm/relation.hpp>
+#include <osmium/osm/tag.hpp>
+#include <osmium/osm/timestamp.hpp>
+#include <osmium/osm/types.hpp>
+#include <osmium/osm/way.hpp>
+#include <osmium/thread/pool.hpp>
+#include <osmium/visitor.hpp>
+
+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 += "&amp;"; break;
+ case '\"': out += "&quot;"; break;
+ case '\'': out += "&apos;"; break;
+ case '<': out += "&lt;"; break;
+ case '>': out += "&gt;"; break;
+ default: out += *in; break;
+ }
+ }
+ }
+
+ const size_t tmp_buffer_size = 100;
+
+ template <typename T>
+ 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<size_t>(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
+
+ std::shared_ptr<osmium::memory::Buffer> m_input_buffer;
+
+ std::shared_ptr<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 += " <tag k=\"";
+ xml_string(*m_out, tag.key());
+ *m_out += "\" v=\"";
+ xml_string(*m_out, tag.value());
+ *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 += " </create>\n";
+ break;
+ case operation::op_modify:
+ *m_out += " </modify>\n";
+ break;
+ case operation::op_delete:
+ *m_out += " </delete>\n";
+ break;
+ }
+
+ switch (op) {
+ case operation::op_none:
+ break;
+ case operation::op_create:
+ *m_out += " <create>\n";
+ break;
+ case operation::op_modify:
+ *m_out += " <modify>\n";
+ break;
+ case operation::op_delete:
+ *m_out += " <delete>\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::make_shared<osmium::memory::Buffer>(std::move(buffer))),
+ m_out(std::make_shared<std::string>()),
+ m_write_visible_flag(write_visible_flag && !write_change_ops),
+ m_write_change_ops(write_change_ops) {
+ }
+
+ 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);
+
+ 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 += "<node";
+
+ write_meta(node);
+
+ if (node.location()) {
+ *m_out += " lat=\"";
+ osmium::util::double2string(std::back_inserter(*m_out), node.location().lat_without_check(), 7);
+ *m_out += "\" lon=\"";
+ osmium::util::double2string(std::back_inserter(*m_out), node.location().lon_without_check(), 7);
+ *m_out += "\"";
+ }
+
+ if (node.tags().empty()) {
+ *m_out += "/>\n";
+ return;
+ }
+
+ *m_out += ">\n";
+
+ write_tags(node.tags());
+
+ write_prefix();
+ *m_out += "</node>\n";
+ }
+
+ void way(const osmium::Way& way) {
+ if (m_write_change_ops) {
+ open_close_op_tag(way.visible() ? (way.version() == 1 ? operation::op_create : operation::op_modify) : operation::op_delete);
+ }
+
+ write_prefix();
+ *m_out += "<way";
+ write_meta(way);
+
+ if (way.tags().empty() && way.nodes().empty()) {
+ *m_out += "/>\n";
+ return;
+ }
+
+ *m_out += ">\n";
+
+ for (const auto& node_ref : way.nodes()) {
+ write_prefix();
+ oprintf(*m_out, " <nd ref=\"%" PRId64 "\"/>\n", node_ref.ref());
+ }
+
+ write_tags(way.tags());
+
+ write_prefix();
+ *m_out += "</way>\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 += "<relation";
+ write_meta(relation);
+
+ if (relation.tags().empty() && relation.members().empty()) {
+ *m_out += "/>\n";
+ return;
+ }
+
+ *m_out += ">\n";
+
+ for (const auto& member : relation.members()) {
+ write_prefix();
+ *m_out += " <member type=\"";
+ *m_out += item_type_to_name(member.type());
+ oprintf(*m_out, "\" ref=\"%" PRId64 "\" role=\"", member.ref());
+ xml_string(*m_out, member.role());
+ *m_out += "\"/>\n";
+ }
+
+ write_tags(relation.tags());
+
+ write_prefix();
+ *m_out += "</relation>\n";
+ }
+
+ void changeset(const osmium::Changeset& changeset) {
+ write_prefix();
+ *m_out += "<changeset";
+
+ oprintf(*m_out, " id=\"%" PRId32 "\"", changeset.id());
+
+ if (changeset.created_at()) {
+ *m_out += " created_at=\"";
+ *m_out += changeset.created_at().to_iso();
+ *m_out += "\"";
+ }
+
+ oprintf(*m_out, " num_changes=\"%" PRId32 "\"", changeset.num_changes());
+
+ if (changeset.closed_at()) {
+ *m_out += " closed_at=\"";
+ *m_out += changeset.closed_at().to_iso();
+ *m_out += "\" open=\"false\"";
+ } else {
+ *m_out += " open=\"true\"";
+ }
+
+ if (changeset.bounds()) {
+ oprintf(*m_out, " min_lon=\"%.7f\"", changeset.bounds().bottom_left().lon_without_check());
+ oprintf(*m_out, " min_lat=\"%.7f\"", changeset.bounds().bottom_left().lat_without_check());
+ oprintf(*m_out, " max_lon=\"%.7f\"", changeset.bounds().top_right().lon_without_check());
+ oprintf(*m_out, " max_lat=\"%.7f\"", changeset.bounds().top_right().lat_without_check());
+ }
+
+ if (!changeset.user_is_anonymous()) {
+ *m_out += " user=\"";
+ xml_string(*m_out, changeset.user());
+ oprintf(*m_out, "\" uid=\"%d\"", changeset.uid());
+ }
+
+ if (changeset.tags().empty()) {
+ *m_out += "/>\n";
+ return;
+ }
+
+ *m_out += ">\n";
+
+ write_tags(changeset.tags());
+
+ write_prefix();
+ *m_out += "</changeset>\n";
+ }
+
+ }; // class XMLOutputBlock
+
+ class XMLOutputFormat : public osmium::io::detail::OutputFormat, public osmium::handler::Handler {
+
+ bool m_write_visible_flag;
+
+ public:
+
+ XMLOutputFormat(const osmium::io::File& file, data_queue_type& output_queue) :
+ OutputFormat(file, output_queue),
+ m_write_visible_flag(file.has_multiple_object_versions() || m_file.is_true("force_visible_flag")) {
+ }
+
+ XMLOutputFormat(const XMLOutputFormat&) = delete;
+ XMLOutputFormat& operator=(const XMLOutputFormat&) = delete;
+
+ ~XMLOutputFormat() override final {
+ }
+
+ void write_buffer(osmium::memory::Buffer&& buffer) override final {
+ m_output_queue.push(osmium::thread::Pool::instance().submit(XMLOutputBlock{std::move(buffer), m_write_visible_flag, m_file.is_true("xml_change_format")}));
+ }
+
+ void write_header(const osmium::io::Header& header) override final {
+ std::string out = "<?xml version='1.0' encoding='UTF-8'?>\n";
+
+ if (m_file.is_true("xml_change_format")) {
+ out += "<osmChange version=\"0.6\" generator=\"";
+ xml_string(out, header.get("generator").c_str());
+ out += "\">\n";
+ } else {
+ out += "<osm version=\"0.6\"";
+
+ std::string xml_josm_upload = header.get("xml_josm_upload");
+ if (xml_josm_upload == "true" || xml_josm_upload == "false") {
+ out += " upload=\"";
+ out += xml_josm_upload;
+ out += "\"";
+ }
+ out += " generator=\"";
+ xml_string(out, header.get("generator").c_str());
+ out += "\">\n";
+ }
+
+ for (const auto& box : header.boxes()) {
+ out += " <bounds";
+ oprintf(out, " minlon=\"%.7f\"", box.bottom_left().lon());
+ oprintf(out, " minlat=\"%.7f\"", box.bottom_left().lat());
+ oprintf(out, " maxlon=\"%.7f\"", box.top_right().lon());
+ oprintf(out, " maxlat=\"%.7f\"/>\n", box.top_right().lat());
+ }
+
+ std::promise<std::string> promise;
+ m_output_queue.push(promise.get_future());
+ promise.set_value(std::move(out));
+ }
+
+ void close() override final {
+ {
+ std::string out;
+ if (m_file.is_true("xml_change_format")) {
+ out += "</osmChange>\n";
+ } else {
+ out += "</osm>\n";
+ }
+
+ std::promise<std::string> promise;
+ m_output_queue.push(promise.get_future());
+ promise.set_value(std::move(out));
+ }
+
+ std::promise<std::string> 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/zlib.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/zlib.hpp
new file mode 100755
index 0000000000..a402bf7e63
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/detail/zlib.hpp
@@ -0,0 +1,113 @@
+#ifndef OSMIUM_IO_DETAIL_ZLIB_HPP
+#define OSMIUM_IO_DETAIL_ZLIB_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+#include <zlib.h>
+
+#include <osmium/util/cast.hpp>
+
+namespace osmium {
+
+ namespace io {
+
+ namespace detail {
+
+ /**
+ * 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(osmium::static_cast_with_assert<unsigned long>(input.size()));
+
+ std::string output(output_size, '\0');
+
+ auto result = ::compress(
+ reinterpret_cast<unsigned char*>(const_cast<char *>(output.data())),
+ &output_size,
+ reinterpret_cast<const unsigned char*>(input.data()),
+ osmium::static_cast_with_assert<unsigned long>(input.size())
+ );
+
+ if (result != Z_OK) {
+ throw std::runtime_error(std::string("failed to compress data: ") + zError(result));
+ }
+
+ output.resize(output_size);
+
+ return output;
+ }
+
+ /**
+ * 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.
+ */
+ inline std::unique_ptr<std::string> zlib_uncompress(const std::string& input, unsigned long raw_size) {
+ auto output = std::unique_ptr<std::string>(new std::string(raw_size, '\0'));
+
+ auto result = ::uncompress(
+ reinterpret_cast<unsigned char*>(const_cast<char *>(output->data())),
+ &raw_size,
+ reinterpret_cast<const unsigned char*>(input.data()),
+ osmium::static_cast_with_assert<unsigned long>(input.size())
+ );
+
+ if (result != Z_OK) {
+ throw std::runtime_error(std::string("failed to uncompress data: ") + zError(result));
+ }
+
+ return output;
+ }
+
+ } // namespace detail
+
+ } // namespace io
+
+} // namespace osmium
+
+#endif // OSMIUM_IO_DETAIL_ZLIB_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/error.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/error.hpp
new file mode 100755
index 0000000000..07652bc598
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/error.hpp
@@ -0,0 +1,58 @@
+#ifndef OSMIUM_IO_ERROR_HPP
+#define OSMIUM_IO_ERROR_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <stdexcept>
+#include <string>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/file.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/file.hpp
new file mode 100755
index 0000000000..5b6c02f132
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/file.hpp
@@ -0,0 +1,344 @@
+#ifndef OSMIUM_IO_FILE_HPP
+#define OSMIUM_IO_FILE_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstddef>
+#include <stdexcept>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <osmium/io/file_format.hpp>
+#include <osmium/io/file_compression.hpp>
+#include <osmium/util/options.hpp>
+#include <osmium/util/compatibility.hpp>
+
+namespace osmium {
+
+ /**
+ * @brief Everything related to input and output of OSM data.
+ */
+ namespace io {
+
+ namespace detail {
+
+ inline std::vector<std::string> split(const std::string& in, const char delim) {
+ std::vector<std::string> 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<std::string> 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<std::string> 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/file_compression.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/file_compression.hpp
new file mode 100755
index 0000000000..292ddcfca6
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <iosfwd>
+
+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 <typename TChar, typename TTraits>
+ inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const file_compression compression) {
+ return out << as_string(compression);
+ }
+
+ } // namespace io
+
+} // namespace osmium
+
+#endif // OSMIUM_IO_FILE_COMPRESSION_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/file_format.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/file_format.hpp
new file mode 100755
index 0000000000..1a63a5e49d
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <iosfwd>
+
+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 <typename TChar, typename TTraits>
+ inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const file_format format) {
+ return out << as_string(format);
+ }
+
+ } // namespace io
+
+} // namespace osmium
+
+#endif // OSMIUM_IO_FILE_FORMAT_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/gzip_compression.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/gzip_compression.hpp
new file mode 100755
index 0000000000..272397707d
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/gzip_compression.hpp
@@ -0,0 +1,246 @@
+#ifndef OSMIUM_IO_GZIP_COMPRESSION_HPP
+#define OSMIUM_IO_GZIP_COMPRESSION_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+/**
+ * @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 <stdexcept>
+#include <string>
+
+#include <errno.h>
+#include <zlib.h>
+
+#include <osmium/io/compression.hpp>
+#include <osmium/io/file_compression.hpp>
+#include <osmium/util/cast.hpp>
+#include <osmium/util/compatibility.hpp>
+
+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<unsigned int>(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<char*>(buffer.data()), static_cast_with_assert<unsigned int>(buffer.size()));
+ if (nread < 0) {
+ detail::throw_gzip_error(m_gzfile, "read failed");
+ }
+ buffer.resize(static_cast<std::string::size_type>(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<unsigned char*>(const_cast<char*>(buffer));
+ m_zstream.avail_in = static_cast_with_assert<unsigned int>(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<unsigned char*>(const_cast<char*>(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<unsigned long>(m_zstream.next_out - reinterpret_cast<const unsigned char*>(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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/header.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/header.hpp
new file mode 100755
index 0000000000..4b0830a626
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <initializer_list>
+#include <vector>
+
+#include <osmium/osm/box.hpp>
+#include <osmium/util/options.hpp>
+
+namespace osmium {
+
+ namespace io {
+
+ /**
+ * Meta information from the header of an OSM file.
+ */
+ class Header : public osmium::util::Options {
+
+ /// Bounding boxes
+ std::vector<osmium::Box> 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<osmium::util::Options::value_type>& values) :
+ Options(values) {
+ }
+
+ Header(const Header&) = default;
+ Header& operator=(const Header&) = default;
+
+ Header(Header&&) = default;
+ Header& operator=(Header&&) = default;
+
+ ~Header() = default;
+
+ std::vector<osmium::Box>& boxes() noexcept {
+ return m_boxes;
+ }
+
+ const std::vector<osmium::Box>& boxes() const noexcept {
+ return m_boxes;
+ }
+
+ Header& boxes(const std::vector<osmium::Box>& 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/input_iterator.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/input_iterator.hpp
new file mode 100755
index 0000000000..f6197299d7
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/input_iterator.hpp
@@ -0,0 +1,140 @@
+#ifndef OSMIUM_IO_INPUT_ITERATOR_HPP
+#define OSMIUM_IO_INPUT_ITERATOR_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <memory>
+#include <type_traits>
+
+#include <osmium/memory/buffer.hpp>
+#include <osmium/memory/item.hpp>
+#include <osmium/util/compatibility.hpp>
+
+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 TSource, class TItem = osmium::memory::Item>
+ class InputIterator {
+
+ static_assert(std::is_base_of<osmium::memory::Item, TItem>::value, "TItem must derive from osmium::buffer::Item");
+
+ typedef typename osmium::memory::Buffer::t_iterator<TItem> item_iterator;
+
+ TSource* m_source;
+ std::shared_ptr<osmium::memory::Buffer> m_buffer;
+ item_iterator m_iter {};
+
+ void update_buffer() {
+ do {
+ m_buffer = std::make_shared<osmium::memory::Buffer>(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<TItem>();
+ } while (m_iter == m_buffer->end<TItem>());
+ }
+
+ 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<TItem>()) {
+ 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<reference>(*m_iter);
+ }
+
+ pointer operator->() const {
+ assert(m_iter);
+ return &static_cast<reference>(*m_iter);
+ }
+
+ }; // class InputIterator
+
+ } // namespace io
+
+} // namespace osmium
+
+#endif // OSMIUM_IO_INPUT_ITERATOR_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/opl_output.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/opl_output.hpp
new file mode 100755
index 0000000000..04385d968c
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/io/writer.hpp> // IWYU pragma: export
+#include <osmium/io/detail/opl_output_format.hpp> // IWYU pragma: export
+
+#endif // OSMIUM_IO_OPL_OUTPUT_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/output_iterator.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/output_iterator.hpp
new file mode 100755
index 0000000000..608852fa97
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/output_iterator.hpp
@@ -0,0 +1,124 @@
+#ifndef OSMIUM_IO_OUTPUT_ITERATOR_HPP
+#define OSMIUM_IO_OUTPUT_ITERATOR_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstddef>
+#include <iterator>
+#include <memory>
+#include <utility>
+
+#include <osmium/memory/buffer.hpp>
+#include <osmium/osm/diff_object.hpp>
+
+namespace osmium {
+
+ namespace memory {
+ class Item;
+ } // namespace memory
+
+ namespace io {
+
+ template <class TDest>
+ class OutputIterator : public std::iterator<std::output_iterator_tag, osmium::memory::Item> {
+
+ 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<buffer_wrapper> 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_wrapper>(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);
+ (*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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/overwrite.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/overwrite.hpp
new file mode 100755
index 0000000000..e33894bd82
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/pbf_input.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/pbf_input.hpp
new file mode 100755
index 0000000000..766153edef
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/pbf_input.hpp
@@ -0,0 +1,49 @@
+#ifndef OSMIUM_IO_PBF_INPUT_HPP
+#define OSMIUM_IO_PBF_INPUT_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+/**
+ * @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 <osmium/io/reader.hpp> // IWYU pragma: export
+#include <osmium/io/detail/pbf_input_format.hpp> // IWYU pragma: export
+
+#endif // OSMIUM_IO_PBF_INPUT_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/pbf_output.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/pbf_output.hpp
new file mode 100755
index 0000000000..5f46ede2b2
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/pbf_output.hpp
@@ -0,0 +1,49 @@
+#ifndef OSMIUM_IO_PBF_OUTPUT_HPP
+#define OSMIUM_IO_PBF_OUTPUT_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+/**
+ * @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 <osmium/io/writer.hpp> // IWYU pragma: export
+#include <osmium/io/detail/pbf_output_format.hpp> // IWYU pragma: export
+
+#endif // OSMIUM_IO_PBF_OUTPUT_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/reader.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/reader.hpp
new file mode 100755
index 0000000000..c68a8e180e
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/reader.hpp
@@ -0,0 +1,312 @@
+#ifndef OSMIUM_IO_READER_HPP
+#define OSMIUM_IO_READER_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <atomic>
+#include <cerrno>
+#include <cstdlib>
+#include <fcntl.h>
+#include <memory>
+#include <string>
+#include <system_error>
+#include <thread>
+#include <utility>
+
+#ifndef _WIN32
+# include <sys/wait.h>
+#endif
+
+#ifndef _MSC_VER
+# include <unistd.h>
+#endif
+
+#include <osmium/io/compression.hpp>
+#include <osmium/io/detail/input_format.hpp>
+#include <osmium/io/detail/read_thread.hpp>
+#include <osmium/io/detail/read_write.hpp>
+#include <osmium/io/file.hpp>
+#include <osmium/io/header.hpp>
+#include <osmium/memory/buffer.hpp>
+#include <osmium/osm/entity_bits.hpp>
+#include <osmium/thread/util.hpp>
+#include <osmium/thread/queue.hpp>
+
+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<bool> m_input_done;
+ int m_childpid;
+
+ osmium::thread::Queue<std::string> m_input_queue;
+
+ std::unique_ptr<osmium::io::Decompressor> m_decompressor;
+ std::future<bool> m_read_future;
+
+ std::unique_ptr<osmium::io::detail::InputFormat> 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();
+ }
+
+ // 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
+ // 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;
+ }
+ }
+ }
+
+ /**
+ * 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 <class... TArgs>
+ osmium::memory::Buffer read_file(TArgs&&... args) {
+ osmium::memory::Buffer buffer(1024*1024, osmium::memory::Buffer::auto_grow::yes);
+
+ Reader reader(std::forward<TArgs>(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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/reader_iterator.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/reader_iterator.hpp
new file mode 100755
index 0000000000..862078935a
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/io/reader.hpp>
+#include <osmium/io/input_iterator.hpp>
+
+namespace std {
+
+ inline osmium::io::InputIterator<osmium::io::Reader> begin(osmium::io::Reader& reader) {
+ return osmium::io::InputIterator<osmium::io::Reader>(reader);
+ }
+
+ inline osmium::io::InputIterator<osmium::io::Reader> end(osmium::io::Reader&) {
+ return osmium::io::InputIterator<osmium::io::Reader>();
+ }
+
+} // namespace std
+
+#endif // OSMIUM_IO_READER_ITERATOR_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/writer.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/writer.hpp
new file mode 100755
index 0000000000..64afe20662
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include <osmium/io/compression.hpp>
+#include <osmium/io/detail/output_format.hpp>
+#include <osmium/io/detail/read_write.hpp>
+#include <osmium/io/detail/write_thread.hpp>
+#include <osmium/io/file.hpp>
+#include <osmium/io/header.hpp>
+#include <osmium/io/overwrite.hpp>
+#include <osmium/memory/buffer.hpp>
+#include <osmium/thread/util.hpp>
+
+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<osmium::io::detail::OutputFormat> m_output;
+
+ std::unique_ptr<osmium::io::Compressor> m_compressor;
+
+ std::future<bool> 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/xml_input.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/xml_input.hpp
new file mode 100755
index 0000000000..dfcd0a9fcf
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/xml_input.hpp
@@ -0,0 +1,48 @@
+#ifndef OSMIUM_IO_XML_INPUT_HPP
+#define OSMIUM_IO_XML_INPUT_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+/**
+ * @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 <osmium/io/reader.hpp> // IWYU pragma: export
+#include <osmium/io/detail/xml_input_format.hpp> // IWYU pragma: export
+
+#endif // OSMIUM_IO_XML_INPUT_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/xml_output.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/xml_output.hpp
new file mode 100755
index 0000000000..18a13869d7
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/io/xml_output.hpp
@@ -0,0 +1,47 @@
+#ifndef OSMIUM_IO_XML_OUTPUT_HPP
+#define OSMIUM_IO_XML_OUTPUT_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+/**
+ * @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 <osmium/io/writer.hpp> // IWYU pragma: export
+#include <osmium/io/detail/xml_output_format.hpp> // IWYU pragma: export
+
+#endif // OSMIUM_IO_XML_OUTPUT_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/memory/buffer.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/memory/buffer.hpp
new file mode 100755
index 0000000000..85a3a46d4d
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <exception>
+#include <functional>
+#include <iterator>
+#include <stdexcept>
+#include <utility>
+#include <vector>
+
+#include <osmium/memory/item.hpp>
+#include <osmium/memory/item_iterator.hpp>
+#include <osmium/osm/entity.hpp>
+
+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<unsigned char> 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<void(Buffer&)> 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<void(Buffer&)> 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 <class T>
+ T& get(const size_t offset) const {
+ return *reinterpret_cast<T*>(&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 <class T>
+ T& add_item(const T& item) {
+ unsigned char* target = reserve_space(item.padded_size());
+ std::copy_n(reinterpret_cast<const unsigned char*>(&item), item.padded_size(), target);
+ return *reinterpret_cast<T*>(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<const unsigned char*>(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 <class T>
+ using t_iterator = osmium::memory::ItemIterator<T>;
+
+ template <class T>
+ using t_const_iterator = osmium::memory::ItemIterator<const T>;
+
+ typedef t_iterator<osmium::OSMEntity> iterator;
+ typedef t_const_iterator<osmium::OSMEntity> const_iterator;
+
+ template <class T>
+ t_iterator<T> begin() {
+ return t_iterator<T>(m_data, m_data + m_committed);
+ }
+
+ iterator begin() {
+ return iterator(m_data, m_data + m_committed);
+ }
+
+ template <class T>
+ t_iterator<T> end() {
+ return t_iterator<T>(m_data + m_committed, m_data + m_committed);
+ }
+
+ iterator end() {
+ return iterator(m_data + m_committed, m_data + m_committed);
+ }
+
+ template <class T>
+ t_const_iterator<T> cbegin() const {
+ return t_const_iterator<T>(m_data, m_data + m_committed);
+ }
+
+ const_iterator cbegin() const {
+ return const_iterator(m_data, m_data + m_committed);
+ }
+
+ template <class T>
+ t_const_iterator<T> cend() const {
+ return t_const_iterator<T>(m_data + m_committed, m_data + m_committed);
+ }
+
+ const_iterator cend() const {
+ return const_iterator(m_data + m_committed, m_data + m_committed);
+ }
+
+ template <class T>
+ t_const_iterator<T> begin() const {
+ return cbegin<T>();
+ }
+
+ const_iterator begin() const {
+ return cbegin();
+ }
+
+ template <class T>
+ t_const_iterator<T> end() const {
+ return cend<T>();
+ }
+
+ 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 <class TCallbackClass>
+ 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<size_t>(it_read.data() - data());
+ size_t new_offset = static_cast<size_t>(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<size_t>(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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/memory/collection.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/memory/collection.hpp
new file mode 100755
index 0000000000..7deb88b458
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/memory/collection.hpp
@@ -0,0 +1,154 @@
+#ifndef OSMIUM_MEMORY_COLLECTION_HPP
+#define OSMIUM_MEMORY_COLLECTION_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <iterator>
+#include <iosfwd>
+#include <type_traits>
+
+#include <osmium/memory/item.hpp>
+#include <osmium/util/compatibility.hpp>
+
+namespace osmium {
+
+ namespace memory {
+
+ template <class TMember>
+ class CollectionIterator : public std::iterator<std::forward_iterator_tag, TMember> {
+
+ // 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<std::is_const<TMember>::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<TMember>& operator++() {
+ m_data = reinterpret_cast<TMember*>(m_data)->next();
+ return *static_cast<CollectionIterator<TMember>*>(this);
+ }
+
+ CollectionIterator<TMember> operator++(int) {
+ CollectionIterator<TMember> tmp(*this);
+ operator++();
+ return tmp;
+ }
+
+ bool operator==(const CollectionIterator<TMember>& rhs) const noexcept {
+ return m_data == rhs.m_data;
+ }
+
+ bool operator!=(const CollectionIterator<TMember>& rhs) const noexcept {
+ return m_data != rhs.m_data;
+ }
+
+ unsigned char* data() const noexcept {
+ return m_data;
+ }
+
+ TMember& operator*() const {
+ return *reinterpret_cast<TMember*>(m_data);
+ }
+
+ TMember* operator->() const {
+ return reinterpret_cast<TMember*>(m_data);
+ }
+
+ template <typename TChar, typename TTraits>
+ friend std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const CollectionIterator<TMember>& iter) {
+ return out << static_cast<const void*>(iter.m_data);
+ }
+
+ }; // class CollectionIterator
+
+ template <class TMember, osmium::item_type TCollectionItemType>
+ class Collection : public Item {
+
+ public:
+
+ typedef CollectionIterator<TMember> iterator;
+ typedef CollectionIterator<const TMember> const_iterator;
+ typedef TMember value_type;
+
+ static constexpr osmium::item_type itemtype = TCollectionItemType;
+
+ Collection() :
+ Item(sizeof(Collection<TMember, TCollectionItemType>), TCollectionItemType) {
+ }
+
+ bool empty() const {
+ return sizeof(Collection<TMember, TCollectionItemType>) == byte_size();
+ }
+
+ iterator begin() {
+ return iterator(data() + sizeof(Collection<TMember, TCollectionItemType>));
+ }
+
+ iterator end() {
+ return iterator(data() + byte_size());
+ }
+
+ const_iterator cbegin() const {
+ return const_iterator(data() + sizeof(Collection<TMember, TCollectionItemType>));
+ }
+
+ 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/memory/item.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/memory/item.hpp
new file mode 100755
index 0000000000..2679ca6f20
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/memory/item.hpp
@@ -0,0 +1,178 @@
+#ifndef OSMIUM_MEMORY_ITEM_HPP
+#define OSMIUM_MEMORY_ITEM_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+
+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 <typename T>
+ inline T padded_length(T length) noexcept {
+ static_assert(std::is_integral<T>::value && std::is_unsigned<T>::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<unsigned char*>(this);
+ }
+
+ const unsigned char* data() const noexcept {
+ return reinterpret_cast<const unsigned char*>(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 <class TMember>
+ friend class CollectionIterator;
+
+ template <class TMember>
+ 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/memory/item_iterator.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/memory/item_iterator.hpp
new file mode 100755
index 0000000000..3e5b5fa8b6
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cassert>
+#include <iterator>
+#include <iosfwd>
+#include <type_traits>
+
+#include <osmium/memory/item.hpp>
+#include <osmium/osm/item_type.hpp>
+
+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 <class T>
+ inline bool type_is_compatible(osmium::item_type) noexcept {
+ return true;
+ }
+
+ template <>
+ inline bool type_is_compatible<osmium::Node>(osmium::item_type t) noexcept {
+ return t == osmium::item_type::node;
+ }
+
+ template <>
+ inline bool type_is_compatible<osmium::Way>(osmium::item_type t) noexcept {
+ return t == osmium::item_type::way;
+ }
+
+ template <>
+ inline bool type_is_compatible<osmium::Relation>(osmium::item_type t) noexcept {
+ return t == osmium::item_type::relation;
+ }
+
+ template <>
+ inline bool type_is_compatible<osmium::Area>(osmium::item_type t) noexcept {
+ return t == osmium::item_type::area;
+ }
+
+ template <>
+ inline bool type_is_compatible<osmium::Changeset>(osmium::item_type t) noexcept {
+ return t == osmium::item_type::changeset;
+ }
+
+ template <>
+ inline bool type_is_compatible<osmium::OSMObject>(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::OSMEntity>(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::TagList>(osmium::item_type t) noexcept {
+ return t == osmium::item_type::tag_list;
+ }
+
+ template <>
+ inline bool type_is_compatible<osmium::WayNodeList>(osmium::item_type t) noexcept {
+ return t == osmium::item_type::way_node_list;
+ }
+
+ template <>
+ inline bool type_is_compatible<osmium::RelationMemberList>(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::OuterRing>(osmium::item_type t) noexcept {
+ return t == osmium::item_type::outer_ring;
+ }
+
+ template <>
+ inline bool type_is_compatible<osmium::InnerRing>(osmium::item_type t) noexcept {
+ return t == osmium::item_type::inner_ring;
+ }
+
+ } // namespace detail
+
+ template <class TMember>
+ class ItemIterator : public std::iterator<std::forward_iterator_tag, TMember> {
+
+ static_assert(std::is_base_of<osmium::memory::Item, TMember>::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<std::is_const<TMember>::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<typename std::remove_const<TMember>::type>(reinterpret_cast<const osmium::memory::Item*>(m_data)->type())) {
+ m_data = reinterpret_cast<TMember*>(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 <class T>
+ ItemIterator<T> cast() const {
+ return ItemIterator<T>(m_data, m_end);
+ }
+
+ ItemIterator<TMember>& operator++() {
+ assert(m_data);
+ assert(m_data != m_end);
+ m_data = reinterpret_cast<TMember*>(m_data)->next();
+ advance_to_next_item_of_right_type();
+ return *static_cast<ItemIterator<TMember>*>(this);
+ }
+
+ /**
+ * Like operator++() but will NOT skip items of unwanted
+ * types. Do not use this unless you know what you are
+ * doing.
+ */
+ ItemIterator<TMember>& advance_once() {
+ assert(m_data);
+ assert(m_data != m_end);
+ m_data = reinterpret_cast<TMember*>(m_data)->next();
+ return *static_cast<ItemIterator<TMember>*>(this);
+ }
+
+ ItemIterator<TMember> operator++(int) {
+ ItemIterator<TMember> tmp(*this);
+ operator++();
+ return tmp;
+ }
+
+ bool operator==(const ItemIterator<TMember>& rhs) const {
+ return m_data == rhs.m_data && m_end == rhs.m_end;
+ }
+
+ bool operator!=(const ItemIterator<TMember>& 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<TMember*>(m_data);
+ }
+
+ TMember* operator->() const {
+ assert(m_data);
+ assert(m_data != m_end);
+ return reinterpret_cast<TMember*>(m_data);
+ }
+
+ explicit operator bool() const {
+ return m_data != nullptr;
+ }
+
+ template <typename TChar, typename TTraits>
+ friend std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const ItemIterator<TMember>& iter) {
+ return out << static_cast<void*>(iter.m_data);
+ }
+
+ }; // class ItemIterator
+
+ } // namespace memory
+
+} // namespace osmium
+
+#endif // OSMIUM_ITEM_ITERATOR_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/object_pointer_collection.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/object_pointer_collection.hpp
new file mode 100755
index 0000000000..752470305d
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <utility>
+#include <vector>
+
+#include <boost/iterator/indirect_iterator.hpp>
+
+#include <osmium/handler.hpp>
+#include <osmium/memory/item.hpp>
+#include <osmium/osm/object.hpp>
+
+// 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<osmium::OSMObject*> m_objects;
+
+ public:
+
+ typedef boost::indirect_iterator<std::vector<osmium::OSMObject*>::iterator, osmium::OSMObject> iterator;
+ typedef boost::indirect_iterator<std::vector<osmium::OSMObject*>::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 <class TCompare>
+ void sort(TCompare&& compare) {
+ std::sort(m_objects.begin(), m_objects.end(), std::forward<TCompare>(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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm.hpp
new file mode 100755
index 0000000000..e92d9b8ef1
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/osm/node.hpp> // IWYU pragma: export
+#include <osmium/osm/way.hpp> // IWYU pragma: export
+#include <osmium/osm/relation.hpp> // IWYU pragma: export
+#include <osmium/osm/area.hpp> // IWYU pragma: export
+#include <osmium/osm/changeset.hpp> // IWYU pragma: export
+
+/**
+ * @brief Namespace for everything in the Osmium library.
+ */
+namespace osmium {
+} // namespace osmium
+
+#endif // OSMIUM_OSM_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/area.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/area.hpp
new file mode 100755
index 0000000000..3e129d0fbe
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/area.hpp
@@ -0,0 +1,214 @@
+#ifndef OSMIUM_OSM_AREA_HPP
+#define OSMIUM_OSM_AREA_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cassert>
+#include <cstdlib>
+#include <utility>
+
+#include <osmium/memory/collection.hpp>
+#include <osmium/memory/item.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/object.hpp>
+#include <osmium/osm/types.hpp>
+#include <osmium/osm/node_ref_list.hpp>
+
+namespace osmium {
+
+ namespace builder {
+ template <class T> class ObjectBuilder;
+ }
+
+ /**
+ * An outer ring of an Area.
+ */
+ class OuterRing : public NodeRefList {
+
+ public:
+
+ static constexpr osmium::item_type itemtype = osmium::item_type::outer_ring;
+
+ OuterRing():
+ NodeRefList(itemtype) {
+ }
+
+ }; // 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:
+
+ static constexpr osmium::item_type itemtype = osmium::item_type::inner_ring;
+
+ InnerRing():
+ NodeRefList(itemtype) {
+ }
+
+ }; // 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) noexcept {
+ 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) noexcept {
+ 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<osmium::Area>;
+
+ 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 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<int, int> num_rings() const {
+ std::pair<int, int> counter { 0, 0 };
+
+ 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;
+ }
+
+ /**
+ * 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<const osmium::InnerRing> inner_ring_cbegin(const osmium::memory::ItemIterator<const osmium::OuterRing>& it) const {
+ return it.cast<const osmium::InnerRing>();
+ }
+
+ /**
+ * 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<const osmium::InnerRing> inner_ring_cend(const osmium::memory::ItemIterator<const osmium::OuterRing>& it) const {
+ return std::next(it).cast<const osmium::InnerRing>();
+ }
+
+ }; // 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/box.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/box.hpp
new file mode 100755
index 0000000000..631f919113
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/box.hpp
@@ -0,0 +1,250 @@
+#ifndef OSMIUM_OSM_BOX_HPP
+#define OSMIUM_OSM_BOX_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cassert>
+#include <iosfwd>
+
+#include <osmium/util/compatibility.hpp>
+#include <osmium/osm/location.hpp>
+
+namespace osmium {
+
+ /**
+ * 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 {
+
+ 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() {
+ }
+
+ /**
+ * 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;
+ Box(Box&&) = default;
+ Box& operator=(const Box&) = default;
+ Box& operator=(Box&&) = default;
+ ~Box() = default;
+
+ /**
+ * 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) {
+ 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 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());
+ extend(box.top_right());
+ return *this;
+ }
+
+ /**
+ * Box is defined, ie. contains defined locations.
+ */
+ explicit constexpr operator bool() const noexcept {
+ return static_cast<bool>(m_bottom_left);
+ }
+
+ /**
+ * Box is valid, ie. defined and inside usual bounds
+ * (-180<=lon<=180, -90<=lat<=90).
+ */
+ OSMIUM_CONSTEXPR bool valid() const noexcept {
+ return bottom_left().valid() && top_right().valid();
+ }
+
+ /**
+ * Access bottom-left location.
+ */
+ OSMIUM_CONSTEXPR Location bottom_left() const noexcept {
+ return m_bottom_left;
+ }
+
+ /**
+ * Access bottom-left location.
+ */
+ Location& bottom_left() noexcept {
+ return m_bottom_left;
+ }
+
+ /**
+ * Access top-right location.
+ */
+ OSMIUM_CONSTEXPR Location top_right() const noexcept {
+ return m_top_right;
+ }
+
+ /**
+ * Access top-right location.
+ */
+ Location& top_right() noexcept {
+ return m_top_right;
+ }
+
+ /**
+ * 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 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();
+ }
+
+ /**
+ * 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. 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();
+ }
+
+ /**
+ * 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 <typename TChar, typename TTraits>
+ inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/changeset.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/changeset.hpp
new file mode 100755
index 0000000000..0ab4e9bade
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/changeset.hpp
@@ -0,0 +1,335 @@
+#ifndef OSMIUM_OSM_CHANGESET_HPP
+#define OSMIUM_OSM_CHANGESET_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstdint>
+#include <cstring>
+
+#include <osmium/memory/collection.hpp>
+#include <osmium/memory/item.hpp>
+#include <osmium/osm/box.hpp>
+#include <osmium/osm/entity.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/tag.hpp>
+#include <osmium/osm/timestamp.hpp>
+#include <osmium/osm/types.hpp>
+
+namespace osmium {
+
+ namespace builder {
+ template <class T> 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::Changeset>;
+
+ 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<user_id_type>(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<const char*>(data() + sizeof(Changeset));
+ }
+
+ /// Get the list of tags.
+ const TagList& tags() const {
+ return osmium::detail::subitem_of_type<const TagList>(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<Item> iterator;
+ typedef osmium::memory::CollectionIterator<const Item> 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/diff_object.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/diff_object.hpp
new file mode 100755
index 0000000000..55a5cef68d
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/object.hpp>
+#include <osmium/osm/timestamp.hpp>
+#include <osmium/osm/types.hpp>
+
+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 T>
+ 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<const T*>(m_prev);
+ }
+
+ const T& curr() const noexcept {
+ return *static_cast<const T*>(m_curr);
+ }
+
+ const T& next() const noexcept {
+ return *static_cast<const T*>(m_next);
+ }
+
+ }; // class DiffObjectDerived
+
+ typedef DiffObjectDerived<osmium::Node> DiffNode;
+ typedef DiffObjectDerived<osmium::Way> DiffWay;
+ typedef DiffObjectDerived<osmium::Relation> DiffRelation;
+
+} // namespace osmium
+
+#endif // OSMIUM_OSM_DIFF_OBJECT_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/entity.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/entity.hpp
new file mode 100755
index 0000000000..14861a2d5c
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/entity.hpp
@@ -0,0 +1,79 @@
+#ifndef OSMIUM_OSM_ENTITY_HPP
+#define OSMIUM_OSM_ENTITY_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/memory/item.hpp>
+#include <osmium/osm/entity_bits.hpp>
+
+namespace osmium {
+
+ namespace detail {
+
+ template <class TSubitem, class TIter>
+ inline TSubitem& subitem_of_type(TIter it, TIter end) {
+ for (; it != end; ++it) {
+ if (it->type() == TSubitem::itemtype) {
+ return reinterpret_cast<TSubitem&>(*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) {
+ }
+
+ 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
+
+#endif // OSMIUM_OSM_ENTITY_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/entity_bits.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/entity_bits.hpp
new file mode 100755
index 0000000000..1c1cb80279
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/entity_bits.hpp
@@ -0,0 +1,105 @@
+#ifndef OSMIUM_OSM_ENTITY_BITS_HPP
+#define OSMIUM_OSM_ENTITY_BITS_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/osm/item_type.hpp>
+
+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<type>(static_cast<int>(lhs) | static_cast<int> (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<type>(static_cast<int>(lhs) & static_cast<int> (rhs));
+ }
+
+ inline type operator~(const type value) noexcept {
+ return static_cast<type>(~static_cast<int>(value));
+ }
+
+ inline type operator&=(type& lhs, const type rhs) noexcept {
+ lhs = lhs & rhs;
+ return lhs;
+ }
+
+ inline type from_item_type(osmium::item_type item_type) noexcept {
+ return static_cast<osmium::osm_entity_bits::type>(0x1 << (static_cast<uint16_t>(item_type) - 1));
+ }
+
+ } // namespace osm_entity_bits
+
+} // namespace osmium
+
+#endif // OSMIUM_OSM_ENTITY_BITS_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/item_type.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/item_type.hpp
new file mode 100755
index 0000000000..c2187a36ae
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstdint> // IWYU pragma: keep
+#include <iosfwd>
+#include <stdexcept>
+
+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 <typename TChar, typename TTraits>
+ inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/location.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/location.hpp
new file mode 100755
index 0000000000..0d4fdc13d2
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cmath>
+#include <cstdint>
+#include <iosfwd>
+#include <stdexcept>
+#include <string>
+
+#include <iostream>
+
+#include <osmium/util/compatibility.hpp>
+#include <osmium/util/double.hpp>
+
+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<int32_t>::max() as
+ // constexpr, so we hard code this for the time being.
+ // static constexpr int32_t undefined_coordinate = std::numeric_limits<int32_t>::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<int32_t>(std::round(c * coordinate_precision));
+ }
+
+ static OSMIUM_CONSTEXPR double fix_to_double(const int32_t c) noexcept {
+ return static_cast<double>(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<int32_t>(x)),
+ m_y(static_cast<int32_t>(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 <typename T>
+ 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 <typename TChar, typename TTraits>
+ inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/node.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/node.hpp
new file mode 100755
index 0000000000..123bfc4fa3
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/memory/item.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/object.hpp>
+
+namespace osmium {
+
+ namespace builder {
+ template <class T> class ObjectBuilder;
+ }
+
+ class Node : public OSMObject {
+
+ friend class osmium::builder::ObjectBuilder<osmium::Node>;
+
+ 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/node_ref.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/node_ref.hpp
new file mode 100755
index 0000000000..76afa75fcb
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstdlib>
+#include <iosfwd>
+
+#include <osmium/memory/item.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/types.hpp>
+
+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<osmium::unsigned_object_id_type>(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 <typename TChar, typename TTraits>
+ inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/node_ref_list.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/node_ref_list.hpp
new file mode 100755
index 0000000000..f0dfedbc19
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/node_ref_list.hpp
@@ -0,0 +1,184 @@
+#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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+
+#include <osmium/memory/item.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/node_ref.hpp>
+
+namespace osmium {
+
+ /**
+ * A vector of NodeRef objects. Usually this is not instantiated directly,
+ * but one of its subclasses are used.
+ */
+ class NodeRefList : public osmium::memory::Item {
+
+ public:
+
+ 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 {
+ auto size_node_refs = osmium::memory::Item::byte_size() - sizeof(NodeRefList);
+ assert(size_node_refs % sizeof(NodeRef) == 0);
+ return size_node_refs / sizeof(NodeRef);
+ }
+
+ /**
+ * 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];
+ }
+
+ /**
+ * Access the first element.
+ *
+ * @pre @code !empty() @endcode
+ */
+ const NodeRef& front() const noexcept {
+ assert(!empty());
+ return operator[](0);
+ }
+
+ /**
+ * Access the last element.
+ *
+ * @pre @code !empty() @endcode
+ */
+ const NodeRef& back() const noexcept {
+ assert(!empty());
+ return operator[](size()-1);
+ }
+
+ /**
+ * 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();
+ }
+
+ /**
+ * 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();
+ }
+
+ typedef NodeRef* iterator;
+ typedef const NodeRef* const_iterator;
+ typedef std::reverse_iterator<const NodeRef*> const_reverse_iterator;
+
+ /// Returns an iterator to the beginning.
+ iterator begin() noexcept {
+ return iterator(data() + sizeof(NodeRefList));
+ }
+
+ /// Returns an iterator to the end.
+ iterator end() noexcept {
+ return iterator(data() + byte_size());
+ }
+
+ /// Returns an iterator to the beginning.
+ const_iterator cbegin() const noexcept {
+ return const_iterator(data() + sizeof(NodeRefList));
+ }
+
+ /// Returns an iterator to the end.
+ const_iterator cend() const noexcept {
+ return const_iterator(data() + byte_size());
+ }
+
+ /// Returns an iterator to the beginning.
+ const_iterator begin() const noexcept {
+ return cbegin();
+ }
+
+ /// Returns an iterator to the end.
+ const_iterator end() const noexcept {
+ return cend();
+ }
+
+ /// Returns a reverse_iterator to the beginning.
+ const_reverse_iterator crbegin() const noexcept {
+ return const_reverse_iterator(cend());
+ }
+
+ /// Returns a reverse_iterator to the end.
+ const_reverse_iterator crend() const noexcept {
+ return const_reverse_iterator(cbegin());
+ }
+
+ }; // class NodeRefList
+
+} // namespace osmium
+
+#endif // OSMIUM_OSM_NODE_REF_LIST_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/object.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/object.hpp
new file mode 100755
index 0000000000..d5ae48aabe
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <stdexcept>
+
+#include <osmium/memory/collection.hpp>
+#include <osmium/memory/item.hpp>
+#include <osmium/memory/item_iterator.hpp>
+#include <osmium/osm/entity.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/tag.hpp>
+#include <osmium/osm/timestamp.hpp>
+#include <osmium/osm/types.hpp>
+
+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<const string_size_type*>(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<string_size_type*>(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<unsigned_object_id_type>(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<user_id_type>(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<const char*>(data() + sizeof_object());
+ }
+
+ /// Get the list of tags for this object.
+ const TagList& tags() const {
+ return osmium::detail::subitem_of_type<const TagList>(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<Item> iterator;
+ typedef osmium::memory::CollectionIterator<const Item> 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 <class T>
+ using t_iterator = osmium::memory::ItemIterator<T>;
+
+ template <class T>
+ using t_const_iterator = osmium::memory::ItemIterator<const T>;
+
+ template <class T>
+ t_iterator<T> begin() {
+ return t_iterator<T>(subitems_position(), next());
+ }
+
+ template <class T>
+ t_iterator<T> end() {
+ return t_iterator<T>(next(), next());
+ }
+
+ template <class T>
+ t_const_iterator<T> cbegin() const {
+ return t_const_iterator<T>(subitems_position(), next());
+ }
+
+ template <class T>
+ t_const_iterator<T> cend() const {
+ return t_const_iterator<T>(next(), next());
+ }
+
+ template <class T>
+ t_const_iterator<T> begin() const {
+ return cbegin<T>();
+ }
+
+ template <class T>
+ t_const_iterator<T> end() const {
+ return cend<T>();
+ }
+
+ }; // 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/object_comparisons.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/object_comparisons.hpp
new file mode 100755
index 0000000000..bdf99e11cd
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/osm/object.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/relation.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/relation.hpp
new file mode 100755
index 0000000000..e5b42fed56
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iterator>
+
+#include <osmium/memory/collection.hpp> // IWYU pragma: keep
+#include <osmium/memory/item.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/object.hpp>
+#include <osmium/osm/types.hpp>
+
+namespace osmium {
+
+ namespace builder {
+ template <class> 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 <class TMember>
+ friend class osmium::memory::CollectionIterator;
+
+ unsigned char* next() {
+ if (full_member()) {
+ return endpos() + reinterpret_cast<osmium::memory::Item*>(endpos())->byte_size();
+ } else {
+ return endpos();
+ }
+ }
+
+ unsigned const char* next() const {
+ if (full_member()) {
+ return endpos() + reinterpret_cast<const osmium::memory::Item*>(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<unsigned_object_id_type>(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<const char*>(data() + sizeof(RelationMember));
+ }
+
+ OSMObject& get_object() {
+ return *reinterpret_cast<OSMObject*>(endpos());
+ }
+
+ const OSMObject& get_object() const {
+ return *reinterpret_cast<const OSMObject*>(endpos());
+ }
+
+ }; // class RelationMember
+
+ class RelationMemberList : public osmium::memory::Collection<RelationMember, osmium::item_type::relation_member_list> {
+
+ public:
+
+ typedef size_t size_type;
+
+ RelationMemberList() :
+ osmium::memory::Collection<RelationMember, osmium::item_type::relation_member_list>() {
+ }
+
+ size_type size() const noexcept {
+ return static_cast<size_type>(std::distance(begin(), end()));
+ }
+
+ }; // class RelationMemberList
+
+ 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<osmium::Relation>;
+
+ 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<RelationMemberList>(begin(), end());
+ }
+
+ const RelationMemberList& members() const {
+ return osmium::detail::subitem_of_type<const RelationMemberList>(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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/segment.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/segment.hpp
new file mode 100755
index 0000000000..f3a82c97fc
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <iosfwd>
+#include <utility>
+
+#include <osmium/osm/location.hpp>
+#include <osmium/util/compatibility.hpp>
+
+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 <typename TChar, typename TTraits>
+ inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const osmium::Segment& segment) {
+ return out << segment.first() << "->" << segment.second();
+ }
+
+} // namespace osmium
+
+#endif // OSMIUM_OSM_SEGMENT_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/tag.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/tag.hpp
new file mode 100755
index 0000000000..2e93ede24c
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <cstddef>
+#include <cstring>
+#include <iosfwd>
+#include <iterator>
+
+#include <osmium/memory/collection.hpp>
+#include <osmium/memory/item.hpp>
+#include <osmium/osm/item_type.hpp>
+
+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 <class TMember>
+ friend class osmium::memory::CollectionIterator;
+
+ static unsigned char* after_null(unsigned char* ptr) {
+ return reinterpret_cast<unsigned char*>(std::strchr(reinterpret_cast<char*>(ptr), 0) + 1);
+ }
+
+ static const unsigned char* after_null(const unsigned char* ptr) {
+ return reinterpret_cast<const unsigned char*>(std::strchr(reinterpret_cast<const char*>(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<const char*>(data());
+ }
+
+ const char* value() const {
+ return reinterpret_cast<const char*>(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 <typename TChar, typename TTraits>
+ inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const Tag& tag) {
+ return out << tag.key() << '=' << tag.value();
+ }
+
+ class TagList : public osmium::memory::Collection<Tag, osmium::item_type::tag_list> {
+
+ public:
+
+ typedef size_t size_type;
+
+ TagList() :
+ osmium::memory::Collection<Tag, osmium::item_type::tag_list>() {
+ }
+
+ size_type size() const noexcept {
+ return static_cast<size_type>(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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/timestamp.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/timestamp.hpp
new file mode 100755
index 0000000000..6b6a6e1898
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/timestamp.hpp
@@ -0,0 +1,175 @@
+#ifndef OSMIUM_OSM_TIMESTAMP_HPP
+#define OSMIUM_OSM_TIMESTAMP_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstdint>
+#include <ctime>
+#include <iosfwd>
+#include <limits>
+#include <stdexcept>
+#include <string>
+#include <time.h>
+
+#include <osmium/util/compatibility.hpp>
+
+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<uint32_t>(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<uint32_t>(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 = static_cast<uint32_t>(_mkgmtime(&tm));
+#endif
+ }
+
+ constexpr time_t seconds_since_epoch() const noexcept {
+ return static_cast<time_t>(m_timestamp);
+ }
+
+ constexpr operator time_t() const noexcept {
+ return static_cast<time_t>(m_timestamp);
+ }
+
+ explicit constexpr operator uint32_t() const noexcept {
+ return m_timestamp;
+ }
+
+ template <typename T>
+ void operator+=(T time_difference) noexcept {
+ m_timestamp += time_difference;
+ }
+
+ template <typename T>
+ 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<char*>(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<time_t>::max());
+ }
+
+ template <typename TChar, typename TTraits>
+ inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, Timestamp timestamp) {
+ out << timestamp.to_iso();
+ return out;
+ }
+
+} // namespace osmium
+
+#endif // OSMIUM_OSM_TIMESTAMP_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/types.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/types.hpp
new file mode 100755
index 0000000000..aea61bd376
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstdint>
+#include <cstdlib>
+
+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<object_version_type>(std::atol(string));
+ }
+
+ inline changeset_id_type string_to_changeset_id(const char* string) {
+ return static_cast<changeset_id_type>(std::atol(string));
+ }
+
+ inline signed_user_id_type string_to_user_id(const char* string) {
+ return static_cast<signed_user_id_type>(std::atol(string));
+ }
+
+ inline num_changes_type string_to_num_changes(const char* string) {
+ return static_cast<num_changes_type>(std::atol(string));
+ }
+
+} // namespace osmium
+
+#endif // OSMIUM_OSM_TYPES_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/undirected_segment.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/undirected_segment.hpp
new file mode 100755
index 0000000000..654ef7d9a9
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <iosfwd>
+
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/segment.hpp>
+
+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 <typename TChar, typename TTraits>
+ inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const osmium::UndirectedSegment& segment) {
+ return out << segment.first() << "--" << segment.second();
+ }
+
+} // namespace osmium
+
+#endif // OSMIUM_OSM_UNDIRECTED_SEGMENT_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/way.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/way.hpp
new file mode 100755
index 0000000000..3c5f1f6dc0
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/osm/way.hpp
@@ -0,0 +1,117 @@
+#ifndef OSMIUM_OSM_WAY_HPP
+#define OSMIUM_OSM_WAY_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <osmium/memory/item.hpp>
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/object.hpp>
+#include <osmium/osm/types.hpp>
+#include <osmium/osm/node_ref.hpp>
+#include <osmium/osm/node_ref_list.hpp>
+
+namespace osmium {
+
+ namespace builder {
+ template <class T> class ObjectBuilder;
+ }
+
+ /**
+ * List of node references (id and location) in a way.
+ */
+ class WayNodeList : public NodeRefList {
+
+ public:
+
+ static constexpr osmium::item_type itemtype = osmium::item_type::way_node_list;
+
+ WayNodeList():
+ NodeRefList(itemtype) {
+ }
+
+ }; // 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<osmium::Way>;
+
+ Way() noexcept :
+ OSMObject(sizeof(Way), osmium::item_type::way) {
+ }
+
+ public:
+
+ WayNodeList& nodes() {
+ return osmium::detail::subitem_of_type<WayNodeList>(begin(), end());
+ }
+
+ const WayNodeList& nodes() const {
+ return osmium::detail::subitem_of_type<const WayNodeList>(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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/relations/collector.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/relations/collector.hpp
new file mode 100755
index 0000000000..e3c4980870
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <functional>
+#include <iomanip>
+#include <iostream>
+#include <vector>
+
+#include <osmium/osm/item_type.hpp>
+#include <osmium/osm/object.hpp>
+#include <osmium/osm/relation.hpp> // IWYU pragma: keep
+#include <osmium/osm/types.hpp>
+#include <osmium/handler.hpp>
+#include <osmium/memory/buffer.hpp>
+#include <osmium/visitor.hpp>
+
+#include <osmium/relations/detail/relation_meta.hpp>
+#include <osmium/relations/detail/member_meta.hpp>
+
+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 TCollector, bool TNodes, bool TWays, bool TRelations>
+ 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<RelationMeta> m_relations;
+
+ /**
+ * One vector each for nodes, ways, and relations containing all
+ * mappings from member ids to their relations.
+ */
+ std::vector<MemberMeta> m_member_meta[3];
+
+ int m_count_complete = 0;
+
+ typedef std::function<void(osmium::memory::Buffer&&)> 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<TCollector*>(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<MemberMeta>& member_meta(const item_type type) {
+ return m_member_meta[static_cast<uint16_t>(type) - 1];
+ }
+
+ callback_func_type callback() {
+ return m_callback;
+ }
+
+ const std::vector<RelationMeta>& 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<osmium::Relation>(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<osmium::OSMObject>(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<osmium::Relation>(offset).members()) {
+ if (static_cast<TCollector*>(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 <class TIter>
+ void read_relations(TIter begin, TIter end) {
+ HandlerPass1 handler(*static_cast<TCollector*>(this));
+ osmium::apply(begin, end, handler);
+ sort_member_meta();
+ }
+
+ template <class TSource>
+ 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<osmium::OSMObject>(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 = static_cast<double>(size_before - size_after);
+ percent /= size_before;
+ percent *= 100;
+ std::cerr << "PURGE (size before=" << size_before << " after=" << size_after << " purged=" << (size_before - size_after) << " / " << static_cast<int>(percent) << "%)\n";
+ 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<const osmium::Relation*> get_incomplete_relations() const {
+ std::vector<const osmium::Relation*> 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/relations/detail/member_meta.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/relations/detail/member_meta.hpp
new file mode 100755
index 0000000000..a45088eab4
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <cstddef>
+#include <iosfwd>
+#include <iterator>
+
+#include <osmium/osm/types.hpp>
+
+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 <typename TChar, typename TTraits>
+ inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& 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 <class TIter>
+ inline typename std::iterator_traits<TIter>::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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/relations/detail/relation_meta.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/relations/detail/relation_meta.hpp
new file mode 100755
index 0000000000..a48c50acc6
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cassert>
+#include <cstddef>
+#include <iosfwd>
+
+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 <typename TChar, typename TTraits>
+ inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/tags/filter.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/tags/filter.hpp
new file mode 100755
index 0000000000..3c1946c54d
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/tags/filter.hpp
@@ -0,0 +1,162 @@
+#ifndef OSMIUM_TAGS_FILTER_HPP
+#define OSMIUM_TAGS_FILTER_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include <boost/iterator/filter_iterator.hpp>
+
+#include <osmium/memory/collection.hpp>
+#include <osmium/osm/tag.hpp>
+
+namespace osmium {
+
+ namespace tags {
+
+ template <class TKey>
+ 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 <class TValue>
+ 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<void> {
+ bool operator()(const bool, const char*) {
+ return true;
+ }
+ }; // struct match_value<void>
+
+ template <class TKey, class TValue=void, class TKeyComp=match_key<TKey>, class TValueComp=match_value<TValue>>
+ class Filter {
+
+ typedef TKey key_type;
+ typedef typename std::conditional<std::is_void<TValue>::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<Rule> m_rules;
+ bool m_default_result;
+
+ public:
+
+ typedef Filter<TKey, TValue, TKeyComp, TValueComp> filter_type;
+ typedef const osmium::Tag& argument_type;
+ typedef bool result_type;
+ typedef boost::filter_iterator<filter_type, osmium::TagList::const_iterator> iterator;
+
+ explicit Filter(bool default_result = false) :
+ m_default_result(default_result) {
+ }
+
+ template <class V=TValue, typename std::enable_if<!std::is_void<V>::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;
+ }
+
+ /**
+ * 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<std::string, std::string> KeyValueFilter;
+ typedef Filter<std::string> KeyFilter;
+ typedef Filter<std::string, void, match_key_prefix> KeyPrefixFilter;
+
+ } // namespace tags
+
+} // namespace osmium
+
+#endif // OSMIUM_TAGS_FILTER_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/tags/regex_filter.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/tags/regex_filter.hpp
new file mode 100755
index 0000000000..725c42376b
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <regex>
+#include <string>
+
+#include <osmium/tags/filter.hpp>
+
+namespace osmium {
+
+ namespace tags {
+
+ template <>
+ struct match_value<std::regex> {
+ bool operator()(const std::regex& rule_value, const char* tag_value) {
+ return std::regex_match(tag_value, rule_value);
+ }
+ }; // struct match_value<std::regex>
+
+ typedef Filter<std::string, std::regex> RegexFilter;
+
+ } // namespace tags
+
+} // namespace osmium
+
+#endif // OSMIUM_TAGS_REGEX_FILTER_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/tags/taglist.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/tags/taglist.hpp
new file mode 100755
index 0000000000..d7c78dc79d
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <utility>
+
+#include <osmium/osm/tag.hpp>
+
+namespace osmium {
+
+ /**
+ * @brief Code related to working with OSM tags
+ */
+ namespace tags {
+
+ template <class TFilter>
+ inline bool match_any_of(const osmium::TagList& tag_list, TFilter&& filter) {
+ return std::any_of(tag_list.cbegin(), tag_list.cend(), std::forward<TFilter>(filter));
+ }
+
+ template <class TFilter>
+ inline bool match_all_of(const osmium::TagList& tag_list, TFilter&& filter) {
+ return std::all_of(tag_list.cbegin(), tag_list.cend(), std::forward<TFilter>(filter));
+ }
+
+ template <class TFilter>
+ inline bool match_none_of(const osmium::TagList& tag_list, TFilter&& filter) {
+ return std::none_of(tag_list.cbegin(), tag_list.cend(), std::forward<TFilter>(filter));
+ }
+
+ } // namespace tags
+
+} // namespace osmium
+
+#endif // OSMIUM_TAGS_TAGLIST_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/thread/function_wrapper.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/thread/function_wrapper.hpp
new file mode 100755
index 0000000000..fe0a492577
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/thread/function_wrapper.hpp
@@ -0,0 +1,111 @@
+#ifndef OSMIUM_THREAD_FUNCTION_WRAPPER_HPP
+#define OSMIUM_THREAD_FUNCTION_WRAPPER_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <memory>
+
+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_base> impl;
+
+ template <typename F>
+ 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 <typename F>
+ function_wrapper(F&& f) :
+ impl(new impl_type<F>(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& operator=(const function_wrapper&) = delete;
+
+ ~function_wrapper() = default;
+
+ explicit operator bool() const {
+ return static_cast<bool>(impl);
+ }
+
+ }; // class function_wrapper
+
+ } // namespace thread
+
+} // namespace osmium
+
+#endif // OSMIUM_THREAD_FUNCTION_WRAPPER_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/thread/pool.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/thread/pool.hpp
new file mode 100755
index 0000000000..87dd1fb933
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <atomic>
+#include <cstddef>
+#include <cstdlib>
+#include <future>
+#include <thread>
+#include <type_traits>
+#include <vector>
+
+#include <osmium/thread/function_wrapper.hpp>
+#include <osmium/thread/queue.hpp>
+#include <osmium/thread/util.hpp>
+#include <osmium/util/config.hpp>
+
+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<std::thread>& m_threads;
+
+ public:
+
+ explicit thread_joiner(std::vector<std::thread>& threads) :
+ m_threads(threads) {
+ }
+
+ ~thread_joiner() {
+ for (auto& thread : m_threads) {
+ if (thread.joinable()) {
+ thread.join();
+ }
+ }
+ }
+
+ }; // class thread_joiner
+
+ std::atomic<bool> m_done;
+ osmium::thread::Queue<function_wrapper> m_work_queue;
+ std::vector<std::thread> 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<int>(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 <typename TFunction>
+ std::future<typename std::result_of<TFunction()>::type> submit(TFunction&& func) {
+
+ typedef typename std::result_of<TFunction()>::type result_type;
+
+ std::packaged_task<result_type()> task(std::forward<TFunction>(func));
+ std::future<result_type> 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/thread/queue.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/thread/queue.hpp
new file mode 100755
index 0000000000..baaf2dc766
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/thread/queue.hpp
@@ -0,0 +1,181 @@
+#ifndef OSMIUM_THREAD_QUEUE_HPP
+#define OSMIUM_THREAD_QUEUE_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <cstddef>
+#include <mutex>
+#include <queue>
+#include <string>
+#include <thread>
+#include <utility>
+
+#include <osmium/util/compatibility.hpp>
+
+namespace osmium {
+
+ namespace thread {
+
+ static const std::chrono::milliseconds full_queue_sleep_duration { 10 }; // XXX
+
+ /**
+ * A thread-safe queue.
+ */
+ template <typename T>
+ 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<T> 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<int> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> lock(m_mutex);
+ return m_queue.empty();
+ }
+
+ size_t size() const {
+ std::lock_guard<std::mutex> lock(m_mutex);
+ return m_queue.size();
+ }
+
+ }; // class Queue
+
+ } // namespace thread
+
+} // namespace osmium
+
+#endif // OSMIUM_THREAD_QUEUE_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/thread/sorted_queue.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/thread/sorted_queue.hpp
new file mode 100755
index 0000000000..e76ade1012
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <condition_variable>
+#include <cstddef>
+#include <deque>
+#include <mutex>
+
+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 <typename T>
+ class SortedQueue {
+
+ typedef typename std::deque<T>::size_type size_type;
+
+ mutable std::mutex m_mutex;
+ std::deque<T> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> lock(m_mutex);
+ return m_queue.size();
+ }
+
+ }; // class SortedQueue
+
+ } // namespace thread
+
+} // namespace osmium
+
+#endif // OSMIUM_THREAD_SORTED_QUEUE_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/thread/util.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/thread/util.hpp
new file mode 100755
index 0000000000..62bb82ab50
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <chrono>
+#include <future>
+
+#ifdef __linux__
+# include <sys/prctl.h>
+#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 <class T>
+ inline void check_for_exception(std::future<T>& 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 <class T>
+ inline void wait_until_done(std::future<T>& 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/cast.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/cast.hpp
new file mode 100755
index 0000000000..4866fdec47
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/cast.hpp
@@ -0,0 +1,103 @@
+#ifndef OSMIUM_UTIL_CAST_HPP
+#define OSMIUM_UTIL_CAST_HPP
+
+/*
+
+This file is part of Osmium (http://osmcode.org/libosmium).
+
+Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#ifndef assert
+# include <cassert>
+#endif
+
+#include <cstdint>
+#include <limits>
+#include <type_traits>
+
+namespace osmium {
+
+ // 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 <typename A, typename B>
+ struct are_real_integers :
+ std::integral_constant<bool,
+ std::is_integral<A>::value &&
+ std::is_integral<B>::value &&
+ !std::is_same<A, bool>::value &&
+ !std::is_same<B, bool>::value> {
+ };
+
+ template <typename T, typename F, typename std::enable_if<are_real_integers<T, F>::value && std::is_same<T, F>::value, int>::type = 0>
+ inline T static_cast_with_assert(const F value) {
+ return value;
+ }
+
+ template <typename T, typename F, typename std::enable_if<are_real_integers<T, F>::value && !std::is_same<T, F>::value && (sizeof(T) > sizeof(F)), int>::type = 0>
+ inline T static_cast_with_assert(const F value) {
+ return static_cast<T>(value);
+ }
+
+ template <typename T, typename F, typename std::enable_if<are_real_integers<T, F>::value && !std::is_same<T, F>::value && std::is_signed<T>::value == std::is_signed<F>::value && (sizeof(T) == sizeof(F)), int>::type = 0>
+ inline T static_cast_with_assert(const F value) {
+ return static_cast<T>(value);
+ }
+
+ template <typename T, typename F, typename std::enable_if<are_real_integers<T, F>::value && !std::is_same<T, F>::value && (sizeof(T) < sizeof(F)) && std::is_signed<T>::value && std::is_signed<F>::value, int>::type = 0>
+ inline T static_cast_with_assert(const F value) {
+ assert(value >= std::numeric_limits<T>::min() && value <= std::numeric_limits<T>::max());
+ return static_cast<T>(value);
+ }
+
+ template <typename T, typename F, typename std::enable_if<are_real_integers<T, F>::value && !std::is_same<T, F>::value && (sizeof(T) <= sizeof(F)) && std::is_unsigned<T>::value && std::is_signed<F>::value, int>::type = 0>
+ inline T static_cast_with_assert(const F value) {
+ assert(value >= 0 && static_cast<typename std::make_unsigned<F>::type>(value) <= std::numeric_limits<T>::max());
+ return static_cast<T>(value);
+ }
+
+ template <typename T, typename F, typename std::enable_if<are_real_integers<T, F>::value && !std::is_same<T, F>::value && (sizeof(T) < sizeof(F)) && std::is_unsigned<T>::value && std::is_unsigned<F>::value, int>::type = 0>
+ inline T static_cast_with_assert(const F value) {
+ assert(value <= std::numeric_limits<T>::max());
+ return static_cast<T>(value);
+ }
+
+ template <typename T, typename F, typename std::enable_if<are_real_integers<T, F>::value && !std::is_same<T, F>::value && (sizeof(T) <= sizeof(F)) && std::is_signed<T>::value && std::is_unsigned<F>::value, int>::type = 0>
+ inline T static_cast_with_assert(const F value) {
+ assert(static_cast<int64_t>(value) <= static_cast<int64_t>(std::numeric_limits<T>::max()));
+ return static_cast<T>(value);
+ }
+
+} // namespace osmium
+
+#endif // OSMIUM_UTIL_CAST_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/compatibility.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/compatibility.hpp
new file mode 100755
index 0000000000..90d85c502a
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+// 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/config.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/config.hpp
new file mode 100755
index 0000000000..3285eedbb9
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <cstdlib>
+#include <cstring>
+
+#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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/double.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/double.hpp
new file mode 100755
index 0000000000..85a2508077
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <cassert>
+#include <cmath>
+#include <cstdio>
+#include <iterator>
+#include <string>
+
+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 <typename T>
+ 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/options.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/options.hpp
new file mode 100755
index 0000000000..fea0752307
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <initializer_list>
+#include <map>
+#include <string>
+#include <utility>
+
+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<std::string, std::string> 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<value_type>& 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/string.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/string.hpp
new file mode 100755
index 0000000000..54eb3616b3
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <string>
+#include <vector>
+#include <iostream>
+
+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<std::string> split_string(const std::string& str, const char sep) {
+ std::vector<std::string> 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/verbose_output.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/util/verbose_output.hpp
new file mode 100755
index 0000000000..249d67fbf7
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <time.h>
+
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+
+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<typename T>
+ 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/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/visitor.hpp b/3party/osrm/osrm-backend/third_party/libosmium/include/osmium/visitor.hpp
new file mode 100755
index 0000000000..0250f11d46
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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-2015 Jochen Topf <jochen@topf.org> and others (see README).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <type_traits>
+
+#include <osmium/io/reader_iterator.hpp> // IWYU pragma: keep
+#include <osmium/memory/buffer.hpp>
+#include <osmium/osm.hpp>
+#include <osmium/osm/entity.hpp>
+#include <osmium/osm/item_type.hpp>
+
+namespace osmium {
+
+ class TagList;
+ class WayNodeList;
+ class RelationMemberList;
+ class OuterRing;
+ class InnerRing;
+
+ namespace memory {
+ class Item;
+ }
+
+ namespace detail {
+
+ template <typename T, typename U>
+ using ConstIfConst = typename std::conditional<std::is_const<T>::value, typename std::add_const<U>::type, U>::type;
+
+ template <class THandler, class TItem>
+ 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<ConstIfConst<TItem, osmium::OSMObject>&>(item));
+ handler.node(static_cast<ConstIfConst<TItem, osmium::Node>&>(item));
+ break;
+ case osmium::item_type::way:
+ handler.osm_object(static_cast<ConstIfConst<TItem, osmium::OSMObject>&>(item));
+ handler.way(static_cast<ConstIfConst<TItem, osmium::Way>&>(item));
+ break;
+ case osmium::item_type::relation:
+ handler.osm_object(static_cast<ConstIfConst<TItem, osmium::OSMObject>&>(item));
+ handler.relation(static_cast<ConstIfConst<TItem, osmium::Relation>&>(item));
+ break;
+ case osmium::item_type::area:
+ handler.osm_object(static_cast<ConstIfConst<TItem, osmium::OSMObject>&>(item));
+ handler.area(static_cast<ConstIfConst<TItem, osmium::Area>&>(item));
+ break;
+ case osmium::item_type::changeset:
+ handler.changeset(static_cast<ConstIfConst<TItem, osmium::Changeset>&>(item));
+ break;
+ case osmium::item_type::tag_list:
+ handler.tag_list(static_cast<ConstIfConst<TItem, osmium::TagList>&>(item));
+ break;
+ case osmium::item_type::way_node_list:
+ handler.way_node_list(static_cast<ConstIfConst<TItem, osmium::WayNodeList>&>(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<ConstIfConst<TItem, osmium::RelationMemberList>&>(item));
+ break;
+ case osmium::item_type::outer_ring:
+ handler.outer_ring(static_cast<ConstIfConst<TItem, osmium::OuterRing>&>(item));
+ break;
+ case osmium::item_type::inner_ring:
+ handler.inner_ring(static_cast<ConstIfConst<TItem, osmium::InnerRing>&>(item));
+ break;
+ }
+ }
+
+ template <class THandler>
+ inline void apply_item_recurse(const osmium::OSMEntity& item, THandler& handler) {
+ switch (item.type()) {
+ case osmium::item_type::node:
+ handler.osm_object(static_cast<const osmium::OSMObject&>(item));
+ handler.node(static_cast<const osmium::Node&>(item));
+ break;
+ case osmium::item_type::way:
+ handler.osm_object(static_cast<const osmium::OSMObject&>(item));
+ handler.way(static_cast<const osmium::Way&>(item));
+ break;
+ case osmium::item_type::relation:
+ handler.osm_object(static_cast<const osmium::OSMObject&>(item));
+ handler.relation(static_cast<const osmium::Relation&>(item));
+ break;
+ case osmium::item_type::area:
+ handler.osm_object(static_cast<const osmium::OSMObject&>(item));
+ handler.area(static_cast<const osmium::Area&>(item));
+ break;
+ case osmium::item_type::changeset:
+ handler.changeset(static_cast<const osmium::Changeset&>(item));
+ break;
+ default:
+ throw osmium::unknown_type();
+ }
+ }
+
+ template <class THandler>
+ inline void apply_item_recurse(osmium::OSMEntity& item, THandler& handler) {
+ switch (item.type()) {
+ case osmium::item_type::node:
+ handler.osm_object(static_cast<osmium::OSMObject&>(item));
+ handler.node(static_cast<osmium::Node&>(item));
+ break;
+ case osmium::item_type::way:
+ handler.osm_object(static_cast<osmium::OSMObject&>(item));
+ handler.way(static_cast<osmium::Way&>(item));
+ break;
+ case osmium::item_type::relation:
+ handler.osm_object(static_cast<osmium::OSMObject&>(item));
+ handler.relation(static_cast<osmium::Relation&>(item));
+ break;
+ case osmium::item_type::area:
+ handler.osm_object(static_cast<osmium::OSMObject&>(item));
+ handler.area(static_cast<osmium::Area&>(item));
+ break;
+ case osmium::item_type::changeset:
+ handler.changeset(static_cast<osmium::Changeset&>(item));
+ break;
+ default:
+ throw osmium::unknown_type();
+ }
+ }
+
+ template <class THandler>
+ 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<const osmium::Node&>(item));
+ break;
+ case osmium::item_type::way:
+ handler.osm_object(item);
+ handler.way(static_cast<const osmium::Way&>(item));
+ break;
+ case osmium::item_type::relation:
+ handler.osm_object(item);
+ handler.relation(static_cast<const osmium::Relation&>(item));
+ break;
+ case osmium::item_type::area:
+ handler.osm_object(item);
+ handler.area(static_cast<const osmium::Area&>(item));
+ break;
+ default:
+ throw osmium::unknown_type();
+ }
+ }
+
+ template <class THandler>
+ 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<osmium::Node&>(item));
+ break;
+ case osmium::item_type::way:
+ handler.osm_object(item);
+ handler.way(static_cast<osmium::Way&>(item));
+ break;
+ case osmium::item_type::relation:
+ handler.osm_object(item);
+ handler.relation(static_cast<osmium::Relation&>(item));
+ break;
+ case osmium::item_type::area:
+ handler.osm_object(item);
+ handler.area(static_cast<osmium::Area&>(item));
+ break;
+ default:
+ throw osmium::unknown_type();
+ }
+ }
+
+ template <class THandler, class TItem, class ...TRest>
+ inline void apply_item_recurse(TItem& item, THandler& handler, TRest&... more) {
+ apply_item_recurse(item, handler);
+ apply_item_recurse(item, more...);
+ }
+
+ template <class THandler>
+ inline void flush_recurse(THandler& handler) {
+ handler.flush();
+ }
+
+ template <class THandler, class ...TRest>
+ inline void flush_recurse(THandler& handler, TRest&... more) {
+ flush_recurse(handler);
+ flush_recurse(more...);
+ }
+
+ } // namespace detail
+
+ template <class ...THandlers>
+ inline void apply_item(const osmium::memory::Item& item, THandlers&... handlers) {
+ detail::apply_item_recurse(item, handlers...);
+ }
+
+ template <class ...THandlers>
+ inline void apply_item(osmium::memory::Item& item, THandlers&... handlers) {
+ detail::apply_item_recurse(item, handlers...);
+ }
+
+ template <class TIterator, class ...THandlers>
+ inline void apply(TIterator it, TIterator end, THandlers&... handlers) {
+ for (; it != end; ++it) {
+ detail::apply_item_recurse(*it, handlers...);
+ }
+ detail::flush_recurse(handlers...);
+ }
+
+ template <class TContainer, class ...THandlers>
+ inline void apply(TContainer& c, THandlers&... handlers) {
+ apply(std::begin(c), std::end(c), handlers...);
+ }
+
+ template <class ...THandlers>
+ 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/3party/osrm/osrm-backend/third_party/libosmium/osmium.imp b/3party/osrm/osrm-backend/third_party/libosmium/osmium.imp
new file mode 100755
index 0000000000..c45794d08e
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/osmium.imp
@@ -0,0 +1,11 @@
+#-----------------------------------------------------------------------------
+#
+# Configuration for Include-What-You-Use tool
+#
+# https://code.google.com/p/include-what-you-use/
+#
+#-----------------------------------------------------------------------------
+[
+ { "include": ["<bits/fcntl-linux.h>", "private", "<fcntl.h>", "public"] },
+ { "include": ["<sys/types.h>", "public", "<cstdint>", "public"] }
+]
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/CMakeLists.txt b/3party/osrm/osrm-backend/third_party/libosmium/test/CMakeLists.txt
new file mode 100755
index 0000000000..7ba455b029
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/CMakeLists.txt
@@ -0,0 +1,165 @@
+#-----------------------------------------------------------------------------
+#
+# CMake Config
+#
+# Libosmium unit tests
+#
+#-----------------------------------------------------------------------------
+
+message(STATUS "Configuring unit tests")
+
+include(CMakeParseArguments)
+include_directories(include)
+
+add_library(testlib STATIC test_main.cpp)
+
+set(ALL_TESTS "")
+
+
+#-----------------------------------------------------------------------------
+#
+# Define function for adding tests
+#
+# 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(_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: ${_tpath}")
+ endif()
+ add_executable(${_testid} t/${_tpath}.cpp)
+ target_link_libraries(${_testid} testlib)
+
+ if(DEFINED _param_LIBS)
+ if(Osmium_DEBUG)
+ message(" Adding libs: ${_param_LIBS}")
+ endif()
+ target_link_libraries(${_testid} ${_param_LIBS})
+ endif()
+
+ add_test(NAME ${_testid}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${_testid}
+ )
+
+ 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 ${_tpath} because a dependency was not found")
+ set(OSMIUM_SKIPPED_TESTS
+ "${OSMIUM_SKIPPED_TESTS} ${_tpath}"
+ 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
+ ENABLE_IF ${GEOS_AND_PROJ_FOUND}
+ LIBS ${GEOS_LIBRARY} ${PROJ_LIBRARY})
+
+add_unit_test(geom test_geojson)
+add_unit_test(geom test_geos ENABLE_IF ${GEOS_FOUND} LIBS ${GEOS_LIBRARY})
+add_unit_test(geom test_geos_wkb ENABLE_IF ${GEOS_FOUND} LIBS ${GEOS_LIBRARY})
+add_unit_test(geom test_mercator)
+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 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 ENABLE_IF ${BZIP2_FOUND} LIBS ${BZIP2_LIBRARIES})
+add_unit_test(io test_file_formats)
+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 ENABLE_IF ${Threads_FOUND} LIBS ${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)
+
+
+#-----------------------------------------------------------------------------
+#
+# 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()
+
+
+#-----------------------------------------------------------------------------
+message(STATUS "Configuring unit tests - done")
+
+
+#-----------------------------------------------------------------------------
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/README b/3party/osrm/osrm-backend/third_party/libosmium/test/README
new file mode 100755
index 0000000000..8195824b48
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/README
@@ -0,0 +1,13 @@
+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:
+* 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/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/.gitignore b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/.gitignore
new file mode 100755
index 0000000000..98df22edaa
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/.gitignore
@@ -0,0 +1 @@
+multipolygon.qgs~
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/CMakeLists.txt b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/CMakeLists.txt
new file mode 100755
index 0000000000..89aead98ee
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/CMakeLists.txt
@@ -0,0 +1,118 @@
+#-----------------------------------------------------------------------------
+#
+# 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
+#
+#-----------------------------------------------------------------------------
+
+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()
+ message(WARNING "Disabled testdata-multipolygon test because 'ruby' and/or 'json' ruby gem and/or 'spatialite' was not found")
+endif()
+
+
+#-----------------------------------------------------------------------------
+message(STATUS "Configuring data tests - done")
+
+
+#-----------------------------------------------------------------------------
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/README.md b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/README.md
new file mode 100755
index 0000000000..5138bf8566
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/README.md
@@ -0,0 +1,10 @@
+# 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.
+
+Tests will be built if the CMake option `BUILD_DATA_TESTS` is set and run as
+part of the `ctest` run.
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/include/check_basics_handler.hpp b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/include/check_basics_handler.hpp
new file mode 100755
index 0000000000..757ab4d3f8
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/include/check_basics_handler.hpp
@@ -0,0 +1,92 @@
+#ifndef CHECK_BASICS_HANDLER_HPP
+#define CHECK_BASICS_HANDLER_HPP
+
+#include <iostream>
+#include <unordered_set>
+
+#include <osmium/handler.hpp>
+#include <osmium/osm.hpp>
+
+/**
+ * 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<osmium::object_id_type> 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/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/include/check_wkt_handler.hpp b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/include/check_wkt_handler.hpp
new file mode 100755
index 0000000000..fe0199e0ac
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/include/check_wkt_handler.hpp
@@ -0,0 +1,86 @@
+#ifndef CHECK_WKT_HANDLER_HPP
+#define CHECK_WKT_HANDLER_HPP
+
+#include <cassert>
+#include <fstream>
+#include <map>
+#include <sstream>
+#include <string>
+
+#include <osmium/handler.hpp>
+#include <osmium/osm.hpp>
+#include <osmium/osm/types.hpp>
+
+class CheckWKTHandler : public osmium::handler::Handler {
+
+ std::map<osmium::object_id_type, std::string> 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/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/include/common.hpp b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/include/common.hpp
new file mode 100755
index 0000000000..a6fd3df616
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/include/common.hpp
@@ -0,0 +1,22 @@
+#ifndef COMMON_HPP
+#define COMMON_HPP
+
+#include <osmium/index/map/dummy.hpp>
+#include <osmium/index/map/sparse_mem_array.hpp>
+
+#include <osmium/geom/wkt.hpp>
+#include <osmium/handler.hpp>
+#include <osmium/handler/node_locations_for_ways.hpp>
+#include <osmium/io/xml_input.hpp>
+#include <osmium/visitor.hpp>
+
+typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
+typedef osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
+typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
+
+#include "check_basics_handler.hpp"
+#include "check_wkt_handler.hpp"
+
+#include "testdata-testcases.hpp"
+
+#endif // COMMON_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/include/testdata-testcases.hpp b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/include/testdata-testcases.hpp
new file mode 100755
index 0000000000..d7d0c01d7e
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/include/testdata-testcases.hpp
@@ -0,0 +1,10 @@
+#ifndef TESTDATA_TESTCASES_HPP
+#define TESTDATA_TESTCASES_HPP
+
+#include <catch.hpp>
+
+#include <string>
+
+extern std::string dirname;
+
+#endif // TESTDATA_TESTCASES_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/multipolygon.qgs b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/multipolygon.qgs
new file mode 100755
index 0000000000..5553670bba
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/multipolygon.qgs
@@ -0,0 +1,880 @@
+<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
+<qgis projectname="" version="2.2.0-Valmiera">
+ <title></title>
+ <relations/>
+ <mapcanvas>
+ <units>degrees</units>
+ <extent>
+ <xmin>0.77500024999999972</xmin>
+ <ymin>-0.84791712574962541</ymin>
+ <xmax>10.22498975000000065</xmax>
+ <ymax>3.94791712574962572</ymax>
+ </extent>
+ <projections>0</projections>
+ <destinationsrs>
+ <spatialrefsys>
+ <proj4>+proj=longlat +datum=WGS84 +no_defs</proj4>
+ <srsid>3452</srsid>
+ <srid>4326</srid>
+ <authid>EPSG:4326</authid>
+ <description>WGS 84</description>
+ <projectionacronym>longlat</projectionacronym>
+ <ellipsoidacronym>WGS84</ellipsoidacronym>
+ <geographicflag>true</geographicflag>
+ </spatialrefsys>
+ </destinationsrs>
+ <layer_coordinate_transform_info/>
+ </mapcanvas>
+ <legend updateDrawingOrder="true">
+ <legendlayer drawingOrder="-1" open="true" checked="Qt::Checked" name="Error Points" showFeatureCount="0">
+ <filegroup open="true" hidden="false">
+ <legendlayerfile isInOverview="0" layerid="perrors20140228163658956" visible="1"/>
+ </filegroup>
+ </legendlayer>
+ <legendlayer drawingOrder="-1" open="true" checked="Qt::Checked" name="Error Lines" showFeatureCount="0">
+ <filegroup open="true" hidden="false">
+ <legendlayerfile isInOverview="0" layerid="lerrors20140228172357933" visible="1"/>
+ </filegroup>
+ </legendlayer>
+ <legendlayer drawingOrder="-1" open="true" checked="Qt::Checked" name="multipolygons" showFeatureCount="0">
+ <filegroup open="true" hidden="false">
+ <legendlayerfile isInOverview="0" layerid="multipolygons20140221151811742" visible="1"/>
+ </filegroup>
+ </legendlayer>
+ <legendgroup embedded="1" drawingOrder="-1" open="true" checked="Qt::Checked" name="Overview" project="../../../osm-testdata/grid/tests.qgs"/>
+ <legendgroup embedded="1" drawingOrder="-1" open="true" checked="Qt::Checked" name="Test Framework" project="../../../osm-testdata/grid/tests.qgs"/>
+ </legend>
+ <projectlayers layercount="9">
+ <maplayer minimumScale="-4.65661e-10" maximumScale="1e+08" simplifyDrawingHints="1" minLabelScale="0" maxLabelScale="1e+08" simplifyDrawingTol="1" geometry="Line" simplifyMaxScale="1" type="vector" hasScaleBasedVisibilityFlag="0" simplifyLocal="1" scaleBasedLabelVisibilityFlag="0">
+ <id>lerrors20140228172357933</id>
+ <datasource>dbname='./multipolygon.db' table="lerrors" (GEOMETRY) sql=</datasource>
+ <title></title>
+ <abstract></abstract>
+ <keywordList>
+ <value></value>
+ </keywordList>
+ <layername>Error Lines</layername>
+ <srs>
+ <spatialrefsys>
+ <proj4>+proj=longlat +datum=WGS84 +no_defs</proj4>
+ <srsid>3452</srsid>
+ <srid>4326</srid>
+ <authid>EPSG:4326</authid>
+ <description>WGS 84</description>
+ <projectionacronym>longlat</projectionacronym>
+ <ellipsoidacronym>WGS84</ellipsoidacronym>
+ <geographicflag>true</geographicflag>
+ </spatialrefsys>
+ </srs>
+ <provider encoding="System">spatialite</provider>
+ <previewExpression>COALESCE( "OGC_FID", '&lt;NULL>' )</previewExpression>
+ <vectorjoins/>
+ <renderer-v2 attr="problem_type" symbollevels="0" type="categorizedSymbol">
+ <categories>
+ <category symbol="0" value="intersection" label="intersection"/>
+ <category symbol="1" value="role_should_be_outer" label="role_should_be_outer"/>
+ <category symbol="2" value="role_should_be_inner" label="role_should_be_inner"/>
+ <category symbol="3" value="" label=""/>
+ </categories>
+ <symbols>
+ <symbol alpha="1" type="line" name="0">
+ <layer pass="0" class="SimpleLine" locked="0">
+ <prop k="capstyle" v="square"/>
+ <prop k="color" v="255,0,0,255"/>
+ <prop k="customdash" v="5;2"/>
+ <prop k="customdash_unit" v="MM"/>
+ <prop k="draw_inside_polygon" v="0"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="offset" v="0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="penstyle" v="solid"/>
+ <prop k="use_custom_dash" v="0"/>
+ <prop k="width" v="0.5"/>
+ <prop k="width_unit" v="MM"/>
+ </layer>
+ </symbol>
+ <symbol alpha="1" type="line" name="1">
+ <layer pass="0" class="SimpleLine" locked="0">
+ <prop k="capstyle" v="square"/>
+ <prop k="color" v="255,122,33,255"/>
+ <prop k="customdash" v="5;2"/>
+ <prop k="customdash_unit" v="MM"/>
+ <prop k="draw_inside_polygon" v="0"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="offset" v="0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="penstyle" v="solid"/>
+ <prop k="use_custom_dash" v="0"/>
+ <prop k="width" v="0.5"/>
+ <prop k="width_unit" v="MM"/>
+ </layer>
+ </symbol>
+ <symbol alpha="1" type="line" name="2">
+ <layer pass="0" class="SimpleLine" locked="0">
+ <prop k="capstyle" v="square"/>
+ <prop k="color" v="255,122,33,255"/>
+ <prop k="customdash" v="5;2"/>
+ <prop k="customdash_unit" v="MM"/>
+ <prop k="draw_inside_polygon" v="0"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="offset" v="0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="penstyle" v="dash"/>
+ <prop k="use_custom_dash" v="0"/>
+ <prop k="width" v="0.5"/>
+ <prop k="width_unit" v="MM"/>
+ </layer>
+ </symbol>
+ <symbol alpha="1" type="line" name="3">
+ <layer pass="0" class="SimpleLine" locked="0">
+ <prop k="capstyle" v="square"/>
+ <prop k="color" v="255,0,0,255"/>
+ <prop k="customdash" v="5;2"/>
+ <prop k="customdash_unit" v="MM"/>
+ <prop k="draw_inside_polygon" v="0"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="offset" v="0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="penstyle" v="solid"/>
+ <prop k="use_custom_dash" v="0"/>
+ <prop k="width" v="0.5"/>
+ <prop k="width_unit" v="MM"/>
+ </layer>
+ </symbol>
+ </symbols>
+ <source-symbol>
+ <symbol alpha="1" type="line" name="0">
+ <layer pass="0" class="SimpleLine" locked="0">
+ <prop k="capstyle" v="square"/>
+ <prop k="color" v="77,243,51,255"/>
+ <prop k="customdash" v="5;2"/>
+ <prop k="customdash_unit" v="MM"/>
+ <prop k="draw_inside_polygon" v="0"/>
+ <prop k="joinstyle" v="bevel"/>
+ <prop k="offset" v="0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="penstyle" v="solid"/>
+ <prop k="use_custom_dash" v="0"/>
+ <prop k="width" v="0.26"/>
+ <prop k="width_unit" v="MM"/>
+ </layer>
+ </symbol>
+ </source-symbol>
+ <rotation/>
+ <sizescale scalemethod="area"/>
+ </renderer-v2>
+ <customproperties>
+ <property key="labeling" value="pal"/>
+ <property key="labeling/addDirectionSymbol" value="false"/>
+ <property key="labeling/angleOffset" value="0"/>
+ <property key="labeling/blendMode" value="0"/>
+ <property key="labeling/bufferBlendMode" value="0"/>
+ <property key="labeling/bufferColorA" value="255"/>
+ <property key="labeling/bufferColorB" value="255"/>
+ <property key="labeling/bufferColorG" value="255"/>
+ <property key="labeling/bufferColorR" value="255"/>
+ <property key="labeling/bufferDraw" value="false"/>
+ <property key="labeling/bufferJoinStyle" value="64"/>
+ <property key="labeling/bufferNoFill" value="false"/>
+ <property key="labeling/bufferSize" value="1"/>
+ <property key="labeling/bufferSizeInMapUnits" value="false"/>
+ <property key="labeling/bufferTransp" value="0"/>
+ <property key="labeling/centroidWhole" value="false"/>
+ <property key="labeling/decimals" value="3"/>
+ <property key="labeling/displayAll" value="false"/>
+ <property key="labeling/dist" value="0"/>
+ <property key="labeling/distInMapUnits" value="false"/>
+ <property key="labeling/enabled" value="false"/>
+ <property key="labeling/fieldName" value=""/>
+ <property key="labeling/fontBold" value="false"/>
+ <property key="labeling/fontCapitals" value="0"/>
+ <property key="labeling/fontFamily" value="Sans"/>
+ <property key="labeling/fontItalic" value="false"/>
+ <property key="labeling/fontLetterSpacing" value="0"/>
+ <property key="labeling/fontLimitPixelSize" value="false"/>
+ <property key="labeling/fontMaxPixelSize" value="10000"/>
+ <property key="labeling/fontMinPixelSize" value="3"/>
+ <property key="labeling/fontSize" value="10"/>
+ <property key="labeling/fontSizeInMapUnits" value="false"/>
+ <property key="labeling/fontStrikeout" value="false"/>
+ <property key="labeling/fontUnderline" value="false"/>
+ <property key="labeling/fontWeight" value="50"/>
+ <property key="labeling/fontWordSpacing" value="0"/>
+ <property key="labeling/formatNumbers" value="false"/>
+ <property key="labeling/isExpression" value="false"/>
+ <property key="labeling/labelOffsetInMapUnits" value="true"/>
+ <property key="labeling/labelPerPart" value="false"/>
+ <property key="labeling/leftDirectionSymbol" value="&lt;"/>
+ <property key="labeling/limitNumLabels" value="false"/>
+ <property key="labeling/maxCurvedCharAngleIn" value="20"/>
+ <property key="labeling/maxCurvedCharAngleOut" value="-20"/>
+ <property key="labeling/maxNumLabels" value="2000"/>
+ <property key="labeling/mergeLines" value="false"/>
+ <property key="labeling/minFeatureSize" value="0"/>
+ <property key="labeling/multilineAlign" value="0"/>
+ <property key="labeling/multilineHeight" value="1"/>
+ <property key="labeling/namedStyle" value=""/>
+ <property key="labeling/obstacle" value="true"/>
+ <property key="labeling/placeDirectionSymbol" value="0"/>
+ <property key="labeling/placement" value="2"/>
+ <property key="labeling/placementFlags" value="10"/>
+ <property key="labeling/plussign" value="false"/>
+ <property key="labeling/preserveRotation" value="true"/>
+ <property key="labeling/previewBkgrdColor" value="#ffffff"/>
+ <property key="labeling/priority" value="5"/>
+ <property key="labeling/quadOffset" value="4"/>
+ <property key="labeling/reverseDirectionSymbol" value="false"/>
+ <property key="labeling/rightDirectionSymbol" value=">"/>
+ <property key="labeling/scaleMax" value="10000000"/>
+ <property key="labeling/scaleMin" value="1"/>
+ <property key="labeling/scaleVisibility" value="false"/>
+ <property key="labeling/shadowBlendMode" value="6"/>
+ <property key="labeling/shadowColorB" value="0"/>
+ <property key="labeling/shadowColorG" value="0"/>
+ <property key="labeling/shadowColorR" value="0"/>
+ <property key="labeling/shadowDraw" value="false"/>
+ <property key="labeling/shadowOffsetAngle" value="135"/>
+ <property key="labeling/shadowOffsetDist" value="1"/>
+ <property key="labeling/shadowOffsetGlobal" value="true"/>
+ <property key="labeling/shadowOffsetUnits" value="1"/>
+ <property key="labeling/shadowRadius" value="1.5"/>
+ <property key="labeling/shadowRadiusAlphaOnly" value="false"/>
+ <property key="labeling/shadowRadiusUnits" value="1"/>
+ <property key="labeling/shadowScale" value="100"/>
+ <property key="labeling/shadowTransparency" value="30"/>
+ <property key="labeling/shadowUnder" value="0"/>
+ <property key="labeling/shapeBlendMode" value="0"/>
+ <property key="labeling/shapeBorderColorA" value="255"/>
+ <property key="labeling/shapeBorderColorB" value="128"/>
+ <property key="labeling/shapeBorderColorG" value="128"/>
+ <property key="labeling/shapeBorderColorR" value="128"/>
+ <property key="labeling/shapeBorderWidth" value="0"/>
+ <property key="labeling/shapeBorderWidthUnits" value="1"/>
+ <property key="labeling/shapeDraw" value="false"/>
+ <property key="labeling/shapeFillColorA" value="255"/>
+ <property key="labeling/shapeFillColorB" value="255"/>
+ <property key="labeling/shapeFillColorG" value="255"/>
+ <property key="labeling/shapeFillColorR" value="255"/>
+ <property key="labeling/shapeJoinStyle" value="64"/>
+ <property key="labeling/shapeOffsetUnits" value="1"/>
+ <property key="labeling/shapeOffsetX" value="0"/>
+ <property key="labeling/shapeOffsetY" value="0"/>
+ <property key="labeling/shapeRadiiUnits" value="1"/>
+ <property key="labeling/shapeRadiiX" value="0"/>
+ <property key="labeling/shapeRadiiY" value="0"/>
+ <property key="labeling/shapeRotation" value="0"/>
+ <property key="labeling/shapeRotationType" value="0"/>
+ <property key="labeling/shapeSVGFile" value=""/>
+ <property key="labeling/shapeSizeType" value="0"/>
+ <property key="labeling/shapeSizeUnits" value="1"/>
+ <property key="labeling/shapeSizeX" value="0"/>
+ <property key="labeling/shapeSizeY" value="0"/>
+ <property key="labeling/shapeTransparency" value="0"/>
+ <property key="labeling/shapeType" value="0"/>
+ <property key="labeling/textColorA" value="255"/>
+ <property key="labeling/textColorB" value="0"/>
+ <property key="labeling/textColorG" value="0"/>
+ <property key="labeling/textColorR" value="0"/>
+ <property key="labeling/textTransp" value="0"/>
+ <property key="labeling/upsidedownLabels" value="0"/>
+ <property key="labeling/wrapChar" value=""/>
+ <property key="labeling/xOffset" value="0"/>
+ <property key="labeling/yOffset" value="0"/>
+ </customproperties>
+ <blendMode>0</blendMode>
+ <featureBlendMode>0</featureBlendMode>
+ <layerTransparency>0</layerTransparency>
+ <displayfield>OGC_FID</displayfield>
+ <label>0</label>
+ <labelattributes>
+ <label fieldname="" text="Label"/>
+ <family fieldname="" name="Sans"/>
+ <size fieldname="" units="pt" value="12"/>
+ <bold fieldname="" on="0"/>
+ <italic fieldname="" on="0"/>
+ <underline fieldname="" on="0"/>
+ <strikeout fieldname="" on="0"/>
+ <color fieldname="" red="0" blue="0" green="0"/>
+ <x fieldname=""/>
+ <y fieldname=""/>
+ <offset x="0" y="0" units="pt" yfieldname="" xfieldname=""/>
+ <angle fieldname="" value="0" auto="0"/>
+ <alignment fieldname="" value="center"/>
+ <buffercolor fieldname="" red="255" blue="255" green="255"/>
+ <buffersize fieldname="" units="pt" value="1"/>
+ <bufferenabled fieldname="" on=""/>
+ <multilineenabled fieldname="" on=""/>
+ <selectedonly on=""/>
+ </labelattributes>
+ <edittypes>
+ <edittype labelontop="0" editable="1" type="0" name="OGC_FID"/>
+ <edittype labelontop="0" editable="1" type="0" name="id"/>
+ <edittype labelontop="0" editable="1" type="0" name="object_id"/>
+ <edittype labelontop="0" editable="1" type="0" name="problem_type"/>
+ <edittype labelontop="0" editable="1" type="0" name="type"/>
+ <edittype labelontop="0" editable="1" type="0" name="way_id"/>
+ </edittypes>
+ <editform>.</editform>
+ <editforminit></editforminit>
+ <featformsuppress>0</featformsuppress>
+ <annotationform>.</annotationform>
+ <editorlayout>generatedlayout</editorlayout>
+ <excludeAttributesWMS/>
+ <excludeAttributesWFS/>
+ <attributeactions/>
+ </maplayer>
+ <maplayer minimumScale="-4.65661e-10" maximumScale="1e+08" simplifyDrawingHints="1" minLabelScale="0" maxLabelScale="1e+08" simplifyDrawingTol="1" geometry="Polygon" simplifyMaxScale="1" type="vector" hasScaleBasedVisibilityFlag="0" simplifyLocal="1" scaleBasedLabelVisibilityFlag="0">
+ <id>multipolygons20140221151811742</id>
+ <datasource>dbname='./multipolygon.db' table="multipolygons" (GEOMETRY) sql=</datasource>
+ <title></title>
+ <abstract></abstract>
+ <keywordList>
+ <value></value>
+ </keywordList>
+ <layername>multipolygons</layername>
+ <srs>
+ <spatialrefsys>
+ <proj4>+proj=longlat +datum=WGS84 +no_defs</proj4>
+ <srsid>3452</srsid>
+ <srid>4326</srid>
+ <authid>EPSG:4326</authid>
+ <description>WGS 84</description>
+ <projectionacronym>longlat</projectionacronym>
+ <ellipsoidacronym>WGS84</ellipsoidacronym>
+ <geographicflag>true</geographicflag>
+ </spatialrefsys>
+ </srs>
+ <provider encoding="System">spatialite</provider>
+ <previewExpression></previewExpression>
+ <vectorjoins/>
+ <renderer-v2 symbollevels="0" type="singleSymbol">
+ <symbols>
+ <symbol alpha="0.494118" type="fill" name="0">
+ <layer pass="0" class="SimpleFill" locked="0">
+ <prop k="border_width_unit" v="MM"/>
+ <prop k="color" v="0,170,255,255"/>
+ <prop k="color_border" v="0,0,0,255"/>
+ <prop k="offset" v="0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="style" v="solid"/>
+ <prop k="style_border" v="solid"/>
+ <prop k="width_border" v="0.26"/>
+ </layer>
+ </symbol>
+ </symbols>
+ <rotation/>
+ <sizescale scalemethod="area"/>
+ </renderer-v2>
+ <customproperties>
+ <property key="labeling" value="pal"/>
+ <property key="labeling/addDirectionSymbol" value="false"/>
+ <property key="labeling/angleOffset" value="0"/>
+ <property key="labeling/blendMode" value="0"/>
+ <property key="labeling/bufferBlendMode" value="0"/>
+ <property key="labeling/bufferColorA" value="255"/>
+ <property key="labeling/bufferColorB" value="255"/>
+ <property key="labeling/bufferColorG" value="255"/>
+ <property key="labeling/bufferColorR" value="255"/>
+ <property key="labeling/bufferDraw" value="false"/>
+ <property key="labeling/bufferJoinStyle" value="64"/>
+ <property key="labeling/bufferNoFill" value="false"/>
+ <property key="labeling/bufferSize" value="1"/>
+ <property key="labeling/bufferSizeInMapUnits" value="false"/>
+ <property key="labeling/bufferTransp" value="0"/>
+ <property key="labeling/centroidWhole" value="false"/>
+ <property key="labeling/decimals" value="3"/>
+ <property key="labeling/displayAll" value="false"/>
+ <property key="labeling/dist" value="0"/>
+ <property key="labeling/distInMapUnits" value="false"/>
+ <property key="labeling/enabled" value="false"/>
+ <property key="labeling/fieldName" value=""/>
+ <property key="labeling/fontBold" value="false"/>
+ <property key="labeling/fontCapitals" value="0"/>
+ <property key="labeling/fontFamily" value="Sans"/>
+ <property key="labeling/fontItalic" value="false"/>
+ <property key="labeling/fontLetterSpacing" value="0"/>
+ <property key="labeling/fontLimitPixelSize" value="false"/>
+ <property key="labeling/fontMaxPixelSize" value="10000"/>
+ <property key="labeling/fontMinPixelSize" value="3"/>
+ <property key="labeling/fontSize" value="10"/>
+ <property key="labeling/fontSizeInMapUnits" value="false"/>
+ <property key="labeling/fontStrikeout" value="false"/>
+ <property key="labeling/fontUnderline" value="false"/>
+ <property key="labeling/fontWeight" value="50"/>
+ <property key="labeling/fontWordSpacing" value="0"/>
+ <property key="labeling/formatNumbers" value="false"/>
+ <property key="labeling/isExpression" value="false"/>
+ <property key="labeling/labelOffsetInMapUnits" value="true"/>
+ <property key="labeling/labelPerPart" value="false"/>
+ <property key="labeling/leftDirectionSymbol" value="&lt;"/>
+ <property key="labeling/limitNumLabels" value="false"/>
+ <property key="labeling/maxCurvedCharAngleIn" value="20"/>
+ <property key="labeling/maxCurvedCharAngleOut" value="-20"/>
+ <property key="labeling/maxNumLabels" value="2000"/>
+ <property key="labeling/mergeLines" value="false"/>
+ <property key="labeling/minFeatureSize" value="0"/>
+ <property key="labeling/multilineAlign" value="0"/>
+ <property key="labeling/multilineHeight" value="1"/>
+ <property key="labeling/namedStyle" value=""/>
+ <property key="labeling/obstacle" value="true"/>
+ <property key="labeling/placeDirectionSymbol" value="0"/>
+ <property key="labeling/placement" value="0"/>
+ <property key="labeling/placementFlags" value="0"/>
+ <property key="labeling/plussign" value="false"/>
+ <property key="labeling/preserveRotation" value="true"/>
+ <property key="labeling/previewBkgrdColor" value="#ffffff"/>
+ <property key="labeling/priority" value="5"/>
+ <property key="labeling/quadOffset" value="4"/>
+ <property key="labeling/reverseDirectionSymbol" value="false"/>
+ <property key="labeling/rightDirectionSymbol" value=">"/>
+ <property key="labeling/scaleMax" value="10000000"/>
+ <property key="labeling/scaleMin" value="1"/>
+ <property key="labeling/scaleVisibility" value="false"/>
+ <property key="labeling/shadowBlendMode" value="6"/>
+ <property key="labeling/shadowColorB" value="0"/>
+ <property key="labeling/shadowColorG" value="0"/>
+ <property key="labeling/shadowColorR" value="0"/>
+ <property key="labeling/shadowDraw" value="false"/>
+ <property key="labeling/shadowOffsetAngle" value="135"/>
+ <property key="labeling/shadowOffsetDist" value="1"/>
+ <property key="labeling/shadowOffsetGlobal" value="true"/>
+ <property key="labeling/shadowOffsetUnits" value="1"/>
+ <property key="labeling/shadowRadius" value="1.5"/>
+ <property key="labeling/shadowRadiusAlphaOnly" value="false"/>
+ <property key="labeling/shadowRadiusUnits" value="1"/>
+ <property key="labeling/shadowScale" value="100"/>
+ <property key="labeling/shadowTransparency" value="30"/>
+ <property key="labeling/shadowUnder" value="0"/>
+ <property key="labeling/shapeBlendMode" value="0"/>
+ <property key="labeling/shapeBorderColorA" value="255"/>
+ <property key="labeling/shapeBorderColorB" value="128"/>
+ <property key="labeling/shapeBorderColorG" value="128"/>
+ <property key="labeling/shapeBorderColorR" value="128"/>
+ <property key="labeling/shapeBorderWidth" value="0"/>
+ <property key="labeling/shapeBorderWidthUnits" value="1"/>
+ <property key="labeling/shapeDraw" value="false"/>
+ <property key="labeling/shapeFillColorA" value="255"/>
+ <property key="labeling/shapeFillColorB" value="255"/>
+ <property key="labeling/shapeFillColorG" value="255"/>
+ <property key="labeling/shapeFillColorR" value="255"/>
+ <property key="labeling/shapeJoinStyle" value="64"/>
+ <property key="labeling/shapeOffsetUnits" value="1"/>
+ <property key="labeling/shapeOffsetX" value="0"/>
+ <property key="labeling/shapeOffsetY" value="0"/>
+ <property key="labeling/shapeRadiiUnits" value="1"/>
+ <property key="labeling/shapeRadiiX" value="0"/>
+ <property key="labeling/shapeRadiiY" value="0"/>
+ <property key="labeling/shapeRotation" value="0"/>
+ <property key="labeling/shapeRotationType" value="0"/>
+ <property key="labeling/shapeSVGFile" value=""/>
+ <property key="labeling/shapeSizeType" value="0"/>
+ <property key="labeling/shapeSizeUnits" value="1"/>
+ <property key="labeling/shapeSizeX" value="0"/>
+ <property key="labeling/shapeSizeY" value="0"/>
+ <property key="labeling/shapeTransparency" value="0"/>
+ <property key="labeling/shapeType" value="0"/>
+ <property key="labeling/textColorA" value="255"/>
+ <property key="labeling/textColorB" value="0"/>
+ <property key="labeling/textColorG" value="0"/>
+ <property key="labeling/textColorR" value="0"/>
+ <property key="labeling/textTransp" value="0"/>
+ <property key="labeling/upsidedownLabels" value="0"/>
+ <property key="labeling/wrapChar" value=""/>
+ <property key="labeling/xOffset" value="0"/>
+ <property key="labeling/yOffset" value="0"/>
+ </customproperties>
+ <blendMode>0</blendMode>
+ <featureBlendMode>0</featureBlendMode>
+ <layerTransparency>0</layerTransparency>
+ <displayfield>OGC_FID</displayfield>
+ <label>0</label>
+ <labelattributes>
+ <label fieldname="" text="Label"/>
+ <family fieldname="" name="Sans"/>
+ <size fieldname="" units="pt" value="12"/>
+ <bold fieldname="" on="0"/>
+ <italic fieldname="" on="0"/>
+ <underline fieldname="" on="0"/>
+ <strikeout fieldname="" on="0"/>
+ <color fieldname="" red="0" blue="0" green="0"/>
+ <x fieldname=""/>
+ <y fieldname=""/>
+ <offset x="0" y="0" units="pt" yfieldname="" xfieldname=""/>
+ <angle fieldname="" value="0" auto="0"/>
+ <alignment fieldname="" value="center"/>
+ <buffercolor fieldname="" red="255" blue="255" green="255"/>
+ <buffersize fieldname="" units="pt" value="1"/>
+ <bufferenabled fieldname="" on=""/>
+ <multilineenabled fieldname="" on=""/>
+ <selectedonly on=""/>
+ </labelattributes>
+ <edittypes>
+ <edittype labelontop="0" editable="1" type="0" name="OGC_FID"/>
+ <edittype labelontop="0" editable="1" type="0" name="id"/>
+ <edittype labelontop="0" editable="1" type="0" name="type"/>
+ </edittypes>
+ <editform>.</editform>
+ <editforminit></editforminit>
+ <featformsuppress>0</featformsuppress>
+ <annotationform>.</annotationform>
+ <editorlayout>generatedlayout</editorlayout>
+ <excludeAttributesWMS/>
+ <excludeAttributesWFS/>
+ <attributeactions/>
+ </maplayer>
+ <maplayer minimumScale="0" maximumScale="1e+08" simplifyDrawingHints="0" minLabelScale="0" maxLabelScale="1e+08" simplifyDrawingTol="1" geometry="Point" simplifyMaxScale="1" type="vector" hasScaleBasedVisibilityFlag="0" simplifyLocal="1" scaleBasedLabelVisibilityFlag="0">
+ <id>perrors20140228163658956</id>
+ <datasource>dbname='./multipolygon.db' table="perrors" (GEOMETRY) sql=</datasource>
+ <title></title>
+ <abstract></abstract>
+ <keywordList>
+ <value></value>
+ </keywordList>
+ <layername>Error Points</layername>
+ <srs>
+ <spatialrefsys>
+ <proj4>+proj=longlat +datum=WGS84 +no_defs</proj4>
+ <srsid>3452</srsid>
+ <srid>4326</srid>
+ <authid>EPSG:4326</authid>
+ <description>WGS 84</description>
+ <projectionacronym>longlat</projectionacronym>
+ <ellipsoidacronym>WGS84</ellipsoidacronym>
+ <geographicflag>true</geographicflag>
+ </spatialrefsys>
+ </srs>
+ <provider encoding="System">spatialite</provider>
+ <previewExpression>COALESCE( "OGC_FID", '&lt;NULL>' )</previewExpression>
+ <vectorjoins/>
+ <renderer-v2 attr="problem_type" symbollevels="0" type="categorizedSymbol">
+ <categories>
+ <category symbol="0" value="intersection" label="intersection"/>
+ <category symbol="1" value="ring_not_closed" label="ring_not_closed"/>
+ <category symbol="2" value="duplicate_node" label="duplicate_node"/>
+ </categories>
+ <symbols>
+ <symbol alpha="1" type="marker" name="0">
+ <layer pass="0" class="SimpleMarker" locked="0">
+ <prop k="angle" v="0"/>
+ <prop k="color" v="255,0,0,255"/>
+ <prop k="color_border" v="255,255,255,255"/>
+ <prop k="horizontal_anchor_point" v="1"/>
+ <prop k="name" v="diamond"/>
+ <prop k="offset" v="0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="outline_style" v="solid"/>
+ <prop k="outline_width" v="0.4"/>
+ <prop k="outline_width_unit" v="MM"/>
+ <prop k="scale_method" v="area"/>
+ <prop k="size" v="2.8"/>
+ <prop k="size_unit" v="MM"/>
+ <prop k="vertical_anchor_point" v="1"/>
+ </layer>
+ </symbol>
+ <symbol alpha="1" type="marker" name="1">
+ <layer pass="0" class="SimpleMarker" locked="0">
+ <prop k="angle" v="0"/>
+ <prop k="color" v="255,0,0,255"/>
+ <prop k="color_border" v="255,255,255,255"/>
+ <prop k="horizontal_anchor_point" v="1"/>
+ <prop k="name" v="triangle"/>
+ <prop k="offset" v="0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="outline_style" v="solid"/>
+ <prop k="outline_width" v="0.4"/>
+ <prop k="outline_width_unit" v="MM"/>
+ <prop k="scale_method" v="area"/>
+ <prop k="size" v="2.8"/>
+ <prop k="size_unit" v="MM"/>
+ <prop k="vertical_anchor_point" v="1"/>
+ </layer>
+ </symbol>
+ <symbol alpha="1" type="marker" name="2">
+ <layer pass="0" class="SimpleMarker" locked="0">
+ <prop k="angle" v="0"/>
+ <prop k="color" v="255,255,255,255"/>
+ <prop k="color_border" v="255,0,0,255"/>
+ <prop k="horizontal_anchor_point" v="1"/>
+ <prop k="name" v="circle"/>
+ <prop k="offset" v="0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="outline_style" v="solid"/>
+ <prop k="outline_width" v="0.4"/>
+ <prop k="outline_width_unit" v="MM"/>
+ <prop k="scale_method" v="area"/>
+ <prop k="size" v="2.4"/>
+ <prop k="size_unit" v="MM"/>
+ <prop k="vertical_anchor_point" v="1"/>
+ </layer>
+ <layer pass="0" class="SimpleMarker" locked="0">
+ <prop k="angle" v="0"/>
+ <prop k="color" v="255,0,0,255"/>
+ <prop k="color_border" v="255,0,0,255"/>
+ <prop k="horizontal_anchor_point" v="1"/>
+ <prop k="name" v="circle"/>
+ <prop k="offset" v="0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="outline_style" v="solid"/>
+ <prop k="outline_width" v="0.8"/>
+ <prop k="outline_width_unit" v="MM"/>
+ <prop k="scale_method" v="area"/>
+ <prop k="size" v="0.5"/>
+ <prop k="size_unit" v="MM"/>
+ <prop k="vertical_anchor_point" v="1"/>
+ </layer>
+ </symbol>
+ </symbols>
+ <source-symbol>
+ <symbol alpha="1" type="marker" name="0">
+ <layer pass="0" class="SimpleMarker" locked="0">
+ <prop k="angle" v="0"/>
+ <prop k="color" v="139,168,110,255"/>
+ <prop k="color_border" v="0,0,0,255"/>
+ <prop k="horizontal_anchor_point" v="1"/>
+ <prop k="name" v="circle"/>
+ <prop k="offset" v="0,0"/>
+ <prop k="offset_unit" v="MM"/>
+ <prop k="outline_style" v="solid"/>
+ <prop k="outline_width" v="0"/>
+ <prop k="outline_width_unit" v="MM"/>
+ <prop k="scale_method" v="area"/>
+ <prop k="size" v="2"/>
+ <prop k="size_unit" v="MM"/>
+ <prop k="vertical_anchor_point" v="1"/>
+ </layer>
+ </symbol>
+ </source-symbol>
+ <rotation/>
+ <sizescale scalemethod="area"/>
+ </renderer-v2>
+ <customproperties>
+ <property key="labeling" value="pal"/>
+ <property key="labeling/addDirectionSymbol" value="false"/>
+ <property key="labeling/angleOffset" value="0"/>
+ <property key="labeling/blendMode" value="0"/>
+ <property key="labeling/bufferBlendMode" value="0"/>
+ <property key="labeling/bufferColorA" value="255"/>
+ <property key="labeling/bufferColorB" value="255"/>
+ <property key="labeling/bufferColorG" value="255"/>
+ <property key="labeling/bufferColorR" value="255"/>
+ <property key="labeling/bufferDraw" value="false"/>
+ <property key="labeling/bufferJoinStyle" value="64"/>
+ <property key="labeling/bufferNoFill" value="false"/>
+ <property key="labeling/bufferSize" value="1"/>
+ <property key="labeling/bufferSizeInMapUnits" value="false"/>
+ <property key="labeling/bufferTransp" value="0"/>
+ <property key="labeling/centroidWhole" value="false"/>
+ <property key="labeling/decimals" value="3"/>
+ <property key="labeling/displayAll" value="false"/>
+ <property key="labeling/dist" value="0"/>
+ <property key="labeling/distInMapUnits" value="false"/>
+ <property key="labeling/enabled" value="false"/>
+ <property key="labeling/fieldName" value=""/>
+ <property key="labeling/fontBold" value="false"/>
+ <property key="labeling/fontCapitals" value="0"/>
+ <property key="labeling/fontFamily" value="Sans"/>
+ <property key="labeling/fontItalic" value="false"/>
+ <property key="labeling/fontLetterSpacing" value="0"/>
+ <property key="labeling/fontLimitPixelSize" value="false"/>
+ <property key="labeling/fontMaxPixelSize" value="10000"/>
+ <property key="labeling/fontMinPixelSize" value="3"/>
+ <property key="labeling/fontSize" value="10"/>
+ <property key="labeling/fontSizeInMapUnits" value="false"/>
+ <property key="labeling/fontStrikeout" value="false"/>
+ <property key="labeling/fontUnderline" value="false"/>
+ <property key="labeling/fontWeight" value="50"/>
+ <property key="labeling/fontWordSpacing" value="0"/>
+ <property key="labeling/formatNumbers" value="false"/>
+ <property key="labeling/isExpression" value="false"/>
+ <property key="labeling/labelOffsetInMapUnits" value="true"/>
+ <property key="labeling/labelPerPart" value="false"/>
+ <property key="labeling/leftDirectionSymbol" value="&lt;"/>
+ <property key="labeling/limitNumLabels" value="false"/>
+ <property key="labeling/maxCurvedCharAngleIn" value="20"/>
+ <property key="labeling/maxCurvedCharAngleOut" value="-20"/>
+ <property key="labeling/maxNumLabels" value="2000"/>
+ <property key="labeling/mergeLines" value="false"/>
+ <property key="labeling/minFeatureSize" value="0"/>
+ <property key="labeling/multilineAlign" value="0"/>
+ <property key="labeling/multilineHeight" value="1"/>
+ <property key="labeling/namedStyle" value=""/>
+ <property key="labeling/obstacle" value="true"/>
+ <property key="labeling/placeDirectionSymbol" value="0"/>
+ <property key="labeling/placement" value="0"/>
+ <property key="labeling/placementFlags" value="0"/>
+ <property key="labeling/plussign" value="false"/>
+ <property key="labeling/preserveRotation" value="true"/>
+ <property key="labeling/previewBkgrdColor" value="#ffffff"/>
+ <property key="labeling/priority" value="5"/>
+ <property key="labeling/quadOffset" value="4"/>
+ <property key="labeling/reverseDirectionSymbol" value="false"/>
+ <property key="labeling/rightDirectionSymbol" value=">"/>
+ <property key="labeling/scaleMax" value="10000000"/>
+ <property key="labeling/scaleMin" value="1"/>
+ <property key="labeling/scaleVisibility" value="false"/>
+ <property key="labeling/shadowBlendMode" value="6"/>
+ <property key="labeling/shadowColorB" value="0"/>
+ <property key="labeling/shadowColorG" value="0"/>
+ <property key="labeling/shadowColorR" value="0"/>
+ <property key="labeling/shadowDraw" value="false"/>
+ <property key="labeling/shadowOffsetAngle" value="135"/>
+ <property key="labeling/shadowOffsetDist" value="1"/>
+ <property key="labeling/shadowOffsetGlobal" value="true"/>
+ <property key="labeling/shadowOffsetUnits" value="1"/>
+ <property key="labeling/shadowRadius" value="1.5"/>
+ <property key="labeling/shadowRadiusAlphaOnly" value="false"/>
+ <property key="labeling/shadowRadiusUnits" value="1"/>
+ <property key="labeling/shadowScale" value="100"/>
+ <property key="labeling/shadowTransparency" value="30"/>
+ <property key="labeling/shadowUnder" value="0"/>
+ <property key="labeling/shapeBlendMode" value="0"/>
+ <property key="labeling/shapeBorderColorA" value="255"/>
+ <property key="labeling/shapeBorderColorB" value="128"/>
+ <property key="labeling/shapeBorderColorG" value="128"/>
+ <property key="labeling/shapeBorderColorR" value="128"/>
+ <property key="labeling/shapeBorderWidth" value="0"/>
+ <property key="labeling/shapeBorderWidthUnits" value="1"/>
+ <property key="labeling/shapeDraw" value="false"/>
+ <property key="labeling/shapeFillColorA" value="255"/>
+ <property key="labeling/shapeFillColorB" value="255"/>
+ <property key="labeling/shapeFillColorG" value="255"/>
+ <property key="labeling/shapeFillColorR" value="255"/>
+ <property key="labeling/shapeJoinStyle" value="64"/>
+ <property key="labeling/shapeOffsetUnits" value="1"/>
+ <property key="labeling/shapeOffsetX" value="0"/>
+ <property key="labeling/shapeOffsetY" value="0"/>
+ <property key="labeling/shapeRadiiUnits" value="1"/>
+ <property key="labeling/shapeRadiiX" value="0"/>
+ <property key="labeling/shapeRadiiY" value="0"/>
+ <property key="labeling/shapeRotation" value="0"/>
+ <property key="labeling/shapeRotationType" value="0"/>
+ <property key="labeling/shapeSVGFile" value=""/>
+ <property key="labeling/shapeSizeType" value="0"/>
+ <property key="labeling/shapeSizeUnits" value="1"/>
+ <property key="labeling/shapeSizeX" value="0"/>
+ <property key="labeling/shapeSizeY" value="0"/>
+ <property key="labeling/shapeTransparency" value="0"/>
+ <property key="labeling/shapeType" value="0"/>
+ <property key="labeling/textColorA" value="255"/>
+ <property key="labeling/textColorB" value="0"/>
+ <property key="labeling/textColorG" value="0"/>
+ <property key="labeling/textColorR" value="0"/>
+ <property key="labeling/textTransp" value="0"/>
+ <property key="labeling/upsidedownLabels" value="0"/>
+ <property key="labeling/wrapChar" value=""/>
+ <property key="labeling/xOffset" value="0"/>
+ <property key="labeling/yOffset" value="0"/>
+ </customproperties>
+ <blendMode>0</blendMode>
+ <featureBlendMode>0</featureBlendMode>
+ <layerTransparency>0</layerTransparency>
+ <displayfield>OGC_FID</displayfield>
+ <label>0</label>
+ <labelattributes>
+ <label fieldname="" text="Label"/>
+ <family fieldname="" name="Sans"/>
+ <size fieldname="" units="pt" value="12"/>
+ <bold fieldname="" on="0"/>
+ <italic fieldname="" on="0"/>
+ <underline fieldname="" on="0"/>
+ <strikeout fieldname="" on="0"/>
+ <color fieldname="" red="0" blue="0" green="0"/>
+ <x fieldname=""/>
+ <y fieldname=""/>
+ <offset x="0" y="0" units="pt" yfieldname="" xfieldname=""/>
+ <angle fieldname="" value="0" auto="0"/>
+ <alignment fieldname="" value="center"/>
+ <buffercolor fieldname="" red="255" blue="255" green="255"/>
+ <buffersize fieldname="" units="pt" value="1"/>
+ <bufferenabled fieldname="" on=""/>
+ <multilineenabled fieldname="" on=""/>
+ <selectedonly on=""/>
+ </labelattributes>
+ <edittypes>
+ <edittype labelontop="0" editable="1" type="0" name="OGC_FID"/>
+ <edittype labelontop="0" editable="1" type="0" name="id"/>
+ <edittype labelontop="0" editable="1" type="0" name="node_id"/>
+ <edittype labelontop="0" editable="1" type="0" name="object_id"/>
+ <edittype labelontop="0" editable="1" type="0" name="problem_type"/>
+ <edittype labelontop="0" editable="1" type="0" name="type"/>
+ </edittypes>
+ <editform>.</editform>
+ <editforminit></editforminit>
+ <featformsuppress>0</featformsuppress>
+ <annotationform>.</annotationform>
+ <editorlayout>generatedlayout</editorlayout>
+ <excludeAttributesWMS/>
+ <excludeAttributesWFS/>
+ <attributeactions/>
+ </maplayer>
+ </projectlayers>
+ <properties>
+ <WMSContactPerson type="QString"></WMSContactPerson>
+ <WMSOnlineResource type="QString"></WMSOnlineResource>
+ <WMSContactOrganization type="QString"></WMSContactOrganization>
+ <WMSExtent type="QStringList">
+ <value>0.82500024999999999</value>
+ <value>-0.35415386986094277</value>
+ <value>8.17498974999999994</value>
+ <value>3.45415386986094308</value>
+ </WMSExtent>
+ <WMSKeywordList type="QStringList">
+ <value></value>
+ </WMSKeywordList>
+ <WFSUrl type="QString"></WFSUrl>
+ <Paths>
+ <Absolute type="bool">false</Absolute>
+ </Paths>
+ <WMSServiceTitle type="QString">mp test</WMSServiceTitle>
+ <WFSLayers type="QStringList"/>
+ <WMSContactMail type="QString"></WMSContactMail>
+ <PositionPrecision>
+ <DecimalPlaces type="int">2</DecimalPlaces>
+ <Automatic type="bool">true</Automatic>
+ <DegreeFormat type="QString">D</DegreeFormat>
+ </PositionPrecision>
+ <WCSUrl type="QString"></WCSUrl>
+ <WMSContactPhone type="QString"></WMSContactPhone>
+ <WMSServiceCapabilities type="bool">true</WMSServiceCapabilities>
+ <WMSServiceAbstract type="QString"></WMSServiceAbstract>
+ <WMSAddWktGeometry type="bool">false</WMSAddWktGeometry>
+ <Measure>
+ <Ellipsoid type="QString">NONE</Ellipsoid>
+ </Measure>
+ <WFSTLayers>
+ <Insert type="QStringList"/>
+ <Update type="QStringList"/>
+ <Delete type="QStringList"/>
+ </WFSTLayers>
+ <Gui>
+ <SelectionColorBluePart type="int">0</SelectionColorBluePart>
+ <CanvasColorGreenPart type="int">255</CanvasColorGreenPart>
+ <CanvasColorRedPart type="int">255</CanvasColorRedPart>
+ <SelectionColorRedPart type="int">255</SelectionColorRedPart>
+ <SelectionColorAlphaPart type="int">255</SelectionColorAlphaPart>
+ <SelectionColorGreenPart type="int">255</SelectionColorGreenPart>
+ <CanvasColorBluePart type="int">255</CanvasColorBluePart>
+ </Gui>
+ <Identify>
+ <disabledLayers type="QStringList"/>
+ </Identify>
+ <Macros>
+ <pythonCode type="QString"></pythonCode>
+ </Macros>
+ <WMSAccessConstraints type="QString"></WMSAccessConstraints>
+ <WCSLayers type="QStringList"/>
+ <SpatialRefSys>
+ <ProjectCrs type="QString">EPSG:4326</ProjectCrs>
+ </SpatialRefSys>
+ <DefaultStyles>
+ <Fill type="QString"></Fill>
+ <Line type="QString"></Line>
+ <Marker type="QString"></Marker>
+ <RandomColors type="bool">true</RandomColors>
+ <AlphaInt type="int">255</AlphaInt>
+ <ColorRamp type="QString"></ColorRamp>
+ </DefaultStyles>
+ <WMSFees type="QString"></WMSFees>
+ <WMSUrl type="QString"></WMSUrl>
+ </properties>
+</qgis>
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/run-testdata-multipolygon.cmake b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/run-testdata-multipolygon.cmake
new file mode 100755
index 0000000000..0d08f5a525
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testcases/test-100.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testcases/test-100.cpp
new file mode 100755
index 0000000000..feafe771ae
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/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/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testcases/test-101.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testcases/test-101.cpp
new file mode 100755
index 0000000000..de2a5fdb76
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/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/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testcases/test-110.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testcases/test-110.cpp
new file mode 100755
index 0000000000..16b039b1b1
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/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/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testdata-multipolygon.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testdata-multipolygon.cpp
new file mode 100755
index 0000000000..0fd0d9849a
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testdata-multipolygon.cpp
@@ -0,0 +1,291 @@
+
+#include <iostream>
+#include <fstream>
+#include <map>
+
+#include <osmium/index/map/sparse_mem_array.hpp>
+
+#include <osmium/area/assembler.hpp>
+#include <osmium/area/multipolygon_collector.hpp>
+#include <osmium/area/problem_reporter_ogr.hpp>
+#include <osmium/geom/ogr.hpp>
+#include <osmium/geom/wkt.hpp>
+#include <osmium/handler.hpp>
+#include <osmium/handler/node_locations_for_ways.hpp>
+#include <osmium/io/xml_input.hpp>
+#include <osmium/visitor.hpp>
+
+typedef osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location> index_type;
+
+typedef osmium::handler::NodeLocationsForWays<index_type> 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<const char*, const char*, less_charptr> 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<OGRPoint> ogr_point = m_ogr_factory.create_point(node);
+ feature->SetGeometry(ogr_point.get());
+ feature->SetField("id", static_cast<double>(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<OGRLineString> 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<double>(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<OGRMultiPolygon> 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<int>(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<char**>(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<osmium::area::Assembler> 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;
+ location_handler_type location_handler(index);
+ 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/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testdata-overview.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testdata-overview.cpp
new file mode 100755
index 0000000000..2d63dc6845
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testdata-overview.cpp
@@ -0,0 +1,197 @@
+/* The code in this file is released into the Public Domain. */
+
+#include <iostream>
+
+#include <osmium/index/map/sparse_mem_array.hpp>
+
+#include <osmium/geom/ogr.hpp>
+#include <osmium/handler.hpp>
+#include <osmium/handler/node_locations_for_ways.hpp>
+#include <osmium/io/xml_input.hpp>
+#include <osmium/visitor.hpp>
+
+typedef osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location> index_type;
+typedef osmium::handler::NodeLocationsForWays<index_type> 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<char**>(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<OGRPoint> ogr_point = m_factory.create_point(node);
+ feature->SetGeometry(ogr_point.get());
+ feature->SetField("id", static_cast<double>(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<OGRPoint> ogr_point = m_factory.create_point(node);
+ feature->SetGeometry(ogr_point.get());
+ feature->SetField("id", static_cast<double>(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<OGRLineString> 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<double>(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_type index;
+ location_handler_type location_handler(index);
+ location_handler.ignore_errors();
+
+ TestOverviewHandler handler(output_format, output_filename);
+
+ osmium::apply(reader, location_handler, handler);
+ reader.close();
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testdata-testcases.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testdata-testcases.cpp
new file mode 100755
index 0000000000..6ed6ae91a2
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testdata-testcases.cpp
@@ -0,0 +1,27 @@
+
+#include <iostream>
+#include <string>
+
+#define CATCH_CONFIG_RUNNER
+
+#include "testdata-testcases.hpp"
+
+#include <osmpbf/osmpbf.h>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testdata-xml.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testdata-xml.cpp
new file mode 100755
index 0000000000..5af4c4f27f
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/data-tests/testdata-xml.cpp
@@ -0,0 +1,462 @@
+/* The code in this file is released into the Public Domain. */
+
+#define CATCH_CONFIG_MAIN
+#include "catch.hpp"
+
+#include <cassert>
+#include <cstdlib>
+#include <iostream>
+#include <string>
+
+#include <osmium/io/xml_input.hpp>
+#include <osmium/io/gzip_compression.hpp>
+#include <osmium/visitor.hpp>
+
+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');
+ auto n = ::read(fd, reinterpret_cast<unsigned char*>(const_cast<char*>(input.data())), 10000);
+ assert(n >= 0);
+ input.resize(static_cast<std::string::size_type>(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<std::string> input_queue;
+ osmium::thread::Queue<osmium::memory::Buffer> output_queue;
+ std::promise<osmium::io::Header> header_promise;
+ std::atomic<bool> 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);
+ }
+
+ 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);
+ }
+
+}
+
+// =============================================
+
+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<osmium::Node>(); it != buffer.end<osmium::Node>(); ++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<osmium::memory::Item>(0).type() == osmium::item_type::node);
+
+ const osmium::Node& node = buffer.get<osmium::Node>(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") {
+
+ 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<osmium::memory::Item>(0).type() == osmium::item_type::node);
+ REQUIRE(r.buffer.get<osmium::Node>(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<osmium::memory::Item>(0).type() == osmium::item_type::node);
+ REQUIRE(buffer.get<osmium::Node>(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<osmium::memory::Item>(0).type() == osmium::item_type::node);
+ REQUIRE(buffer.get<osmium::Node>(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/3party/osrm/osrm-backend/third_party/libosmium/test/include/catch.hpp b/3party/osrm/osrm-backend/third_party/libosmium/test/include/catch.hpp
new file mode 100755
index 0000000000..bb87af296d
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/include/catch.hpp
@@ -0,0 +1,9003 @@
+
+// This is needed for Windows
+#define CATCH_CONFIG_CPP11_NULLPTR
+
+/*
+ * 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.
+ *
+ * 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"
+#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
+# 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 <sstream>
+#include <stdexcept>
+#include <algorithm>
+
+// #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<typename ContainerT>
+ 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<typename AssociativeContainerT>
+ 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<typename T>
+ T const& operator + ( T const& value, StreamEndStop ) {
+ return value;
+ }
+}
+
+#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
+#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
+
+#include <ostream>
+
+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 <string>
+
+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<typename T>
+ 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<typename T = IShared>
+ 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 <memory>
+#include <vector>
+#include <stdlib.h>
+
+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<IConfig const> getConfig() const = 0;
+ };
+
+ struct IMutableContext : IContext
+ {
+ virtual ~IMutableContext();
+ virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
+ virtual void setRunner( IRunner* runner ) = 0;
+ virtual void setConfig( Ptr<IConfig const> 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 <vector>
+
+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<TestCase> const& getAllTests() const = 0;
+ virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const = 0;
+
+ };
+}
+
+namespace Catch {
+
+template<typename C>
+class MethodTestCase : public SharedImpl<ITestCase> {
+
+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<typename C>
+ AutoReg( void (C::*method)(),
+ char const* className,
+ NameAndDesc const& nameAndDesc,
+ SourceLineInfo const& lineInfo ) {
+ registerTestCase( new MethodTestCase<C>( 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<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( 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 <string>
+
+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<typename T> 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<typename T>
+ ExpressionLhs<T const&> operator->* ( T const& operand );
+ ExpressionLhs<bool> operator->* ( bool value );
+
+ template<typename T>
+ ResultBuilder& operator << ( T const& value ) {
+ m_stream.oss << value;
+ return *this;
+ }
+
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
+ template<typename RhsT> 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 <cstddef>
+
+namespace Catch {
+namespace Internal {
+
+ enum Operator {
+ IsEqualTo,
+ IsNotEqualTo,
+ IsLessThan,
+ IsGreaterThan,
+ IsLessThanOrEqualTo,
+ IsGreaterThanOrEqualTo
+ };
+
+ template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
+ template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
+ template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
+ template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
+ template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
+ template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
+ template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
+
+ template<typename T>
+ inline T& opCast(T const& t) { return const_cast<T&>(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<typename T1, typename T2, Operator Op>
+ class Evaluator{};
+
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsEqualTo> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs) {
+ return opCast( lhs ) == opCast( rhs );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsNotEqualTo> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) != opCast( rhs );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsLessThan> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) < opCast( rhs );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsGreaterThan> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) > opCast( rhs );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) >= opCast( rhs );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) <= opCast( rhs );
+ }
+ };
+
+ template<Operator Op, typename T1, typename T2>
+ bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
+ return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
+ }
+
+ // This level of indirection allows us to specialise for integer types
+ // to avoid signed/ unsigned warnings
+
+ // "base" overload
+ template<Operator Op, typename T1, typename T2>
+ bool compare( T1 const& lhs, T2 const& rhs ) {
+ return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
+ }
+
+ // unsigned X to int
+ template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+ }
+ template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+ }
+ template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+ }
+
+ // unsigned X to long
+ template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+ }
+ template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+ }
+ template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+ }
+
+ // int to unsigned X
+ template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+ }
+
+ // long to unsigned X
+ template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+
+ // pointer to long (when comparing against NULL)
+ template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
+ }
+ template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
+ }
+
+ // pointer to int (when comparing against NULL)
+ template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
+ }
+ template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
+ }
+
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+ // pointer to nullptr_t (when comparing against nullptr)
+ template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( NULL, rhs );
+ }
+ template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
+ return Evaluator<T*, T*, Op>::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<bool> struct NotABooleanExpression;
+
+ template<bool c> struct If : NotABooleanExpression<c> {};
+ template<> struct If<true> : TrueType {};
+ template<> struct If<false> : FalseType {};
+
+ template<int size> struct SizedIf;
+ template<> struct SizedIf<sizeof(TrueType)> : TrueType {};
+ template<> struct SizedIf<sizeof(FalseType)> : FalseType {};
+
+#endif // CATCH_CONFIG_SFINAE
+
+} // end namespace Catch
+
+#include <sstream>
+#include <iomanip>
+#include <limits>
+#include <vector>
+#include <cstddef>
+
+#ifdef __OBJC__
+// #included from: catch_objc_arc.hpp
+#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
+
+#import <Foundation/Foundation.h>
+
+#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<typename T>
+ class IsStreamInsertableHelper {
+ template<int N> struct TrueIfSizeable : TrueType {};
+
+ template<typename T2>
+ static TrueIfSizeable<sizeof((*(std::ostream*)0) << *((T2 const*)0))> dummy(T2*);
+ static FalseType dummy(...);
+
+ public:
+ typedef SizedIf<sizeof(dummy((T*)0))> type;
+ };
+
+ template<typename T>
+ struct IsStreamInsertable : IsStreamInsertableHelper<T>::type {};
+
+#else
+
+ struct BorgType {
+ template<typename T> BorgType( T const& );
+ };
+
+ TrueType& testStreamable( std::ostream& );
+ FalseType testStreamable( FalseType );
+
+ FalseType operator<<( std::ostream const&, BorgType const& );
+
+ template<typename T>
+ struct IsStreamInsertable {
+ static std::ostream &s;
+ static T const&t;
+ enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
+ };
+
+#endif
+
+ template<bool C>
+ struct StringMakerBase {
+ template<typename T>
+ static std::string convert( T const& ) { return "{?}"; }
+ };
+
+ template<>
+ struct StringMakerBase<true> {
+ template<typename T>
+ 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<typename T>
+ inline std::string rawMemoryToString( const T& object ) {
+ return rawMemoryToString( &object, sizeof(object) );
+ }
+
+} // end namespace Detail
+
+template<typename T>
+std::string toString( T const& value );
+
+template<typename T>
+struct StringMaker :
+ Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
+
+template<typename T>
+struct StringMaker<T*> {
+ template<typename U>
+ static std::string convert( U* p ) {
+ if( !p )
+ return INTERNAL_CATCH_STRINGIFY( NULL );
+ else
+ return Detail::rawMemoryToString( p );
+ }
+};
+
+template<typename R, typename C>
+struct StringMaker<R C::*> {
+ static std::string convert( R C::* p ) {
+ if( !p )
+ return INTERNAL_CATCH_STRINGIFY( NULL );
+ else
+ return Detail::rawMemoryToString( p );
+ }
+};
+
+namespace Detail {
+ template<typename InputIterator>
+ std::string rangeToString( InputIterator first, InputIterator last );
+}
+
+template<typename T, typename Allocator>
+struct StringMaker<std::vector<T, Allocator> > {
+ static std::string convert( std::vector<T,Allocator> const& v ) {
+ return Detail::rangeToString( v.begin(), v.end() );
+ }
+};
+
+namespace Detail {
+ template<typename T>
+ std::string makeString( T const& value ) {
+ return StringMaker<T>::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<typename T>
+std::string toString( T const& value ) {
+ return StringMaker<T>::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( 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 );
+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<typename InputIterator>
+ 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<typename T>
+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<typename RhsT>
+ ResultBuilder& operator == ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsEqualTo>( rhs );
+ }
+
+ template<typename RhsT>
+ ResultBuilder& operator != ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsNotEqualTo>( rhs );
+ }
+
+ template<typename RhsT>
+ ResultBuilder& operator < ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsLessThan>( rhs );
+ }
+
+ template<typename RhsT>
+ ResultBuilder& operator > ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsGreaterThan>( rhs );
+ }
+
+ template<typename RhsT>
+ ResultBuilder& operator <= ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
+ }
+
+ template<typename RhsT>
+ ResultBuilder& operator >= ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
+ }
+
+ ResultBuilder& operator == ( bool rhs ) {
+ return captureExpression<Internal::IsEqualTo>( rhs );
+ }
+
+ ResultBuilder& operator != ( bool rhs ) {
+ return captureExpression<Internal::IsNotEqualTo>( 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<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& );
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& );
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& );
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& );
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
+
+private:
+ template<Internal::Operator Op, typename RhsT>
+ ResultBuilder& captureExpression( RhsT const& rhs ) {
+ return m_rb
+ .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
+ .setLhs( Catch::toString( m_lhs ) )
+ .setRhs( Catch::toString( rhs ) )
+ .setOp( Internal::OperatorTraits<Op>::getName() );
+ }
+
+private:
+ ResultBuilder& m_rb;
+ T m_lhs;
+};
+
+} // end namespace Catch
+
+
+namespace Catch {
+
+ template<typename T>
+ inline ExpressionLhs<T const&> ResultBuilder::operator->* ( T const& operand ) {
+ return ExpressionLhs<T const&>( *this, operand );
+ }
+
+ inline ExpressionLhs<bool> ResultBuilder::operator->* ( bool value ) {
+ return ExpressionLhs<bool>( *this, value );
+ }
+
+} // namespace Catch
+
+// #included from: catch_message.h
+#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
+
+#include <string>
+
+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<typename T>
+ 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 <string>
+
+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 <string>
+
+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 <cstddef>
+
+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 <stdint.h>
+#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 <string>
+
+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 <iterator>
+#include <vector>
+#include <string>
+#include <stdlib.h>
+
+namespace Catch {
+
+template<typename T>
+struct IGenerator {
+ virtual ~IGenerator() {}
+ virtual T getValue( std::size_t index ) const = 0;
+ virtual std::size_t size () const = 0;
+};
+
+template<typename T>
+class BetweenGenerator : public IGenerator<T> {
+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<int>( index );
+ }
+
+ virtual std::size_t size() const {
+ return static_cast<std::size_t>( 1+m_to-m_from );
+ }
+
+private:
+
+ T m_from;
+ T m_to;
+};
+
+template<typename T>
+class ValuesGenerator : public IGenerator<T> {
+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<T> m_values;
+};
+
+template<typename T>
+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 IGenerator<T>*>::const_iterator it = m_composed.begin();
+ typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
+ for( size_t index = 0; it != itEnd; ++it )
+ {
+ const IGenerator<T>* 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<T>* generator ) {
+ m_totalSize += generator->size();
+ m_composed.push_back( generator );
+ }
+
+ CompositeGenerator& then( CompositeGenerator& other ) {
+ move( other );
+ return *this;
+ }
+
+ CompositeGenerator& then( T value ) {
+ ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+ 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<const IGenerator<T>*> m_composed;
+ std::string m_fileInfo;
+ size_t m_totalSize;
+};
+
+namespace Generators
+{
+ template<typename T>
+ CompositeGenerator<T> between( T from, T to ) {
+ CompositeGenerator<T> generators;
+ generators.add( new BetweenGenerator<T>( from, to ) );
+ return generators;
+ }
+
+ template<typename T>
+ CompositeGenerator<T> values( T val1, T val2 ) {
+ CompositeGenerator<T> generators;
+ ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+ valuesGen->add( val1 );
+ valuesGen->add( val2 );
+ generators.add( valuesGen );
+ return generators;
+ }
+
+ template<typename T>
+ CompositeGenerator<T> values( T val1, T val2, T val3 ){
+ CompositeGenerator<T> generators;
+ ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+ valuesGen->add( val1 );
+ valuesGen->add( val2 );
+ valuesGen->add( val3 );
+ generators.add( valuesGen );
+ return generators;
+ }
+
+ template<typename T>
+ CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
+ CompositeGenerator<T> generators;
+ ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+ 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 <string>
+// #included from: catch_interfaces_registry_hub.h
+#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
+
+#include <string>
+
+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<typename T>
+ 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<typename T>
+ ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
+ getMutableRegistryHub().registerTranslator
+ ( new ExceptionTranslator<T>( 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 <cmath>
+#include <limits>
+
+namespace Catch {
+namespace Detail {
+
+ class Approx {
+ public:
+ explicit Approx ( double value )
+ : m_epsilon( std::numeric_limits<float>::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>( 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<typename ExpressionT>
+ struct Matcher : SharedImpl<IShared>
+ {
+ typedef ExpressionT ExpressionType;
+
+ virtual ~Matcher() {}
+ virtual Ptr<Matcher> clone() const = 0;
+ virtual bool match( ExpressionT const& expr ) const = 0;
+ virtual std::string toString() const = 0;
+ };
+
+ template<typename DerivedT, typename ExpressionT>
+ struct MatcherImpl : Matcher<ExpressionT> {
+
+ virtual Ptr<Matcher<ExpressionT> > clone() const {
+ return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
+ }
+ };
+
+ namespace Generic {
+
+ template<typename ExpressionT>
+ class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
+ public:
+
+ AllOf() {}
+ AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
+
+ AllOf& add( Matcher<ExpressionT> 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<Ptr<Matcher<ExpressionT> > > m_matchers;
+ };
+
+ template<typename ExpressionT>
+ class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
+ public:
+
+ AnyOf() {}
+ AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
+
+ AnyOf& add( Matcher<ExpressionT> 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<Ptr<Matcher<ExpressionT> > > 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> {
+ 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> {
+ 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> {
+ 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> {
+ 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<typename ExpressionT>
+ inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
+ Impl::Matcher<ExpressionT> const& m2 ) {
+ return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
+ }
+ template<typename ExpressionT>
+ inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
+ Impl::Matcher<ExpressionT> const& m2,
+ Impl::Matcher<ExpressionT> const& m3 ) {
+ return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
+ }
+ template<typename ExpressionT>
+ inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
+ Impl::Matcher<ExpressionT> const& m2 ) {
+ return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
+ }
+ template<typename ExpressionT>
+ inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
+ Impl::Matcher<ExpressionT> const& m2,
+ Impl::Matcher<ExpressionT> const& m3 ) {
+ return Impl::Generic::AnyOf<ExpressionT>().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 <string>
+
+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<typename T>
+ 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<TagAlias> 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 <string>
+#include <set>
+
+#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<std::string> 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<std::string> tags;
+ std::set<std::string> 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<ITestCase> 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 <objc/runtime.h>
+
+#include <string>
+
+// 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<ITestCase> {
+
+ 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<typename MatcherT>
+ struct StringHolder : MatcherImpl<MatcherT, NSString*>{
+ 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> {
+ 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> {
+ 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> {
+ 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> {
+ 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 <string>
+#include <vector>
+
+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<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.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
+ }
+ private:
+ std::string m_tag;
+ };
+ class ExcludedPattern : public Pattern {
+ public:
+ ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
+ virtual ~ExcludedPattern();
+ virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
+ private:
+ Ptr<Pattern> m_underlyingPattern;
+ };
+
+ struct Filter {
+ std::vector<Ptr<Pattern> > 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<Ptr<Pattern> >::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<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
+ if( it->matches( testCase ) )
+ return true;
+ return false;
+ }
+
+ private:
+ std::vector<Filter> 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<TestSpec::NamePattern>();
+ 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<TestSpec::NamePattern>();
+ addFilter();
+ }
+ else if( c == '[' ) {
+ if( subString() == "exclude:" )
+ m_exclusion = true;
+ else
+ addPattern<TestSpec::NamePattern>();
+ startNewMode( Tag, ++m_pos );
+ }
+ }
+ else if( m_mode == QuotedName && c == '"' )
+ addPattern<TestSpec::NamePattern>();
+ else if( m_mode == Tag && c == ']' )
+ addPattern<TestSpec::TagPattern>();
+ }
+ 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<typename T>
+ void addPattern() {
+ std::string token = subString();
+ if( startsWith( token, "exclude:" ) ) {
+ m_exclusion = true;
+ token = token.substr( 8 );
+ }
+ if( !token.empty() ) {
+ Ptr<TestSpec::Pattern> 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 <iostream>
+#include <string>
+#include <vector>
+
+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 <streambuf>
+
+#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 <memory>
+#include <vector>
+#include <string>
+#include <iostream>
+
+#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<std::string> testsOrTags;
+ };
+
+ class Config : public SharedImpl<IConfig> {
+ 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 <string>
+#include <vector>
+#include <sstream>
+
+// 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<std::string>::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<std::string> 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 <map>
+#include <algorithm>
+#include <stdexcept>
+#include <memory>
+
+// 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<typename T> struct RemoveConstRef{ typedef T type; };
+ template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
+ template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
+ template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
+
+ template<typename T> struct IsBool { static const bool value = false; };
+ template<> struct IsBool<bool> { static const bool value = true; };
+
+ template<typename T>
+ 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<typename T>
+ inline void convertInto( bool, T& ) {
+ throw std::runtime_error( "Invalid conversion" );
+ }
+
+ template<typename ConfigT>
+ 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<typename ConfigT>
+ class BoundArgFunction {
+ public:
+ BoundArgFunction() : functionObj( NULL ) {}
+ BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
+ BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {}
+ BoundArgFunction& operator = ( BoundArgFunction const& other ) {
+ IArgFunction<ConfigT>* 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<ConfigT>* functionObj;
+ };
+
+ template<typename C>
+ struct NullBinder : IArgFunction<C>{
+ virtual void set( C&, std::string const& ) const {}
+ virtual void setFlag( C& ) const {}
+ virtual bool takesArg() const { return true; }
+ virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
+ };
+
+ template<typename C, typename M>
+ struct BoundDataMember : IArgFunction<C>{
+ 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<M>::value; }
+ virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
+ M C::* member;
+ };
+ template<typename C, typename M>
+ struct BoundUnaryMethod : IArgFunction<C>{
+ BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
+ virtual void set( C& p, std::string const& stringValue ) const {
+ typename RemoveConstRef<M>::type value;
+ convertInto( stringValue, value );
+ (p.*member)( value );
+ }
+ virtual void setFlag( C& p ) const {
+ typename RemoveConstRef<M>::type value;
+ convertInto( true, value );
+ (p.*member)( value );
+ }
+ virtual bool takesArg() const { return !IsBool<M>::value; }
+ virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
+ void (C::*member)( M );
+ };
+ template<typename C>
+ struct BoundNullaryMethod : IArgFunction<C>{
+ 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<C>* clone() const { return new BoundNullaryMethod( *this ); }
+ void (C::*member)();
+ };
+
+ template<typename C>
+ struct BoundUnaryFunction : IArgFunction<C>{
+ 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<C>* clone() const { return new BoundUnaryFunction( *this ); }
+ void (*function)( C& );
+ };
+
+ template<typename C, typename T>
+ struct BoundBinaryFunction : IArgFunction<C>{
+ BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
+ virtual void set( C& obj, std::string const& stringValue ) const {
+ typename RemoveConstRef<T>::type value;
+ convertInto( stringValue, value );
+ function( obj, value );
+ }
+ virtual void setFlag( C& obj ) const {
+ typename RemoveConstRef<T>::type value;
+ convertInto( true, value );
+ function( obj, value );
+ }
+ virtual bool takesArg() const { return !IsBool<T>::value; }
+ virtual IArgFunction<C>* 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<Parser::Token>& 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<Parser::Token>& 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<typename ConfigT>
+ struct CommonArgProperties {
+ CommonArgProperties() {}
+ CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
+
+ Detail::BoundArgFunction<ConfigT> 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<std::string> 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<typename ConfigT>
+ class CommandLine {
+
+ struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
+ Arg() {}
+ Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
+
+ using CommonArgProperties<ConfigT>::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<std::string>::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<Arg> ArgAutoPtr;
+#else
+ typedef std::auto_ptr<Arg> 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<typename C, typename M>
+ void bind( M C::* field, std::string const& placeholder ) {
+ m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
+ m_arg->placeholder = placeholder;
+ }
+ // Bind a boolean data member (no placeholder required)
+ template<typename C>
+ void bind( bool C::* field ) {
+ m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
+ }
+
+ // Bind a method taking a single, non-boolean argument (requires a placeholder string)
+ template<typename C, typename M>
+ void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
+ m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
+ m_arg->placeholder = placeholder;
+ }
+
+ // Bind a method taking a single, boolean argument (no placeholder string required)
+ template<typename C>
+ void bind( void (C::* unaryMethod)( bool ) ) {
+ m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
+ }
+
+ // Bind a method that takes no arguments (will be called if opt is present)
+ template<typename C>
+ void bind( void (C::* nullaryMethod)() ) {
+ m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
+ }
+
+ // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
+ template<typename C>
+ void bind( void (* unaryFunction)( C& ) ) {
+ m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
+ }
+
+ // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
+ template<typename C, typename T>
+ void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
+ m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( 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<ConfigT>() ),
+ 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<typename C, typename M>
+ void bindProcessName( M C::* field ) {
+ m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
+ }
+ template<typename C, typename M>
+ void bindProcessName( void (C::*_unaryMethod)( M ) ) {
+ m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
+ }
+
+ void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
+ typename std::vector<Arg>::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<int, Arg>::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<Parser::Token> 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<Parser::Token> tokens;
+ Parser parser;
+ parser.parseIntoTokens( argc, argv, tokens );
+ return populate( tokens, config );
+ }
+
+ std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+ validate();
+ std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
+ unusedTokens = populateFixedArgs( unusedTokens, config );
+ unusedTokens = populateFloatingArgs( unusedTokens, config );
+ return unusedTokens;
+ }
+
+ std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+ std::vector<Parser::Token> unusedTokens;
+ std::vector<std::string> errors;
+ for( std::size_t i = 0; i < tokens.size(); ++i ) {
+ Parser::Token const& token = tokens[i];
+ typename std::vector<Arg>::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<std::string>::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<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+ std::vector<Parser::Token> unusedTokens;
+ int position = 1;
+ for( std::size_t i = 0; i < tokens.size(); ++i ) {
+ Parser::Token const& token = tokens[i];
+ typename std::map<int, Arg>::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<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+ if( !m_floatingArg.get() )
+ return tokens;
+ std::vector<Parser::Token> 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<Arg>::const_iterator it = m_options.begin(),
+ itEnd = m_options.end();
+ it != itEnd; ++it )
+ it->validate();
+ }
+
+ private:
+ Detail::BoundArgFunction<ConfigT> m_boundProcessName;
+ std::vector<Arg> m_options;
+ std::map<int, Arg> 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 <fstream>
+
+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<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 = static_cast<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<ConfigData> makeCommandLineParser() {
+
+ using namespace Clara;
+ CommandLine<ConfigData> 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 <string>
+#include <vector>
+#include <sstream>
+
+// 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<std::string>::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<std::string> 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 <string>
+#include <ostream>
+#include <map>
+#include <assert.h>
+
+namespace Catch
+{
+ struct ReporterConfig {
+ explicit ReporterConfig( Ptr<IConfig> const& _fullConfig )
+ : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
+
+ ReporterConfig( Ptr<IConfig> const& _fullConfig, std::ostream& _stream )
+ : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
+
+ std::ostream& stream() const { return *m_stream; }
+ Ptr<IConfig> fullConfig() const { return m_fullConfig; }
+
+ private:
+ std::ostream* m_stream;
+ Ptr<IConfig> m_fullConfig;
+ };
+
+ struct ReporterPreferences {
+ ReporterPreferences()
+ : shouldRedirectStdOut( false )
+ {}
+
+ bool shouldRedirectStdOut;
+ };
+
+ template<typename T>
+ struct LazyStat : Option<T> {
+ LazyStat() : used( false ) {}
+ LazyStat& operator=( T const& _value ) {
+ Option<T>::operator=( _value );
+ used = false;
+ return *this;
+ }
+ void reset() {
+ Option<T>::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<MessageInfo> 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<MessageInfo> 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<std::string, IReporterFactory*> FactoryMap;
+
+ virtual ~IReporterRegistry();
+ virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const = 0;
+ virtual FactoryMap const& getFactories() const = 0;
+ };
+
+}
+
+#include <limits>
+#include <algorithm>
+
+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<TestCase> matchedTestCases;
+ getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
+ for( std::vector<TestCase>::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<TestCase> matchedTestCases;
+ getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
+ for( std::vector<TestCase>::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<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
+ it != itEnd;
+ ++it )
+ out += "[" + *it + "]";
+ return out;
+ }
+ std::set<std::string> 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<std::string, TagInfo> tagCounts;
+
+ std::vector<TestCase> matchedTestCases;
+ getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
+ for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
+ it != itEnd;
+ ++it ) {
+ for( std::set<std::string>::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<std::string, TagInfo>::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<std::string, TagInfo>::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<std::size_t> list( Config const& config ) {
+ Option<std::size_t> 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 <map>
+#include <string>
+#include <assert.h>
+
+namespace Catch {
+namespace SectionTracking {
+
+ class TrackedSection {
+
+ typedef std::map<std::string, TrackedSection> 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 <set>
+#include <string>
+
+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<IConfig const> const& config, Ptr<IStreamingReporter> 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<IConfig const> 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<std::size_t>( 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<UnfinishedSections>::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<TestCaseTracker> m_testCaseTracker;
+ AssertionResult m_lastResult;
+
+ Ptr<IConfig const> m_config;
+ Totals m_totals;
+ Ptr<IStreamingReporter> m_reporter;
+ std::vector<MessageInfo> m_messages;
+ IRunner* m_prevRunner;
+ IResultCapture* m_prevResultCapture;
+ Ptr<IConfig const> m_prevConfig;
+ AssertionInfo m_lastAssertionInfo;
+ std::vector<UnfinishedSections> 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 <fstream>
+#include <stdlib.h>
+#include <limits>
+
+namespace Catch {
+
+ class Runner {
+
+ public:
+ Runner( Ptr<Config> 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<TestCase> testCases;
+ getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases );
+
+ int testsRunForGroup = 0;
+ for( std::vector<TestCase>::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<Config> m_config;
+ std::ofstream m_ofs;
+ Ptr<IStreamingReporter> m_reporter;
+ std::set<TestCase> 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<int>::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<std::size_t> listed = list( config() ) )
+ return static_cast<int>( *listed );
+
+ return static_cast<int>( runner.runTests().assertions.failed );
+ }
+ catch( std::exception& ex ) {
+ std::cerr << ex.what() << std::endl;
+ return (std::numeric_limits<int>::max)();
+ }
+ }
+
+ Clara::CommandLine<ConfigData> const& cli() const {
+ return m_cli;
+ }
+ std::vector<Clara::Parser::Token> 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<ConfigData> m_cli;
+ std::vector<Clara::Parser::Token> m_unusedTokens;
+ ConfigData m_configData;
+ Ptr<Config> 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 <vector>
+#include <set>
+#include <sstream>
+#include <iostream>
+
+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<TestCase> const& getAllTests() const {
+ return m_functionsInOrder;
+ }
+
+ virtual std::vector<TestCase> const& getAllNonHiddenTests() const {
+ return m_nonHiddenFunctions;
+ }
+
+ virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const {
+ for( std::vector<TestCase>::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<TestCase> m_functions;
+ std::vector<TestCase> m_functionsInOrder;
+ std::vector<TestCase> m_nonHiddenFunctions;
+ size_t m_unnamedCount;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ class FreeFunctionTestCase : public SharedImpl<ITestCase> {
+ 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 <map>
+
+namespace Catch {
+
+ class ReporterRegistry : public IReporterRegistry {
+
+ public:
+
+ virtual ~ReporterRegistry() {
+ deleteAllValues( m_factories );
+ }
+
+ virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> 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 IExceptionTranslator*>::const_iterator it ) const {
+ if( it == m_translators.end() )
+ return "Unknown exception";
+
+ try {
+ return (*it)->translate();
+ }
+ catch(...) {
+ return tryTranslators( it+1 );
+ }
+ }
+
+ private:
+ std::vector<const IExceptionTranslator*> 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 <ostream>
+
+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 <streambuf>
+
+namespace Catch {
+
+ class StreamBufBase : public std::streambuf {
+ public:
+ virtual ~StreamBufBase() CATCH_NOEXCEPT;
+ };
+}
+
+#include <stdexcept>
+#include <cstdio>
+
+namespace Catch {
+
+ template<typename WriterF, size_t bufferSize=256>
+ 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<char>( c ) ) );
+ else
+ sputc( static_cast<char>( c ) );
+ }
+ return 0;
+ }
+
+ int sync() {
+ if( pbase() != pptr() ) {
+ m_writer( std::string( pbase(), static_cast<std::string::size_type>( 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<IConfig const> 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<IConfig const> const& config ) {
+ m_config = config;
+ }
+
+ friend IMutableContext& getCurrentMutableContext();
+
+ private:
+ IGeneratorsForTest* findGeneratorsForCurrentTest() {
+ std::string testName = getResultCapture()->getCurrentTestName();
+
+ std::map<std::string, IGeneratorsForTest*>::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<IConfig const> m_config;
+ IRunner* m_runner;
+ IResultCapture* m_resultCapture;
+ std::map<std::string, IGeneratorsForTest*> 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<OutputDebugWriter>, 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 <AfxWin.h>
+#else
+#include <windows.h>
+#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 <unistd.h>
+
+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<Colour&>( _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 <vector>
+#include <string>
+#include <map>
+
+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<std::string, IGeneratorInfo*>::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<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
+ std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
+ for(; it != itEnd; ++it ) {
+ if( (*it)->moveNext() )
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ std::map<std::string, IGeneratorInfo*> m_generatorsByName;
+ std::vector<IGeneratorInfo*> 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<std::string> 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<std::string> const& _tags,
+ SourceLineInfo const& _lineInfo )
+ : name( _name ),
+ className( _className ),
+ description( _description ),
+ tags( _tags ),
+ lineInfo( _lineInfo ),
+ properties( None )
+ {
+ std::ostringstream oss;
+ for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) {
+ oss << "[" << *it << "]";
+ std::string lcaseTag = toLower( *it );
+ properties = static_cast<SpecialProperties>( 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<TestCaseInfo&>( 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, 53, "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<IStreamingReporter>
+ {
+ public:
+ LegacyReporterAdapter( Ptr<IReporter> 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<IReporter> m_legacyReporter;
+ };
+}
+
+namespace Catch
+{
+ LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> 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<MessageInfo>::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 <windows.h>
+#else
+#include <sys/time.h>
+#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<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec );
+ }
+#endif
+ }
+
+ void Timer::start() {
+ m_ticks = getCurrentTicks();
+ }
+ unsigned int Timer::getElapsedNanoseconds() const {
+ return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
+ }
+ unsigned int Timer::getElapsedMilliseconds() const {
+ return static_cast<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( 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 <iostream>
+
+#ifdef CATCH_PLATFORM_MAC
+
+ #include <assert.h>
+ #include <stdbool.h>
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <sys/sysctl.h>
+
+ 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<int>( size ), inc = 1;
+ if( Endianness::which() == Endianness::Little ) {
+ i = end-1;
+ end = inc = -1;
+ }
+
+ unsigned char const *bytes = static_cast<unsigned char const *>(object);
+ std::ostringstream os;
+ os << "0x" << std::setfill('0') << std::hex;
+ for( ; i != end; i += inc )
+ os << std::setw(2) << static_cast<unsigned>(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<char>( 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<const char*>( 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<const wchar_t*>( 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<unsigned long>( value ) );
+}
+
+template<typename T>
+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<unsigned int>( value ) )
+ : Detail::makeString( value );
+}
+
+std::string toString( signed char value ) {
+ return toString( static_cast<char>( value ) );
+}
+
+std::string toString( unsigned char value ) {
+ return toString( static_cast<char>( 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 <map>
+
+namespace Catch {
+
+ class TagAliasRegistry : public ITagAliasRegistry {
+ public:
+ virtual ~TagAliasRegistry();
+ virtual Option<TagAlias> 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<std::string, TagAlias> m_registry;
+ };
+
+} // end namespace Catch
+
+#include <map>
+#include <iostream>
+
+namespace Catch {
+
+ TagAliasRegistry::~TagAliasRegistry() {}
+
+ Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const {
+ std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias );
+ if( it != m_registry.end() )
+ return it->second;
+ else
+ return Option<TagAlias>();
+ }
+
+ std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
+ std::string expandedTestSpec = unexpandedTestSpec;
+ for( std::map<std::string, TagAlias>::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<IStreamingReporter> {
+
+ 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<IConfig> m_config;
+ std::ostream& stream;
+
+ LazyStat<TestRunInfo> currentTestRunInfo;
+ LazyStat<GroupInfo> currentGroupInfo;
+ LazyStat<TestCaseInfo> currentTestCaseInfo;
+
+ std::vector<SectionInfo> m_sectionStack;
+ };
+
+ struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
+ template<typename T, typename ChildNodeT>
+ struct Node : SharedImpl<> {
+ explicit Node( T const& _value ) : value( _value ) {}
+ virtual ~Node() {}
+
+ typedef std::vector<Ptr<ChildNodeT> > 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<SectionNode> const& other ) const {
+ return operator==( *other );
+ }
+
+ SectionStats stats;
+ typedef std::vector<Ptr<SectionNode> > ChildSections;
+ typedef std::vector<AssertionStats> 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<SectionNode> const& node ) const {
+ return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
+ }
+ private:
+ void operator=( BySectionInfo const& );
+ SectionInfo const& m_other;
+ };
+
+ typedef Node<TestCaseStats, SectionNode> TestCaseNode;
+ typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
+ typedef Node<TestRunStats, TestGroupNode> 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<SectionNode> 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<TestCaseNode> 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<TestGroupNode> node = new TestGroupNode( testGroupStats );
+ node->children.swap( m_testCases );
+ m_testGroups.push_back( node );
+ }
+ virtual void testRunEnded( TestRunStats const& testRunStats ) {
+ Ptr<TestRunNode> node = new TestRunNode( testRunStats );
+ node->children.swap( m_testGroups );
+ m_testRuns.push_back( node );
+ testRunEndedCumulative();
+ }
+ virtual void testRunEndedCumulative() = 0;
+
+ Ptr<IConfig> m_config;
+ std::ostream& stream;
+ std::vector<AssertionStats> m_assertions;
+ std::vector<std::vector<Ptr<SectionNode> > > m_sections;
+ std::vector<Ptr<TestCaseNode> > m_testCases;
+ std::vector<Ptr<TestGroupNode> > m_testGroups;
+
+ std::vector<Ptr<TestRunNode> > m_testRuns;
+
+ Ptr<SectionNode> m_rootSection;
+ Ptr<SectionNode> m_deepestSection;
+ std::vector<Ptr<SectionNode> > m_sectionStack;
+
+ };
+
+} // end namespace Catch
+
+// #included from: ../internal/catch_reporter_registrars.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
+
+namespace Catch {
+
+ template<typename T>
+ 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<typename T>
+ 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<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
+#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
+ namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
+
+// #included from: ../internal/catch_xmlwriter.hpp
+#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
+
+#include <sstream>
+#include <iostream>
+#include <string>
+#include <vector>
+
+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<typename T>
+ 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 << "</" << m_tags.back() << ">\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<typename T>
+ 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 << "<!--" << text << "-->";
+ 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() << "&lt;";
+ break;
+ case '&':
+ stream() << "&amp;";
+ break;
+ case '\"':
+ stream() << "&quot;";
+ break;
+ }
+ mtext = mtext.substr( pos+1 );
+ pos = mtext.find_first_of( charsToEncode );
+ }
+ stream() << mtext;
+ }
+
+ bool m_tagIsOpen;
+ bool m_needsNewline;
+ std::vector<std::string> m_tags;
+ std::string m_indent;
+ std::ostream* m_os;
+ };
+
+}
+namespace Catch {
+ class XmlReporter : public SharedImpl<IReporter> {
+ 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 <assert.h>
+
+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<MessageInfo>::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 <cstring>
+
+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<MessageInfo>::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<MessageInfo> 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<SectionInfo>::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<std::string>::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<std::string> 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<SummaryColumn> 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<SummaryColumn> const& cols, std::size_t row ) {
+ for( std::vector<SummaryColumn>::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<char C>
+ 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<MessageInfo>::const_iterator itEnd = messages.end();
+ const std::size_t N = static_cast<std::size_t>( 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<MessageInfo> messages;
+ std::vector<MessageInfo>::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__ )
+#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, "" )
+#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__ )
+#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, "" )
+#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
+#elif defined __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/include/catch_orig.hpp b/3party/osrm/osrm-backend/third_party/libosmium/test/include/catch_orig.hpp
new file mode 100755
index 0000000000..6b8dfb5ebd
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/include/catch_orig.hpp
@@ -0,0 +1,8997 @@
+/*
+ * 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.
+ *
+ * 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"
+#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
+# 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 <sstream>
+#include <stdexcept>
+#include <algorithm>
+
+// #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<typename ContainerT>
+ 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<typename AssociativeContainerT>
+ 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<typename T>
+ T const& operator + ( T const& value, StreamEndStop ) {
+ return value;
+ }
+}
+
+#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
+#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
+
+#include <ostream>
+
+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 <string>
+
+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<typename T>
+ 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<typename T = IShared>
+ 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 <memory>
+#include <vector>
+#include <stdlib.h>
+
+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<IConfig const> getConfig() const = 0;
+ };
+
+ struct IMutableContext : IContext
+ {
+ virtual ~IMutableContext();
+ virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
+ virtual void setRunner( IRunner* runner ) = 0;
+ virtual void setConfig( Ptr<IConfig const> 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 <vector>
+
+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<TestCase> const& getAllTests() const = 0;
+ virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const = 0;
+
+ };
+}
+
+namespace Catch {
+
+template<typename C>
+class MethodTestCase : public SharedImpl<ITestCase> {
+
+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<typename C>
+ AutoReg( void (C::*method)(),
+ char const* className,
+ NameAndDesc const& nameAndDesc,
+ SourceLineInfo const& lineInfo ) {
+ registerTestCase( new MethodTestCase<C>( 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<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( 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 <string>
+
+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<typename T> 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<typename T>
+ ExpressionLhs<T const&> operator->* ( T const& operand );
+ ExpressionLhs<bool> operator->* ( bool value );
+
+ template<typename T>
+ ResultBuilder& operator << ( T const& value ) {
+ m_stream.oss << value;
+ return *this;
+ }
+
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
+ template<typename RhsT> 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 <cstddef>
+
+namespace Catch {
+namespace Internal {
+
+ enum Operator {
+ IsEqualTo,
+ IsNotEqualTo,
+ IsLessThan,
+ IsGreaterThan,
+ IsLessThanOrEqualTo,
+ IsGreaterThanOrEqualTo
+ };
+
+ template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
+ template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
+ template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
+ template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
+ template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
+ template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
+ template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
+
+ template<typename T>
+ inline T& opCast(T const& t) { return const_cast<T&>(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<typename T1, typename T2, Operator Op>
+ class Evaluator{};
+
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsEqualTo> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs) {
+ return opCast( lhs ) == opCast( rhs );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsNotEqualTo> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) != opCast( rhs );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsLessThan> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) < opCast( rhs );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsGreaterThan> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) > opCast( rhs );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) >= opCast( rhs );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) <= opCast( rhs );
+ }
+ };
+
+ template<Operator Op, typename T1, typename T2>
+ bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
+ return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
+ }
+
+ // This level of indirection allows us to specialise for integer types
+ // to avoid signed/ unsigned warnings
+
+ // "base" overload
+ template<Operator Op, typename T1, typename T2>
+ bool compare( T1 const& lhs, T2 const& rhs ) {
+ return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
+ }
+
+ // unsigned X to int
+ template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+ }
+ template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+ }
+ template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+ }
+
+ // unsigned X to long
+ template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+ }
+ template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+ }
+ template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+ }
+
+ // int to unsigned X
+ template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+ }
+
+ // long to unsigned X
+ template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+
+ // pointer to long (when comparing against NULL)
+ template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
+ }
+ template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
+ }
+
+ // pointer to int (when comparing against NULL)
+ template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
+ }
+ template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
+ }
+
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+ // pointer to nullptr_t (when comparing against nullptr)
+ template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( NULL, rhs );
+ }
+ template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
+ return Evaluator<T*, T*, Op>::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<bool> struct NotABooleanExpression;
+
+ template<bool c> struct If : NotABooleanExpression<c> {};
+ template<> struct If<true> : TrueType {};
+ template<> struct If<false> : FalseType {};
+
+ template<int size> struct SizedIf;
+ template<> struct SizedIf<sizeof(TrueType)> : TrueType {};
+ template<> struct SizedIf<sizeof(FalseType)> : FalseType {};
+
+#endif // CATCH_CONFIG_SFINAE
+
+} // end namespace Catch
+
+#include <sstream>
+#include <iomanip>
+#include <limits>
+#include <vector>
+#include <cstddef>
+
+#ifdef __OBJC__
+// #included from: catch_objc_arc.hpp
+#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
+
+#import <Foundation/Foundation.h>
+
+#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<typename T>
+ class IsStreamInsertableHelper {
+ template<int N> struct TrueIfSizeable : TrueType {};
+
+ template<typename T2>
+ static TrueIfSizeable<sizeof((*(std::ostream*)0) << *((T2 const*)0))> dummy(T2*);
+ static FalseType dummy(...);
+
+ public:
+ typedef SizedIf<sizeof(dummy((T*)0))> type;
+ };
+
+ template<typename T>
+ struct IsStreamInsertable : IsStreamInsertableHelper<T>::type {};
+
+#else
+
+ struct BorgType {
+ template<typename T> BorgType( T const& );
+ };
+
+ TrueType& testStreamable( std::ostream& );
+ FalseType testStreamable( FalseType );
+
+ FalseType operator<<( std::ostream const&, BorgType const& );
+
+ template<typename T>
+ struct IsStreamInsertable {
+ static std::ostream &s;
+ static T const&t;
+ enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
+ };
+
+#endif
+
+ template<bool C>
+ struct StringMakerBase {
+ template<typename T>
+ static std::string convert( T const& ) { return "{?}"; }
+ };
+
+ template<>
+ struct StringMakerBase<true> {
+ template<typename T>
+ 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<typename T>
+ inline std::string rawMemoryToString( const T& object ) {
+ return rawMemoryToString( &object, sizeof(object) );
+ }
+
+} // end namespace Detail
+
+template<typename T>
+std::string toString( T const& value );
+
+template<typename T>
+struct StringMaker :
+ Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
+
+template<typename T>
+struct StringMaker<T*> {
+ template<typename U>
+ static std::string convert( U* p ) {
+ if( !p )
+ return INTERNAL_CATCH_STRINGIFY( NULL );
+ else
+ return Detail::rawMemoryToString( p );
+ }
+};
+
+template<typename R, typename C>
+struct StringMaker<R C::*> {
+ static std::string convert( R C::* p ) {
+ if( !p )
+ return INTERNAL_CATCH_STRINGIFY( NULL );
+ else
+ return Detail::rawMemoryToString( p );
+ }
+};
+
+namespace Detail {
+ template<typename InputIterator>
+ std::string rangeToString( InputIterator first, InputIterator last );
+}
+
+template<typename T, typename Allocator>
+struct StringMaker<std::vector<T, Allocator> > {
+ static std::string convert( std::vector<T,Allocator> const& v ) {
+ return Detail::rangeToString( v.begin(), v.end() );
+ }
+};
+
+namespace Detail {
+ template<typename T>
+ std::string makeString( T const& value ) {
+ return StringMaker<T>::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<typename T>
+std::string toString( T const& value ) {
+ return StringMaker<T>::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( 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 );
+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<typename InputIterator>
+ 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<typename T>
+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<typename RhsT>
+ ResultBuilder& operator == ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsEqualTo>( rhs );
+ }
+
+ template<typename RhsT>
+ ResultBuilder& operator != ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsNotEqualTo>( rhs );
+ }
+
+ template<typename RhsT>
+ ResultBuilder& operator < ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsLessThan>( rhs );
+ }
+
+ template<typename RhsT>
+ ResultBuilder& operator > ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsGreaterThan>( rhs );
+ }
+
+ template<typename RhsT>
+ ResultBuilder& operator <= ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
+ }
+
+ template<typename RhsT>
+ ResultBuilder& operator >= ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
+ }
+
+ ResultBuilder& operator == ( bool rhs ) {
+ return captureExpression<Internal::IsEqualTo>( rhs );
+ }
+
+ ResultBuilder& operator != ( bool rhs ) {
+ return captureExpression<Internal::IsNotEqualTo>( 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<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& );
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& );
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& );
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& );
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
+
+private:
+ template<Internal::Operator Op, typename RhsT>
+ ResultBuilder& captureExpression( RhsT const& rhs ) {
+ return m_rb
+ .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
+ .setLhs( Catch::toString( m_lhs ) )
+ .setRhs( Catch::toString( rhs ) )
+ .setOp( Internal::OperatorTraits<Op>::getName() );
+ }
+
+private:
+ ResultBuilder& m_rb;
+ T m_lhs;
+};
+
+} // end namespace Catch
+
+
+namespace Catch {
+
+ template<typename T>
+ inline ExpressionLhs<T const&> ResultBuilder::operator->* ( T const& operand ) {
+ return ExpressionLhs<T const&>( *this, operand );
+ }
+
+ inline ExpressionLhs<bool> ResultBuilder::operator->* ( bool value ) {
+ return ExpressionLhs<bool>( *this, value );
+ }
+
+} // namespace Catch
+
+// #included from: catch_message.h
+#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
+
+#include <string>
+
+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<typename T>
+ 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 <string>
+
+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 <string>
+
+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 <cstddef>
+
+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 <stdint.h>
+#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 <string>
+
+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 <iterator>
+#include <vector>
+#include <string>
+#include <stdlib.h>
+
+namespace Catch {
+
+template<typename T>
+struct IGenerator {
+ virtual ~IGenerator() {}
+ virtual T getValue( std::size_t index ) const = 0;
+ virtual std::size_t size () const = 0;
+};
+
+template<typename T>
+class BetweenGenerator : public IGenerator<T> {
+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<int>( index );
+ }
+
+ virtual std::size_t size() const {
+ return static_cast<std::size_t>( 1+m_to-m_from );
+ }
+
+private:
+
+ T m_from;
+ T m_to;
+};
+
+template<typename T>
+class ValuesGenerator : public IGenerator<T> {
+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<T> m_values;
+};
+
+template<typename T>
+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 IGenerator<T>*>::const_iterator it = m_composed.begin();
+ typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
+ for( size_t index = 0; it != itEnd; ++it )
+ {
+ const IGenerator<T>* 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<T>* generator ) {
+ m_totalSize += generator->size();
+ m_composed.push_back( generator );
+ }
+
+ CompositeGenerator& then( CompositeGenerator& other ) {
+ move( other );
+ return *this;
+ }
+
+ CompositeGenerator& then( T value ) {
+ ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+ 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<const IGenerator<T>*> m_composed;
+ std::string m_fileInfo;
+ size_t m_totalSize;
+};
+
+namespace Generators
+{
+ template<typename T>
+ CompositeGenerator<T> between( T from, T to ) {
+ CompositeGenerator<T> generators;
+ generators.add( new BetweenGenerator<T>( from, to ) );
+ return generators;
+ }
+
+ template<typename T>
+ CompositeGenerator<T> values( T val1, T val2 ) {
+ CompositeGenerator<T> generators;
+ ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+ valuesGen->add( val1 );
+ valuesGen->add( val2 );
+ generators.add( valuesGen );
+ return generators;
+ }
+
+ template<typename T>
+ CompositeGenerator<T> values( T val1, T val2, T val3 ){
+ CompositeGenerator<T> generators;
+ ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+ valuesGen->add( val1 );
+ valuesGen->add( val2 );
+ valuesGen->add( val3 );
+ generators.add( valuesGen );
+ return generators;
+ }
+
+ template<typename T>
+ CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
+ CompositeGenerator<T> generators;
+ ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+ 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 <string>
+// #included from: catch_interfaces_registry_hub.h
+#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
+
+#include <string>
+
+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<typename T>
+ 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<typename T>
+ ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
+ getMutableRegistryHub().registerTranslator
+ ( new ExceptionTranslator<T>( 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 <cmath>
+#include <limits>
+
+namespace Catch {
+namespace Detail {
+
+ class Approx {
+ public:
+ explicit Approx ( double value )
+ : m_epsilon( std::numeric_limits<float>::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>( 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<typename ExpressionT>
+ struct Matcher : SharedImpl<IShared>
+ {
+ typedef ExpressionT ExpressionType;
+
+ virtual ~Matcher() {}
+ virtual Ptr<Matcher> clone() const = 0;
+ virtual bool match( ExpressionT const& expr ) const = 0;
+ virtual std::string toString() const = 0;
+ };
+
+ template<typename DerivedT, typename ExpressionT>
+ struct MatcherImpl : Matcher<ExpressionT> {
+
+ virtual Ptr<Matcher<ExpressionT> > clone() const {
+ return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
+ }
+ };
+
+ namespace Generic {
+
+ template<typename ExpressionT>
+ class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
+ public:
+
+ AllOf() {}
+ AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
+
+ AllOf& add( Matcher<ExpressionT> 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<Ptr<Matcher<ExpressionT> > > m_matchers;
+ };
+
+ template<typename ExpressionT>
+ class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
+ public:
+
+ AnyOf() {}
+ AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
+
+ AnyOf& add( Matcher<ExpressionT> 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<Ptr<Matcher<ExpressionT> > > 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> {
+ 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> {
+ 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> {
+ 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> {
+ 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<typename ExpressionT>
+ inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
+ Impl::Matcher<ExpressionT> const& m2 ) {
+ return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
+ }
+ template<typename ExpressionT>
+ inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
+ Impl::Matcher<ExpressionT> const& m2,
+ Impl::Matcher<ExpressionT> const& m3 ) {
+ return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
+ }
+ template<typename ExpressionT>
+ inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
+ Impl::Matcher<ExpressionT> const& m2 ) {
+ return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
+ }
+ template<typename ExpressionT>
+ inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
+ Impl::Matcher<ExpressionT> const& m2,
+ Impl::Matcher<ExpressionT> const& m3 ) {
+ return Impl::Generic::AnyOf<ExpressionT>().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 <string>
+
+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<typename T>
+ 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<TagAlias> 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 <string>
+#include <set>
+
+#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<std::string> 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<std::string> tags;
+ std::set<std::string> 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<ITestCase> 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 <objc/runtime.h>
+
+#include <string>
+
+// 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<ITestCase> {
+
+ 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<typename MatcherT>
+ struct StringHolder : MatcherImpl<MatcherT, NSString*>{
+ 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> {
+ 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> {
+ 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> {
+ 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> {
+ 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 <string>
+#include <vector>
+
+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<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.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
+ }
+ private:
+ std::string m_tag;
+ };
+ class ExcludedPattern : public Pattern {
+ public:
+ ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
+ virtual ~ExcludedPattern();
+ virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
+ private:
+ Ptr<Pattern> m_underlyingPattern;
+ };
+
+ struct Filter {
+ std::vector<Ptr<Pattern> > 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<Ptr<Pattern> >::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<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
+ if( it->matches( testCase ) )
+ return true;
+ return false;
+ }
+
+ private:
+ std::vector<Filter> 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<TestSpec::NamePattern>();
+ 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<TestSpec::NamePattern>();
+ addFilter();
+ }
+ else if( c == '[' ) {
+ if( subString() == "exclude:" )
+ m_exclusion = true;
+ else
+ addPattern<TestSpec::NamePattern>();
+ startNewMode( Tag, ++m_pos );
+ }
+ }
+ else if( m_mode == QuotedName && c == '"' )
+ addPattern<TestSpec::NamePattern>();
+ else if( m_mode == Tag && c == ']' )
+ addPattern<TestSpec::TagPattern>();
+ }
+ 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<typename T>
+ void addPattern() {
+ std::string token = subString();
+ if( startsWith( token, "exclude:" ) ) {
+ m_exclusion = true;
+ token = token.substr( 8 );
+ }
+ if( !token.empty() ) {
+ Ptr<TestSpec::Pattern> 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 <iostream>
+#include <string>
+#include <vector>
+
+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 <streambuf>
+
+#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 <memory>
+#include <vector>
+#include <string>
+#include <iostream>
+
+#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<std::string> testsOrTags;
+ };
+
+ class Config : public SharedImpl<IConfig> {
+ 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 <string>
+#include <vector>
+#include <sstream>
+
+// 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<std::string>::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<std::string> 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 <map>
+#include <algorithm>
+#include <stdexcept>
+#include <memory>
+
+// 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<typename T> struct RemoveConstRef{ typedef T type; };
+ template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
+ template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
+ template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
+
+ template<typename T> struct IsBool { static const bool value = false; };
+ template<> struct IsBool<bool> { static const bool value = true; };
+
+ template<typename T>
+ 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<typename T>
+ inline void convertInto( bool, T& ) {
+ throw std::runtime_error( "Invalid conversion" );
+ }
+
+ template<typename ConfigT>
+ 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<typename ConfigT>
+ class BoundArgFunction {
+ public:
+ BoundArgFunction() : functionObj( NULL ) {}
+ BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
+ BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {}
+ BoundArgFunction& operator = ( BoundArgFunction const& other ) {
+ IArgFunction<ConfigT>* 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<ConfigT>* functionObj;
+ };
+
+ template<typename C>
+ struct NullBinder : IArgFunction<C>{
+ virtual void set( C&, std::string const& ) const {}
+ virtual void setFlag( C& ) const {}
+ virtual bool takesArg() const { return true; }
+ virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
+ };
+
+ template<typename C, typename M>
+ struct BoundDataMember : IArgFunction<C>{
+ 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<M>::value; }
+ virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
+ M C::* member;
+ };
+ template<typename C, typename M>
+ struct BoundUnaryMethod : IArgFunction<C>{
+ BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
+ virtual void set( C& p, std::string const& stringValue ) const {
+ typename RemoveConstRef<M>::type value;
+ convertInto( stringValue, value );
+ (p.*member)( value );
+ }
+ virtual void setFlag( C& p ) const {
+ typename RemoveConstRef<M>::type value;
+ convertInto( true, value );
+ (p.*member)( value );
+ }
+ virtual bool takesArg() const { return !IsBool<M>::value; }
+ virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
+ void (C::*member)( M );
+ };
+ template<typename C>
+ struct BoundNullaryMethod : IArgFunction<C>{
+ 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<C>* clone() const { return new BoundNullaryMethod( *this ); }
+ void (C::*member)();
+ };
+
+ template<typename C>
+ struct BoundUnaryFunction : IArgFunction<C>{
+ 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<C>* clone() const { return new BoundUnaryFunction( *this ); }
+ void (*function)( C& );
+ };
+
+ template<typename C, typename T>
+ struct BoundBinaryFunction : IArgFunction<C>{
+ BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
+ virtual void set( C& obj, std::string const& stringValue ) const {
+ typename RemoveConstRef<T>::type value;
+ convertInto( stringValue, value );
+ function( obj, value );
+ }
+ virtual void setFlag( C& obj ) const {
+ typename RemoveConstRef<T>::type value;
+ convertInto( true, value );
+ function( obj, value );
+ }
+ virtual bool takesArg() const { return !IsBool<T>::value; }
+ virtual IArgFunction<C>* 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<Parser::Token>& 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<Parser::Token>& 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<typename ConfigT>
+ struct CommonArgProperties {
+ CommonArgProperties() {}
+ CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
+
+ Detail::BoundArgFunction<ConfigT> 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<std::string> 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<typename ConfigT>
+ class CommandLine {
+
+ struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
+ Arg() {}
+ Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
+
+ using CommonArgProperties<ConfigT>::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<std::string>::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<Arg> ArgAutoPtr;
+#else
+ typedef std::auto_ptr<Arg> 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<typename C, typename M>
+ void bind( M C::* field, std::string const& placeholder ) {
+ m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
+ m_arg->placeholder = placeholder;
+ }
+ // Bind a boolean data member (no placeholder required)
+ template<typename C>
+ void bind( bool C::* field ) {
+ m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
+ }
+
+ // Bind a method taking a single, non-boolean argument (requires a placeholder string)
+ template<typename C, typename M>
+ void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
+ m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
+ m_arg->placeholder = placeholder;
+ }
+
+ // Bind a method taking a single, boolean argument (no placeholder string required)
+ template<typename C>
+ void bind( void (C::* unaryMethod)( bool ) ) {
+ m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
+ }
+
+ // Bind a method that takes no arguments (will be called if opt is present)
+ template<typename C>
+ void bind( void (C::* nullaryMethod)() ) {
+ m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
+ }
+
+ // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
+ template<typename C>
+ void bind( void (* unaryFunction)( C& ) ) {
+ m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
+ }
+
+ // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
+ template<typename C, typename T>
+ void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
+ m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( 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<ConfigT>() ),
+ 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<typename C, typename M>
+ void bindProcessName( M C::* field ) {
+ m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
+ }
+ template<typename C, typename M>
+ void bindProcessName( void (C::*_unaryMethod)( M ) ) {
+ m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
+ }
+
+ void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
+ typename std::vector<Arg>::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<int, Arg>::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<Parser::Token> 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<Parser::Token> tokens;
+ Parser parser;
+ parser.parseIntoTokens( argc, argv, tokens );
+ return populate( tokens, config );
+ }
+
+ std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+ validate();
+ std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
+ unusedTokens = populateFixedArgs( unusedTokens, config );
+ unusedTokens = populateFloatingArgs( unusedTokens, config );
+ return unusedTokens;
+ }
+
+ std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+ std::vector<Parser::Token> unusedTokens;
+ std::vector<std::string> errors;
+ for( std::size_t i = 0; i < tokens.size(); ++i ) {
+ Parser::Token const& token = tokens[i];
+ typename std::vector<Arg>::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<std::string>::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<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+ std::vector<Parser::Token> unusedTokens;
+ int position = 1;
+ for( std::size_t i = 0; i < tokens.size(); ++i ) {
+ Parser::Token const& token = tokens[i];
+ typename std::map<int, Arg>::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<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+ if( !m_floatingArg.get() )
+ return tokens;
+ std::vector<Parser::Token> 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<Arg>::const_iterator it = m_options.begin(),
+ itEnd = m_options.end();
+ it != itEnd; ++it )
+ it->validate();
+ }
+
+ private:
+ Detail::BoundArgFunction<ConfigT> m_boundProcessName;
+ std::vector<Arg> m_options;
+ std::map<int, Arg> 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 <fstream>
+
+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<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 = static_cast<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<ConfigData> makeCommandLineParser() {
+
+ using namespace Clara;
+ CommandLine<ConfigData> 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 <string>
+#include <vector>
+#include <sstream>
+
+// 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<std::string>::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<std::string> 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 <string>
+#include <ostream>
+#include <map>
+#include <assert.h>
+
+namespace Catch
+{
+ struct ReporterConfig {
+ explicit ReporterConfig( Ptr<IConfig> const& _fullConfig )
+ : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
+
+ ReporterConfig( Ptr<IConfig> const& _fullConfig, std::ostream& _stream )
+ : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
+
+ std::ostream& stream() const { return *m_stream; }
+ Ptr<IConfig> fullConfig() const { return m_fullConfig; }
+
+ private:
+ std::ostream* m_stream;
+ Ptr<IConfig> m_fullConfig;
+ };
+
+ struct ReporterPreferences {
+ ReporterPreferences()
+ : shouldRedirectStdOut( false )
+ {}
+
+ bool shouldRedirectStdOut;
+ };
+
+ template<typename T>
+ struct LazyStat : Option<T> {
+ LazyStat() : used( false ) {}
+ LazyStat& operator=( T const& _value ) {
+ Option<T>::operator=( _value );
+ used = false;
+ return *this;
+ }
+ void reset() {
+ Option<T>::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<MessageInfo> 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<MessageInfo> 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<std::string, IReporterFactory*> FactoryMap;
+
+ virtual ~IReporterRegistry();
+ virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const = 0;
+ virtual FactoryMap const& getFactories() const = 0;
+ };
+
+}
+
+#include <limits>
+#include <algorithm>
+
+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<TestCase> matchedTestCases;
+ getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
+ for( std::vector<TestCase>::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<TestCase> matchedTestCases;
+ getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
+ for( std::vector<TestCase>::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<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
+ it != itEnd;
+ ++it )
+ out += "[" + *it + "]";
+ return out;
+ }
+ std::set<std::string> 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<std::string, TagInfo> tagCounts;
+
+ std::vector<TestCase> matchedTestCases;
+ getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
+ for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
+ it != itEnd;
+ ++it ) {
+ for( std::set<std::string>::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<std::string, TagInfo>::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<std::string, TagInfo>::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<std::size_t> list( Config const& config ) {
+ Option<std::size_t> 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 <map>
+#include <string>
+#include <assert.h>
+
+namespace Catch {
+namespace SectionTracking {
+
+ class TrackedSection {
+
+ typedef std::map<std::string, TrackedSection> 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 <set>
+#include <string>
+
+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<IConfig const> const& config, Ptr<IStreamingReporter> 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<IConfig const> 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<std::size_t>( 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<UnfinishedSections>::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<TestCaseTracker> m_testCaseTracker;
+ AssertionResult m_lastResult;
+
+ Ptr<IConfig const> m_config;
+ Totals m_totals;
+ Ptr<IStreamingReporter> m_reporter;
+ std::vector<MessageInfo> m_messages;
+ IRunner* m_prevRunner;
+ IResultCapture* m_prevResultCapture;
+ Ptr<IConfig const> m_prevConfig;
+ AssertionInfo m_lastAssertionInfo;
+ std::vector<UnfinishedSections> 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 <fstream>
+#include <stdlib.h>
+#include <limits>
+
+namespace Catch {
+
+ class Runner {
+
+ public:
+ Runner( Ptr<Config> 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<TestCase> testCases;
+ getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases );
+
+ int testsRunForGroup = 0;
+ for( std::vector<TestCase>::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<Config> m_config;
+ std::ofstream m_ofs;
+ Ptr<IStreamingReporter> m_reporter;
+ std::set<TestCase> 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<int>::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<std::size_t> listed = list( config() ) )
+ return static_cast<int>( *listed );
+
+ return static_cast<int>( runner.runTests().assertions.failed );
+ }
+ catch( std::exception& ex ) {
+ std::cerr << ex.what() << std::endl;
+ return (std::numeric_limits<int>::max)();
+ }
+ }
+
+ Clara::CommandLine<ConfigData> const& cli() const {
+ return m_cli;
+ }
+ std::vector<Clara::Parser::Token> 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<ConfigData> m_cli;
+ std::vector<Clara::Parser::Token> m_unusedTokens;
+ ConfigData m_configData;
+ Ptr<Config> 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 <vector>
+#include <set>
+#include <sstream>
+#include <iostream>
+
+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<TestCase> const& getAllTests() const {
+ return m_functionsInOrder;
+ }
+
+ virtual std::vector<TestCase> const& getAllNonHiddenTests() const {
+ return m_nonHiddenFunctions;
+ }
+
+ virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const {
+ for( std::vector<TestCase>::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<TestCase> m_functions;
+ std::vector<TestCase> m_functionsInOrder;
+ std::vector<TestCase> m_nonHiddenFunctions;
+ size_t m_unnamedCount;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ class FreeFunctionTestCase : public SharedImpl<ITestCase> {
+ 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 <map>
+
+namespace Catch {
+
+ class ReporterRegistry : public IReporterRegistry {
+
+ public:
+
+ virtual ~ReporterRegistry() {
+ deleteAllValues( m_factories );
+ }
+
+ virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> 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 IExceptionTranslator*>::const_iterator it ) const {
+ if( it == m_translators.end() )
+ return "Unknown exception";
+
+ try {
+ return (*it)->translate();
+ }
+ catch(...) {
+ return tryTranslators( it+1 );
+ }
+ }
+
+ private:
+ std::vector<const IExceptionTranslator*> 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 <ostream>
+
+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 <streambuf>
+
+namespace Catch {
+
+ class StreamBufBase : public std::streambuf {
+ public:
+ virtual ~StreamBufBase() CATCH_NOEXCEPT;
+ };
+}
+
+#include <stdexcept>
+#include <cstdio>
+
+namespace Catch {
+
+ template<typename WriterF, size_t bufferSize=256>
+ 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<char>( c ) ) );
+ else
+ sputc( static_cast<char>( c ) );
+ }
+ return 0;
+ }
+
+ int sync() {
+ if( pbase() != pptr() ) {
+ m_writer( std::string( pbase(), static_cast<std::string::size_type>( 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<IConfig const> 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<IConfig const> const& config ) {
+ m_config = config;
+ }
+
+ friend IMutableContext& getCurrentMutableContext();
+
+ private:
+ IGeneratorsForTest* findGeneratorsForCurrentTest() {
+ std::string testName = getResultCapture()->getCurrentTestName();
+
+ std::map<std::string, IGeneratorsForTest*>::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<IConfig const> m_config;
+ IRunner* m_runner;
+ IResultCapture* m_resultCapture;
+ std::map<std::string, IGeneratorsForTest*> 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<OutputDebugWriter>, 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 <AfxWin.h>
+#else
+#include <windows.h>
+#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 <unistd.h>
+
+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<Colour&>( _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 <vector>
+#include <string>
+#include <map>
+
+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<std::string, IGeneratorInfo*>::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<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
+ std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
+ for(; it != itEnd; ++it ) {
+ if( (*it)->moveNext() )
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ std::map<std::string, IGeneratorInfo*> m_generatorsByName;
+ std::vector<IGeneratorInfo*> 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<std::string> 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<std::string> const& _tags,
+ SourceLineInfo const& _lineInfo )
+ : name( _name ),
+ className( _className ),
+ description( _description ),
+ tags( _tags ),
+ lineInfo( _lineInfo ),
+ properties( None )
+ {
+ std::ostringstream oss;
+ for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) {
+ oss << "[" << *it << "]";
+ std::string lcaseTag = toLower( *it );
+ properties = static_cast<SpecialProperties>( 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<TestCaseInfo&>( 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, 53, "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<IStreamingReporter>
+ {
+ public:
+ LegacyReporterAdapter( Ptr<IReporter> 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<IReporter> m_legacyReporter;
+ };
+}
+
+namespace Catch
+{
+ LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> 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<MessageInfo>::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 <windows.h>
+#else
+#include <sys/time.h>
+#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<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec );
+ }
+#endif
+ }
+
+ void Timer::start() {
+ m_ticks = getCurrentTicks();
+ }
+ unsigned int Timer::getElapsedNanoseconds() const {
+ return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
+ }
+ unsigned int Timer::getElapsedMilliseconds() const {
+ return static_cast<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( 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 <iostream>
+
+#ifdef CATCH_PLATFORM_MAC
+
+ #include <assert.h>
+ #include <stdbool.h>
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <sys/sysctl.h>
+
+ 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<int>( size ), inc = 1;
+ if( Endianness::which() == Endianness::Little ) {
+ i = end-1;
+ end = inc = -1;
+ }
+
+ unsigned char const *bytes = static_cast<unsigned char const *>(object);
+ std::ostringstream os;
+ os << "0x" << std::setfill('0') << std::hex;
+ for( ; i != end; i += inc )
+ os << std::setw(2) << static_cast<unsigned>(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<char>( 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<const char*>( 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<const wchar_t*>( 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<unsigned long>( value ) );
+}
+
+template<typename T>
+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<unsigned int>( value ) )
+ : Detail::makeString( value );
+}
+
+std::string toString( signed char value ) {
+ return toString( static_cast<char>( value ) );
+}
+
+std::string toString( unsigned char value ) {
+ return toString( static_cast<char>( 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 <map>
+
+namespace Catch {
+
+ class TagAliasRegistry : public ITagAliasRegistry {
+ public:
+ virtual ~TagAliasRegistry();
+ virtual Option<TagAlias> 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<std::string, TagAlias> m_registry;
+ };
+
+} // end namespace Catch
+
+#include <map>
+#include <iostream>
+
+namespace Catch {
+
+ TagAliasRegistry::~TagAliasRegistry() {}
+
+ Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const {
+ std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias );
+ if( it != m_registry.end() )
+ return it->second;
+ else
+ return Option<TagAlias>();
+ }
+
+ std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
+ std::string expandedTestSpec = unexpandedTestSpec;
+ for( std::map<std::string, TagAlias>::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<IStreamingReporter> {
+
+ 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<IConfig> m_config;
+ std::ostream& stream;
+
+ LazyStat<TestRunInfo> currentTestRunInfo;
+ LazyStat<GroupInfo> currentGroupInfo;
+ LazyStat<TestCaseInfo> currentTestCaseInfo;
+
+ std::vector<SectionInfo> m_sectionStack;
+ };
+
+ struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
+ template<typename T, typename ChildNodeT>
+ struct Node : SharedImpl<> {
+ explicit Node( T const& _value ) : value( _value ) {}
+ virtual ~Node() {}
+
+ typedef std::vector<Ptr<ChildNodeT> > 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<SectionNode> const& other ) const {
+ return operator==( *other );
+ }
+
+ SectionStats stats;
+ typedef std::vector<Ptr<SectionNode> > ChildSections;
+ typedef std::vector<AssertionStats> 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<SectionNode> const& node ) const {
+ return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
+ }
+ private:
+ void operator=( BySectionInfo const& );
+ SectionInfo const& m_other;
+ };
+
+ typedef Node<TestCaseStats, SectionNode> TestCaseNode;
+ typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
+ typedef Node<TestRunStats, TestGroupNode> 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<SectionNode> 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<TestCaseNode> 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<TestGroupNode> node = new TestGroupNode( testGroupStats );
+ node->children.swap( m_testCases );
+ m_testGroups.push_back( node );
+ }
+ virtual void testRunEnded( TestRunStats const& testRunStats ) {
+ Ptr<TestRunNode> node = new TestRunNode( testRunStats );
+ node->children.swap( m_testGroups );
+ m_testRuns.push_back( node );
+ testRunEndedCumulative();
+ }
+ virtual void testRunEndedCumulative() = 0;
+
+ Ptr<IConfig> m_config;
+ std::ostream& stream;
+ std::vector<AssertionStats> m_assertions;
+ std::vector<std::vector<Ptr<SectionNode> > > m_sections;
+ std::vector<Ptr<TestCaseNode> > m_testCases;
+ std::vector<Ptr<TestGroupNode> > m_testGroups;
+
+ std::vector<Ptr<TestRunNode> > m_testRuns;
+
+ Ptr<SectionNode> m_rootSection;
+ Ptr<SectionNode> m_deepestSection;
+ std::vector<Ptr<SectionNode> > m_sectionStack;
+
+ };
+
+} // end namespace Catch
+
+// #included from: ../internal/catch_reporter_registrars.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
+
+namespace Catch {
+
+ template<typename T>
+ 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<typename T>
+ 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<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
+#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
+ namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
+
+// #included from: ../internal/catch_xmlwriter.hpp
+#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
+
+#include <sstream>
+#include <iostream>
+#include <string>
+#include <vector>
+
+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<typename T>
+ 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 << "</" << m_tags.back() << ">\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<typename T>
+ 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 << "<!--" << text << "-->";
+ 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() << "&lt;";
+ break;
+ case '&':
+ stream() << "&amp;";
+ break;
+ case '\"':
+ stream() << "&quot;";
+ break;
+ }
+ mtext = mtext.substr( pos+1 );
+ pos = mtext.find_first_of( charsToEncode );
+ }
+ stream() << mtext;
+ }
+
+ bool m_tagIsOpen;
+ bool m_needsNewline;
+ std::vector<std::string> m_tags;
+ std::string m_indent;
+ std::ostream* m_os;
+ };
+
+}
+namespace Catch {
+ class XmlReporter : public SharedImpl<IReporter> {
+ 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 <assert.h>
+
+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<MessageInfo>::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 <cstring>
+
+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<MessageInfo>::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<MessageInfo> 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<SectionInfo>::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<std::string>::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<std::string> 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<SummaryColumn> 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<SummaryColumn> const& cols, std::size_t row ) {
+ for( std::vector<SummaryColumn>::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<char C>
+ 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<MessageInfo>::const_iterator itEnd = messages.end();
+ const std::size_t N = static_cast<std::size_t>( 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<MessageInfo> messages;
+ std::vector<MessageInfo>::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__ )
+#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, "" )
+#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__ )
+#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, "" )
+#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
+#elif defined __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/include/utils.hpp b/3party/osrm/osrm-backend/third_party/libosmium/test/include/utils.hpp
new file mode 100755
index 0000000000..662155abf2
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/include/utils.hpp
@@ -0,0 +1,18 @@
+
+#include <cstdlib>
+#include <string>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/test/include/win_mkstemp.hpp b/3party/osrm/osrm-backend/third_party/libosmium/test/include/win_mkstemp.hpp
new file mode 100755
index 0000000000..693c266f31
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 <keithmarshall@users.sourceforge.net>
+ * 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 <stdio.h>
+#include <fcntl.h>
+#include <share.h>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/test/t/area/test_area_id.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/area/test_area_id.cpp
new file mode 100755
index 0000000000..fbd8d784cb
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/area/test_area_id.cpp
@@ -0,0 +1,25 @@
+#include "catch.hpp"
+
+#include <osmium/osm/area.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/test/t/area/test_node_ref_segment.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/area/test_node_ref_segment.cpp
new file mode 100755
index 0000000000..309768744c
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/area/test_node_ref_segment.cpp
@@ -0,0 +1,115 @@
+#include "catch.hpp"
+
+#include <osmium/area/detail/node_ref_segment.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/helper.hpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/helper.hpp
new file mode 100755
index 0000000000..61e076934d
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/helper.hpp
@@ -0,0 +1,97 @@
+#ifndef TEST_BASIC_HELPER_HPP
+#define TEST_BASIC_HELPER_HPP
+
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include <osmium/builder/osm_object_builder.hpp>
+
+inline void add_tags(osmium::memory::Buffer& buffer, osmium::builder::Builder& builder, const std::vector<std::pair<const char*, const char*>>& 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<std::pair<const char*, const char*>>& 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<std::pair<const char*, const char*>>& tags, const std::vector<osmium::object_id_type>& 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<std::pair<const char*, const char*>>& tags, const std::vector<std::pair<osmium::object_id_type, osmium::Location>>& 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<std::pair<const char*, const char*>>& tags, const std::vector<std::tuple<char, osmium::object_id_type, const char*>>& 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<std::pair<const char*, const char*>>& tags,
+ const std::vector<std::pair<bool,
+ std::vector<std::pair<osmium::object_id_type, osmium::Location>>>>& 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<std::pair<const char*, const char*>>& 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/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_box.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_box.cpp
new file mode 100755
index 0000000000..8182fbf353
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_box.cpp
@@ -0,0 +1,91 @@
+#include "catch.hpp"
+
+#include <sstream>
+
+#include <osmium/osm/box.hpp>
+#include <osmium/geom/relations.hpp>
+
+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;
+ osmium::Location loc1 { 1.2, 3.4 };
+ b.extend(loc1);
+ REQUIRE(!!b);
+ REQUIRE(!!b.bottom_left());
+ REQUIRE(!!b.top_right());
+ REQUIRE(b.contains(loc1));
+
+ osmium::Location loc2 { 3.4, 4.5 };
+ osmium::Location loc3 { 5.6, 7.8 };
+
+ 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));
+
+ // 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));
+
+ REQUIRE(b.contains(loc1));
+ REQUIRE(b.contains(loc2));
+ REQUIRE(b.contains(loc3));
+ }
+
+ 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));
+ }
+
+ 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/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_changeset.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_changeset.cpp
new file mode 100755
index 0000000000..2549c1e676
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_changeset.cpp
@@ -0,0 +1,57 @@
+#include "catch.hpp"
+
+#include <osmium/osm/changeset.hpp>
+
+#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/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_entity_bits.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_entity_bits.cpp
new file mode 100755
index 0000000000..f15068b1c2
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_entity_bits.cpp
@@ -0,0 +1,31 @@
+#include "catch.hpp"
+
+#include <osmium/osm/entity_bits.hpp>
+
+TEST_CASE("entity_bits") {
+
+ SECTION("can_be_set_and_checked") {
+ osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::node | osmium::osm_entity_bits::way;
+ REQUIRE(entities == (osmium::osm_entity_bits::node | osmium::osm_entity_bits::way));
+
+ entities |= osmium::osm_entity_bits::relation;
+ REQUIRE((entities & osmium::osm_entity_bits::object));
+
+ entities |= osmium::osm_entity_bits::area;
+ REQUIRE(entities == osmium::osm_entity_bits::object);
+
+ REQUIRE(! (entities & osmium::osm_entity_bits::changeset));
+
+ entities &= osmium::osm_entity_bits::node;
+ REQUIRE((entities & osmium::osm_entity_bits::node));
+ REQUIRE(! (entities & osmium::osm_entity_bits::way));
+ REQUIRE(entities == osmium::osm_entity_bits::node);
+
+ REQUIRE(osmium::osm_entity_bits::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/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_location.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_location.cpp
new file mode 100755
index 0000000000..3fd8d155a5
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_location.cpp
@@ -0,0 +1,154 @@
+#include "catch.hpp"
+
+#include <sstream>
+#include <type_traits>
+
+#include <osmium/osm/location.hpp>
+
+TEST_CASE("Location") {
+
+// fails on MSVC and doesn't really matter
+// static_assert(std::is_literal_type<osmium::Location>::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/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_node.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_node.cpp
new file mode 100755
index 0000000000..6c2c899bd2
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_node.cpp
@@ -0,0 +1,117 @@
+#include "catch.hpp"
+
+#include <osmium/osm/node.hpp>
+
+#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(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());
+ 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<osmium::unsigned_object_id_type>(id) == node.positive_id());
+
+ node.set_id(-id);
+ REQUIRE(-id == node.id());
+ REQUIRE(static_cast<osmium::unsigned_object_id_type>(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/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_node_ref.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_node_ref.cpp
new file mode 100755
index 0000000000..ac7ccbf4b6
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_node_ref.cpp
@@ -0,0 +1,57 @@
+#include "catch.hpp"
+
+#include <osmium/osm/node_ref.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_object_comparisons.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_object_comparisons.cpp
new file mode 100755
index 0000000000..2bfdcad90c
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_object_comparisons.cpp
@@ -0,0 +1,147 @@
+#include "catch.hpp"
+
+#include <osmium/builder/osm_object_builder.hpp>
+#include <osmium/osm.hpp>
+#include <osmium/osm/object_comparisons.hpp>
+
+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<osmium::Node&>(*it);
+ osmium::Node& node2 = static_cast<osmium::Node&>(*(++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<const osmium::Node&>(*it);
+ const osmium::Node& node2 = static_cast<const osmium::Node&>(*(++it));
+ const osmium::Node& node3 = static_cast<const osmium::Node&>(*(++it));
+ const osmium::Way& way = static_cast<const osmium::Way&>(*(++it));
+ const osmium::Relation& relation = static_cast<const osmium::Relation&>(*(++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/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_relation.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_relation.cpp
new file mode 100755
index 0000000000..4c62a4189c
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_relation.cpp
@@ -0,0 +1,60 @@
+#include "catch.hpp"
+
+#include <osmium/osm/relation.hpp>
+
+#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/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_timestamp.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_timestamp.cpp
new file mode 100755
index 0000000000..6a04a4d095
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_timestamp.cpp
@@ -0,0 +1,58 @@
+#include "catch.hpp"
+
+#include <sstream>
+
+#include <osmium/osm/timestamp.hpp>
+
+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<time_t>(0));
+ REQUIRE(0 == t);
+ REQUIRE("" == t.to_iso());
+ }
+
+ SECTION("can be initialized from time_t") {
+ osmium::Timestamp t(static_cast<time_t>(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 implicitly cast to time_t") {
+ osmium::Timestamp t(4242);
+ time_t x = t;
+ REQUIRE(x == 4242);
+ }
+
+ 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/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_way.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_way.cpp
new file mode 100755
index 0000000000..9d2ba0691e
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/basic/test_way.cpp
@@ -0,0 +1,82 @@
+#include "catch.hpp"
+
+#include <osmium/builder/osm_object_builder.hpp>
+#include <osmium/osm/way.hpp>
+
+#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(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());
+ 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<osmium::Way>(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/3party/osrm/osrm-backend/third_party/libosmium/test/t/buffer/test_buffer_node.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/buffer/test_buffer_node.cpp
new file mode 100755
index 0000000000..9bc8f701da
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/buffer/test_buffer_node.cpp
@@ -0,0 +1,135 @@
+#include "catch.hpp"
+
+#include <osmium/builder/osm_object_builder.hpp>
+#include <osmium/osm/node.hpp>
+
+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<osmium::Node&>(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/3party/osrm/osrm-backend/third_party/libosmium/test/t/buffer/test_buffer_purge.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/buffer/test_buffer_purge.cpp
new file mode 100755
index 0000000000..10cdfe72ce
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/buffer/test_buffer_purge.cpp
@@ -0,0 +1,186 @@
+#include "catch.hpp"
+
+#include <osmium/builder/osm_object_builder.hpp>
+#include <osmium/osm/node.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/helper.hpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/helper.hpp
new file mode 100755
index 0000000000..e0cefe6d1e
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/helper.hpp
@@ -0,0 +1,15 @@
+#ifndef TEST_GEOM_HELPER_HPP
+#define TEST_GEOM_HELPER_HPP
+
+#include <string>
+
+#include <geos/io/WKBWriter.h>
+
+inline std::string geos_to_wkb(const geos::geom::Geometry* geometry) {
+ std::stringstream ss;
+ geos::io::WKBWriter wkb_writer;
+ wkb_writer.writeHEX(*geometry, ss);
+ return ss.str();
+}
+
+#endif // TEST_GEOM_HELPER_HPP
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_factory_with_projection.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_factory_with_projection.cpp
new file mode 100755
index 0000000000..42fc864bb3
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_factory_with_projection.cpp
@@ -0,0 +1,41 @@
+#include "catch.hpp"
+
+#include <osmium/geom/geos.hpp>
+#include <osmium/geom/mercator_projection.hpp>
+#include <osmium/geom/projection.hpp>
+#include <osmium/geom/wkb.hpp>
+#include <osmium/geom/wkt.hpp>
+
+#include "helper.hpp"
+
+TEST_CASE("Projection") {
+
+ SECTION("point_mercator") {
+ osmium::geom::WKTFactory<osmium::geom::MercatorProjection> factory(2);
+
+ std::string wkt {factory.create_point(osmium::Location(3.2, 4.2))};
+ REQUIRE(std::string {"POINT(356222.37 467961.14)"} == wkt);
+ }
+
+ SECTION("point_epsg_3857") {
+ osmium::geom::WKTFactory<osmium::geom::Projection> factory(osmium::geom::Projection(3857), 2);
+
+ std::string wkt {factory.create_point(osmium::Location(3.2, 4.2))};
+ REQUIRE(std::string {"POINT(356222.37 467961.14)"} == wkt);
+ }
+
+ SECTION("wkb_with_parameter") {
+ osmium::geom::WKBFactory<osmium::geom::Projection> wkb_factory(osmium::geom::Projection(3857), osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex);
+ osmium::geom::GEOSFactory<osmium::geom::Projection> geos_factory(osmium::geom::Projection(3857));
+
+ std::string wkb = wkb_factory.create_point(osmium::Location(3.2, 4.2));
+ std::unique_ptr<geos::geom::Point> geos_point = geos_factory.create_point(osmium::Location(3.2, 4.2));
+ REQUIRE(geos_to_wkb(geos_point.get()) == wkb);
+ }
+
+ SECTION("cleanup") {
+ // trying to make valgrind happy, but there is still a memory leak in proj library
+ pj_deallocate_grids();
+ }
+
+}
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_geojson.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_geojson.cpp
new file mode 100755
index 0000000000..8d7df3521a
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_geojson.cpp
@@ -0,0 +1,236 @@
+#include "catch.hpp"
+
+#include <osmium/builder/builder_helper.hpp>
+#include <osmium/geom/geojson.hpp>
+
+#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<osmium::OuterRing>(), area.cend<osmium::OuterRing>()) == 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<osmium::OuterRing>(), area.cend<osmium::OuterRing>()) == area.num_rings().first);
+ REQUIRE(std::distance(area.cbegin<osmium::InnerRing>(), area.cend<osmium::InnerRing>()) == 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<osmium::OuterRing>(), area.cend<osmium::OuterRing>()) == area.num_rings().first);
+ REQUIRE(std::distance(area.cbegin<osmium::InnerRing>(), area.cend<osmium::InnerRing>()) == area.num_rings().second);
+
+ int outer_ring=0;
+ int inner_ring=0;
+ for (auto it_outer = area.cbegin<osmium::OuterRing>(); it_outer != area.cend<osmium::OuterRing>(); ++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/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_geos.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_geos.cpp
new file mode 100755
index 0000000000..e93228b4cc
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_geos.cpp
@@ -0,0 +1,198 @@
+#include "catch.hpp"
+
+#include <osmium/builder/builder_helper.hpp>
+#include <osmium/geom/geos.hpp>
+
+#include "../basic/helper.hpp"
+
+TEST_CASE("GEOS_Geometry") {
+
+SECTION("point") {
+ osmium::geom::GEOSFactory<> factory;
+
+ std::unique_ptr<geos::geom::Point> 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<geos::geom::Point> 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<geos::geom::LineString> linestring {factory.create_linestring(wnl)};
+ REQUIRE(3 == linestring->getNumPoints());
+
+ std::unique_ptr<geos::geom::Point> p0 = std::unique_ptr<geos::geom::Point>(linestring->getPointN(0));
+ REQUIRE(3.2 == p0->getX());
+ std::unique_ptr<geos::geom::Point> p2 = std::unique_ptr<geos::geom::Point>(linestring->getPointN(2));
+ REQUIRE(3.6 == p2->getX());
+ }
+
+ {
+ std::unique_ptr<geos::geom::LineString> linestring {factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward)};
+ REQUIRE(3 == linestring->getNumPoints());
+ std::unique_ptr<geos::geom::Point> p0 = std::unique_ptr<geos::geom::Point>(linestring->getPointN(0));
+ REQUIRE(3.6 == p0->getX());
+ std::unique_ptr<geos::geom::Point> p2 = std::unique_ptr<geos::geom::Point>(linestring->getPointN(2));
+ REQUIRE(3.2 == p2->getX());
+ }
+
+ {
+ std::unique_ptr<geos::geom::LineString> linestring {factory.create_linestring(wnl, osmium::geom::use_nodes::all)};
+ REQUIRE(4 == linestring->getNumPoints());
+ std::unique_ptr<geos::geom::Point> p0 = std::unique_ptr<geos::geom::Point>(linestring->getPointN(0));
+ REQUIRE(3.2 == p0->getX());
+ }
+
+ {
+ std::unique_ptr<geos::geom::LineString> linestring {factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward)};
+ REQUIRE(4 == linestring->getNumPoints());
+ std::unique_ptr<geos::geom::Point> p0 = std::unique_ptr<geos::geom::Point>(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<geos::geom::MultiPolygon> mp {factory.create_multipolygon(area)};
+ REQUIRE(1 == mp->getNumGeometries());
+
+ const geos::geom::Polygon* p0 = dynamic_cast<const geos::geom::Polygon*>(mp->getGeometryN(0));
+ REQUIRE(0 == p0->getNumInteriorRing());
+
+ const geos::geom::LineString* l0e = p0->getExteriorRing();
+ REQUIRE(4 == l0e->getNumPoints());
+
+ std::unique_ptr<geos::geom::Point> l0e_p0 = std::unique_ptr<geos::geom::Point>(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<geos::geom::MultiPolygon> mp {factory.create_multipolygon(area)};
+ REQUIRE(1 == mp->getNumGeometries());
+
+ const geos::geom::Polygon* p0 = dynamic_cast<const geos::geom::Polygon*>(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<geos::geom::MultiPolygon> mp {factory.create_multipolygon(area)};
+ REQUIRE(2 == mp->getNumGeometries());
+
+ const geos::geom::Polygon* p0 = dynamic_cast<const geos::geom::Polygon*>(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<const geos::geom::Polygon*>(mp->getGeometryN(1));
+ REQUIRE(0 == p1->getNumInteriorRing());
+
+ const geos::geom::LineString* l1e = p1->getExteriorRing();
+ REQUIRE(5 == l1e->getNumPoints());
+}
+
+}
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_geos_wkb.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_geos_wkb.cpp
new file mode 100755
index 0000000000..0f54427e5d
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_geos_wkb.cpp
@@ -0,0 +1,156 @@
+#include "catch.hpp"
+
+#include <osmium/builder/builder_helper.hpp>
+#include <osmium/geom/geos.hpp>
+#include <osmium/geom/wkb.hpp>
+
+#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::geom::Point> geos_point = geos_factory.create_point(osmium::Location(3.2, 4.2));
+ REQUIRE(geos_to_wkb(geos_point.get()) == wkb);
+}
+
+
+SECTION("linestring") {
+ osmium::geom::WKBFactory<> wkb_factory(osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex);
+ osmium::geom::GEOSFactory<> geos_factory;
+
+ osmium::memory::Buffer buffer(10000);
+ auto& wnl = 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::geom::LineString> geos = geos_factory.create_linestring(wnl);
+ REQUIRE(geos_to_wkb(geos.get()) == wkb);
+ }
+
+ {
+ std::string wkb = wkb_factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward);
+ std::unique_ptr<geos::geom::LineString> geos = geos_factory.create_linestring(wnl, osmium::geom::use_nodes::unique, osmium::geom::direction::backward);
+ REQUIRE(geos_to_wkb(geos.get()) == wkb);
+ }
+
+ {
+ std::string wkb = wkb_factory.create_linestring(wnl, osmium::geom::use_nodes::all);
+ std::unique_ptr<geos::geom::LineString> geos = geos_factory.create_linestring(wnl, osmium::geom::use_nodes::all);
+ REQUIRE(geos_to_wkb(geos.get()) == wkb);
+ }
+
+ {
+ std::string wkb = wkb_factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward);
+ std::unique_ptr<geos::geom::LineString> geos = geos_factory.create_linestring(wnl, osmium::geom::use_nodes::all, osmium::geom::direction::backward);
+ REQUIRE(geos_to_wkb(geos.get()) == wkb);
+ }
+}
+
+SECTION("area_1outer_0inner") {
+ osmium::geom::WKBFactory<> wkb_factory(osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex);
+ osmium::geom::GEOSFactory<> geos_factory;
+
+ osmium::memory::Buffer buffer(10000);
+ 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::geom::MultiPolygon> geos = geos_factory.create_multipolygon(area);
+ REQUIRE(geos_to_wkb(geos.get()) == wkb);
+}
+
+SECTION("area_1outer_1inner") {
+ osmium::geom::WKBFactory<> wkb_factory(osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex);
+ osmium::geom::GEOSFactory<> geos_factory;
+
+ osmium::memory::Buffer buffer(10000);
+ 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::geom::MultiPolygon> geos = geos_factory.create_multipolygon(area);
+ REQUIRE(geos_to_wkb(geos.get()) == wkb);
+}
+
+SECTION("area_2outer_2inner") {
+ osmium::geom::WKBFactory<> wkb_factory(osmium::geom::wkb_type::wkb, osmium::geom::out_type::hex);
+ osmium::geom::GEOSFactory<> geos_factory;
+
+ osmium::memory::Buffer buffer(10000);
+ 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::geom::MultiPolygon> geos = geos_factory.create_multipolygon(area);
+ REQUIRE(geos_to_wkb(geos.get()) == wkb);
+}
+
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_mercator.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_mercator.cpp
new file mode 100755
index 0000000000..cc16e55cf6
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_mercator.cpp
@@ -0,0 +1,37 @@
+#include "catch.hpp"
+
+#include <osmium/geom/mercator_projection.hpp>
+
+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(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 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));
+ }
+
+}
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_ogr.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_ogr.cpp
new file mode 100755
index 0000000000..28a10717de
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_ogr.cpp
@@ -0,0 +1,185 @@
+#include "catch.hpp"
+
+#include <osmium/builder/builder_helper.hpp>
+#include <osmium/geom/ogr.hpp>
+
+#include "../basic/helper.hpp"
+
+TEST_CASE("OGR_Geometry") {
+
+SECTION("point") {
+ osmium::geom::OGRFactory<> factory;
+
+ std::unique_ptr<OGRPoint> 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<OGRLineString> linestring {factory.create_linestring(wnl)};
+ REQUIRE(3 == linestring->getNumPoints());
+
+ REQUIRE(3.2 == linestring->getX(0));
+ REQUIRE(3.6 == linestring->getX(2));
+ }
+
+ {
+ std::unique_ptr<OGRLineString> 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<OGRLineString> linestring {factory.create_linestring(wnl, osmium::geom::use_nodes::all)};
+ REQUIRE(4 == linestring->getNumPoints());
+
+ REQUIRE(3.2 == linestring->getX(0));
+ }
+
+ {
+ std::unique_ptr<OGRLineString> 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<OGRMultiPolygon> mp {factory.create_multipolygon(area)};
+ REQUIRE(1 == mp->getNumGeometries());
+
+ const OGRPolygon* p0 = dynamic_cast<const OGRPolygon*>(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<OGRMultiPolygon> mp {factory.create_multipolygon(area)};
+ REQUIRE(1 == mp->getNumGeometries());
+
+ const OGRPolygon* p0 = dynamic_cast<const OGRPolygon*>(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<OGRMultiPolygon> mp {factory.create_multipolygon(area)};
+ REQUIRE(2 == mp->getNumGeometries());
+
+ const OGRPolygon* p0 = dynamic_cast<const OGRPolygon*>(mp->getGeometryRef(0));
+ REQUIRE(2 == p0->getNumInteriorRings());
+
+ const OGRLineString* l0e = p0->getExteriorRing();
+ REQUIRE(5 == l0e->getNumPoints());
+
+ const OGRPolygon* p1 = dynamic_cast<const OGRPolygon*>(mp->getGeometryRef(1));
+ REQUIRE(0 == p1->getNumInteriorRings());
+
+ const OGRLineString* l1e = p1->getExteriorRing();
+ REQUIRE(5 == l1e->getNumPoints());
+}
+
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_projection.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_projection.cpp
new file mode 100755
index 0000000000..2257d7f066
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_projection.cpp
@@ -0,0 +1,131 @@
+#include "catch.hpp"
+
+#include <osmium/geom/factory.hpp>
+#include <osmium/geom/mercator_projection.hpp>
+#include <osmium/geom/projection.hpp>
+
+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(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(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(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(projection(loc).x == Approx(c.x).epsilon(0.1));
+ REQUIRE(projection(loc).y == Approx(c.y).epsilon(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(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(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(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(projection(loc).x == Approx(c.x).epsilon(0.1));
+ REQUIRE(projection(loc).y == Approx(c.y).epsilon(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(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(projection_merc(loc).x == Approx(projection_3857(loc).x).epsilon(0.1));
+ REQUIRE(projection_merc(loc).y == Approx(projection_3857(loc).y).epsilon(0.1));
+ }
+ {
+ const osmium::Location loc(-0.001, 0.001);
+ REQUIRE(projection_merc(loc).x == Approx(projection_3857(loc).x).epsilon(0.1));
+ REQUIRE(projection_merc(loc).y == Approx(projection_3857(loc).y).epsilon(0.1));
+ }
+ {
+ const osmium::Location loc(-85.2, -85.2);
+ REQUIRE(projection_merc(loc).x == Approx(projection_3857(loc).x).epsilon(0.1));
+ REQUIRE(projection_merc(loc).y == Approx(projection_3857(loc).y).epsilon(0.1));
+ }
+}
+
+}
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_wkb.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_wkb.cpp
new file mode 100755
index 0000000000..730ee75adf
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_wkb.cpp
@@ -0,0 +1,133 @@
+#include "catch.hpp"
+
+#include <osmium/builder/builder_helper.hpp>
+#include <osmium/geom/wkb.hpp>
+
+#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/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_wkt.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_wkt.cpp
new file mode 100755
index 0000000000..ff1417c72e
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/geom/test_wkt.cpp
@@ -0,0 +1,198 @@
+#include "catch.hpp"
+
+#include <osmium/builder/builder_helper.hpp>
+#include <osmium/geom/wkt.hpp>
+
+#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/3party/osrm/osrm-backend/third_party/libosmium/test/t/index/test_id_to_location.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/index/test_id_to_location.cpp
new file mode 100755
index 0000000000..4aca238b69
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/index/test_id_to_location.cpp
@@ -0,0 +1,170 @@
+#include "catch.hpp"
+
+#include <osmium/osm/types.hpp>
+#include <osmium/osm/location.hpp>
+
+#include <osmium/index/map/dense_file_array.hpp>
+#include <osmium/index/map/dense_mem_array.hpp>
+#include <osmium/index/map/dense_mmap_array.hpp>
+#include <osmium/index/map/dummy.hpp>
+#include <osmium/index/map/sparse_file_array.hpp>
+#include <osmium/index/map/sparse_mem_array.hpp>
+#include <osmium/index/map/sparse_mem_map.hpp>
+#include <osmium/index/map/sparse_mem_table.hpp>
+#include <osmium/index/map/sparse_mmap_array.hpp>
+
+#include <osmium/index/node_locations_map.hpp>
+
+template <typename TIndex>
+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 <typename TIndex>
+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<osmium::unsigned_object_id_type, osmium::Location> index_type;
+
+ index_type index1;
+
+ REQUIRE(0 == index1.size());
+ REQUIRE(0 == index1.used_memory());
+
+ test_func_all<index_type>(index1);
+
+ REQUIRE(0 == index1.size());
+ REQUIRE(0 == index1.used_memory());
+ }
+
+ SECTION("DenseMemArray") {
+ typedef osmium::index::map::DenseMemArray<osmium::unsigned_object_id_type, osmium::Location> index_type;
+
+ index_type index1;
+ index1.reserve(1000);
+ test_func_all<index_type>(index1);
+
+ index_type index2;
+ index2.reserve(1000);
+ test_func_real<index_type>(index2);
+ }
+
+#ifdef __linux__
+ SECTION("DenseMmapArray") {
+ typedef osmium::index::map::DenseMmapArray<osmium::unsigned_object_id_type, osmium::Location> index_type;
+
+ index_type index1;
+ test_func_all<index_type>(index1);
+
+ index_type index2;
+ test_func_real<index_type>(index2);
+ }
+#else
+# pragma message("not running 'DenseMapMmap' test case on this machine")
+#endif
+
+ SECTION("DenseFileArray") {
+ typedef osmium::index::map::DenseFileArray<osmium::unsigned_object_id_type, osmium::Location> index_type;
+
+ index_type index1;
+ test_func_all<index_type>(index1);
+
+ index_type index2;
+ test_func_real<index_type>(index2);
+ }
+
+#ifdef OSMIUM_WITH_SPARSEHASH
+
+ SECTION("SparseMemTable") {
+ typedef osmium::index::map::SparseMemTable<osmium::unsigned_object_id_type, osmium::Location> index_type;
+
+ index_type index1;
+ test_func_all<index_type>(index1);
+
+ index_type index2;
+ test_func_real<index_type>(index2);
+ }
+
+#endif
+
+ SECTION("SparseMemMap") {
+ typedef osmium::index::map::SparseMemMap<osmium::unsigned_object_id_type, osmium::Location> index_type;
+
+ index_type index1;
+ test_func_all<index_type>(index1);
+
+ index_type index2;
+ test_func_real<index_type>(index2);
+ }
+
+ SECTION("SparseMemArray") {
+ typedef osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location> index_type;
+
+ index_type index1;
+
+ REQUIRE(0 == index1.size());
+ REQUIRE(0 == index1.used_memory());
+
+ test_func_all<index_type>(index1);
+
+ REQUIRE(2 == index1.size());
+
+ index_type index2;
+ test_func_real<index_type>(index2);
+ }
+
+ SECTION("Dynamic map choice") {
+ typedef osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location> map_type;
+ const auto& map_factory = osmium::index::MapFactory<osmium::unsigned_object_id_type, osmium::Location>::instance();
+
+ std::vector<std::string> 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<map_type> index1 = map_factory.create_map(map_type_name);
+ index1->reserve(1000);
+ test_func_all<map_type>(*index1);
+
+ std::unique_ptr<map_type> index2 = map_factory.create_map(map_type_name);
+ index2->reserve(1000);
+ test_func_real<map_type>(*index2);
+ }
+ }
+
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/t/index/test_typed_mmap.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/index/test_typed_mmap.cpp
new file mode 100755
index 0000000000..bcc17bd2d2
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/index/test_typed_mmap.cpp
@@ -0,0 +1,76 @@
+#include "catch.hpp"
+
+#include <osmium/index/detail/typed_mmap.hpp>
+
+#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<uint64_t>::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<uint64_t>::unmap(data, 10);
+ }
+
+ SECTION("MmapSizeZero") {
+ REQUIRE_THROWS_AS(osmium::detail::typed_mmap<uint64_t>::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<uint64_t>::map(1ULL << (sizeof(size_t) * 6)), std::system_error);
+ }
+ }
+
+#ifdef __linux__
+ SECTION("Remap") {
+ uint64_t* data = osmium::detail::typed_mmap<uint64_t>::map(10);
+
+ data[0] = 4ul;
+ data[3] = 9ul;
+ data[9] = 25ul;
+
+ uint64_t* new_data = osmium::detail::typed_mmap<uint64_t>::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[] = "test_mmap_file_size_XXXXXX";
+ const int fd = mkstemp(filename);
+ REQUIRE(fd > 0);
+ REQUIRE(0 == osmium::detail::typed_mmap<uint64_t>::file_size(fd));
+ REQUIRE(0 == ftruncate(fd, size * sizeof(uint64_t)));
+ REQUIRE(size == osmium::detail::typed_mmap<uint64_t>::file_size(fd));
+
+ osmium::detail::typed_mmap<uint64_t>::grow_file(size / 2, fd);
+ REQUIRE(size == osmium::detail::typed_mmap<uint64_t>::file_size(fd));
+
+ osmium::detail::typed_mmap<uint64_t>::grow_file(size, fd);
+ REQUIRE(size == osmium::detail::typed_mmap<uint64_t>::file_size(fd));
+
+ osmium::detail::typed_mmap<uint64_t>::grow_file(size * 2, fd);
+ REQUIRE((size * 2) == osmium::detail::typed_mmap<uint64_t>::file_size(fd));
+
+ REQUIRE(0 == close(fd));
+ REQUIRE(0 == unlink(filename));
+ }
+
+}
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/t/index/test_typed_mmap_grow.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/index/test_typed_mmap_grow.cpp
new file mode 100755
index 0000000000..92ee0b40ea
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/index/test_typed_mmap_grow.cpp
@@ -0,0 +1,34 @@
+#include "catch.hpp"
+
+#include <osmium/index/detail/typed_mmap.hpp>
+
+#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<uint64_t>::grow_and_map(size, fd);
+ REQUIRE(size == osmium::detail::typed_mmap<uint64_t>::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<uint64_t>::unmap(data, size);
+
+ REQUIRE(0 == close(fd));
+ REQUIRE(0 == unlink(filename));
+ }
+
+}
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data.osm b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data.osm
new file mode 100755
index 0000000000..fffb77ad3c
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data.osm
@@ -0,0 +1,4 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<osm version="0.6" generator="testdata" upload="false">
+ <node id="1" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lon="1.02" lat="1.02"/>
+</osm>
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data.osm.bz2 b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data.osm.bz2
new file mode 100755
index 0000000000..0f38797ebc
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data.osm.bz2
Binary files differ
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data.osm.gz b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data.osm.gz
new file mode 100755
index 0000000000..07edb9095b
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data.osm.gz
Binary files differ
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data_bzip2.txt b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data_bzip2.txt
new file mode 100755
index 0000000000..755d6af45a
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data_bzip2.txt
@@ -0,0 +1 @@
+TESTDATA
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data_bzip2.txt.bz2 b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data_bzip2.txt.bz2
new file mode 100755
index 0000000000..f0ee7e7d65
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/data_bzip2.txt.bz2
Binary files differ
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/test_bzip2.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/test_bzip2.cpp
new file mode 100755
index 0000000000..5cc30b4272
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/test_bzip2.cpp
@@ -0,0 +1,33 @@
+#include "catch.hpp"
+#include "utils.hpp"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <osmium/io/bzip2_compression.hpp>
+
+TEST_CASE("Bzip2") {
+
+ 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);
+
+ 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/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/test_file_formats.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/test_file_formats.cpp
new file mode 100755
index 0000000000..e8785d6a41
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/test_file_formats.cpp
@@ -0,0 +1,251 @@
+#include "catch.hpp"
+
+#include <iterator>
+
+#include <osmium/io/file.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/test_output_iterator.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/test_output_iterator.cpp
new file mode 100755
index 0000000000..7a1f570275
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/test_output_iterator.cpp
@@ -0,0 +1,37 @@
+#include "catch.hpp"
+
+#include <osmium/io/xml_output.hpp>
+#include <osmium/io/output_iterator.hpp>
+#include <osmium/io/writer.hpp>
+
+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<osmium::io::Writer> out1(writer);
+
+ osmium::io::OutputIterator<osmium::io::Writer> 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<osmium::io::Writer> out1(writer1);
+ osmium::io::OutputIterator<osmium::io::Writer> 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<osmium::io::Writer> out(writer);
+
+ ++out;
+ }
+
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/test_reader.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/test_reader.cpp
new file mode 100755
index 0000000000..9a06d84085
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/io/test_reader.cpp
@@ -0,0 +1,117 @@
+#include "catch.hpp"
+#include "utils.hpp"
+
+#include <osmium/handler.hpp>
+#include <osmium/io/any_compression.hpp>
+#include <osmium/io/xml_input.hpp>
+#include <osmium/visitor.hpp>
+#include <osmium/memory/buffer.hpp>
+
+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(with_data_dir("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(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(with_data_dir("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(with_data_dir("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(with_data_dir("t/io/data.osm"));
+ REQUIRE(fd >= 0);
+
+ const size_t buffer_size = 1000;
+ char buffer[buffer_size];
+ auto length = ::read(fd, buffer, buffer_size);
+ REQUIRE(length > 0);
+
+ osmium::io::File file(buffer, static_cast<size_t>(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(with_data_dir("t/io/data.osm.gz"));
+ REQUIRE(fd >= 0);
+
+ const size_t buffer_size = 1000;
+ char buffer[buffer_size];
+ auto length = ::read(fd, buffer, buffer_size);
+ REQUIRE(length > 0);
+
+ osmium::io::File file(buffer, static_cast<size_t>(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(with_data_dir("t/io/data.osm.bz2"));
+ REQUIRE(fd >= 0);
+
+ const size_t buffer_size = 1000;
+ char buffer[buffer_size];
+ auto length = ::read(fd, buffer, buffer_size);
+ REQUIRE(length > 0);
+
+ osmium::io::File file(buffer, static_cast<size_t>(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/3party/osrm/osrm-backend/third_party/libosmium/test/t/tags/test_filter.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/tags/test_filter.cpp
new file mode 100755
index 0000000000..eefa5b076d
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/tags/test_filter.cpp
@@ -0,0 +1,216 @@
+#include "catch.hpp"
+
+#include <algorithm>
+
+#include <osmium/builder/builder_helper.hpp>
+#include <osmium/memory/buffer.hpp>
+#include <osmium/osm/tag.hpp>
+#include <osmium/tags/taglist.hpp>
+#include <osmium/tags/filter.hpp>
+#include <osmium/tags/regex_filter.hpp>
+
+template <class TFilter>
+void check_filter(const osmium::TagList& tag_list, const TFilter filter, const std::vector<bool>& 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<bool> 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<bool> 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/3party/osrm/osrm-backend/third_party/libosmium/test/t/tags/test_operators.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/tags/test_operators.cpp
new file mode 100755
index 0000000000..33a53c2a25
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/tags/test_operators.cpp
@@ -0,0 +1,61 @@
+#include "catch.hpp"
+
+#include <iterator>
+
+#include <osmium/builder/osm_object_builder.hpp>
+#include <osmium/memory/buffer.hpp>
+#include <osmium/osm/tag.hpp>
+
+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<const osmium::TagList>(0);
+ const osmium::TagList& tl2 = buffer2.get<const osmium::TagList>(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<const osmium::TagList>(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/3party/osrm/osrm-backend/third_party/libosmium/test/t/tags/test_tag_list.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/tags/test_tag_list.cpp
new file mode 100755
index 0000000000..c2512d1251
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/tags/test_tag_list.cpp
@@ -0,0 +1,76 @@
+#include "catch.hpp"
+
+#include <osmium/builder/builder_helper.hpp>
+#include <osmium/memory/buffer.hpp>
+#include <osmium/osm/tag.hpp>
+
+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<const char*, const char*>({
+ { "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/3party/osrm/osrm-backend/third_party/libosmium/test/t/thread/test_pool.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/thread/test_pool.cpp
new file mode 100755
index 0000000000..66bb3734a8
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/thread/test_pool.cpp
@@ -0,0 +1,69 @@
+#include "catch.hpp"
+
+#include <chrono>
+#include <stdexcept>
+#include <thread>
+
+#include <osmium/thread/pool.hpp>
+
+static std::atomic<int> 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/3party/osrm/osrm-backend/third_party/libosmium/test/t/util/test_cast_with_assert.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/util/test_cast_with_assert.cpp
new file mode 100755
index 0000000000..0231f30e14
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/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 <osmium/util/cast.hpp>
+
+TEST_CASE("static_cast_with_assert") {
+
+ SECTION("same types is always okay") {
+ int f = 10;
+ auto t = osmium::static_cast_with_assert<int>(f);
+ REQUIRE(t == f);
+ }
+
+ SECTION("casting to larger type is always okay") {
+ int16_t f = 10;
+ auto t = osmium::static_cast_with_assert<int32_t>(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<int16_t>(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<int16_t>(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<uint16_t>(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<uint16_t>(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<uint16_t>(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<uint16_t>(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<uint16_t>(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<uint16_t>(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<int16_t>(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<int16_t>(f), assert_error);
+ }
+
+
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/t/util/test_double.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/util/test_double.cpp
new file mode 100755
index 0000000000..6cc87a03ae
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/util/test_double.cpp
@@ -0,0 +1,33 @@
+#include "catch.hpp"
+
+#include <osmium/util/double.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/test/t/util/test_options.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/util/test_options.cpp
new file mode 100755
index 0000000000..969f20103f
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/util/test_options.cpp
@@ -0,0 +1,48 @@
+#include "catch.hpp"
+
+#include <iterator>
+
+#include <osmium/util/options.hpp>
+
+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/3party/osrm/osrm-backend/third_party/libosmium/test/t/util/test_string.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/t/util/test_string.cpp
new file mode 100755
index 0000000000..fa49787791
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/t/util/test_string.cpp
@@ -0,0 +1,57 @@
+#include "catch.hpp"
+
+#include <osmium/util/string.hpp>
+
+TEST_CASE("split_string") {
+
+ SECTION("split_string string") {
+ std::string str { "foo,baramba,baz" };
+ std::vector<std::string> result = {"foo", "baramba", "baz"};
+
+ REQUIRE(result == osmium::split_string(str, ','));
+ }
+
+ SECTION("split_string string without sep") {
+ std::string str { "foo" };
+ std::vector<std::string> result = {"foo"};
+
+ REQUIRE(result == osmium::split_string(str, ','));
+ }
+
+ SECTION("split_string string with empty at end") {
+ std::string str { "foo,bar," };
+ std::vector<std::string> result = {"foo", "bar", ""};
+
+ REQUIRE(result == osmium::split_string(str, ','));
+ }
+
+ SECTION("split_string string with empty in middle") {
+ std::string str { "foo,,bar" };
+ std::vector<std::string> result = {"foo", "", "bar"};
+
+ REQUIRE(result == osmium::split_string(str, ','));
+ }
+
+ SECTION("split_string string with empty at start") {
+ std::string str { ",bar,baz" };
+ std::vector<std::string> result = {"", "bar", "baz"};
+
+ REQUIRE(result == osmium::split_string(str, ','));
+ }
+
+ SECTION("split_string sep") {
+ std::string str { "," };
+ std::vector<std::string> result = {"", ""};
+
+ REQUIRE(result == osmium::split_string(str, ','));
+ }
+
+ SECTION("split_string empty string") {
+ std::string str { "" };
+ std::vector<std::string> result;
+
+ REQUIRE(result == osmium::split_string(str, ','));
+ }
+
+}
+
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/test_main.cpp b/3party/osrm/osrm-backend/third_party/libosmium/test/test_main.cpp
new file mode 100755
index 0000000000..0c7c351f43
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/test_main.cpp
@@ -0,0 +1,2 @@
+#define CATCH_CONFIG_MAIN
+#include "catch.hpp"
diff --git a/3party/osrm/osrm-backend/third_party/libosmium/test/valgrind.supp b/3party/osrm/osrm-backend/third_party/libosmium/test/valgrind.supp
new file mode 100755
index 0000000000..f6ef1f65a2
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/libosmium/test/valgrind.supp
@@ -0,0 +1,47 @@
+#-----------------------------------------------------------------------------
+#
+# 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
+ 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_*
+}
diff --git a/3party/osrm/osrm-backend/third_party/variant/.gitignore b/3party/osrm/osrm-backend/third_party/variant/.gitignore
new file mode 100755
index 0000000000..5620e5dd16
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/.gitignore
@@ -0,0 +1,3 @@
+.DS_Store
+out
+profiling \ No newline at end of file
diff --git a/3party/osrm/osrm-backend/third_party/variant/.travis.yml b/3party/osrm/osrm-backend/third_party/variant/.travis.yml
new file mode 100755
index 0000000000..cd1e655785
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/.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/3party/osrm/osrm-backend/third_party/variant/Jamroot b/3party/osrm/osrm-backend/third_party/variant/Jamroot
new file mode 100755
index 0000000000..aead87091b
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/Jamroot
@@ -0,0 +1,75 @@
+local BOOST_DIR = "/opt/boost" ;
+
+#using clang : : ;
+
+lib system : : <name>boost_system <search>$(BOOST_DIR)/lib ;
+lib timer : chrono : <name>boost_timer <search>$(BOOST_DIR)/lib ;
+lib chrono : system : <name>boost_chrono <search>$(BOOST_DIR)/lib ;
+
+exe variant-test
+ :
+ test/bench_variant.cpp
+ .//system
+ .//timer
+ .//chrono
+ :
+ <include>$(BOOST_DIR)/include
+ <include>./
+ <cxxflags>-std=c++11
+ #<define>SINGLE_THREADED
+ <variant>release:<cxxflags>-march=native
+ ;
+
+
+exe binary-visitor-test
+ :
+ test/binary_visitor_test.cpp
+ .//system
+ .//timer
+ .//chrono
+ :
+ <include>$(BOOST_DIR)/include
+ <include>./
+ <cxxflags>-std=c++11
+ <variant>release:<cxxflags>-march=native
+ ;
+
+exe recursive-wrapper-test
+ :
+ test/recursive_wrapper_test.cpp
+ .//system
+ .//timer
+ .//chrono
+ :
+ <include>$(BOOST_DIR)/include
+ <include>./
+ <cxxflags>-std=c++11
+ <variant>release:<cxxflags>-march=native
+ ;
+
+exe unique-ptr-test
+ :
+ test/unique_ptr_test.cpp
+ .//system
+ .//timer
+ .//chrono
+ :
+ <include>$(BOOST_DIR)/include
+ <include>./
+ <cxxflags>-std=c++11
+ <variant>release:<cxxflags>-march=native
+ ;
+
+
+exe reference_wrapper_test
+ :
+ test/reference_wrapper_test.cpp
+ .//system
+ .//timer
+ .//chrono
+ :
+ <include>$(BOOST_DIR)/include
+ <include>./
+ <cxxflags>-std=c++11
+ <variant>release:<cxxflags>-march=native
+ ;
diff --git a/3party/osrm/osrm-backend/third_party/variant/LICENSE b/3party/osrm/osrm-backend/third_party/variant/LICENSE
new file mode 100755
index 0000000000..6c4ce40d5a
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/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/3party/osrm/osrm-backend/third_party/variant/README.md b/3party/osrm/osrm-backend/third_party/variant/README.md
new file mode 100755
index 0000000000..791131d39a
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/README.md
@@ -0,0 +1,67 @@
+# 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)
+[![Coverage Status](https://coveralls.io/repos/mapbox/variant/badge.svg?branch=master)](https://coveralls.io/r/mapbox/variant?branch=master)
+
+# 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/3party/osrm/osrm-backend/third_party/variant/appveyor.yml b/3party/osrm/osrm-backend/third_party/variant/appveyor.yml
new file mode 100755
index 0000000000..9d7c59984c
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/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/3party/osrm/osrm-backend/third_party/variant/common.gypi b/3party/osrm/osrm-backend/third_party/variant/common.gypi
new file mode 100755
index 0000000000..67e333b7ee
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/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/3party/osrm/osrm-backend/third_party/variant/optional.hpp b/3party/osrm/osrm-backend/third_party/variant/optional.hpp
new file mode 100755
index 0000000000..133e2c8f97
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/optional.hpp
@@ -0,0 +1,69 @@
+#ifndef MAPBOX_UTIL_OPTIONAL_HPP
+#define MAPBOX_UTIL_OPTIONAL_HPP
+
+#include <type_traits>
+
+#include "variant.hpp"
+
+namespace mapbox
+{
+namespace util
+{
+
+template <typename T> class optional
+{
+ static_assert(!std::is_reference<T>::value, "optional doesn't support references");
+
+ struct none_type
+ {
+ };
+
+ variant<none_type, T> 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>(); }
+
+ T const &get() const { return variant_.template get<T>(); }
+ T &get() { return variant_.template get<T>(); }
+
+ 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 <typename... Args> void emplace(Args &&... args)
+ {
+ variant_ = T{std::forward<Args>(args)...};
+ }
+
+ void reset() { variant_ = none_type{}; }
+};
+}
+}
+
+#endif
diff --git a/3party/osrm/osrm-backend/ThirdParty/variant/recursive_wrapper.hpp b/3party/osrm/osrm-backend/third_party/variant/recursive_wrapper.hpp
index 05c18e9647..54b27634a3 100644..100755
--- a/3party/osrm/osrm-backend/ThirdParty/variant/recursive_wrapper.hpp
+++ b/3party/osrm/osrm-backend/third_party/variant/recursive_wrapper.hpp
@@ -2,7 +2,6 @@
#define MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP
#include <utility>
-#include "../../../../../std/msvc_cpp11_workarounds.hpp"
namespace mapbox { namespace util {
@@ -43,7 +42,7 @@ public:
return *this;
}
- inline void swap(recursive_wrapper& operand) NOEXCEPT_MODIFIER
+ inline void swap(recursive_wrapper& operand) noexcept
{
T* temp = operand.p_;
operand.p_ = p_;
@@ -51,7 +50,7 @@ public:
}
- recursive_wrapper& operator=(recursive_wrapper&& rhs) NOEXCEPT_MODIFIER
+ recursive_wrapper& operator=(recursive_wrapper&& rhs) noexcept
{
swap(rhs);
return *this;
@@ -118,7 +117,7 @@ void recursive_wrapper<T>::assign(const T& rhs)
}
template <typename T>
-inline void swap(recursive_wrapper<T>& lhs, recursive_wrapper<T>& rhs) NOEXCEPT_MODIFIER
+inline void swap(recursive_wrapper<T>& lhs, recursive_wrapper<T>& rhs) noexcept
{
lhs.swap(rhs);
}
diff --git a/3party/osrm/osrm-backend/third_party/variant/scripts/linux.sh b/3party/osrm/osrm-backend/third_party/variant/scripts/linux.sh
new file mode 100755
index 0000000000..f173db5c35
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/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/3party/osrm/osrm-backend/third_party/variant/scripts/osx.sh b/3party/osrm/osrm-backend/third_party/variant/scripts/osx.sh
new file mode 100755
index 0000000000..14149ca042
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/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/3party/osrm/osrm-backend/third_party/variant/test/bench_variant.cpp b/3party/osrm/osrm-backend/third_party/variant/test/bench_variant.cpp
new file mode 100755
index 0000000000..f27124593a
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/test/bench_variant.cpp
@@ -0,0 +1,204 @@
+#include <iostream>
+#include <vector>
+#include <thread>
+#include <string>
+#include <utility>
+#include <boost/variant.hpp>
+#include <boost/timer/timer.hpp>
+#include "variant.hpp"
+
+#define TEXT "Testing various variant implementations with a longish string ........................................."
+//#define BOOST_VARIANT_MINIMIZE_SIZE
+
+using namespace mapbox;
+
+namespace test {
+
+template <typename V>
+struct Holder
+{
+ typedef V value_type;
+ std::vector<value_type> data;
+
+ template <typename T>
+ void append_move(T && obj)
+ {
+ data.emplace_back(std::forward<T>(obj));
+ }
+
+ template <typename T>
+ void append(T const& obj)
+ {
+ data.push_back(obj);
+ }
+};
+
+} // namespace test
+
+struct print : util::static_visitor<>
+{
+ template <typename T>
+ void operator() (T const& val) const
+ {
+ std::cerr << val << ":" << typeid(T).name() << std::endl;
+ }
+};
+
+
+template <typename V>
+struct dummy : boost::static_visitor<>
+{
+ dummy(V & v)
+ : v_(v) {}
+
+ template <typename T>
+ void operator() (T const& val) const
+ {
+ v_ = val;
+ }
+ V & v_;
+};
+
+template <typename V>
+struct dummy2 : util::static_visitor<>
+{
+ dummy2(V & v)
+ : v_(v) {}
+
+ template <typename T>
+ void operator() (T const& val) const
+ {
+ v_.template set<T>(val);
+ }
+ V & v_;
+};
+
+void run_boost_test(std::size_t runs)
+{
+ test::Holder<boost::variant<int, double, std::string>> 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<int, double, std::string> v;
+ for (auto const& v2 : h.data)
+ {
+ dummy<boost::variant<int, double, std::string>> d(v);
+ boost::apply_visitor(d, v2);
+ }
+}
+
+void run_variant_test(std::size_t runs)
+{
+ test::Holder<util::variant<int, double, std::string>> 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<int, double, std::string> v;
+ for (auto const& v2 : h.data)
+ {
+ dummy2<util::variant<int, double, std::string>> d(v);
+ util::apply_visitor (d, v2);
+ }
+}
+
+int main (int argc, char** argv)
+{
+ if (argc!=2)
+ {
+ std::cerr << "Usage:" << argv[0] << " <num-runs>" << std::endl;
+ return 1;
+ }
+
+#ifndef SINGLE_THREADED
+ const std::size_t THREADS = 4;
+#endif
+ const std::size_t NUM_RUNS = static_cast<std::size_t>(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<std::unique_ptr<std::thread>> 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; i<THREADS; ++i)
+ {
+ tg.emplace_back(new std::thread(run_variant_test, NUM_RUNS));
+ }
+ std::for_each(tg.begin(), tg.end(), [](value_type & t) {if (t->joinable()) t->join();});
+ }
+
+ {
+ typedef std::vector<std::unique_ptr<std::thread>> 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; i<THREADS; ++i)
+ {
+ tg.emplace_back(new std::thread(run_boost_test, NUM_RUNS));
+ }
+ std::for_each(tg.begin(), tg.end(), [](value_type & t) {if (t->joinable()) t->join();});
+ }
+
+ {
+ typedef std::vector<std::unique_ptr<std::thread>> 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; i<THREADS; ++i)
+ {
+ tg.emplace_back(new std::thread(run_variant_test, NUM_RUNS));
+ }
+ std::for_each(tg.begin(), tg.end(), [](value_type & t) {if (t->joinable()) t->join();});
+ }
+
+ {
+ typedef std::vector<std::unique_ptr<std::thread>> 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; i<THREADS; ++i)
+ {
+ tg.emplace_back(new std::thread(run_boost_test, NUM_RUNS));
+ }
+ std::for_each(tg.begin(), tg.end(), [](value_type & t) {if (t->joinable()) t->join();});
+ }
+#endif
+
+
+ return EXIT_SUCCESS;
+}
diff --git a/3party/osrm/osrm-backend/third_party/variant/test/binary_visitor_test.cpp b/3party/osrm/osrm-backend/third_party/variant/test/binary_visitor_test.cpp
new file mode 100755
index 0000000000..de2a30e6c9
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/test/binary_visitor_test.cpp
@@ -0,0 +1,136 @@
+#include <cstdint>
+#include <iostream>
+#include <vector>
+#include <thread>
+#include <string>
+#include <sstream>
+#include <utility>
+#include <type_traits>
+#include <boost/variant.hpp>
+#include <boost/timer/timer.hpp>
+#include "variant.hpp"
+#include "variant_io.hpp"
+
+using namespace mapbox;
+
+namespace test {
+
+template <typename T>
+struct string_to_number {};
+
+template <>
+struct string_to_number<double>
+{
+ double operator() (std::string const& str) const
+ {
+ return std::stod(str);
+ }
+};
+
+template <>
+struct string_to_number<std::int64_t>
+{
+ std::int64_t operator() (std::string const& str) const
+ {
+ return std::stoll(str);
+ }
+};
+
+template <>
+struct string_to_number<std::uint64_t>
+{
+ std::uint64_t operator() (std::string const& str) const
+ {
+ return std::stoull(str);
+ }
+};
+
+template <>
+struct string_to_number<bool>
+{
+ bool operator() (std::string const& str) const
+ {
+ bool result;
+ std::istringstream(str) >> std::boolalpha >> result;
+ return result;
+ }
+};
+
+struct javascript_equal_visitor : util::static_visitor<bool>
+{
+ template <typename T>
+ bool operator() (T lhs, T rhs) const
+ {
+ return lhs == rhs;
+ }
+
+ template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
+ bool operator() (T lhs, std::string const& rhs) const
+ {
+ return lhs == string_to_number<T>()(rhs);
+ }
+
+ template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
+ bool operator() (std::string const& lhs, T rhs) const
+ {
+ return string_to_number<T>()(lhs) == rhs;
+ }
+
+ template <typename T0, typename T1>
+ bool operator() (T0 lhs, T1 rhs) const
+ {
+ return lhs == static_cast<T0>(rhs);
+ }
+};
+
+template <typename T>
+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<bool, std::int64_t, std::uint64_t, double, std::string> 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<variant_type> 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<variant_type>(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/3party/osrm/osrm-backend/third_party/variant/test/boost_variant_hello_world.cpp b/3party/osrm/osrm-backend/third_party/variant/test/boost_variant_hello_world.cpp
new file mode 100755
index 0000000000..0d0925a7e3
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/test/boost_variant_hello_world.cpp
@@ -0,0 +1,19 @@
+#include <boost/variant.hpp>
+#include <cstdint>
+#include <stdexcept>
+
+struct check : boost::static_visitor<>
+{
+ template <typename T>
+ void operator() (T const& val) const
+ {
+ if (val != 0) throw std::runtime_error("invalid");
+ }
+};
+
+int main() {
+ typedef boost::variant<bool, int, double> variant_type;
+ variant_type v(0);
+ boost::apply_visitor(check(), v);
+ return 0;
+}
diff --git a/3party/osrm/osrm-backend/third_party/variant/test/catch.hpp b/3party/osrm/osrm-backend/third_party/variant/test/catch.hpp
new file mode 100755
index 0000000000..057c82ee0a
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/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 <sstream>
+#include <stdexcept>
+#include <algorithm>
+
+// #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<typename ContainerT>
+ 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<typename AssociativeContainerT>
+ 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<typename T>
+ T const& operator + ( T const& value, StreamEndStop ) {
+ return value;
+ }
+}
+
+#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
+#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
+
+#include <ostream>
+
+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 <string>
+
+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<typename T>
+ 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<typename T = IShared>
+ 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 <memory>
+#include <vector>
+#include <stdlib.h>
+
+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<IConfig const> getConfig() const = 0;
+ };
+
+ struct IMutableContext : IContext
+ {
+ virtual ~IMutableContext();
+ virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
+ virtual void setRunner( IRunner* runner ) = 0;
+ virtual void setConfig( Ptr<IConfig const> 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 <vector>
+
+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<TestCase> const& getAllTests() const = 0;
+ virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const = 0;
+
+ };
+}
+
+namespace Catch {
+
+template<typename C>
+class MethodTestCase : public SharedImpl<ITestCase> {
+
+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<typename C>
+ AutoReg( void (C::*method)(),
+ char const* className,
+ NameAndDesc const& nameAndDesc,
+ SourceLineInfo const& lineInfo ) {
+ registerTestCase( new MethodTestCase<C>( 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<bool> struct NotABooleanExpression;
+
+ template<bool c> struct If : NotABooleanExpression<c> {};
+ template<> struct If<true> : TrueType {};
+ template<> struct If<false> : FalseType {};
+
+ template<int size> struct SizedIf;
+ template<> struct SizedIf<sizeof(TrueType)> : TrueType {};
+ template<> struct SizedIf<sizeof(FalseType)> : FalseType {};
+
+#endif // CATCH_CONFIG_SFINAE
+
+} // end namespace Catch
+
+#include <sstream>
+#include <iomanip>
+#include <limits>
+#include <vector>
+#include <cstddef>
+
+#ifdef __OBJC__
+// #included from: catch_objc_arc.hpp
+#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
+
+#import <Foundation/Foundation.h>
+
+#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<typename T>
+ class IsStreamInsertableHelper {
+ template<int N> struct TrueIfSizeable : TrueType {};
+
+ template<typename T2>
+ static TrueIfSizeable<sizeof((*(std::ostream*)0) << *((T2 const*)0))> dummy(T2*);
+ static FalseType dummy(...);
+
+ public:
+ typedef SizedIf<sizeof(dummy((T*)0))> type;
+ };
+
+ template<typename T>
+ struct IsStreamInsertable : IsStreamInsertableHelper<T>::type {};
+
+#else
+
+ struct BorgType {
+ template<typename T> BorgType( T const& );
+ };
+
+ TrueType& testStreamable( std::ostream& );
+ FalseType testStreamable( FalseType );
+
+ FalseType operator<<( std::ostream const&, BorgType const& );
+
+ template<typename T>
+ struct IsStreamInsertable {
+ static std::ostream &s;
+ static T const&t;
+ enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
+ };
+
+#endif
+
+ template<bool C>
+ struct StringMakerBase {
+ template<typename T>
+ static std::string convert( T const& ) { return "{?}"; }
+ };
+
+ template<>
+ struct StringMakerBase<true> {
+ template<typename T>
+ 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<typename T>
+ 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<typename T>
+std::string toString( T const& value );
+
+template<typename T>
+struct StringMaker :
+ Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
+
+template<typename T>
+struct StringMaker<T*> {
+ template<typename U>
+ static std::string convert( U* p ) {
+ if( !p )
+ return INTERNAL_CATCH_STRINGIFY( NULL );
+ else
+ return Detail::rawMemoryToString( p );
+ }
+};
+
+template<typename R, typename C>
+struct StringMaker<R C::*> {
+ static std::string convert( R C::* p ) {
+ if( !p )
+ return INTERNAL_CATCH_STRINGIFY( NULL );
+ else
+ return Detail::rawMemoryToString( p );
+ }
+};
+
+namespace Detail {
+ template<typename InputIterator>
+ std::string rangeToString( InputIterator first, InputIterator last );
+}
+
+template<typename T, typename Allocator>
+struct StringMaker<std::vector<T, Allocator> > {
+ static std::string convert( std::vector<T,Allocator> const& v ) {
+ return Detail::rangeToString( v.begin(), v.end() );
+ }
+};
+
+namespace Detail {
+ template<typename T>
+ std::string makeString( T const& value ) {
+ return StringMaker<T>::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<typename T>
+std::string toString( T const& value ) {
+ return StringMaker<T>::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<typename InputIterator>
+ 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 <string>
+// #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<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( 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 <cstddef>
+
+namespace Catch {
+namespace Internal {
+
+ enum Operator {
+ IsEqualTo,
+ IsNotEqualTo,
+ IsLessThan,
+ IsGreaterThan,
+ IsLessThanOrEqualTo,
+ IsGreaterThanOrEqualTo
+ };
+
+ template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
+ template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
+ template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
+ template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
+ template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
+ template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
+ template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
+
+ template<typename T>
+ inline T& opCast(T const& t) { return const_cast<T&>(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<typename T1, typename T2, Operator Op>
+ class Evaluator{};
+
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsEqualTo> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs) {
+ return opCast( lhs ) == opCast( rhs );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsNotEqualTo> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) != opCast( rhs );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsLessThan> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) < opCast( rhs );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsGreaterThan> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) > opCast( rhs );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) >= opCast( rhs );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) <= opCast( rhs );
+ }
+ };
+
+ template<Operator Op, typename T1, typename T2>
+ bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
+ return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
+ }
+
+ // This level of indirection allows us to specialise for integer types
+ // to avoid signed/ unsigned warnings
+
+ // "base" overload
+ template<Operator Op, typename T1, typename T2>
+ bool compare( T1 const& lhs, T2 const& rhs ) {
+ return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
+ }
+
+ // unsigned X to int
+ template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+ }
+ template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+ }
+ template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+ }
+
+ // unsigned X to long
+ template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+ }
+ template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+ }
+ template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+ }
+
+ // int to unsigned X
+ template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+ }
+
+ // long to unsigned X
+ template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+
+ // pointer to long (when comparing against NULL)
+ template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
+ }
+ template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
+ }
+
+ // pointer to int (when comparing against NULL)
+ template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
+ }
+ template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
+ }
+
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+ // pointer to nullptr_t (when comparing against nullptr)
+ template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( NULL, rhs );
+ }
+ template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
+ return Evaluator<T*, T*, Op>::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<typename T>
+ ExpressionResultBuilder& operator << ( T const& value ) {
+ m_stream << value;
+ return *this;
+ }
+
+ std::string reconstructExpression( AssertionInfo const& info ) const;
+
+ AssertionResult buildResult( AssertionInfo const& info ) const;
+
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
+ template<typename RhsT> 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<typename T>
+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<typename RhsT>
+ ExpressionResultBuilder& operator == ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsEqualTo>( rhs );
+ }
+
+ template<typename RhsT>
+ ExpressionResultBuilder& operator != ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsNotEqualTo>( rhs );
+ }
+
+ template<typename RhsT>
+ ExpressionResultBuilder& operator < ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsLessThan>( rhs );
+ }
+
+ template<typename RhsT>
+ ExpressionResultBuilder& operator > ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsGreaterThan>( rhs );
+ }
+
+ template<typename RhsT>
+ ExpressionResultBuilder& operator <= ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
+ }
+
+ template<typename RhsT>
+ ExpressionResultBuilder& operator >= ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
+ }
+
+ ExpressionResultBuilder& operator == ( bool rhs ) {
+ return captureExpression<Internal::IsEqualTo>( rhs );
+ }
+
+ ExpressionResultBuilder& operator != ( bool rhs ) {
+ return captureExpression<Internal::IsNotEqualTo>( 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<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& );
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& );
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& );
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& );
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
+ template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
+
+private:
+ template<Internal::Operator Op, typename RhsT>
+ ExpressionResultBuilder& captureExpression( RhsT const& rhs ) {
+ return m_result
+ .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
+ .setLhs( Catch::toString( m_lhs ) )
+ .setRhs( Catch::toString( rhs ) )
+ .setOp( Internal::OperatorTraits<Op>::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<typename T>
+ ExpressionLhs<T const&> operator->* ( T const& operand ) {
+ return ExpressionLhs<T const&>( operand );
+ }
+
+ ExpressionLhs<bool> operator->* ( bool value ) {
+ return ExpressionLhs<bool>( value );
+ }
+};
+
+} // end namespace Catch
+
+// #included from: catch_message.h
+#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
+
+#include <string>
+
+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<typename T>
+ 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 <string>
+
+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 <string>
+
+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 <string>
+
+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 <iostream>
+#include <string>
+#include <vector>
+
+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 <ostream>
+
+namespace Catch {
+
+ inline IResultCapture& getResultCapture() {
+ return getCurrentContext().getResultCapture();
+ }
+
+ template<typename MatcherT>
+ 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<typename MatcherT, typename ArgT>
+ 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<typename MatcherT, typename ArgT>
+ 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 <cstddef>
+
+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 <stdint.h>
+#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 <string>
+
+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 <iterator>
+#include <vector>
+#include <string>
+#include <stdlib.h>
+
+namespace Catch {
+
+template<typename T>
+struct IGenerator {
+ virtual ~IGenerator() {}
+ virtual T getValue( std::size_t index ) const = 0;
+ virtual std::size_t size () const = 0;
+};
+
+template<typename T>
+class BetweenGenerator : public IGenerator<T> {
+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<int>( index );
+ }
+
+ virtual std::size_t size() const {
+ return static_cast<std::size_t>( 1+m_to-m_from );
+ }
+
+private:
+
+ T m_from;
+ T m_to;
+};
+
+template<typename T>
+class ValuesGenerator : public IGenerator<T> {
+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<T> m_values;
+};
+
+template<typename T>
+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 IGenerator<T>*>::const_iterator it = m_composed.begin();
+ typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
+ for( size_t index = 0; it != itEnd; ++it )
+ {
+ const IGenerator<T>* 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<T>* generator ) {
+ m_totalSize += generator->size();
+ m_composed.push_back( generator );
+ }
+
+ CompositeGenerator& then( CompositeGenerator& other ) {
+ move( other );
+ return *this;
+ }
+
+ CompositeGenerator& then( T value ) {
+ ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+ 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<const IGenerator<T>*> m_composed;
+ std::string m_fileInfo;
+ size_t m_totalSize;
+};
+
+namespace Generators
+{
+ template<typename T>
+ CompositeGenerator<T> between( T from, T to ) {
+ CompositeGenerator<T> generators;
+ generators.add( new BetweenGenerator<T>( from, to ) );
+ return generators;
+ }
+
+ template<typename T>
+ CompositeGenerator<T> values( T val1, T val2 ) {
+ CompositeGenerator<T> generators;
+ ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+ valuesGen->add( val1 );
+ valuesGen->add( val2 );
+ generators.add( valuesGen );
+ return generators;
+ }
+
+ template<typename T>
+ CompositeGenerator<T> values( T val1, T val2, T val3 ){
+ CompositeGenerator<T> generators;
+ ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+ valuesGen->add( val1 );
+ valuesGen->add( val2 );
+ valuesGen->add( val3 );
+ generators.add( valuesGen );
+ return generators;
+ }
+
+ template<typename T>
+ CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
+ CompositeGenerator<T> generators;
+ ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+ 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 <string>
+
+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<typename T>
+ 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<typename T>
+ ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
+ getMutableRegistryHub().registerTranslator
+ ( new ExceptionTranslator<T>( 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 <cmath>
+#include <limits>
+
+namespace Catch {
+namespace Detail {
+
+ class Approx {
+ public:
+ explicit Approx ( double value )
+ : m_epsilon( std::numeric_limits<float>::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>( 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<typename ExpressionT>
+ struct Matcher : SharedImpl<IShared>
+ {
+ typedef ExpressionT ExpressionType;
+
+ virtual ~Matcher() {}
+ virtual Ptr<Matcher> clone() const = 0;
+ virtual bool match( ExpressionT const& expr ) const = 0;
+ virtual std::string toString() const = 0;
+ };
+
+ template<typename DerivedT, typename ExpressionT>
+ struct MatcherImpl : Matcher<ExpressionT> {
+
+ virtual Ptr<Matcher<ExpressionT> > clone() const {
+ return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
+ }
+ };
+
+ namespace Generic {
+
+ template<typename ExpressionT>
+ class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
+ public:
+
+ AllOf() {}
+ AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
+
+ AllOf& add( Matcher<ExpressionT> 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<Ptr<Matcher<ExpressionT> > > m_matchers;
+ };
+
+ template<typename ExpressionT>
+ class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
+ public:
+
+ AnyOf() {}
+ AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
+
+ AnyOf& add( Matcher<ExpressionT> 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<Ptr<Matcher<ExpressionT> > > 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> {
+ 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> {
+ 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> {
+ 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> {
+ 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<typename ExpressionT>
+ inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
+ Impl::Matcher<ExpressionT> const& m2 ) {
+ return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
+ }
+ template<typename ExpressionT>
+ inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
+ Impl::Matcher<ExpressionT> const& m2,
+ Impl::Matcher<ExpressionT> const& m3 ) {
+ return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
+ }
+ template<typename ExpressionT>
+ inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
+ Impl::Matcher<ExpressionT> const& m2 ) {
+ return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
+ }
+ template<typename ExpressionT>
+ inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
+ Impl::Matcher<ExpressionT> const& m2,
+ Impl::Matcher<ExpressionT> const& m3 ) {
+ return Impl::Generic::AnyOf<ExpressionT>().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 <string>
+#include <set>
+
+#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<std::string> const& _tags,
+ bool _isHidden,
+ SourceLineInfo const& _lineInfo );
+
+ TestCaseInfo( TestCaseInfo const& other );
+
+ std::string name;
+ std::string className;
+ std::string description;
+ std::set<std::string> 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<ITestCase> 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 <objc/runtime.h>
+
+#include <string>
+
+// 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<ITestCase> {
+
+ 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<typename MatcherT>
+ struct StringHolder : MatcherImpl<MatcherT, NSString*>{
+ 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> {
+ 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> {
+ 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> {
+ 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> {
+ 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 <string>
+#include <vector>
+
+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<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
+ virtual ~ExcludedPattern();
+ virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
+ private:
+ Ptr<Pattern> m_underlyingPattern;
+ };
+
+ struct Filter {
+ std::vector<Ptr<Pattern> > 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<Ptr<Pattern> >::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<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
+ if( it->matches( testCase ) )
+ return true;
+ return false;
+ }
+
+ private:
+ std::vector<Filter> 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<TestSpec::NamePattern>();
+ 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<TestSpec::NamePattern>();
+ addFilter();
+ }
+ else if( c == '[' ) {
+ if( subString() == "exclude:" )
+ m_exclusion = true;
+ else
+ addPattern<TestSpec::NamePattern>();
+ startNewMode( Tag, ++m_pos );
+ }
+ }
+ else if( m_mode == QuotedName && c == '"' )
+ addPattern<TestSpec::NamePattern>();
+ else if( m_mode == Tag && c == ']' )
+ addPattern<TestSpec::TagPattern>();
+ }
+ 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<typename T>
+ void addPattern() {
+ std::string token = subString();
+ if( startsWith( token, "exclude:" ) ) {
+ m_exclusion = true;
+ token = token.substr( 8 );
+ }
+ if( !token.empty() ) {
+ Ptr<TestSpec::Pattern> 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 <streambuf>
+
+#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 <memory>
+#include <vector>
+#include <string>
+#include <iostream>
+
+#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<std::string> testsOrTags;
+ };
+
+ class Config : public SharedImpl<IConfig> {
+ 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 <string>
+#include <vector>
+#include <sstream>
+
+// 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<std::string>::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<std::string> 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 <map>
+#include <algorithm>
+#include <stdexcept>
+#include <memory>
+
+// 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<typename T> struct RemoveConstRef{ typedef T type; };
+ template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
+ template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
+ template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
+
+ template<typename T> struct IsBool { static const bool value = false; };
+ template<> struct IsBool<bool> { static const bool value = true; };
+
+ template<typename T>
+ 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<typename T>
+ inline void convertInto( bool, T& ) {
+ throw std::runtime_error( "Invalid conversion" );
+ }
+
+ template<typename ConfigT>
+ 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<typename ConfigT>
+ class BoundArgFunction {
+ public:
+ BoundArgFunction() : functionObj( NULL ) {}
+ BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
+ BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {}
+ BoundArgFunction& operator = ( BoundArgFunction const& other ) {
+ IArgFunction<ConfigT>* 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<ConfigT>* functionObj;
+ };
+
+ template<typename C>
+ struct NullBinder : IArgFunction<C>{
+ virtual void set( C&, std::string const& ) const {}
+ virtual void setFlag( C& ) const {}
+ virtual bool takesArg() const { return true; }
+ virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
+ };
+
+ template<typename C, typename M>
+ struct BoundDataMember : IArgFunction<C>{
+ 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<M>::value; }
+ virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
+ M C::* member;
+ };
+ template<typename C, typename M>
+ struct BoundUnaryMethod : IArgFunction<C>{
+ BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
+ virtual void set( C& p, std::string const& stringValue ) const {
+ typename RemoveConstRef<M>::type value;
+ convertInto( stringValue, value );
+ (p.*member)( value );
+ }
+ virtual void setFlag( C& p ) const {
+ typename RemoveConstRef<M>::type value;
+ convertInto( true, value );
+ (p.*member)( value );
+ }
+ virtual bool takesArg() const { return !IsBool<M>::value; }
+ virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
+ void (C::*member)( M );
+ };
+ template<typename C>
+ struct BoundNullaryMethod : IArgFunction<C>{
+ 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<C>* clone() const { return new BoundNullaryMethod( *this ); }
+ void (C::*member)();
+ };
+
+ template<typename C>
+ struct BoundUnaryFunction : IArgFunction<C>{
+ 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<C>* clone() const { return new BoundUnaryFunction( *this ); }
+ void (*function)( C& );
+ };
+
+ template<typename C, typename T>
+ struct BoundBinaryFunction : IArgFunction<C>{
+ BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
+ virtual void set( C& obj, std::string const& stringValue ) const {
+ typename RemoveConstRef<T>::type value;
+ convertInto( stringValue, value );
+ function( obj, value );
+ }
+ virtual void setFlag( C& obj ) const {
+ typename RemoveConstRef<T>::type value;
+ convertInto( true, value );
+ function( obj, value );
+ }
+ virtual bool takesArg() const { return !IsBool<T>::value; }
+ virtual IArgFunction<C>* 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<Parser::Token>& 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<Parser::Token>& 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<typename ConfigT>
+ struct CommonArgProperties {
+ CommonArgProperties() {}
+ CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
+
+ Detail::BoundArgFunction<ConfigT> 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<std::string> 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<typename ConfigT>
+ class CommandLine {
+
+ struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
+ Arg() {}
+ Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
+
+ using CommonArgProperties<ConfigT>::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<std::string>::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<Arg> ArgAutoPtr;
+#else
+ typedef std::auto_ptr<Arg> 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<typename C, typename M>
+ void bind( M C::* field, std::string const& placeholder ) {
+ m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
+ m_arg->placeholder = placeholder;
+ }
+ // Bind a boolean data member (no placeholder required)
+ template<typename C>
+ void bind( bool C::* field ) {
+ m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
+ }
+
+ // Bind a method taking a single, non-boolean argument (requires a placeholder string)
+ template<typename C, typename M>
+ void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
+ m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
+ m_arg->placeholder = placeholder;
+ }
+
+ // Bind a method taking a single, boolean argument (no placeholder string required)
+ template<typename C>
+ void bind( void (C::* unaryMethod)( bool ) ) {
+ m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
+ }
+
+ // Bind a method that takes no arguments (will be called if opt is present)
+ template<typename C>
+ void bind( void (C::* nullaryMethod)() ) {
+ m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
+ }
+
+ // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
+ template<typename C>
+ void bind( void (* unaryFunction)( C& ) ) {
+ m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
+ }
+
+ // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
+ template<typename C, typename T>
+ void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
+ m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( 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<ConfigT>() ),
+ 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<typename C, typename M>
+ void bindProcessName( M C::* field ) {
+ m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
+ }
+ template<typename C, typename M>
+ void bindProcessName( void (C::*_unaryMethod)( M ) ) {
+ m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
+ }
+
+ void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
+ typename std::vector<Arg>::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<int, Arg>::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<Parser::Token> 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<Parser::Token> tokens;
+ Parser parser;
+ parser.parseIntoTokens( argc, argv, tokens );
+ return populate( tokens, config );
+ }
+
+ std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+ validate();
+ std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
+ unusedTokens = populateFixedArgs( unusedTokens, config );
+ unusedTokens = populateFloatingArgs( unusedTokens, config );
+ return unusedTokens;
+ }
+
+ std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+ std::vector<Parser::Token> unusedTokens;
+ std::vector<std::string> errors;
+ for( std::size_t i = 0; i < tokens.size(); ++i ) {
+ Parser::Token const& token = tokens[i];
+ typename std::vector<Arg>::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<std::string>::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<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+ std::vector<Parser::Token> unusedTokens;
+ int position = 1;
+ for( std::size_t i = 0; i < tokens.size(); ++i ) {
+ Parser::Token const& token = tokens[i];
+ typename std::map<int, Arg>::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<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+ if( !m_floatingArg.get() )
+ return tokens;
+ std::vector<Parser::Token> 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<Arg>::const_iterator it = m_options.begin(),
+ itEnd = m_options.end();
+ it != itEnd; ++it )
+ it->validate();
+ }
+
+ private:
+ Detail::BoundArgFunction<ConfigT> m_boundProcessName;
+ std::vector<Arg> m_options;
+ std::map<int, Arg> 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 <fstream>
+
+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<ConfigData> makeCommandLineParser() {
+
+ using namespace Clara;
+ CommandLine<ConfigData> 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 <string>
+#include <vector>
+#include <sstream>
+
+// 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<std::string>::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<std::string> 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<typename T>
+ 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 <string>
+#include <ostream>
+#include <map>
+#include <assert.h>
+
+namespace Catch
+{
+ struct ReporterConfig {
+ explicit ReporterConfig( Ptr<IConfig> const& _fullConfig )
+ : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
+
+ ReporterConfig( Ptr<IConfig> const& _fullConfig, std::ostream& _stream )
+ : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
+
+ std::ostream& stream() const { return *m_stream; }
+ Ptr<IConfig> fullConfig() const { return m_fullConfig; }
+
+ private:
+ std::ostream* m_stream;
+ Ptr<IConfig> m_fullConfig;
+ };
+
+ struct ReporterPreferences {
+ ReporterPreferences()
+ : shouldRedirectStdOut( false )
+ {}
+
+ bool shouldRedirectStdOut;
+ };
+
+ template<typename T>
+ struct LazyStat : Option<T> {
+ LazyStat() : used( false ) {}
+ LazyStat& operator=( T const& _value ) {
+ Option<T>::operator=( _value );
+ used = false;
+ return *this;
+ }
+ void reset() {
+ Option<T>::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<MessageInfo> 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<MessageInfo> 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<std::string, IReporterFactory*> FactoryMap;
+
+ virtual ~IReporterRegistry();
+ virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const = 0;
+ virtual FactoryMap const& getFactories() const = 0;
+ };
+
+}
+
+#include <limits>
+#include <algorithm>
+
+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<TestCase> matchedTestCases;
+ getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
+ for( std::vector<TestCase>::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<TestCase> matchedTestCases;
+ getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
+ for( std::vector<TestCase>::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<std::string, int> tagCounts;
+
+ std::vector<TestCase> matchedTestCases;
+ getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
+ for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
+ it != itEnd;
+ ++it ) {
+ for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
+ tagItEnd = it->getTestCaseInfo().tags.end();
+ tagIt != tagItEnd;
+ ++tagIt ) {
+ std::string tagName = *tagIt;
+ std::map<std::string, int>::iterator countIt = tagCounts.find( tagName );
+ if( countIt == tagCounts.end() )
+ tagCounts.insert( std::make_pair( tagName, 1 ) );
+ else
+ countIt->second++;
+ }
+ }
+
+ for( std::map<std::string, int>::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<std::size_t> list( Config const& config ) {
+ Option<std::size_t> 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 <map>
+#include <string>
+#include <assert.h>
+
+namespace Catch {
+namespace SectionTracking {
+
+ class TrackedSection {
+
+ typedef std::map<std::string, TrackedSection> 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 <set>
+#include <string>
+
+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<IConfig const> const& config, Ptr<IStreamingReporter> 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<IConfig const> 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<std::size_t>( 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<UnfinishedSections>::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<TestCaseTracker> m_testCaseTracker;
+ AssertionResult m_lastResult;
+
+ Ptr<IConfig const> m_config;
+ Totals m_totals;
+ Ptr<IStreamingReporter> m_reporter;
+ std::vector<MessageInfo> m_messages;
+ IRunner* m_prevRunner;
+ IResultCapture* m_prevResultCapture;
+ Ptr<IConfig const> m_prevConfig;
+ AssertionInfo m_lastAssertionInfo;
+ std::vector<UnfinishedSections> 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 <fstream>
+#include <stdlib.h>
+#include <limits>
+
+namespace Catch {
+
+ class Runner {
+
+ public:
+ Runner( Ptr<Config> 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<TestCase> testCases;
+ getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases );
+
+ int testsRunForGroup = 0;
+ for( std::vector<TestCase>::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<Config> m_config;
+ std::ofstream m_ofs;
+ Ptr<IStreamingReporter> m_reporter;
+ std::set<TestCase> 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<int>::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<std::size_t> listed = list( config() ) )
+ return static_cast<int>( *listed );
+
+ return static_cast<int>( runner.runTests().assertions.failed );
+ }
+ catch( std::exception& ex ) {
+ std::cerr << ex.what() << std::endl;
+ return (std::numeric_limits<int>::max)();
+ }
+ }
+
+ Clara::CommandLine<ConfigData> const& cli() const {
+ return m_cli;
+ }
+ std::vector<Clara::Parser::Token> 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<ConfigData> m_cli;
+ std::vector<Clara::Parser::Token> m_unusedTokens;
+ ConfigData m_configData;
+ Ptr<Config> 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 <vector>
+#include <set>
+#include <sstream>
+#include <iostream>
+
+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<TestCase> const& getAllTests() const {
+ return m_functionsInOrder;
+ }
+
+ virtual std::vector<TestCase> const& getAllNonHiddenTests() const {
+ return m_nonHiddenFunctions;
+ }
+
+ virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const {
+ for( std::vector<TestCase>::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<TestCase> m_functions;
+ std::vector<TestCase> m_functionsInOrder;
+ std::vector<TestCase> m_nonHiddenFunctions;
+ size_t m_unnamedCount;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ class FreeFunctionTestCase : public SharedImpl<ITestCase> {
+ 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 <map>
+
+namespace Catch {
+
+ class ReporterRegistry : public IReporterRegistry {
+
+ public:
+
+ virtual ~ReporterRegistry() {
+ deleteAllValues( m_factories );
+ }
+
+ virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> 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 IExceptionTranslator*>::const_iterator it ) const {
+ if( it == m_translators.end() )
+ return "Unknown exception";
+
+ try {
+ return (*it)->translate();
+ }
+ catch(...) {
+ return tryTranslators( it+1 );
+ }
+ }
+
+ private:
+ std::vector<const IExceptionTranslator*> 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 <ostream>
+
+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 <streambuf>
+
+namespace Catch {
+
+ class StreamBufBase : public std::streambuf {
+ public:
+ virtual ~StreamBufBase() CATCH_NOEXCEPT;
+ };
+}
+
+#include <stdexcept>
+#include <cstdio>
+
+namespace Catch {
+
+ template<typename WriterF, size_t bufferSize=256>
+ 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<char>( c ) ) );
+ else
+ sputc( static_cast<char>( c ) );
+ }
+ return 0;
+ }
+
+ int sync() {
+ if( pbase() != pptr() ) {
+ m_writer( std::string( pbase(), static_cast<std::string::size_type>( 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<IConfig const> 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<IConfig const> const& config ) {
+ m_config = config;
+ }
+
+ friend IMutableContext& getCurrentMutableContext();
+
+ private:
+ IGeneratorsForTest* findGeneratorsForCurrentTest() {
+ std::string testName = getResultCapture().getCurrentTestName();
+
+ std::map<std::string, IGeneratorsForTest*>::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<IConfig const> m_config;
+ IRunner* m_runner;
+ IResultCapture* m_resultCapture;
+ std::map<std::string, IGeneratorsForTest*> 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<OutputDebugWriter>, 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 <AfxWin.h>
+#else
+#include <windows.h>
+#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 <unistd.h>
+
+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 <vector>
+#include <string>
+#include <map>
+
+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<std::string, IGeneratorInfo*>::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<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
+ std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
+ for(; it != itEnd; ++it ) {
+ if( (*it)->moveNext() )
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ std::map<std::string, IGeneratorInfo*> m_generatorsByName;
+ std::vector<IGeneratorInfo*> 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 <assert.h>
+
+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<std::string> 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<std::string> 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<std::string>::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<IStreamingReporter>
+ {
+ public:
+ LegacyReporterAdapter( Ptr<IReporter> 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<IReporter> m_legacyReporter;
+ };
+}
+
+namespace Catch
+{
+ LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> 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<MessageInfo>::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 <windows.h>
+#else
+#include <sys/time.h>
+#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 <iostream>
+
+#ifdef CATCH_PLATFORM_MAC
+
+ #include <assert.h>
+ #include <stdbool.h>
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <sys/sysctl.h>
+
+ 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<char>( 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<const char*>( 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<unsigned long>( 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<unsigned int>( value ) )
+ : Detail::makeString( value );
+}
+
+std::string toString( signed char value ) {
+ return toString( static_cast<char>( value ) );
+}
+
+std::string toString( unsigned char value ) {
+ return toString( static_cast<char>( 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<IStreamingReporter> {
+
+ 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<IConfig> m_config;
+ std::ostream& stream;
+
+ LazyStat<TestRunInfo> currentTestRunInfo;
+ LazyStat<GroupInfo> currentGroupInfo;
+ LazyStat<TestCaseInfo> currentTestCaseInfo;
+
+ std::vector<SectionInfo> m_sectionStack;
+ };
+
+ struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
+ template<typename T, typename ChildNodeT>
+ struct Node : SharedImpl<> {
+ explicit Node( T const& _value ) : value( _value ) {}
+ virtual ~Node() {}
+
+ typedef std::vector<Ptr<ChildNodeT> > 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<SectionNode> const& other ) const {
+ return operator==( *other );
+ }
+
+ SectionStats stats;
+ typedef std::vector<Ptr<SectionNode> > ChildSections;
+ typedef std::vector<AssertionStats> Assertions;
+ ChildSections childSections;
+ Assertions assertions;
+ std::string stdOut;
+ std::string stdErr;
+ };
+
+ struct BySectionInfo {
+ BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
+ bool operator() ( Ptr<SectionNode> const& node ) const {
+ return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
+ }
+ private:
+ BySectionInfo& operator=( BySectionInfo const& other ); // = delete;
+
+ SectionInfo const& m_other;
+ };
+
+ typedef Node<TestCaseStats, SectionNode> TestCaseNode;
+ typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
+ typedef Node<TestRunStats, TestGroupNode> 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<SectionNode> 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<TestCaseNode> 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<TestGroupNode> node = new TestGroupNode( testGroupStats );
+ node->children.swap( m_testCases );
+ m_testGroups.push_back( node );
+ }
+ virtual void testRunEnded( TestRunStats const& testRunStats ) {
+ Ptr<TestRunNode> node = new TestRunNode( testRunStats );
+ node->children.swap( m_testGroups );
+ m_testRuns.push_back( node );
+ testRunEndedCumulative();
+ }
+ virtual void testRunEndedCumulative() = 0;
+
+ Ptr<IConfig> m_config;
+ std::ostream& stream;
+ std::vector<AssertionStats> m_assertions;
+ std::vector<std::vector<Ptr<SectionNode> > > m_sections;
+ std::vector<Ptr<TestCaseNode> > m_testCases;
+ std::vector<Ptr<TestGroupNode> > m_testGroups;
+
+ std::vector<Ptr<TestRunNode> > m_testRuns;
+
+ Ptr<SectionNode> m_rootSection;
+ Ptr<SectionNode> m_deepestSection;
+ std::vector<Ptr<SectionNode> > m_sectionStack;
+
+ };
+
+} // end namespace Catch
+
+// #included from: ../internal/catch_reporter_registrars.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
+
+namespace Catch {
+
+ template<typename T>
+ 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<typename T>
+ 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<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
+#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
+ namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
+
+// #included from: ../internal/catch_xmlwriter.hpp
+#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
+
+#include <sstream>
+#include <iostream>
+#include <string>
+#include <vector>
+
+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<typename T>
+ 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 << "</" << m_tags.back() << ">\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<typename T>
+ 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 << "<!--" << text << "-->";
+ 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() << "&lt;";
+ break;
+ case '&':
+ stream() << "&amp;";
+ break;
+ case '\"':
+ stream() << "&quot;";
+ break;
+ }
+ mtext = mtext.substr( pos+1 );
+ pos = mtext.find_first_of( charsToEncode );
+ }
+ stream() << mtext;
+ }
+
+ bool m_tagIsOpen;
+ bool m_needsNewline;
+ std::vector<std::string> m_tags;
+ std::string m_indent;
+ std::ostream* m_os;
+ };
+
+}
+namespace Catch {
+ class XmlReporter : public SharedImpl<IReporter> {
+ 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 <assert.h>
+
+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<MessageInfo>::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 <cstring>
+
+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<MessageInfo>::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<MessageInfo> 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<SectionInfo>::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<char C>
+ 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<MessageInfo>::const_iterator itEnd = messages.end();
+ const std::size_t N = static_cast<std::size_t>( 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<MessageInfo> messages;
+ std::vector<MessageInfo>::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/3party/osrm/osrm-backend/third_party/variant/test/optional_unit.cpp b/3party/osrm/osrm-backend/third_party/variant/test/optional_unit.cpp
new file mode 100755
index 0000000000..a6573ca412
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/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<double> 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<double> dbl_opt;
+
+ REQUIRE(!dbl_opt);
+ dbl_opt = 3.1415;
+ REQUIRE(dbl_opt);
+
+ mapbox::util::optional<double> other = dbl_opt;
+
+ REQUIRE(other.get() == 3.1415);
+ REQUIRE(*other == 3.1415);
+}
+
+TEST_CASE( "const operator*, const get()", "[optiona]" ) {
+ mapbox::util::optional<double> 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> 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<int> a;
+ mapbox::util::optional<int> 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/3party/osrm/osrm-backend/third_party/variant/test/recursive_wrapper_test.cpp b/3party/osrm/osrm-backend/third_party/variant/test/recursive_wrapper_test.cpp
new file mode 100755
index 0000000000..3cd79b5ce0
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/test/recursive_wrapper_test.cpp
@@ -0,0 +1,132 @@
+#include <iostream>
+#include <vector>
+#include <thread>
+#include <string>
+#include <sstream>
+#include <utility>
+#include <type_traits>
+#include <boost/timer/timer.hpp>
+#include "variant.hpp"
+
+using namespace mapbox;
+
+namespace test {
+
+struct add;
+struct sub;
+template <typename OpTag> struct binary_op;
+
+typedef util::variant<int ,
+ util::recursive_wrapper<binary_op<add>>,
+ util::recursive_wrapper<binary_op<sub>>
+ > expression;
+
+template <typename Op>
+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<void>
+{
+ template <typename T>
+ void operator() (T const& val) const
+ {
+ std::cerr << val << ":" << typeid(T).name() << std::endl;
+ }
+};
+
+
+struct test : util::static_visitor<std::string>
+{
+ template <typename T>
+ std::string operator() (T const& obj) const
+ {
+ return std::string("TYPE_ID=") + typeid(obj).name();
+ }
+};
+
+struct calculator : public util::static_visitor<int>
+{
+public:
+
+ int operator()(int value) const
+ {
+ return value;
+ }
+
+ int operator()(binary_op<add> const& binary) const
+ {
+ return util::apply_visitor(calculator(), binary.left)
+ + util::apply_visitor(calculator(), binary.right);
+ }
+
+ int operator()(binary_op<sub> const& binary) const
+ {
+ return util::apply_visitor(calculator(), binary.left)
+ - util::apply_visitor(calculator(), binary.right);
+ }
+};
+
+struct to_string : public util::static_visitor<std::string>
+{
+public:
+
+ std::string operator()(int value) const
+ {
+ return std::to_string(value);
+ }
+
+ std::string operator()(binary_op<add> 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<sub> 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] << " <num-iter>" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ const std::size_t NUM_ITER = static_cast<std::size_t>(std::stol(argv[1]));
+
+ test::expression result(
+ test::binary_op<test::sub>(
+ test::binary_op<test::add>(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/3party/osrm/osrm-backend/third_party/variant/test/reference_wrapper_test.cpp b/3party/osrm/osrm-backend/third_party/variant/test/reference_wrapper_test.cpp
new file mode 100755
index 0000000000..2abf027844
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/test/reference_wrapper_test.cpp
@@ -0,0 +1,74 @@
+#include <iostream>
+#include <vector>
+#include <thread>
+#include <string>
+#include <sstream>
+#include <utility>
+#include <type_traits>
+#include <boost/timer/timer.hpp>
+#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<point> {};
+struct polygon : std::vector<line_string> {};
+using variant = util::variant<std::reference_wrapper<const point>,
+ std::reference_wrapper<const line_string>,
+ std::reference_wrapper<const polygon>>;
+
+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 <typename T>
+ 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::reference_wrapper<test::line_string const>>() << std::endl;
+ auto const& line2 = var.get<test::line_string>(); // accessing underlying type of std::reference_wrapper<T>
+ test::print printer;
+ printer(line2);
+ return EXIT_SUCCESS;
+}
diff --git a/3party/osrm/osrm-backend/third_party/variant/test/unique_ptr_test.cpp b/3party/osrm/osrm-backend/third_party/variant/test/unique_ptr_test.cpp
new file mode 100755
index 0000000000..2a51efef09
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/test/unique_ptr_test.cpp
@@ -0,0 +1,128 @@
+#include <iostream>
+#include <vector>
+#include <thread>
+#include <string>
+#include <sstream>
+#include <utility>
+#include <type_traits>
+#include <boost/variant.hpp>
+#include <boost/timer/timer.hpp>
+#include "variant.hpp"
+
+using namespace mapbox;
+
+namespace test {
+
+struct add;
+struct sub;
+template <typename OpTag> struct binary_op;
+
+typedef util::variant<int ,
+ std::unique_ptr<binary_op<add>>,
+ std::unique_ptr<binary_op<sub>>
+ > expression;
+
+template <typename Op>
+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<void>
+{
+ template <typename T>
+ void operator() (T const& val) const
+ {
+ std::cerr << val << ":" << typeid(T).name() << std::endl;
+ }
+};
+
+
+struct test : util::static_visitor<std::string>
+{
+ template <typename T>
+ std::string operator() (T const& obj) const
+ {
+ return std::string("TYPE_ID=") + typeid(obj).name();
+ }
+};
+
+struct calculator : public util::static_visitor<int>
+{
+public:
+
+ int operator()(int value) const
+ {
+ return value;
+ }
+
+ int operator()(std::unique_ptr<binary_op<add>> const& binary) const
+ {
+ return util::apply_visitor(calculator(), binary->left)
+ + util::apply_visitor(calculator(), binary->right);
+ }
+
+ int operator()(std::unique_ptr<binary_op<sub>> const& binary) const
+ {
+ return util::apply_visitor(calculator(), binary->left)
+ - util::apply_visitor(calculator(), binary->right);
+ }
+};
+
+struct to_string : public util::static_visitor<std::string>
+{
+public:
+
+ std::string operator()(int value) const
+ {
+ return std::to_string(value);
+ }
+
+ std::string operator()(std::unique_ptr<binary_op<add>> 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<binary_op<sub>> 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] << " <num-iter>" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ const std::size_t NUM_ITER = static_cast<std::size_t>(std::stol(argv[1]));
+
+ test::expression sum(std::unique_ptr<test::binary_op<test::add>>(new test::binary_op<test::add>(2, 3)));
+ test::expression result(std::unique_ptr<test::binary_op<test::sub>>(new test::binary_op<test::sub>(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/3party/osrm/osrm-backend/third_party/variant/test/unit.cpp b/3party/osrm/osrm-backend/third_party/variant/test/unit.cpp
new file mode 100755
index 0000000000..9b874c707b
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/test/unit.cpp
@@ -0,0 +1,314 @@
+#define CATCH_CONFIG_RUNNER
+#include "catch.hpp"
+
+#include "variant.hpp"
+#include "variant_io.hpp"
+#include <algorithm>
+#include <cstdint>
+#include <iterator>
+#include <limits>
+#include <memory>
+#include <ostream>
+#include <sstream>
+#include <string>
+
+using namespace mapbox;
+
+template <typename T>
+struct mutating_visitor
+{
+ mutating_visitor(T & val)
+ : val_(val) {}
+
+ void operator() (T & val) const
+ {
+ val = val_;
+ }
+
+ template <typename T1>
+ 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<bool,std::string> variant_type;
+ variant_type v(std::string("test"));
+ std::vector<variant_type> vec;
+ vec.emplace_back(std::move(v));
+ REQUIRE(v.get<std::string>() != std::string("test"));
+ REQUIRE(vec.at(0).get<std::string>() == std::string("test"));
+}
+
+TEST_CASE( "variant should support built-in types", "[variant]" ) {
+ SECTION( "bool" ) {
+ util::variant<bool> v(true);
+ REQUIRE(v.valid());
+ REQUIRE(v.is<bool>());
+ REQUIRE(v.get_type_index() == 0);
+ REQUIRE(v.get<bool>() == true);
+ v.set<bool>(false);
+ REQUIRE(v.get<bool>() == false);
+ v = true;
+ REQUIRE(v == util::variant<bool>(true));
+ }
+ SECTION( "nullptr" ) {
+ typedef std::nullptr_t value_type;
+ util::variant<value_type> v(nullptr);
+ REQUIRE(v.valid());
+ REQUIRE(v.is<value_type>());
+ REQUIRE(v.get_type_index() == 0);
+ // TODO: commented since it breaks on windows: 'operator << is ambiguous'
+ //REQUIRE(v.get<value_type>() == nullptr);
+ // FIXME: does not compile: ./variant.hpp:340:14: error: use of overloaded operator '<<' is ambiguous (with operand types 'std::__1::basic_ostream<char>' and 'const nullptr_t')
+ // https://github.com/mapbox/variant/issues/14
+ //REQUIRE(v == util::variant<value_type>(nullptr));
+ }
+ SECTION( "unique_ptr" ) {
+ typedef std::unique_ptr<std::string> value_type;
+ util::variant<value_type> v(value_type(new std::string("hello")));
+ REQUIRE(v.valid());
+ REQUIRE(v.is<value_type>());
+ REQUIRE(v.get_type_index() == 0);
+ REQUIRE(*v.get<value_type>().get() == *value_type(new std::string("hello")).get());
+ }
+ SECTION( "string" ) {
+ typedef std::string value_type;
+ util::variant<value_type> v(value_type("hello"));
+ REQUIRE(v.valid());
+ REQUIRE(v.is<value_type>());
+ REQUIRE(v.get_type_index() == 0);
+ REQUIRE(v.get<value_type>() == value_type("hello"));
+ v.set<value_type>(value_type("there"));
+ REQUIRE(v.get<value_type>() == value_type("there"));
+ v = value_type("variant");
+ REQUIRE(v == util::variant<value_type>(value_type("variant")));
+ }
+ SECTION( "size_t" ) {
+ typedef std::size_t value_type;
+ util::variant<value_type> v(std::numeric_limits<value_type>::max());
+ REQUIRE(v.valid());
+ REQUIRE(v.is<value_type>());
+ REQUIRE(v.get_type_index() == 0);
+ REQUIRE(v.get<value_type>() == std::numeric_limits<value_type>::max());
+ v.set<value_type>(value_type(0));
+ REQUIRE(v.get<value_type>() == value_type(0));
+ v = value_type(1);
+ REQUIRE(v == util::variant<value_type>(value_type(1)));
+ }
+ SECTION( "int8_t" ) {
+ typedef std::int8_t value_type;
+ util::variant<value_type> v(std::numeric_limits<value_type>::max());
+ REQUIRE(v.valid());
+ REQUIRE(v.is<value_type>());
+ REQUIRE(v.get_type_index() == 0);
+ REQUIRE(v.get<value_type>() == std::numeric_limits<value_type>::max());
+ v.set<value_type>(0);
+ REQUIRE(v.get<value_type>() == value_type(0));
+ v = value_type(1);
+ REQUIRE(v == util::variant<value_type>(value_type(1)));
+ }
+ SECTION( "int16_t" ) {
+ typedef std::int16_t value_type;
+ util::variant<value_type> v(std::numeric_limits<value_type>::max());
+ REQUIRE(v.valid());
+ REQUIRE(v.is<value_type>());
+ REQUIRE(v.get_type_index() == 0);
+ REQUIRE(v.get<value_type>() == std::numeric_limits<value_type>::max());
+ v.set<value_type>(0);
+ REQUIRE(v.get<value_type>() == value_type(0));
+ v = value_type(1);
+ REQUIRE(v == util::variant<value_type>(value_type(1)));
+ }
+ SECTION( "int32_t" ) {
+ typedef std::int32_t value_type;
+ util::variant<value_type> v(std::numeric_limits<value_type>::max());
+ REQUIRE(v.valid());
+ REQUIRE(v.is<value_type>());
+ REQUIRE(v.get_type_index() == 0);
+ REQUIRE(v.get<value_type>() == std::numeric_limits<value_type>::max());
+ v.set<value_type>(0);
+ REQUIRE(v.get<value_type>() == value_type(0));
+ v = value_type(1);
+ REQUIRE(v == util::variant<value_type>(value_type(1)));
+ }
+ SECTION( "int64_t" ) {
+ typedef std::int64_t value_type;
+ util::variant<value_type> v(std::numeric_limits<value_type>::max());
+ REQUIRE(v.valid());
+ REQUIRE(v.is<value_type>());
+ REQUIRE(v.get_type_index() == 0);
+ REQUIRE(v.get<value_type>() == std::numeric_limits<value_type>::max());
+ v.set<value_type>(0);
+ REQUIRE(v.get<value_type>() == value_type(0));
+ v = value_type(1);
+ REQUIRE(v == util::variant<value_type>(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<MissionInteger> v(MissionInteger(34838300));
+ REQUIRE(v.valid());
+ REQUIRE(v.is<MissionInteger>());
+ REQUIRE(v.get_type_index() == 0);
+ REQUIRE(v.get<MissionInteger>() == MissionInteger(34838300));
+ REQUIRE(v.get<MissionInteger>().get() == MissionInteger::value_type(34838300));
+ // TODO: should both of the set usages below compile?
+ v.set<MissionInteger>(MissionInteger::value_type(0));
+ v.set<MissionInteger>(MissionInteger(0));
+ REQUIRE(v.get<MissionInteger>().get() == MissionInteger::value_type(0));
+ v = MissionInteger(1);
+ REQUIRE(v == util::variant<MissionInteger>(MissionInteger(1)));
+}
+
+// Test internal api
+TEST_CASE( "variant should correctly index types", "[variant]" ) {
+ typedef util::variant<bool,std::string,std::uint64_t,std::int64_t,double,float> 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 internal api
+TEST_CASE( "variant::which() returns zero based index of stored type", "[variant]" ) {
+ typedef util::variant<bool,std::string,std::uint64_t,std::int64_t,double,float> 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<int> variant_type;
+ variant_type var = 5;
+ REQUIRE(var.get<int>() == 5);
+}
+
+TEST_CASE( "get with wrong type (here: double) should throw", "[variant]" ) {
+ typedef util::variant<int, double> variant_type;
+ variant_type var = 5;
+ REQUIRE(var.get<int>() == 5);
+ REQUIRE_THROWS(var.get<double>());
+}
+
+TEST_CASE( "get with wrong type (here: int) should throw", "[variant]" ) {
+ typedef util::variant<int, double> variant_type;
+ variant_type var = 5.0;
+ REQUIRE(var.get<double>() == 5.0);
+ REQUIRE_THROWS(var.get<int>());
+}
+
+TEST_CASE( "implicit conversion", "[variant][implicit conversion]" ) {
+ typedef util::variant<int> variant_type;
+ variant_type var(5.0); // converted to int
+ REQUIRE(var.get<int>() == 5);
+ var = 6.0; // works for operator=, too
+ REQUIRE(var.get<int>() == 6);
+}
+
+TEST_CASE( "implicit conversion to first type in variant type list", "[variant][implicit conversion]" ) {
+ typedef util::variant<long, char> variant_type;
+ variant_type var = 5.0; // converted to long
+ REQUIRE(var.get<long>() == 5);
+ REQUIRE_THROWS(var.get<char>());
+}
+
+TEST_CASE( "implicit conversion to unsigned char", "[variant][implicit conversion]" ) {
+ typedef util::variant<unsigned char> variant_type;
+ variant_type var = 100.0;
+ CHECK(var.get<unsigned char>() == static_cast<unsigned char>(100.0));
+ CHECK(var.get<unsigned char>() == static_cast<unsigned char>(static_cast<unsigned int>(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<bool, bool, int, double, std::string>::index == 3));
+ REQUIRE((util::detail::value_traits<int, bool, int, double, std::string>::index == 2));
+ REQUIRE((util::detail::value_traits<double, bool, int, double, std::string>::index == 1));
+ REQUIRE((util::detail::value_traits<std::string, bool, int, double, std::string>::index == 0));
+ REQUIRE((util::detail::value_traits<dummy, bool, int, double, std::string>::index == util::detail::invalid_value));
+ REQUIRE((util::detail::value_traits<std::vector<int>, 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<int, double, std::string>().get_type_index() == 2));
+ REQUIRE((util::variant<int, double, std::string>(util::no_init()).get_type_index() == util::detail::invalid_value));
+}
+
+TEST_CASE( "variant visitation", "[visitor][unary visitor]" ) {
+ util::variant<int, double, std::string> var(123);
+ REQUIRE(var.get<int>() == 123);
+ int val = 456;
+ mutating_visitor<int> visitor(val);
+ util::apply_visitor(visitor, var);
+ REQUIRE(var.get<int>() == 456);
+}
+
+TEST_CASE( "variant printer", "[visitor][unary visitor][printer]" ) {
+ typedef util::variant<int, double, std::string> variant_type;
+ std::vector<variant_type> var = {2.1, 123, "foo", 456};
+ std::stringstream out;
+ std::copy(var.begin(), var.end(), std::ostream_iterator<variant_type>(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/3party/osrm/osrm-backend/third_party/variant/test/variant_hello_world.cpp b/3party/osrm/osrm-backend/third_party/variant/test/variant_hello_world.cpp
new file mode 100755
index 0000000000..b445fdbab8
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/test/variant_hello_world.cpp
@@ -0,0 +1,22 @@
+#include "variant.hpp"
+#include <cstdint>
+#include <stdexcept>
+
+using namespace mapbox;
+
+struct check : util::static_visitor<>
+{
+ template <typename T>
+ void operator() (T const& val) const
+ {
+ if (val != 0) throw std::runtime_error("invalid");
+ }
+};
+
+
+int main() {
+ typedef util::variant<bool, int, double> variant_type;
+ variant_type v(0);
+ util::apply_visitor(check(), v);
+ return 0;
+}
diff --git a/3party/osrm/osrm-backend/third_party/variant/variant.gyp b/3party/osrm/osrm-backend/third_party/variant/variant.gyp
new file mode 100755
index 0000000000..712cafed12
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/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/3party/osrm/osrm-backend/ThirdParty/variant/variant.hpp b/3party/osrm/osrm-backend/third_party/variant/variant.hpp
index 8b578ac7e5..837b162dfc 100644..100755
--- a/3party/osrm/osrm-backend/ThirdParty/variant/variant.hpp
+++ b/3party/osrm/osrm-backend/third_party/variant/variant.hpp
@@ -12,8 +12,6 @@
#include "recursive_wrapper.hpp"
-#include "../../../../../std/msvc_cpp11_workarounds.hpp"
-
#ifdef _MSC_VER
// http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx
#ifdef NDEBUG
@@ -36,9 +34,21 @@
// translates to 100
#define VARIANT_VERSION (VARIANT_MAJOR_VERSION*100000) + (VARIANT_MINOR_VERSION*100) + (VARIANT_PATCH_VERSION)
-namespace mapbox { namespace util { namespace detail {
+namespace mapbox { namespace util {
+
+// static visitor
+template <typename R = void>
+struct static_visitor
+{
+ using result_type = R;
+protected:
+ static_visitor() {}
+ ~static_visitor() {}
+};
+
+namespace detail {
-static CONSTEXPR_VALUE std::size_t invalid_value = std::size_t(-1);
+static constexpr std::size_t invalid_value = std::size_t(-1);
template <typename T, typename...Types>
struct direct_type;
@@ -46,14 +56,14 @@ struct direct_type;
template <typename T, typename First, typename...Types>
struct direct_type<T, First, Types...>
{
- static CONSTEXPR_VALUE std::size_t index = std::is_same<T, First>::value
+ static constexpr std::size_t index = std::is_same<T, First>::value
? sizeof...(Types) : direct_type<T, Types...>::index;
};
template <typename T>
struct direct_type<T>
{
- static CONSTEXPR_VALUE std::size_t index = invalid_value;
+ static constexpr std::size_t index = invalid_value;
};
template <typename T, typename...Types>
@@ -62,21 +72,21 @@ struct convertible_type;
template <typename T, typename First, typename...Types>
struct convertible_type<T, First, Types...>
{
- static CONSTEXPR_VALUE std::size_t index = std::is_convertible<T, First>::value
+ static constexpr std::size_t index = std::is_convertible<T, First>::value
? sizeof...(Types) : convertible_type<T, Types...>::index;
};
template <typename T>
struct convertible_type<T>
{
- static CONSTEXPR_VALUE std::size_t index = invalid_value;
+ static constexpr std::size_t index = invalid_value;
};
template <typename T, typename...Types>
struct value_traits
{
- static CONSTEXPR_VALUE std::size_t direct_index = direct_type<T, Types...>::index;
- static CONSTEXPR_VALUE std::size_t index =
+ static constexpr std::size_t direct_index = direct_type<T, Types...>::index;
+ static constexpr std::size_t index =
(direct_index == invalid_value) ? convertible_type<T, Types...>::index : direct_index;
};
@@ -86,7 +96,7 @@ struct is_valid_type;
template <typename T, typename First, typename... Types>
struct is_valid_type<T, First, Types...>
{
- static CONSTEXPR_VALUE bool value = std::is_convertible<T, First>::value
+ static constexpr bool value = std::is_convertible<T, First>::value
|| is_valid_type<T, Types...>::value;
};
@@ -111,19 +121,39 @@ struct select_type<0, T, Types...>
using type = T;
};
-} // namespace detail
-// static visitor
-template <typename R = void>
-struct static_visitor
+template <typename T, typename R = void>
+struct enable_if_type { using type = R; };
+
+template <typename F, typename V, typename Enable = void>
+struct result_of_unary_visit
{
- using result_type = R;
-protected:
- static_visitor() {}
- ~static_visitor() {}
+ using type = typename std::result_of<F(V&)>::type;
+};
+
+template <typename F, typename V>
+struct result_of_unary_visit<F, V, typename enable_if_type<typename F::result_type>::type >
+{
+ using type = typename F::result_type;
+};
+
+template <typename F, typename V, class Enable = void>
+struct result_of_binary_visit
+{
+ using type = typename std::result_of<F(V&,V&)>::type;
};
+template <typename F, typename V>
+struct result_of_binary_visit<F, V, typename enable_if_type<typename F::result_type>::type >
+{
+ using type = typename F::result_type;
+};
+
+
+} // namespace detail
+
+
template <std::size_t arg1, std::size_t ... others>
struct static_max;
@@ -220,14 +250,25 @@ struct unwrapper<recursive_wrapper<T>>
}
};
+template <typename T>
+struct unwrapper<std::reference_wrapper<T>>
+{
+ auto operator() (std::reference_wrapper<T> const& obj) const
+ -> typename std::reference_wrapper<T>::type const&
+ {
+ return obj.get();
+ }
+
+};
+
-template <typename F, typename V, typename...Types>
+template <typename F, typename V, typename R, typename...Types>
struct dispatcher;
-template <typename F, typename V, typename T, typename...Types>
-struct dispatcher<F, V, T, Types...>
+template <typename F, typename V, typename R, typename T, typename...Types>
+struct dispatcher<F, V, R, T, Types...>
{
- using result_type = typename F::result_type;
+ using result_type = R;
VARIANT_INLINE static result_type apply_const(V const& v, F f)
{
if (v.get_type_index() == sizeof...(Types))
@@ -236,7 +277,7 @@ struct dispatcher<F, V, T, Types...>
}
else
{
- return dispatcher<F, V, Types...>::apply_const(v, f);
+ return dispatcher<F, V, R, Types...>::apply_const(v, f);
}
}
@@ -248,15 +289,15 @@ struct dispatcher<F, V, T, Types...>
}
else
{
- return dispatcher<F, V, Types...>::apply(v, f);
+ return dispatcher<F, V, R, Types...>::apply(v, f);
}
}
};
-template<typename F, typename V>
-struct dispatcher<F, V>
+template<typename F, typename V, typename R>
+struct dispatcher<F, V, R>
{
- using result_type = typename F::result_type;
+ 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());
@@ -269,13 +310,13 @@ struct dispatcher<F, V>
};
-template <typename F, typename V, typename T, typename...Types>
+template <typename F, typename V, typename R, typename T, typename...Types>
struct binary_dispatcher_rhs;
-template <typename F, typename V, typename T0, typename T1, typename...Types>
-struct binary_dispatcher_rhs<F, V, T0, T1, Types...>
+template <typename F, typename V, typename R, typename T0, typename T1, typename...Types>
+struct binary_dispatcher_rhs<F, V, R, T0, T1, Types...>
{
- using result_type = typename F::result_type;
+ 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
@@ -285,7 +326,7 @@ struct binary_dispatcher_rhs<F, V, T0, T1, Types...>
}
else
{
- return binary_dispatcher_rhs<F, V, T0, Types...>::apply_const(lhs, rhs, f);
+ return binary_dispatcher_rhs<F, V, R, T0, Types...>::apply_const(lhs, rhs, f);
}
}
@@ -298,16 +339,16 @@ struct binary_dispatcher_rhs<F, V, T0, T1, Types...>
}
else
{
- return binary_dispatcher_rhs<F, V, T0, Types...>::apply(lhs, rhs, f);
+ return binary_dispatcher_rhs<F, V, R, T0, Types...>::apply(lhs, rhs, f);
}
}
};
-template<typename F, typename V, typename T>
-struct binary_dispatcher_rhs<F, V, T>
+template<typename F, typename V, typename R, typename T>
+struct binary_dispatcher_rhs<F, V, R, T>
{
- using result_type = typename F::result_type;
+ using result_type = R;
VARIANT_INLINE static result_type apply_const(V const&, V const&, F)
{
throw std::runtime_error("binary dispatch: FAIL");
@@ -319,13 +360,13 @@ struct binary_dispatcher_rhs<F, V, T>
};
-template <typename F, typename V, typename T, typename...Types>
+template <typename F, typename V, typename R, typename T, typename...Types>
struct binary_dispatcher_lhs;
-template <typename F, typename V, typename T0, typename T1, typename...Types>
-struct binary_dispatcher_lhs<F, V, T0, T1, Types...>
+template <typename F, typename V, typename R, typename T0, typename T1, typename...Types>
+struct binary_dispatcher_lhs<F, V, R, T0, T1, Types...>
{
- using result_type = typename F::result_type;
+ 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
@@ -334,7 +375,7 @@ struct binary_dispatcher_lhs<F, V, T0, T1, Types...>
}
else
{
- return binary_dispatcher_lhs<F, V, T0, Types...>::apply_const(lhs, rhs, f);
+ return binary_dispatcher_lhs<F, V, R, T0, Types...>::apply_const(lhs, rhs, f);
}
}
@@ -346,16 +387,16 @@ struct binary_dispatcher_lhs<F, V, T0, T1, Types...>
}
else
{
- return binary_dispatcher_lhs<F, V, T0, Types...>::apply(lhs, rhs, f);
+ return binary_dispatcher_lhs<F, V, R, T0, Types...>::apply(lhs, rhs, f);
}
}
};
-template<typename F, typename V, typename T>
-struct binary_dispatcher_lhs<F, V, T>
+template<typename F, typename V, typename R, typename T>
+struct binary_dispatcher_lhs<F, V, R, T>
{
- using result_type = typename F::result_type;
+ using result_type = R;
VARIANT_INLINE static result_type apply_const(V const&, V const&, F)
{
throw std::runtime_error("binary dispatch: FAIL");
@@ -367,13 +408,13 @@ struct binary_dispatcher_lhs<F, V, T>
}
};
-template <typename F, typename V, typename...Types>
+template <typename F, typename V, typename R, typename...Types>
struct binary_dispatcher;
-template <typename F, typename V, typename T, typename...Types>
-struct binary_dispatcher<F, V, T, Types...>
+template <typename F, typename V, typename R, typename T, typename...Types>
+struct binary_dispatcher<F, V, R, T, Types...>
{
- using result_type = typename F::result_type;
+ 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))
@@ -384,14 +425,14 @@ struct binary_dispatcher<F, V, T, Types...>
}
else
{
- return binary_dispatcher_rhs<F, V, T, Types...>::apply_const(v0, v1, f);
+ return binary_dispatcher_rhs<F, V, R, T, Types...>::apply_const(v0, v1, f);
}
}
else if (v1.get_type_index() == sizeof...(Types))
{
- return binary_dispatcher_lhs<F, V, T, Types...>::apply_const(v0, v1, f);
+ return binary_dispatcher_lhs<F, V, R, T, Types...>::apply_const(v0, v1, f);
}
- return binary_dispatcher<F, V, Types...>::apply_const(v0, v1, f);
+ return binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, f);
}
VARIANT_INLINE static result_type apply(V & v0, V & v1, F f)
@@ -404,21 +445,21 @@ struct binary_dispatcher<F, V, T, Types...>
}
else
{
- return binary_dispatcher_rhs<F, V, T, Types...>::apply(v0, v1, f);
+ return binary_dispatcher_rhs<F, V, R, T, Types...>::apply(v0, v1, f);
}
}
else if (v1.get_type_index() == sizeof...(Types))
{
- return binary_dispatcher_lhs<F, V, T, Types...>::apply(v0, v1, f);
+ return binary_dispatcher_lhs<F, V, R, T, Types...>::apply(v0, v1, f);
}
- return binary_dispatcher<F, V, Types...>::apply(v0, v1, f);
+ return binary_dispatcher<F, V, R, Types...>::apply(v0, v1, f);
}
};
-template<typename F, typename V>
-struct binary_dispatcher<F, V>
+template<typename F, typename V, typename R>
+struct binary_dispatcher<F, V, R>
{
- using result_type = typename F::result_type;
+ using result_type = R;
VARIANT_INLINE static result_type apply_const(V const&, V const&, F)
{
throw std::runtime_error("binary dispatch: FAIL");
@@ -450,10 +491,10 @@ struct less_comp
};
template <typename Variant, typename Comp>
-class comparer : public static_visitor<bool>
+class comparer
{
public:
- explicit comparer(Variant const& lhs) NOEXCEPT_MODIFIER
+ explicit comparer(Variant const& lhs) noexcept
: lhs_(lhs) {}
comparer& operator=(comparer const&) = delete;
// visitor
@@ -467,24 +508,6 @@ private:
Variant const& lhs_;
};
-// operator<< helper
-template <typename Out>
-class printer : public static_visitor<>
-{
-public:
- explicit printer(Out & out)
- : out_(out) {}
- printer& operator=(printer const&) = delete;
-
-// visitor
- template <typename T>
- void operator()(T const& operand) const
- {
- out_ << operand;
- }
-private:
- Out & out_;
-};
} // namespace detail
@@ -496,7 +519,7 @@ class variant
private:
static const std::size_t data_size = static_max<sizeof(Types)...>::value;
- static const std::size_t data_align = static_max<ALIGNOF(Types)...>::value;
+ static const std::size_t data_align = static_max<alignof(Types)...>::value;
using data_type = typename std::aligned_storage<data_size, data_align>::type;
using helper_type = variant_helper<Types...>;
@@ -506,7 +529,6 @@ private:
public:
-
VARIANT_INLINE variant()
: type_index(sizeof...(Types) - 1)
{
@@ -519,10 +541,10 @@ public:
// http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers
template <typename T, class = typename std::enable_if<
detail::is_valid_type<typename std::remove_reference<T>::type, Types...>::value>::type>
- VARIANT_INLINE variant(T && val) NOEXCEPT_MODIFIER
+ VARIANT_INLINE variant(T && val) noexcept
: type_index(detail::value_traits<typename std::remove_reference<T>::type, Types...>::index)
{
- CONSTEXPR_VALUE std::size_t index = sizeof...(Types) - detail::value_traits<typename std::remove_reference<T>::type, Types...>::index - 1;
+ constexpr std::size_t index = sizeof...(Types) - detail::value_traits<typename std::remove_reference<T>::type, Types...>::index - 1;
using target_type = typename detail::select_type<index, Types...>::type;
new (&data) target_type(std::forward<T>(val)); // nothrow
}
@@ -533,7 +555,7 @@ public:
helper_type::copy(old.type_index, &old.data, &data);
}
- VARIANT_INLINE variant(variant<Types...>&& old) NOEXCEPT_MODIFIER
+ VARIANT_INLINE variant(variant<Types...>&& old) noexcept
: type_index(old.type_index)
{
helper_type::move(old.type_index, &old.data, &data);
@@ -555,7 +577,7 @@ public:
// conversions
// move-assign
template <typename T>
- VARIANT_INLINE variant<Types...>& operator=(T && rhs) NOEXCEPT_MODIFIER
+ VARIANT_INLINE variant<Types...>& operator=(T && rhs) noexcept
{
variant<Types...> temp(std::forward<T>(rhs));
swap(*this, temp);
@@ -590,7 +612,8 @@ public:
type_index = detail::direct_type<T, Types...>::index;
}
- template<typename T>
+ // get<T>()
+ template<typename T, typename std::enable_if<(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE T& get()
{
if (type_index == detail::direct_type<T, Types...>::index)
@@ -599,11 +622,13 @@ public:
}
else
{
- throw std::runtime_error("in get()");
+ throw std::runtime_error("in get<T>()");
}
}
- template<typename T>
+ template <typename T, typename std::enable_if<
+ (detail::direct_type<T, Types...>::index != detail::invalid_value)
+ >::type* = nullptr>
VARIANT_INLINE T const& get() const
{
if (type_index == detail::direct_type<T, Types...>::index)
@@ -612,7 +637,69 @@ public:
}
else
{
- throw std::runtime_error("in get()");
+ throw std::runtime_error("in get<T>()");
+ }
+ }
+
+ // get<T>() - T stored as recursive_wrapper<T>
+ template <typename T, typename std::enable_if<
+ (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)
+ >::type* = nullptr>
+ VARIANT_INLINE T& get()
+ {
+ if (type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index)
+ {
+ return (*reinterpret_cast<recursive_wrapper<T>*>(&data)).get();
+ }
+ else
+ {
+ throw std::runtime_error("in get<T>()");
+ }
+ }
+
+ template <typename T,typename std::enable_if<
+ (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)
+ >::type* = nullptr>
+ VARIANT_INLINE T const& get() const
+ {
+ if (type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index)
+ {
+ return (*reinterpret_cast<recursive_wrapper<T> const*>(&data)).get();
+ }
+ else
+ {
+ throw std::runtime_error("in get<T>()");
+ }
+ }
+
+ // get<T>() - T stored as std::reference_wrapper<T>
+ template <typename T, typename std::enable_if<
+ (detail::direct_type<std::reference_wrapper<T>, Types...>::index != detail::invalid_value)
+ >::type* = nullptr>
+ VARIANT_INLINE T& get()
+ {
+ if (type_index == detail::direct_type<std::reference_wrapper<T>, Types...>::index)
+ {
+ return (*reinterpret_cast<std::reference_wrapper<T>*>(&data)).get();
+ }
+ else
+ {
+ throw std::runtime_error("in get<T>()");
+ }
+ }
+
+ template <typename T,typename std::enable_if<
+ (detail::direct_type<std::reference_wrapper<T const>, Types...>::index != detail::invalid_value)
+ >::type* = nullptr>
+ VARIANT_INLINE T const& get() const
+ {
+ if (type_index == detail::direct_type<std::reference_wrapper<T const>, Types...>::index)
+ {
+ return (*reinterpret_cast<std::reference_wrapper<T const> const*>(&data)).get();
+ }
+ else
+ {
+ throw std::runtime_error("in get<T>()");
}
}
@@ -621,22 +708,33 @@ public:
return type_index;
}
+ VARIANT_INLINE int which() const noexcept
+ {
+ return static_cast<int>(sizeof...(Types) - type_index - 1);
+ }
+
// visitor
// unary
template <typename F, typename V>
auto VARIANT_INLINE
static visit(V const& v, F f)
- -> decltype(detail::dispatcher<F, V, Types...>::apply_const(v, f))
+ -> decltype(detail::dispatcher<F, V,
+ typename detail::result_of_unary_visit<F,
+ typename detail::select_type<0, Types...>::type>::type, Types...>::apply_const(v, f))
{
- return detail::dispatcher<F, V, Types...>::apply_const(v, f);
+ using R = typename detail::result_of_unary_visit<F, typename detail::select_type<0, Types...>::type>::type;
+ return detail::dispatcher<F, V, R, Types...>::apply_const(v, f);
}
// non-const
template <typename F, typename V>
auto VARIANT_INLINE
static visit(V & v, F f)
- -> decltype(detail::dispatcher<F, V, Types...>::apply(v, f))
+ -> decltype(detail::dispatcher<F, V,
+ typename detail::result_of_unary_visit<F,
+ typename detail::select_type<0, Types...>::type>::type, Types...>::apply(v, f))
{
- return detail::dispatcher<F, V, Types...>::apply(v, f);
+ using R = typename detail::result_of_unary_visit<F, typename detail::select_type<0, Types...>::type>::type;
+ return detail::dispatcher<F, V, R, Types...>::apply(v, f);
}
// binary
@@ -644,20 +742,26 @@ public:
template <typename F, typename V>
auto VARIANT_INLINE
static binary_visit(V const& v0, V const& v1, F f)
- -> decltype(detail::binary_dispatcher<F, V, Types...>::apply_const(v0, v1, f))
+ -> decltype(detail::binary_dispatcher<F, V,
+ typename detail::result_of_binary_visit<F,
+ typename detail::select_type<0, Types...>::type>::type, Types...>::apply_const(v0, v1, f))
{
- return detail::binary_dispatcher<F, V, Types...>::apply_const(v0, v1, f);
+ using R = typename detail::result_of_binary_visit<F,typename detail::select_type<0, Types...>::type>::type;
+ return detail::binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, f);
}
// non-const
template <typename F, typename V>
auto VARIANT_INLINE
static binary_visit(V& v0, V& v1, F f)
- -> decltype(detail::binary_dispatcher<F, V, Types...>::apply(v0, v1, f))
+ -> decltype(detail::binary_dispatcher<F, V,
+ typename detail::result_of_binary_visit<F,
+ typename detail::select_type<0, Types...>::type>::type, Types...>::apply(v0, v1, f))
{
- return detail::binary_dispatcher<F, V, Types...>::apply(v0, v1, f);
+ using R = typename detail::result_of_binary_visit<F,typename detail::select_type<0, Types...>::type>::type;
+ return detail::binary_dispatcher<F, V, R, Types...>::apply(v0, v1, f);
}
- ~variant() NOEXCEPT_MODIFIER
+ ~variant() noexcept
{
helper_type::destroy(type_index, &data);
}
@@ -715,28 +819,18 @@ auto VARIANT_INLINE static apply_visitor(F f, V & v0, V & v1) -> decltype(V::bin
// getter interface
template<typename ResultType, typename T>
-ResultType & get(T & var)
+ResultType & get(T & var)
{
return var.template get<ResultType>();
}
template<typename ResultType, typename T>
-ResultType const& get(T const& var)
+ResultType const& get(T const& var)
{
return var.template get<ResultType>();
}
-// operator<<
-template <typename charT, typename traits, typename... Types>
-VARIANT_INLINE std::basic_ostream<charT, traits>&
-operator<< (std::basic_ostream<charT, traits>& out, variant<Types...> const& rhs)
-{
- detail::printer<std::basic_ostream<charT, traits>> visitor(out);
- apply_visitor(visitor, rhs);
- return out;
-}
-
}}
#endif // MAPBOX_UTIL_VARIANT_HPP
diff --git a/3party/osrm/osrm-backend/third_party/variant/variant_io.hpp b/3party/osrm/osrm-backend/third_party/variant/variant_io.hpp
new file mode 100755
index 0000000000..8b0c13743e
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/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 <typename Out>
+class printer
+{
+public:
+ explicit printer(Out & out)
+ : out_(out) {}
+ printer& operator=(printer const&) = delete;
+
+// visitor
+ template <typename T>
+ void operator()(T const& operand) const
+ {
+ out_ << operand;
+ }
+private:
+ Out & out_;
+};
+}
+
+// operator<<
+template <typename charT, typename traits, typename... Types>
+VARIANT_INLINE std::basic_ostream<charT, traits>&
+operator<< (std::basic_ostream<charT, traits>& out, variant<Types...> const& rhs)
+{
+ detail::printer<std::basic_ostream<charT, traits>> visitor(out);
+ apply_visitor(visitor, rhs);
+ return out;
+}
+
+}}
+
+#endif //MAPBOX_UTIL_VARIANT_IO_HPP
diff --git a/3party/osrm/osrm-backend/third_party/variant/vcbuild.bat b/3party/osrm/osrm-backend/third_party/variant/vcbuild.bat
new file mode 100755
index 0000000000..21489a1344
--- /dev/null
+++ b/3party/osrm/osrm-backend/third_party/variant/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
diff --git a/3party/osrm/osrm-backend/Tools/.gitignore b/3party/osrm/osrm-backend/tools/.gitignore
index 5c861788d2..5c861788d2 100644..100755
--- a/3party/osrm/osrm-backend/Tools/.gitignore
+++ b/3party/osrm/osrm-backend/tools/.gitignore
diff --git a/3party/osrm/osrm-backend/Tools/check-hsgr.cpp b/3party/osrm/osrm-backend/tools/check-hsgr.cpp
index b3b157ad11..2418a473fe 100644..100755
--- a/3party/osrm/osrm-backend/Tools/check-hsgr.cpp
+++ b/3party/osrm/osrm-backend/tools/check-hsgr.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -24,13 +24,13 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "../DataStructures/Percent.h"
-#include "../DataStructures/QueryEdge.h"
-#include "../DataStructures/Range.h"
-#include "../DataStructures/StaticGraph.h"
-#include "../Util/GraphLoader.h"
-#include "../Util/simple_logger.hpp"
-#include "../Util/OSRMException.h"
+#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 <boost/assert.hpp>
#include <boost/filesystem.hpp>
@@ -85,18 +85,18 @@ int main(int argc, char *argv[])
const EdgeID edge_id_1 = m_query_graph->FindEdgeInEitherDirection(node_u, data.id);
if (SPECIAL_EDGEID == edge_id_1)
{
- throw OSRMException("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));
+ 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));
}
const EdgeID edge_id_2 = m_query_graph->FindEdgeInEitherDirection(data.id, node_v);
if (SPECIAL_EDGEID == edge_id_2)
{
- throw OSRMException("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));
+ 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));
}
}
progress.printStatus(node_u);
diff --git a/3party/osrm/osrm-backend/tools/components.cpp b/3party/osrm/osrm-backend/tools/components.cpp
new file mode 100755
index 0000000000..7ac64f8d9a
--- /dev/null
+++ b/3party/osrm/osrm-backend/tools/components.cpp
@@ -0,0 +1,293 @@
+/*
+
+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 "../typedefs.h"
+#include "../algorithms/tiny_components.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"
+#include "../util/osrm_exception.hpp"
+#include "../util/simple_logger.hpp"
+
+#include <boost/filesystem.hpp>
+
+#if defined(__APPLE__) || defined(_WIN32)
+#include <gdal.h>
+#include <ogrsf_frmts.h>
+#else
+#include <gdal/gdal.h>
+#include <gdal/ogrsf_frmts.h>
+#endif
+
+#include <osrm/coordinate.hpp>
+
+#include <fstream>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace
+{
+
+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 TarjanGraph = StaticGraph<TarjanEdgeData>;
+using TarjanEdge = TarjanGraph::InputEdge;
+
+void DeleteFileIfExists(const std::string &file_name)
+{
+ if (boost::filesystem::exists(file_name))
+ {
+ boost::filesystem::remove(file_name);
+ }
+}
+}
+
+int main(int argc, char *argv[])
+{
+ std::vector<QueryNode> coordinate_list;
+ std::vector<TurnRestriction> restriction_list;
+ std::vector<NodeID> bollard_node_list;
+ std::vector<NodeID> traffic_lights_list;
+
+ LogPolicy::GetInstance().Unmute();
+ try
+ {
+ // enable logging
+ if (argc < 3)
+ {
+ SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0]
+ << " <osrm> <osrm.restrictions>";
+ 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<char *>(&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 <osrm-restrictions> files");
+ }
+ uint32_t usable_restrictions = 0;
+ restriction_ifstream.read(reinterpret_cast<char *>(&usable_restrictions), sizeof(uint32_t));
+ restriction_list.resize(usable_restrictions);
+
+ // load restrictions
+ if (usable_restrictions > 0)
+ {
+ restriction_ifstream.read(reinterpret_cast<char *>(&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<ImportEdge> 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<TarjanEdge> graph_edge_list;
+// DeallocatingVector<TarjanEdge> graph_edge_list;
+ for (const auto &input_edge : edge_list)
+ {
+ if (input_edge.source == input_edge.target)
+ {
+ continue;
+ }
+
+ if (input_edge.forward)
+ {
+ 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)
+ {
+ 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(graph_edge_list.begin(), graph_edge_list.end());
+ const auto graph = std::make_shared<TarjanGraph>(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<TarjanSCC<TarjanGraph>>(graph,
+ restriction_map,
+ bollard_node_list);
+ tarjan->run();
+ SimpleLogger().Write() << "identified: " << tarjan->get_number_of_components()
+ << " many components";
+ SimpleLogger().Write() << "identified " << tarjan->get_size_one_count() << " size 1 SCCs";
+
+ // output
+ TIMER_START(SCC_RUN_SETUP);
+
+ // remove files from previous run if exist
+ DeleteFileIfExists("component.dbf");
+ DeleteFileIfExists("component.shx");
+ DeleteFileIfExists("component.shp");
+
+ Percent percentage(graph->GetNumberOfNodes());
+
+ OGRRegisterAll();
+
+ const char *pszDriverName = "ESRI Shapefile";
+ OGRSFDriver *poDriver =
+ OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(pszDriverName);
+ if (nullptr == poDriver)
+ {
+ throw osrm::exception("ESRI Shapefile driver not available");
+ }
+ OGRDataSource *poDS = poDriver->CreateDataSource("component.shp", nullptr);
+
+ if (nullptr == poDS)
+ {
+ throw osrm::exception("Creation of output file failed");
+ }
+
+ OGRSpatialReference *poSRS = new OGRSpatialReference();
+ poSRS->importFromEPSG(4326);
+
+ OGRLayer *poLayer = poDS->CreateLayer("component", poSRS, wkbLineString, nullptr);
+
+ if (nullptr == poLayer)
+ {
+ throw osrm::exception("Layer creation failed.");
+ }
+ TIMER_STOP(SCC_RUN_SETUP);
+ SimpleLogger().Write() << "shapefile setup took " << TIMER_MSEC(SCC_RUN_SETUP) / 1000.
+ << "s";
+
+ uint64_t total_network_length = 0;
+ percentage.reinit(graph->GetNumberOfNodes());
+ TIMER_START(SCC_OUTPUT);
+ for (const NodeID source : osrm::irange(0u, graph->GetNumberOfNodes()))
+ {
+ percentage.printIncrement();
+ for (const auto current_edge : graph->GetAdjacentEdgeRange(source))
+ {
+ const TarjanGraph::NodeIterator target = graph->GetTarget(current_edge);
+
+ if (source < target || SPECIAL_EDGEID == graph->FindEdge(target, source))
+ {
+ total_network_length +=
+ 100 * coordinate_calculation::euclidean_distance(
+ 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));
+
+ // edges that end on bollard nodes may actually be in two distinct components
+ if (size_of_containing_component < 1000)
+ {
+ OGRLineString lineString;
+ lineString.addPoint(coordinate_list[source].lon / COORDINATE_PRECISION,
+ coordinate_list[source].lat / COORDINATE_PRECISION);
+ lineString.addPoint(coordinate_list[target].lon / COORDINATE_PRECISION,
+ coordinate_list[target].lat / COORDINATE_PRECISION);
+
+ OGRFeature *poFeature = OGRFeature::CreateFeature(poLayer->GetLayerDefn());
+
+ poFeature->SetGeometry(&lineString);
+ if (OGRERR_NONE != poLayer->CreateFeature(poFeature))
+ {
+ throw osrm::exception("Failed to create feature in shapefile.");
+ }
+ OGRFeature::DestroyFeature(poFeature);
+ }
+ }
+ }
+ }
+ OGRSpatialReference::DestroySpatialReference(poSRS);
+ OGRDataSource::DestroyDataSource(poDS);
+ TIMER_STOP(SCC_OUTPUT);
+ SimpleLogger().Write() << "generating output took: " << TIMER_MSEC(SCC_OUTPUT) / 1000.
+ << "s";
+
+ SimpleLogger().Write() << "total network distance: "
+ << static_cast<uint64_t>(total_network_length / 100 / 1000.)
+ << " km";
+
+ SimpleLogger().Write() << "finished component analysis";
+ }
+ catch (const std::exception &e)
+ {
+ SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
+ }
+ return 0;
+}
diff --git a/3party/osrm/osrm-backend/tools/graph_compare.cpp b/3party/osrm/osrm-backend/tools/graph_compare.cpp
new file mode 100755
index 0000000000..8adc06e788
--- /dev/null
+++ b/3party/osrm/osrm-backend/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 <algorithm>
+#include <fstream>
+
+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<TarjanEdgeData>;
+using DynamicTestGraph = StaticGraph<TarjanEdgeData>;
+using StaticEdge = StaticTestGraph::InputEdge;
+using DynamicEdge = DynamicTestGraph::InputEdge;
+
+int main(int argc, char *argv[])
+{
+ std::vector<QueryNode> coordinate_list;
+ std::vector<TurnRestriction> restriction_list;
+ std::vector<NodeID> bollard_node_list;
+ std::vector<NodeID> traffic_lights_list;
+
+ LogPolicy::GetInstance().Unmute();
+ try
+ {
+ // enable logging
+ if (argc < 3)
+ {
+ SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0]
+ << " <osrm> <osrm.restrictions>";
+ 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<char *>(&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 <osrm-restrictions> files");
+ }
+ uint32_t usable_restrictions = 0;
+ restriction_ifstream.read(reinterpret_cast<char *>(&usable_restrictions), sizeof(uint32_t));
+ restriction_list.resize(usable_restrictions);
+
+ // load restrictions
+ if (usable_restrictions > 0)
+ {
+ restriction_ifstream.read(reinterpret_cast<char *>(&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<ImportEdge> 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<StaticEdge> static_graph_edge_list;
+ std::vector<DynamicEdge> 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<StaticTestGraph>(number_of_nodes, static_graph_edge_list);
+ auto dynamic_graph =
+ osrm::make_unique<DynamicTestGraph>(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 (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);
+ 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<EdgeID> static_target_ids, dynamic_target_ids;
+ std::vector<TarjanEdgeData> 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;
+}
diff --git a/3party/osrm/osrm-backend/Tools/io-benchmark.cpp b/3party/osrm/osrm-backend/tools/io-benchmark.cpp
index b438000558..ae76327e20 100644..100755
--- a/3party/osrm/osrm-backend/Tools/io-benchmark.cpp
+++ b/3party/osrm/osrm-backend/tools/io-benchmark.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,17 +25,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "../Util/GitDescription.h"
-#include "../Util/OSRMException.h"
-#include "../Util/simple_logger.hpp"
-#include "../Util/TimingUtil.h"
+#include "../util/git_sha.hpp"
+#include "../util/osrm_exception.hpp"
+#include "../util/simple_logger.hpp"
+#include "../util/timing_util.hpp"
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <cmath>
#include <cstdio>
-#include <cstdlib>
#include <fcntl.h>
#ifdef __linux__
#include <malloc.h>
@@ -45,6 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <chrono>
#include <iomanip>
#include <numeric>
+#include <random>
#include <vector>
const unsigned number_of_elements = 268435456;
@@ -63,28 +63,29 @@ void RunStatistics(std::vector<double> &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));
}
int main(int argc, char *argv[])
{
+
+#ifdef __FreeBSD__
+ SimpleLogger().Write() << "Not supported on FreeBSD";
+ return 0;
+#endif
+#ifdef _WIN32
+ SimpleLogger().Write() << "Not supported on Windows";
+ return 0;
+#else
+
LogPolicy::GetInstance().Unmute();
boost::filesystem::path test_path;
try
{
SimpleLogger().Write() << "starting up engines, " << g_GIT_DESCRIPTION;
-#ifdef __FreeBSD__
- SimpleLogger().Write() << "Not supported on FreeBSD";
- return 0;
-#endif
-#ifdef WIN32
- SimpleLogger().Write() << "Not supported on Windows";
- return 0;
-#else
-
if (1 == argc)
{
SimpleLogger().Write(logWARNING) << "usage: " << argv[0] << " /path/on/device";
@@ -101,7 +102,7 @@ int main(int argc, char *argv[])
// create file to test
if (boost::filesystem::exists(test_path))
{
- throw OSRMException("Data file already exists");
+ throw osrm::exception("Data file already exists");
}
int *random_array = new int[number_of_elements];
@@ -120,13 +121,13 @@ int main(int argc, char *argv[])
open(test_path.string().c_str(), O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, S_IRWXU);
if (-1 == file_desc)
{
- throw OSRMException("Could not open random data file");
+ throw osrm::exception("Could not open random data file");
}
TIMER_START(write_1gb);
int ret = write(file_desc, random_array, number_of_elements * sizeof(unsigned));
if (0 > ret)
{
- throw OSRMException("could not write random data file");
+ throw osrm::exception("could not write random data file");
}
TIMER_STOP(write_1gb);
close(file_desc);
@@ -145,7 +146,7 @@ int main(int argc, char *argv[])
// Run Non-Cached I/O benchmarks
if (!boost::filesystem::exists(test_path))
{
- throw OSRMException("data file does not exist");
+ throw osrm::exception("data file does not exist");
}
// volatiles do not get optimized
@@ -200,9 +201,12 @@ int main(int argc, char *argv[])
#endif
// make 1000 random access, time each I/O seperately
unsigned number_of_blocks = (number_of_elements * sizeof(unsigned) - 1) / 4096;
+ std::random_device rd;
+ std::default_random_engine e1(rd());
+ std::uniform_int_distribution<unsigned> uniform_dist(0, number_of_blocks - 1);
for (unsigned i = 0; i < 1000; ++i)
{
- unsigned block_to_read = std::rand() % number_of_blocks;
+ unsigned block_to_read = uniform_dist(e1);
off_t current_offset = block_to_read * 4096;
TIMER_START(random_access);
#ifdef __APPLE__
@@ -224,13 +228,13 @@ int main(int argc, char *argv[])
{
SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
SimpleLogger().Write(logWARNING) << "seek error " << strerror(errno);
- throw OSRMException("seek error");
+ throw osrm::exception("seek error");
}
if (-1 == ret2)
{
SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
SimpleLogger().Write(logWARNING) << "read error " << strerror(errno);
- throw OSRMException("read error");
+ throw osrm::exception("read error");
}
timing_results_raw_random.push_back(TIMER_SEC(random_access));
}
@@ -285,13 +289,13 @@ int main(int argc, char *argv[])
{
SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
SimpleLogger().Write(logWARNING) << "seek error " << strerror(errno);
- throw OSRMException("seek error");
+ throw osrm::exception("seek error");
}
if (-1 == ret2)
{
SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
SimpleLogger().Write(logWARNING) << "read error " << strerror(errno);
- throw OSRMException("read error");
+ throw osrm::exception("read error");
}
timing_results_raw_seq.push_back(TIMER_SEC(read_every_100));
}
diff --git a/3party/osrm/osrm-backend/Tools/simpleclient.cpp b/3party/osrm/osrm-backend/tools/simpleclient.cpp
index b6714566a2..ce590ccd87 100644..100755
--- a/3party/osrm/osrm-backend/Tools/simpleclient.cpp
+++ b/3party/osrm/osrm-backend/tools/simpleclient.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,39 +25,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "../Library/OSRM.h"
-#include "../Util/GitDescription.h"
-#include "../Util/ProgramOptions.h"
-#include "../Util/simple_logger.hpp"
+#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 <osrm/Reply.h>
-#include <osrm/RouteParameters.h>
-#include <osrm/ServerPaths.h>
+#include <osrm/json_container.hpp>
+#include <osrm/libosrm_config.hpp>
+#include <osrm/route_parameters.hpp>
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/json_parser.hpp>
-
-#include <iostream>
-#include <stack>
#include <string>
-#include <sstream>
-
-// 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::string>()
- << std::endl;
- print_tree(tree_iterator->second, recursion_depth + 1);
- }
-}
int main(int argc, const char *argv[])
{
@@ -65,24 +43,25 @@ int main(int argc, const char *argv[])
try
{
std::string ip_address;
- int ip_port, requested_thread_num;
- bool use_shared_memory = false, trial = false;
- ServerPaths server_paths;
- if (!GenerateServerProgramOptions(argc,
- argv,
- server_paths,
- ip_address,
- ip_port,
- requested_thread_num,
- use_shared_memory,
- trial))
+ 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,
+ max_locations_map_matching);
+
+ 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);
+ OSRM routing_machine(lib_config);
RouteParameters route_parameters;
route_parameters.zoom_level = 18; // no generalization
@@ -90,7 +69,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
@@ -103,23 +82,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);
+ osrm::json::Object json_result;
+ const int result_code = routing_machine.RunQuery(route_parameters, json_result);
+ SimpleLogger().Write() << "http code: " << result_code;
+ osrm::json::render(SimpleLogger().Write(), json_result);
}
catch (std::exception &current_exception)
{
diff --git a/3party/osrm/osrm-backend/Tools/springclean.cpp b/3party/osrm/osrm-backend/tools/springclean.cpp
index f528d3da38..2d8910621e 100644..100755
--- a/3party/osrm/osrm-backend/Tools/springclean.cpp
+++ b/3party/osrm/osrm-backend/tools/springclean.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -27,10 +27,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cstdio>
-#include "../DataStructures/SharedMemoryFactory.h"
-#include "../Server/DataStructures/SharedDataType.h"
-#include "../Util/GitDescription.h"
-#include "../Util/simple_logger.hpp"
+#include "../data_structures/shared_memory_factory.hpp"
+#include "../server/data_structures/shared_datatype.hpp"
+#include "../util/git_sha.hpp"
+#include "../util/simple_logger.hpp"
void delete_region(const SharedDataType region)
{
@@ -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/3party/osrm/osrm-backend/Tools/unlock_all_mutexes.cpp b/3party/osrm/osrm-backend/tools/unlock_all_mutexes.cpp
index d448a2049c..299aa61f55 100644..100755
--- a/3party/osrm/osrm-backend/Tools/unlock_all_mutexes.cpp
+++ b/3party/osrm/osrm-backend/tools/unlock_all_mutexes.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,9 +25,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "../Util/GitDescription.h"
-#include "../Util/simple_logger.hpp"
-#include "../Server/DataStructures/SharedBarriers.h"
+#include "../util/git_sha.hpp"
+#include "../util/simple_logger.hpp"
+#include "../server/data_structures/shared_barriers.hpp"
#include <iostream>
diff --git a/3party/osrm/osrm-backend/typedefs.h b/3party/osrm/osrm-backend/typedefs.h
index e45a6e8c90..d1b0a53a84 100644..100755
--- a/3party/osrm/osrm-backend/typedefs.h
+++ b/3party/osrm/osrm-backend/typedefs.h
@@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Necessary workaround for Windows as VS doesn't implement C99
#ifdef _MSC_VER
+#define WIN32_LEAN_AND_MEAN
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
diff --git a/3party/osrm/osrm-backend/unit_tests/algorithm_tests.cpp b/3party/osrm/osrm-backend/unit_tests/algorithm_tests.cpp
new file mode 100755
index 0000000000..0a9f3fdff1
--- /dev/null
+++ b/3party/osrm/osrm-backend/unit_tests/algorithm_tests.cpp
@@ -0,0 +1,34 @@
+/*
+
+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.
+
+*/
+
+#define BOOST_TEST_MODULE algorithm tests
+
+#include <boost/test/unit_test.hpp>
+
+/*
+ * This file will contain an automatically generated main function.
+ */
diff --git a/3party/osrm/osrm-backend/unit_tests/algorithms/douglas_peucker.cpp b/3party/osrm/osrm-backend/unit_tests/algorithms/douglas_peucker.cpp
new file mode 100755
index 0000000000..9654e4da3d
--- /dev/null
+++ b/3party/osrm/osrm-backend/unit_tests/algorithms/douglas_peucker.cpp
@@ -0,0 +1,105 @@
+/*
+
+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 "../../algorithms/douglas_peucker.hpp"
+#include "../../data_structures/segment_information.hpp"
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/test_case_template.hpp>
+#include <boost/mpl/list.hpp>
+
+#include <osrm/coordinate.hpp>
+
+#include <iostream>
+
+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);
+}
+
+BOOST_AUTO_TEST_CASE(all_necessary_test)
+{
+ /*
+ * x
+ * / \
+ * x \
+ * / \
+ * x x
+ */
+ std::vector<SegmentInformation> 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)
+ {
+ BOOST_CHECK_EQUAL(i.necessary, true);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(remove_second_node_test)
+{
+ DouglasPeucker dp;
+ for (unsigned z = 0; z < DOUGLAS_PEUCKER_THRESHOLDS.size(); z++)
+ {
+ /*
+ * x--x
+ * | \
+ * x-x x
+ * |
+ * x
+ */
+ std::vector<SegmentInformation> 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(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],
+ 15 * COORDINATE_PRECISION, true),
+ };
+ BOOST_TEST_MESSAGE("Threshold (" << z << "): " << DOUGLAS_PEUCKER_THRESHOLDS[z]);
+ dp.Run(info, z);
+ BOOST_CHECK_EQUAL(info[0].necessary, true);
+ BOOST_CHECK_EQUAL(info[1].necessary, false);
+ BOOST_CHECK_EQUAL(info[2].necessary, true);
+ BOOST_CHECK_EQUAL(info[3].necessary, true);
+ BOOST_CHECK_EQUAL(info[4].necessary, false);
+ BOOST_CHECK_EQUAL(info[5].necessary, true);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/3party/osrm/osrm-backend/unit_tests/algorithms/duration_parsing.cpp b/3party/osrm/osrm-backend/unit_tests/algorithms/duration_parsing.cpp
new file mode 100755
index 0000000000..ec3b8191ad
--- /dev/null
+++ b/3party/osrm/osrm-backend/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 <boost/test/unit_test.hpp>
+#include <boost/test/test_case_template.hpp>
+
+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/3party/osrm/osrm-backend/unit_tests/algorithms/string_util.cpp b/3party/osrm/osrm-backend/unit_tests/algorithms/string_util.cpp
new file mode 100755
index 0000000000..865ddd5a26
--- /dev/null
+++ b/3party/osrm/osrm-backend/unit_tests/algorithms/string_util.cpp
@@ -0,0 +1,75 @@
+/*
+
+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 <boost/test/unit_test.hpp>
+#include <boost/test/test_case_template.hpp>
+
+#include <iostream>
+
+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)
+{
+ 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\\"};
+ 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()
diff --git a/3party/osrm/osrm-backend/UnitTests/DataStructures/BinaryHeapTest.cpp b/3party/osrm/osrm-backend/unit_tests/data_structures/binary_heap.cpp
index dc2b21b304..d039710c03 100644..100755
--- a/3party/osrm/osrm-backend/UnitTests/DataStructures/BinaryHeapTest.cpp
+++ b/3party/osrm/osrm-backend/unit_tests/data_structures/binary_heap.cpp
@@ -1,4 +1,31 @@
-#include "../../DataStructures/BinaryHeap.h"
+/*
+
+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/binary_heap.hpp"
#include "../../typedefs.h"
#include <boost/test/unit_test.hpp>
diff --git a/3party/osrm/osrm-backend/unit_tests/data_structures/coordinate.cpp b/3party/osrm/osrm-backend/unit_tests/data_structures/coordinate.cpp
new file mode 100755
index 0000000000..6e891563a4
--- /dev/null
+++ b/3party/osrm/osrm-backend/unit_tests/data_structures/coordinate.cpp
@@ -0,0 +1,50 @@
+/*
+
+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 <boost/test/unit_test.hpp>
+
+#include "../../data_structures/coordinate_calculation.hpp"
+
+#include <osrm/coordinate.hpp>
+
+#include <cmath>
+
+// 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 = coordinate_calculation::perpendicular_distance(u, v, q);
+
+ float ratio;
+ FixedPointCoordinate nearest_location;
+ float d2 = coordinate_calculation::perpendicular_distance(u, v, q, nearest_location, ratio);
+
+ BOOST_CHECK_LE(std::abs(d1 - d2), 0.01f);
+}
diff --git a/3party/osrm/osrm-backend/unit_tests/data_structures/dynamic_graph.cpp b/3party/osrm/osrm-backend/unit_tests/data_structures/dynamic_graph.cpp
new file mode 100755
index 0000000000..27dc7dc68f
--- /dev/null
+++ b/3party/osrm/osrm-backend/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 <boost/test/unit_test.hpp>
+#include <boost/test/test_case_template.hpp>
+#include <boost/mpl/list.hpp>
+
+#include <random>
+#include <unordered_map>
+
+BOOST_AUTO_TEST_SUITE(dynamic_graph)
+
+struct TestData
+{
+ EdgeID id;
+};
+
+typedef DynamicGraph<TestData> TestDynamicGraph;
+typedef TestDynamicGraph::InputEdge TestInputEdge;
+
+BOOST_AUTO_TEST_CASE(find_test)
+{
+ /*
+ * (0) -1-> (1)
+ * ^ ^
+ * 2 5
+ * | |
+ * (3) -3-> (4)
+ * <-4-
+ */
+ std::vector<TestInputEdge> 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/3party/osrm/osrm-backend/UnitTests/DataStructures/RangeTableTest.cpp b/3party/osrm/osrm-backend/unit_tests/data_structures/range_table.cpp
index c439badbf5..ec3b724ad1 100644..100755
--- a/3party/osrm/osrm-backend/UnitTests/DataStructures/RangeTableTest.cpp
+++ b/3party/osrm/osrm-backend/unit_tests/data_structures/range_table.cpp
@@ -1,4 +1,31 @@
-#include "../../DataStructures/RangeTable.h"
+/*
+
+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/range_table.hpp"
#include "../../typedefs.h"
#include <boost/test/unit_test.hpp>
@@ -25,8 +52,9 @@ void ConstructionTest(std::vector<unsigned> lengths, std::vector<unsigned> offse
}
}
-void
-ComputeLengthsOffsets(std::vector<unsigned> &lengths, std::vector<unsigned> &offsets, unsigned num)
+void ComputeLengthsOffsets(std::vector<unsigned> &lengths,
+ std::vector<unsigned> &offsets,
+ unsigned num)
{
lengths.resize(num);
offsets.resize(num + 1);
diff --git a/3party/osrm/osrm-backend/UnitTests/DataStructures/StaticGraphTest.cpp b/3party/osrm/osrm-backend/unit_tests/data_structures/static_graph.cpp
index db2fddefac..ed303b7919 100644..100755
--- a/3party/osrm/osrm-backend/UnitTests/DataStructures/StaticGraphTest.cpp
+++ b/3party/osrm/osrm-backend/unit_tests/data_structures/static_graph.cpp
@@ -1,4 +1,31 @@
-#include "../../DataStructures/StaticGraph.h"
+/*
+
+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/static_graph.hpp"
#include "../../typedefs.h"
#include <boost/test/unit_test.hpp>
@@ -13,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<TestData> TestStaticGraph;
@@ -31,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 <unsigned NUM_NODES, unsigned NUM_EDGES> struct RandomArrayEntryFixture
@@ -67,8 +85,7 @@ template <unsigned NUM_NODES, unsigned NUM_EDGES> struct RandomArrayEntryFixture
for (unsigned i = 0; i < NUM_EDGES; i++)
{
edges.emplace_back(
- TestEdgeArrayEntry{static_cast<unsigned>(node_udist(g)),
- TestData{i, false, static_cast<unsigned>(lengths_udist(g))}});
+ TestEdgeArrayEntry{static_cast<unsigned>(node_udist(g)), TestData{i}});
}
for (unsigned i = 0; i < NUM_NODES; i++)
@@ -101,49 +118,37 @@ BOOST_FIXTURE_TEST_CASE(array_test, TestRandomArrayEntryFixture)
}
}
-TestStaticGraph GraphFromEdgeList(const std::vector<TestEdge> &edges)
-{
- std::vector<TestInputEdge> 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<TestInputEdge> 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);
@@ -152,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()
diff --git a/3party/osrm/osrm-backend/UnitTests/DataStructures/StaticRTreeTest.cpp b/3party/osrm/osrm-backend/unit_tests/data_structures/static_rtree.cpp
index 46dbc4e4bb..42bc718985 100644..100755
--- a/3party/osrm/osrm-backend/UnitTests/DataStructures/StaticRTreeTest.cpp
+++ b/3party/osrm/osrm-backend/unit_tests/data_structures/static_rtree.cpp
@@ -1,15 +1,43 @@
-#include "../../DataStructures/StaticRTree.h"
-#include "../../DataStructures/QueryNode.h"
-#include "../../DataStructures/EdgeBasedNode.h"
-#include "../../Util/floating_point.hpp"
-#include "../../typedefs.h"
+/*
-#include <osrm/Coordinate.h>
+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 "../../data_structures/coordinate_calculation.hpp"
+#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 "../../typedefs.h"
#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/mpl/list.hpp>
+#include <osrm/coordinate.hpp>
+
#include <random>
#include <unordered_set>
@@ -26,7 +54,7 @@ typedef StaticRTree<TestData,
TEST_LEAF_NODE_SIZE> TestStaticRTree;
// Choosen by a fair W20 dice roll (this value is completely arbitrary)
-constexpr unsigned RANDOM_SEED = 15;
+constexpr unsigned RANDOM_SEED = 42;
static const int32_t WORLD_MIN_LAT = -90 * COORDINATE_PRECISION;
static const int32_t WORLD_MAX_LAT = 90 * COORDINATE_PRECISION;
static const int32_t WORLD_MIN_LON = -180 * COORDINATE_PRECISION;
@@ -42,21 +70,15 @@ class LinearSearchNN
}
bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
- FixedPointCoordinate &result_coordinate,
- const unsigned zoom_level)
+ FixedPointCoordinate &result_coordinate)
{
- bool ignore_tiny_components = (zoom_level <= 14);
-
float min_dist = std::numeric_limits<float>::max();
FixedPointCoordinate min_coord;
for (const TestData &e : edges)
{
- if (ignore_tiny_components && e.is_in_tiny_cc)
- continue;
-
const FixedPointCoordinate &start = coords->at(e.u);
const FixedPointCoordinate &end = coords->at(e.v);
- float distance = FixedPointCoordinate::ApproximateEuclideanDistance(
+ float distance = coordinate_calculation::euclidean_distance(
input_coordinate.lat, input_coordinate.lon, start.lat, start.lon);
if (distance < min_dist)
{
@@ -64,7 +86,7 @@ class LinearSearchNN
min_dist = distance;
}
- distance = FixedPointCoordinate::ApproximateEuclideanDistance(
+ distance = coordinate_calculation::euclidean_distance(
input_coordinate.lat, input_coordinate.lon, end.lat, end.lon);
if (distance < min_dist)
{
@@ -74,26 +96,24 @@ class LinearSearchNN
}
result_coordinate = min_coord;
- return result_coordinate.isValid();
+ return result_coordinate.is_valid();
}
bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
PhantomNode &result_phantom_node,
const unsigned zoom_level)
{
- bool ignore_tiny_components = (zoom_level <= 14);
-
float min_dist = std::numeric_limits<float>::max();
TestData nearest_edge;
for (const TestData &e : edges)
{
- if (ignore_tiny_components && e.is_in_tiny_cc)
+ if (e.component_id != 0)
continue;
float current_ratio = 0.;
FixedPointCoordinate nearest;
const float current_perpendicular_distance =
- FixedPointCoordinate::ComputePerpendicularDistance(
+ coordinate_calculation::perpendicular_distance(
coords->at(e.u), coords->at(e.v), input_coordinate, nearest, current_ratio);
if ((current_perpendicular_distance < min_dist) &&
@@ -108,6 +128,7 @@ class LinearSearchNN
e.forward_offset,
e.reverse_offset,
e.packed_geometry_id,
+ e.component_id,
nearest,
e.fwd_segment_position,
e.forward_travel_mode,
@@ -116,7 +137,7 @@ class LinearSearchNN
}
}
- if (result_phantom_node.location.isValid())
+ if (result_phantom_node.location.is_valid())
{
// Hack to fix rounding errors and wandering via nodes.
if (1 == std::abs(input_coordinate.lon - result_phantom_node.location.lon))
@@ -128,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::euclidean_distance(
coords->at(nearest_edge.u), result_phantom_node.location);
- const float distance_2 = FixedPointCoordinate::ApproximateEuclideanDistance(
+ 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);
@@ -144,7 +165,7 @@ class LinearSearchNN
}
}
- return result_phantom_node.location.isValid();
+ return result_phantom_node.location.is_valid();
}
private:
@@ -181,7 +202,7 @@ template <unsigned NUM_NODES, unsigned NUM_EDGES> struct RandomGraphFixture
{
int lat = lat_udist(g);
int lon = lon_udist(g);
- nodes.emplace_back(NodeInfo(lat, lon, i));
+ nodes.emplace_back(QueryNode(lat, lon, i));
coords->emplace_back(FixedPointCoordinate(lat, lon));
}
@@ -197,14 +218,14 @@ template <unsigned NUM_NODES, unsigned NUM_EDGES> struct RandomGraphFixture
if (used_edges.find(std::pair<unsigned, unsigned>(
std::min(data.u, data.v), std::max(data.u, data.v))) == used_edges.end())
{
- data.is_in_tiny_cc = false;
+ data.component_id = 0;
edges.emplace_back(data);
used_edges.emplace(std::min(data.u, data.v), std::max(data.u, data.v));
}
}
}
- std::vector<NodeInfo> nodes;
+ std::vector<QueryNode> nodes;
std::shared_ptr<std::vector<FixedPointCoordinate>> coords;
std::vector<TestData> edges;
};
@@ -221,7 +242,7 @@ struct GraphFixture
FixedPointCoordinate c(input_coords[i].first * COORDINATE_PRECISION,
input_coords[i].second * COORDINATE_PRECISION);
coords->emplace_back(c);
- nodes.emplace_back(NodeInfo(c.lat, c.lon, i));
+ nodes.emplace_back(QueryNode(c.lat, c.lon, i));
}
for (const auto &pair : input_edges)
@@ -233,23 +254,23 @@ struct GraphFixture
}
}
- std::vector<NodeInfo> nodes;
+ std::vector<QueryNode> nodes;
std::shared_ptr<std::vector<FixedPointCoordinate>> coords;
std::vector<TestData> edges;
};
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * 3, TEST_LEAF_NODE_SIZE / 2>
-TestRandomGraphFixture_LeafHalfFull;
+ TestRandomGraphFixture_LeafHalfFull;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * 5, TEST_LEAF_NODE_SIZE>
-TestRandomGraphFixture_LeafFull;
+ TestRandomGraphFixture_LeafFull;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * 10, TEST_LEAF_NODE_SIZE * 2>
-TestRandomGraphFixture_TwoLeaves;
+ TestRandomGraphFixture_TwoLeaves;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * TEST_BRANCHING_FACTOR * 3,
TEST_LEAF_NODE_SIZE * TEST_BRANCHING_FACTOR>
-TestRandomGraphFixture_Branch;
+ TestRandomGraphFixture_Branch;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * TEST_BRANCHING_FACTOR * 3,
TEST_LEAF_NODE_SIZE * TEST_BRANCHING_FACTOR * 2>
-TestRandomGraphFixture_MultipleLevels;
+ TestRandomGraphFixture_MultipleLevels;
template <typename RTreeT>
void simple_verify_rtree(RTreeT &rtree,
@@ -265,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 = FixedPointCoordinate::ApproximateEuclideanDistance(
- 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<float>::epsilon());
- float dist_v = FixedPointCoordinate::ApproximateEuclideanDistance(
- 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<float>::epsilon());
}
}
@@ -292,7 +313,7 @@ void sampling_verify_rtree(RTreeT &rtree, LinearSearchNN &lsnn, unsigned num_sam
FixedPointCoordinate result_rtree;
rtree.LocateClosestEndPointForCoordinate(q, result_rtree, 1);
FixedPointCoordinate result_ln;
- lsnn.LocateClosestEndPointForCoordinate(q, result_ln, 1);
+ lsnn.LocateClosestEndPointForCoordinate(q, result_ln);
BOOST_CHECK_EQUAL(result_ln, result_rtree);
PhantomNode phantom_rtree;
@@ -314,9 +335,9 @@ 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<unsigned>(fixture->nodes.size());
node_stream.write((char *)&num_nodes, sizeof(unsigned));
- node_stream.write((char *)&(fixture->nodes[0]), num_nodes * sizeof(NodeInfo));
+ node_stream.write((char *)&(fixture->nodes[0]), num_nodes * sizeof(QueryNode));
node_stream.close();
RTreeT r(fixture->edges, nodes_path, leaves_path, fixture->nodes);
@@ -368,30 +389,31 @@ BOOST_AUTO_TEST_CASE(regression_test)
{
typedef std::pair<float, float> Coord;
typedef std::pair<unsigned, unsigned> 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<TestData, std::vector<FixedPointCoordinate>, false, 2, 3> MiniStaticRTree;
std::string leaves_path;
std::string nodes_path;
- build_rtree<GraphFixture, MiniStaticRTree>(
- "test_regression", &fixture, leaves_path, nodes_path);
+ build_rtree<GraphFixture, MiniStaticRTree>("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
@@ -400,9 +422,10 @@ BOOST_AUTO_TEST_CASE(regression_test)
rtree.LocateClosestEndPointForCoordinate(input, result, 1);
FixedPointCoordinate result_ln;
LinearSearchNN lsnn(fixture.coords, fixture.edges);
- lsnn.LocateClosestEndPointForCoordinate(input, result_ln, 1);
+ lsnn.LocateClosestEndPointForCoordinate(input, result_ln);
- BOOST_CHECK_EQUAL(result_ln, result);
+ // TODO: reactivate
+ // BOOST_CHECK_EQUAL(result_ln, result);
}
void TestRectangle(double width, double height, double center_lat, double center_lon)
@@ -428,30 +451,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::euclidean_distance(
north, FixedPointCoordinate(rect.max_lat, north.lon)));
BOOST_CHECK_EQUAL(rect.GetMinDist(south),
- FixedPointCoordinate::ApproximateEuclideanDistance(
+ coordinate_calculation::euclidean_distance(
south, FixedPointCoordinate(rect.min_lat, south.lon)));
BOOST_CHECK_EQUAL(rect.GetMinDist(west),
- FixedPointCoordinate::ApproximateEuclideanDistance(
+ coordinate_calculation::euclidean_distance(
west, FixedPointCoordinate(west.lat, rect.min_lon)));
BOOST_CHECK_EQUAL(rect.GetMinDist(east),
- FixedPointCoordinate::ApproximateEuclideanDistance(
+ coordinate_calculation::euclidean_distance(
east, FixedPointCoordinate(east.lat, rect.max_lon)));
/* Distance to corner points */
BOOST_CHECK_EQUAL(rect.GetMinDist(north_east),
- FixedPointCoordinate::ApproximateEuclideanDistance(
+ coordinate_calculation::euclidean_distance(
north_east, FixedPointCoordinate(rect.max_lat, rect.max_lon)));
BOOST_CHECK_EQUAL(rect.GetMinDist(north_west),
- FixedPointCoordinate::ApproximateEuclideanDistance(
+ coordinate_calculation::euclidean_distance(
north_west, FixedPointCoordinate(rect.max_lat, rect.min_lon)));
BOOST_CHECK_EQUAL(rect.GetMinDist(south_east),
- FixedPointCoordinate::ApproximateEuclideanDistance(
+ coordinate_calculation::euclidean_distance(
south_east, FixedPointCoordinate(rect.min_lat, rect.max_lon)));
BOOST_CHECK_EQUAL(rect.GetMinDist(south_west),
- FixedPointCoordinate::ApproximateEuclideanDistance(
+ coordinate_calculation::euclidean_distance(
south_west, FixedPointCoordinate(rect.min_lat, rect.min_lon)));
}
diff --git a/3party/osrm/osrm-backend/unit_tests/datastructure_tests.cpp b/3party/osrm/osrm-backend/unit_tests/datastructure_tests.cpp
new file mode 100755
index 0000000000..850d619100
--- /dev/null
+++ b/3party/osrm/osrm-backend/unit_tests/datastructure_tests.cpp
@@ -0,0 +1,34 @@
+/*
+
+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.
+
+*/
+
+#define BOOST_TEST_MODULE datastructure tests
+
+#include <boost/test/unit_test.hpp>
+
+/*
+ * This file will contain an automatically generated main function.
+ */
diff --git a/3party/osrm/osrm-backend/util/bearing.cpp b/3party/osrm/osrm-backend/util/bearing.cpp
new file mode 100755
index 0000000000..48fd7f92b4
--- /dev/null
+++ b/3party/osrm/osrm-backend/util/bearing.cpp
@@ -0,0 +1,65 @@
+/*
+
+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 "bearing.hpp"
+
+std::string bearing::get(const double heading) noexcept
+{
+ 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/3party/osrm/osrm-backend/util/bearing.hpp b/3party/osrm/osrm-backend/util/bearing.hpp
new file mode 100755
index 0000000000..8b16ebc164
--- /dev/null
+++ b/3party/osrm/osrm-backend/util/bearing.hpp
@@ -0,0 +1,38 @@
+/*
+
+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 BEARING_HPP
+#define BEARING_HPP
+
+#include <string>
+
+struct bearing
+{
+ static std::string get(const double heading) noexcept;
+};
+
+#endif // BEARING_HPP
diff --git a/3party/osrm/osrm-backend/Util/BoostFileSystemFix.h b/3party/osrm/osrm-backend/util/boost_filesystem_2_fix.hpp
index d7049cc2e1..2e41abd6a2 100644..100755
--- a/3party/osrm/osrm-backend/Util/BoostFileSystemFix.h
+++ b/3party/osrm/osrm-backend/util/boost_filesystem_2_fix.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef BOOST_FILE_SYSTEM_FIX_H
#define BOOST_FILE_SYSTEM_FIX_H
-#include "OSRMException.h"
+#include "osrm_exception.hpp"
// #include <boost/any.hpp>
#include <boost/filesystem.hpp>
@@ -50,7 +50,7 @@ namespace filesystem
// 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
-// void validate(
+// inline void validate(
// boost::any & v,
// const std::vector<std::string> & values,
// boost::filesystem::path *,
@@ -62,13 +62,13 @@ namespace filesystem
// if(boost::filesystem::is_regular_file(input_string)) {
// v = boost::any(boost::filesystem::path(input_string));
// } else {
-// throw OSRMException(input_string + " not found");
+// throw osrm::exception(input_string + " not found");
// }
// }
// adapted from:
// http://stackoverflow.com/questions/1746136/how-do-i-normalize-a-pathname-using-boostfilesystem
-boost::filesystem::path
+inline boost::filesystem::path
portable_canonical(const boost::filesystem::path &relative_path,
const boost::filesystem::path &current_path = boost::filesystem::current_path())
{
@@ -115,7 +115,7 @@ portable_canonical(const boost::filesystem::path &relative_path,
#if BOOST_FILESYSTEM_VERSION < 3
-path temp_directory_path()
+inline path temp_directory_path()
{
char *buffer;
buffer = tmpnam(nullptr);
@@ -123,7 +123,7 @@ path temp_directory_path()
return path(buffer);
}
-path unique_path(const path &) { return temp_directory_path(); }
+inline path unique_path(const path &) { return temp_directory_path(); }
#endif
}
@@ -133,11 +133,11 @@ path unique_path(const path &) { return temp_directory_path(); }
#define BOOST_FILESYSTEM_VERSION 3
#endif
-void AssertPathExists(const boost::filesystem::path &path)
+inline void AssertPathExists(const boost::filesystem::path &path)
{
if (!boost::filesystem::is_regular_file(path))
{
- throw OSRMException(path.string() + " not found.");
+ throw osrm::exception(path.string() + " not found.");
}
}
diff --git a/3party/osrm/osrm-backend/Util/cast.hpp b/3party/osrm/osrm-backend/util/cast.hpp
index 7807eda9ac..6d6ff6548c 100644..100755
--- a/3party/osrm/osrm-backend/Util/cast.hpp
+++ b/3party/osrm/osrm-backend/util/cast.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -38,7 +38,8 @@ struct cast
{
// convert scoped enums to integers
template <typename Enumeration>
- static auto enum_to_underlying(Enumeration const value) -> typename std::underlying_type<Enumeration>::type
+ static auto enum_to_underlying(Enumeration const value) ->
+ typename std::underlying_type<Enumeration>::type
{
return static_cast<typename std::underlying_type<Enumeration>::type>(value);
}
@@ -108,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;
@@ -145,13 +146,10 @@ struct cast
template <typename T> struct scientific_policy : boost::spirit::karma::real_policies<T>
{
// we want the numbers always to be in fixed format
- static int floatfield(T n)
- {
- return boost::spirit::karma::real_policies<T>::fmtflags::fixed;
- }
+ static int floatfield(T) { return boost::spirit::karma::real_policies<T>::fmtflags::fixed; }
static unsigned int precision(T) { return 6; }
};
- typedef boost::spirit::karma::real_generator<double, scientific_policy<double>> science_type;
+ using science_type = boost::spirit::karma::real_generator<double, scientific_policy<double>>;
static std::string double_fixed_to_string(const double value)
{
@@ -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/3party/osrm/osrm-backend/Util/compute_angle.cpp b/3party/osrm/osrm-backend/util/compute_angle.cpp
index b6350e445f..8cd8aa4410 100644..100755
--- a/3party/osrm/osrm-backend/Util/compute_angle.cpp
+++ b/3party/osrm/osrm-backend/util/compute_angle.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -27,20 +27,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "compute_angle.hpp"
-#include "TrigonometryTables.h"
-#include "../Util/MercatorUtil.h"
-#include <osrm/Coordinate.h>
+#include "trigonometry_table.hpp"
+#include "../util/mercator.hpp"
+
+#include <osrm/coordinate.hpp>
#include <cmath>
-double ComputeAngle::OfThreeFixedPointCoordinates(const FixedPointCoordinate &A,
- const FixedPointCoordinate &C,
- const FixedPointCoordinate &B)
+double ComputeAngle::OfThreeFixedPointCoordinates(const FixedPointCoordinate &first,
+ const FixedPointCoordinate &second,
+ const FixedPointCoordinate &third) noexcept
{
- const double v1x = (A.lon - C.lon) / COORDINATE_PRECISION;
- const double v1y = lat2y(A.lat / COORDINATE_PRECISION) - 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 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/3party/osrm/osrm-backend/Util/compute_angle.hpp b/3party/osrm/osrm-backend/util/compute_angle.hpp
index 72c861a45d..da84cafaa4 100644..100755
--- a/3party/osrm/osrm-backend/Util/compute_angle.hpp
+++ b/3party/osrm/osrm-backend/util/compute_angle.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -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) noexcept;
};
+
#endif // COMPUTE_ANGLE_HPP
diff --git a/3party/osrm/osrm-backend/Util/container.hpp b/3party/osrm/osrm-backend/util/container.hpp
index 86e9de31ca..d455e94e2a 100644..100755
--- a/3party/osrm/osrm-backend/Util/container.hpp
+++ b/3party/osrm/osrm-backend/util/container.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -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 <algorithm>
#include <iterator>
@@ -34,22 +34,41 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace osrm
{
-template <typename T> void sort_unique_resize(std::vector<T> &vector)
+namespace detail
{
- 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);
+// Culled by SFINAE if reserve does not exist or is not accessible
+template <typename T>
+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(...) noexcept { return false; }
+}
+
+template <typename Container> void sort_unique_resize(Container &vector) noexcept
+{
+ std::sort(std::begin(vector), std::end(vector));
+ const auto 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 <typename T> void sort_unique_resize_shrink_vector(std::vector<T> &vector)
+// template <typename T> inline void sort_unique_resize_shrink_vector(std::vector<T> &vector)
// {
// sort_unique_resize(vector);
// vector.shrink_to_fit();
// }
-// template <typename T> void remove_consecutive_duplicates_from_vector(std::vector<T> &vector)
+// template <typename T> inline void remove_consecutive_duplicates_from_vector(std::vector<T>
+// &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,9 +86,26 @@ 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;
}
+
+template <class ContainerT, typename Function>
+Function for_each_pair(ContainerT &container, Function function)
+{
+ return for_each_pair(std::begin(container), std::end(container), function);
}
-#endif /* CONTAINER_HPP_ */
+
+template <class Container> void append_to_container(Container &&a) {}
+
+template <class Container, typename T, typename... Args>
+void append_to_container(Container &&container, T value, Args &&... args)
+{
+ container.emplace_back(value);
+ append_to_container(std::forward<Container>(container), std::forward<Args>(args)...);
+}
+
+} // namespace osrm
+#endif /* CONTAINER_HPP */
diff --git a/3party/osrm/osrm-backend/Util/DataStoreOptions.h b/3party/osrm/osrm-backend/util/datastore_options.hpp
index f67b12d727..76edc78279 100644..100755
--- a/3party/osrm/osrm-backend/Util/DataStoreOptions.h
+++ b/3party/osrm/osrm-backend/util/datastore_options.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,16 +25,16 @@ 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 "GitDescription.h"
-#include "IniFileUtil.h"
-#include "OSRMException.h"
+#include "boost_filesystem_2_fix.hpp"
+#include "git_sha.hpp"
+#include "ini_file.hpp"
+#include "osrm_exception.hpp"
#include "simple_logger.hpp"
-#include <osrm/ServerPaths.h>
+#include <osrm/server_paths.hpp>
#include <boost/any.hpp>
#include <boost/filesystem.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<boost::filesystem::path>(&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<boost::filesystem::path>(&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<boost::filesystem::path>(&paths["hsgrdata"]),
+ "hsgrdata", boost::program_options::value<boost::filesystem::path>(&paths["hsgrdata"]),
".hsgr file")("nodesdata",
boost::program_options::value<boost::filesystem::path>(&paths["nodesdata"]),
".nodes file")(
- "edgesdata",
- boost::program_options::value<boost::filesystem::path>(&paths["edgesdata"]),
+ "edgesdata", boost::program_options::value<boost::filesystem::path>(&paths["edgesdata"]),
".edges file")("geometry",
boost::program_options::value<boost::filesystem::path>(&paths["geometry"]),
".geometry file")(
- "ramindex",
- boost::program_options::value<boost::filesystem::path>(&paths["ramindex"]),
+ "ramindex", boost::program_options::value<boost::filesystem::path>(&paths["ramindex"]),
".ramIndex file")(
- "fileindex",
- boost::program_options::value<boost::filesystem::path>(&paths["fileindex"]),
+ "fileindex", boost::program_options::value<boost::filesystem::path>(&paths["fileindex"]),
".fileIndex file")(
- "namesdata",
- boost::program_options::value<boost::filesystem::path>(&paths["namesdata"]),
+ "namesdata", boost::program_options::value<boost::filesystem::path>(&paths["namesdata"]),
".names file")("timestamp",
boost::program_options::value<boost::filesystem::path>(&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<boost::filesystem::path>(&paths["base"]),
+ "base,b", boost::program_options::value<boost::filesystem::path>(&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);
@@ -221,59 +215,59 @@ bool GenerateDataStoreOptions(const int argc, const char *argv[], ServerPaths &p
path_iterator = paths.find("hsgrdata");
if (path_iterator == paths.end() || path_iterator->second.string().empty())
{
- throw OSRMException(".hsgr file must be specified");
+ 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 OSRMException(".nodes file must be specified");
+ 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 OSRMException(".edges file must be specified");
+ 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 OSRMException(".geometry file must be specified");
+ 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 OSRMException(".ramindex file must be specified");
+ 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 OSRMException(".fileindex file must be specified");
+ 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 OSRMException(".names file must be specified");
+ 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 OSRMException(".timestamp file must be specified");
+ throw osrm::exception(".timestamp file must be specified");
}
return true;
}
-#endif /* DATA_STORE_OPTIONS_H */
+#endif /* DATASTORE_OPTIONS_HPP */
diff --git a/3party/osrm/osrm-backend/util/fingerprint.cpp b/3party/osrm/osrm-backend/util/fingerprint.cpp
new file mode 100755
index 0000000000..8c7ab404e8
--- /dev/null
+++ b/3party/osrm/osrm-backend/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"
diff --git a/3party/osrm/osrm-backend/Util/FingerPrint.h b/3party/osrm/osrm-backend/util/fingerprint.hpp
index c61fe360ec..82eb1364a1 100644..100755
--- a/3party/osrm/osrm-backend/Util/FingerPrint.h
+++ b/3party/osrm/osrm-backend/util/fingerprint.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -35,14 +35,13 @@ class FingerPrint
{
public:
FingerPrint();
- FingerPrint(const FingerPrint&) = delete;
+ 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 TestNodeInfo(const FingerPrint &other) const;
bool TestQueryObjects(const FingerPrint &other) const;
private:
diff --git a/3party/osrm/osrm-backend/util/fingerprint_impl.hpp b/3party/osrm/osrm-backend/util/fingerprint_impl.hpp
new file mode 100755
index 0000000000..1a528267b5
--- /dev/null
+++ b/3party/osrm/osrm-backend/util/fingerprint_impl.hpp
@@ -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 <boost/uuid/name_generator.hpp>
+
+#include <cstring>
+
+#include <algorithm>
+#include <string>
+
+#define HAS64BITS 0
+#define MD5PREPARE "b04b5d82a15a1f412e3dd3f8d054b0cc"
+#define MD5RTREE "92ac7e134019fdad361a15d6da036584"
+#define MD5GRAPH "409a612147d22797f5b4c1bdb809b8c9"
+#define MD5OBJECTS "4c258d9311a7e1f1d5305ab73180bd92"
+
+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/3party/osrm/osrm-backend/Util/FingerPrint.cpp.in b/3party/osrm/osrm-backend/util/fingerprint_impl.hpp.in
index c3bf0c035f..9259afd37f 100644..100755
--- a/3party/osrm/osrm-backend/Util/FingerPrint.cpp.in
+++ b/3party/osrm/osrm-backend/util/fingerprint_impl.hpp.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,12 +25,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "FingerPrint.h"
-
-#include "OSRMException.h"
+#include "osrm_exception.hpp"
#include <boost/uuid/name_generator.hpp>
+#include <cstring>
+
#include <algorithm>
#include <string>
@@ -70,7 +70,7 @@ bool FingerPrint::TestGraphUtil(const FingerPrint &other) const
{
if (!other.IsMagicNumberOK())
{
- throw OSRMException("hsgr input file misses magic number. Check or reprocess the file");
+ 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);
}
@@ -79,7 +79,7 @@ bool FingerPrint::TestPrepare(const FingerPrint &other) const
{
if (!other.IsMagicNumberOK())
{
- throw OSRMException("osrm input file misses magic number. Check or reprocess the file");
+ 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);
}
@@ -88,7 +88,7 @@ bool FingerPrint::TestRTree(const FingerPrint &other) const
{
if (!other.IsMagicNumberOK())
{
- throw OSRMException("r-tree input file misses magic number. Check or reprocess the file");
+ 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);
}
@@ -97,7 +97,7 @@ bool FingerPrint::TestQueryObjects(const FingerPrint &other) const
{
if (!other.IsMagicNumberOK())
{
- throw OSRMException("missing magic number. Check or reprocess the file");
+ 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/3party/osrm/osrm-backend/Util/floating_point.hpp b/3party/osrm/osrm-backend/util/floating_point.hpp
index 5c4810279a..13f2d3bc4d 100644..100755
--- a/3party/osrm/osrm-backend/Util/floating_point.hpp
+++ b/3party/osrm/osrm-backend/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/3party/osrm/osrm-backend/util/git_sha.cpp b/3party/osrm/osrm-backend/util/git_sha.cpp
new file mode 100755
index 0000000000..9d0e91da02
--- /dev/null
+++ b/3party/osrm/osrm-backend/util/git_sha.cpp
@@ -0,0 +1,31 @@
+/*
+
+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 "git_sha.hpp"
+
+#define GIT_DESCRIPTION "HEAD-HASH-NOTFOUND"
+char g_GIT_DESCRIPTION[] = GIT_DESCRIPTION;
diff --git a/3party/osrm/osrm-backend/Util/GitDescription.cpp.in b/3party/osrm/osrm-backend/util/git_sha.cpp.in
index 6f4ba7ed3b..e3686da199 100644..100755
--- a/3party/osrm/osrm-backend/Util/GitDescription.cpp.in
+++ b/3party/osrm/osrm-backend/util/git_sha.cpp.in
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,5 +25,7 @@ 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/3party/osrm/osrm-backend/Util/GitDescription.h b/3party/osrm/osrm-backend/util/git_sha.hpp
index d3a00f49a3..b0a9a7ca39 100644..100755
--- a/3party/osrm/osrm-backend/Util/GitDescription.h
+++ b/3party/osrm/osrm-backend/util/git_sha.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,9 +25,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef GIT_DESCRIPTION_H
-#define GIT_DESCRIPTION_H
+#ifndef GIT_SHA_HPP
+#define GIT_SHA_HPP
extern char g_GIT_DESCRIPTION[];
-#endif //GIT_DESCRIPTION_H
+#endif // GIT_SHA_HPP
diff --git a/3party/osrm/osrm-backend/util/graph_loader.hpp b/3party/osrm/osrm-backend/util/graph_loader.hpp
new file mode 100755
index 0000000000..d741334baf
--- /dev/null
+++ b/3party/osrm/osrm-backend/util/graph_loader.hpp
@@ -0,0 +1,539 @@
+/*
+
+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 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 <boost/assert.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+#include <tbb/parallel_sort.h>
+
+#include <cmath>
+
+#include <algorithm>
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+#include <unordered_map>
+#include <vector>
+
+template <typename EdgeT>
+NodeID read_undirected_osrm_stream(std::istream &input_stream,
+ std::vector<EdgeT> &edge_list,
+ std::vector<FixedPointCoordinate> &coordinate_list)
+{
+ const FingerPrint fingerprint_orig;
+ FingerPrint fingerprint_loaded;
+ input_stream.read(reinterpret_cast<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<NodeID, NodeID> ext_to_int_id_map;
+
+ NodeID n;
+ input_stream.read(reinterpret_cast<char *>(&n), sizeof(NodeID));
+ SimpleLogger().Write() << "Importing n = " << n << " nodes ";
+
+ ExternalMemoryNode current_node;
+ for (NodeID i = 0; i < n; ++i)
+ {
+ input_stream.read(reinterpret_cast<char *>(&current_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 &current_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<char *>(&m), sizeof(unsigned));
+ edge_list.reserve(m);
+ SimpleLogger().Write() << " and " << m << " edges ";
+
+ for (EdgeID i = 0; i < m; ++i)
+ {
+ input_stream.read(reinterpret_cast<char *>(&source), sizeof(unsigned));
+ input_stream.read(reinterpret_cast<char *>(&target), sizeof(unsigned));
+ input_stream.read(reinterpret_cast<char *>(&length), sizeof(int));
+ input_stream.read(reinterpret_cast<char *>(&dir), sizeof(short));
+ input_stream.read(reinterpret_cast<char *>(&weight), sizeof(int));
+ input_stream.read(reinterpret_cast<char *>(&nameID), sizeof(unsigned));
+ input_stream.read(reinterpret_cast<char *>(&is_roundabout), sizeof(bool));
+ input_stream.read(reinterpret_cast<char *>(&ignore_in_grid), sizeof(bool));
+ input_stream.read(reinterpret_cast<char *>(&is_access_restricted), sizeof(bool));
+ input_stream.read(reinterpret_cast<char *>(&travel_mode), sizeof(TravelMode));
+ input_stream.read(reinterpret_cast<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);
+ }
+ 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 <typename EdgeT>
+NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream,
+ std::vector<EdgeT> &edge_list,
+ std::vector<NodeID> &barrier_node_list,
+ std::vector<NodeID> &traffic_light_node_list,
+ std::vector<QueryNode> *int_to_ext_node_id_map,
+ std::vector<TurnRestriction> &restriction_list)
+{
+ const FingerPrint fingerprint_orig;
+ FingerPrint fingerprint_loaded;
+ input_stream.read(reinterpret_cast<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<NodeID, NodeID> ext_to_int_id_map;
+
+ NodeID n;
+ input_stream.read(reinterpret_cast<char *>(&n), sizeof(NodeID));
+ SimpleLogger().Write() << "Importing n = " << n << " nodes ";
+
+ ExternalMemoryNode current_node;
+ for (NodeID i = 0; i < n; ++i)
+ {
+ input_stream.read(reinterpret_cast<char *>(&current_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 &current_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<char *>(&m), sizeof(unsigned));
+ edge_list.reserve(m);
+ SimpleLogger().Write() << " and " << m << " edges ";
+
+ for (EdgeID i = 0; i < m; ++i)
+ {
+ input_stream.read(reinterpret_cast<char *>(&source), sizeof(unsigned));
+ input_stream.read(reinterpret_cast<char *>(&target), sizeof(unsigned));
+ input_stream.read(reinterpret_cast<char *>(&length), sizeof(int));
+ input_stream.read(reinterpret_cast<char *>(&dir), sizeof(short));
+ input_stream.read(reinterpret_cast<char *>(&weight), sizeof(int));
+ input_stream.read(reinterpret_cast<char *>(&nameID), sizeof(unsigned));
+ input_stream.read(reinterpret_cast<char *>(&is_roundabout), sizeof(bool));
+ input_stream.read(reinterpret_cast<char *>(&ignore_in_grid), sizeof(bool));
+ input_stream.read(reinterpret_cast<char *>(&is_access_restricted), sizeof(bool));
+ input_stream.read(reinterpret_cast<char *>(&travel_mode), sizeof(TravelMode));
+ input_stream.read(reinterpret_cast<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 <typename NodeT, typename EdgeT>
+unsigned readHSGRFromStream(const boost::filesystem::path &hsgr_file,
+ std::vector<NodeT> &node_list,
+ std::vector<EdgeT> &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(reinterpret_cast<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(reinterpret_cast<char *>(check_sum), sizeof(unsigned));
+ hsgr_input_stream.read(reinterpret_cast<char *>(&number_of_nodes), sizeof(unsigned));
+ BOOST_ASSERT_MSG(0 != number_of_nodes, "number of nodes is zero");
+ hsgr_input_stream.read(reinterpret_cast<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(reinterpret_cast<char *>(&node_list[0]),
+ number_of_nodes * sizeof(NodeT));
+
+ edge_list.resize(number_of_edges);
+ if (number_of_edges > 0)
+ {
+ hsgr_input_stream.read(reinterpret_cast<char *>(&edge_list[0]),
+ number_of_edges * sizeof(EdgeT));
+ }
+ hsgr_input_stream.close();
+
+ return number_of_nodes;
+}
+
+#endif // GRAPH_LOADER_HPP
diff --git a/3party/osrm/osrm-backend/Util/IniFileUtil.h b/3party/osrm/osrm-backend/util/ini_file.hpp
index ea1d7a13b5..b42f9aef8d 100644..100755
--- a/3party/osrm/osrm-backend/Util/IniFileUtil.h
+++ b/3party/osrm/osrm-backend/util/ini_file.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -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 <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
-#include <boost/regex.hpp>
-#include <regex>
+#include <algorithm>
#include <string>
+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<char>(config_stream)),
- std::istreambuf_iterator<char>());
- 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<char>());
+ 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/3party/osrm/osrm-backend/DataStructures/Range.h b/3party/osrm/osrm-backend/util/integer_range.hpp
index 7e2461ce73..46b69ba031 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/Range.h
+++ b/3party/osrm/osrm-backend/util/integer_range.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013,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,
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef RANGE_H
-#define RANGE_H
+#ifndef INTEGER_RANGE_HPP
+#define INTEGER_RANGE_HPP
#include <type_traits>
@@ -40,28 +40,33 @@ template <typename Integer> 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<Integer>::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; }
+ 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 <typename Integer> range<Integer> irange(Integer first, Integer last)
+template <typename Integer>
+range<Integer>
+irange(const Integer first,
+ const Integer last,
+ typename std::enable_if<std::is_integral<Integer>::value>::type * = 0) noexcept
{
return range<Integer>(first, last);
}
}
-#endif // RANGE_H
+#endif // INTEGER_RANGE_HPP
diff --git a/3party/osrm/osrm-backend/util/iso_8601_duration_parser.hpp b/3party/osrm/osrm-backend/util/iso_8601_duration_parser.hpp
new file mode 100755
index 0000000000..1981c89829
--- /dev/null
+++ b/3party/osrm/osrm-backend/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 <boost/bind.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+
+namespace qi = boost::spirit::qi;
+
+template <typename Iterator> struct iso_8601_grammar : qi::grammar<Iterator>
+{
+ 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<Iterator>::set_temp, this, ::_1)];
+ second = (qi::lit('s') |
+ qi::lit('S'))[boost::bind(&iso_8601_grammar<Iterator>::set_seconds, this)];
+ minute = (qi::lit('m') |
+ qi::lit('M'))[boost::bind(&iso_8601_grammar<Iterator>::set_minutes, this)];
+ hour = (qi::lit('h') |
+ qi::lit('H'))[boost::bind(&iso_8601_grammar<Iterator>::set_hours, this)];
+ }
+
+ qi::rule<Iterator> iso_period;
+ qi::rule<Iterator, std::string()> 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<unsigned>::max();
+ }
+ return temp;
+ }
+};
+
+#endif // ISO_8601_DURATION_PARSER_HPP
diff --git a/3party/osrm/osrm-backend/util/iterator_range.hpp b/3party/osrm/osrm-backend/util/iterator_range.hpp
new file mode 100755
index 0000000000..f4fa4f8289
--- /dev/null
+++ b/3party/osrm/osrm-backend/util/iterator_range.hpp
@@ -0,0 +1,71 @@
+/*
+
+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 ITERATOR_RANGE_HPP
+#define ITERATOR_RANGE_HPP
+
+namespace osrm
+{
+template <typename Iterator> class iter_range
+{
+ public:
+ iter_range(Iterator begin, Iterator end) noexcept : begin_(begin), end_(end) {}
+
+ Iterator begin() const noexcept { return begin_; }
+ Iterator end() const noexcept { return end_; }
+
+ private:
+ Iterator begin_;
+ Iterator end_;
+};
+
+// Convenience functions for template parameter inference,
+// akin to std::make_pair.
+
+template <typename Iterator>
+iter_range<Iterator> integer_range(Iterator begin, Iterator end) noexcept
+{
+ return iter_range<Iterator>(begin, end);
+}
+
+template <typename Reversable>
+iter_range<typename Reversable::reverse_iterator> reverse(Reversable *reversable) noexcept
+{
+ return iter_range<typename Reversable::reverse_iterator>(reversable->rbegin(),
+ reversable->rend());
+}
+
+template <typename ConstReversable>
+iter_range<typename ConstReversable::const_reverse_iterator>
+const_reverse(const ConstReversable *const_reversable) noexcept
+{
+ return iter_range<typename ConstReversable::const_reverse_iterator>(const_reversable->crbegin(),
+ const_reversable->crend());
+}
+}
+
+#endif // ITERATOR_RANGE_HPP
diff --git a/3party/osrm/osrm-backend/DataStructures/HashTable.h b/3party/osrm/osrm-backend/util/json_logger.hpp
index 40d952a9f8..b7de7cbea6 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/HashTable.h
+++ b/3party/osrm/osrm-backend/util/json_logger.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,54 +25,64 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef HASH_TABLE_H
-#define HASH_TABLE_H
+#ifndef JSON_LOGGER_HPP
+#define JSON_LOGGER_HPP
-#include <vector>
+#include <osrm/json_container.hpp>
-template <typename Key, typename Value>
-class HashTable
+#include <boost/thread.hpp>
+
+namespace osrm
+{
+namespace json
{
- private:
- using KeyValPair = std::pair<Key, Value>;
- std::vector<KeyValPair> table;
- public:
- HashTable() {}
+// Used to append additional debugging information to the JSON response in a
+// thread safe manner.
+class Logger
+{
+ using MapT = std::unordered_map<std::string, osrm::json::Value>;
- inline void Add(Key const &key, Value const &value)
+ public:
+ static Logger* get()
{
- table.emplace_back(std::move(key), std::move(value));
- }
+ static Logger logger;
- inline void Clear()
- {
- table.clear();
- }
+ bool return_logger = true;
+#ifdef NDEBUG
+ return_logger = false;
+#endif
+#ifdef ENABLE_JSON_LOGGING
+ return_logger = true;
+#endif
- inline const Value Find(Key const &key) const
- {
- for (const auto &key_val_pair : table)
+ if (return_logger)
{
- if (key_val_pair.first == key)
- {
- return key_val_pair.second;
- }
+ return &logger;
}
- return Value();
+
+ return nullptr;
}
- inline bool Holds(Key const &key) const
+ void initialize(const std::string& name)
{
- for (const auto &key_val_pair : table)
+ if (!map.get())
{
- if (key_val_pair.first == key)
- {
- return true;
- }
+ map.reset(new MapT());
}
- return false;
+ (*map)[name] = Object();
+ }
+
+ void render(const std::string& name, Object& obj) const
+ {
+ obj.values["debug"] = map->at(name);
}
+
+ boost::thread_specific_ptr<MapT> map;
};
-#endif /* HASH_TABLE_H */
+
+}
+}
+
+#endif /* JSON_LOGGER_HPP */
diff --git a/3party/osrm/osrm-backend/DataStructures/JSONContainer.h b/3party/osrm/osrm-backend/util/json_renderer.hpp
index 350441d12b..e5bbf6f92c 100644..100755
--- a/3party/osrm/osrm-backend/DataStructures/JSONContainer.h
+++ b/3party/osrm/osrm-backend/util/json_renderer.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -28,73 +28,29 @@ 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_RENDERER_HPP
+#define JSON_RENDERER_HPP
-#include "../ThirdParty/variant/variant.hpp"
-#include "../Util/cast.hpp"
+#include "cast.hpp"
+#include "string_util.hpp"
-#include <iostream>
-#include <vector>
-#include <string>
-#include <unordered_map>
+#include <osrm/json_container.hpp>
-namespace JSON
+namespace osrm
{
-
-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(value) {}
- double value;
-};
-
-struct True
-{
-};
-
-struct False
-{
-};
-
-struct Null
+namespace json
{
-};
-
-using Value = mapbox::util::variant<String,
- Number,
- mapbox::util::recursive_wrapper<Object>,
- mapbox::util::recursive_wrapper<Array>,
- True,
- False,
- Null>;
-
-struct Object
-{
- std::unordered_map<std::string, Value> values;
-};
-
-struct Array
-{
- std::vector<Value> values;
-};
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 << "\"";
+ out << escape_JSON(string.value);
+ out << "\"";
+ }
void operator()(const Number &number) const
{
@@ -151,7 +107,8 @@ 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());
+ 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('\"');
}
@@ -231,6 +188,6 @@ inline void render(std::vector<char> &out, const Object &object)
mapbox::util::apply_visitor(ArrayRenderer(out), value);
}
-} // namespace JSON
-
-#endif // JSON_CONTAINER_H
+} // namespace json
+} // namespace osrm
+#endif // JSON_RENDERER_HPP
diff --git a/3party/osrm/osrm-backend/util/json_util.hpp b/3party/osrm/osrm-backend/util/json_util.hpp
new file mode 100755
index 0000000000..bfb8a8bc44
--- /dev/null
+++ b/3party/osrm/osrm-backend/util/json_util.hpp
@@ -0,0 +1,103 @@
+/*
+
+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 JSON_UTIL_HPP
+#define JSON_UTIL_HPP
+
+#include <osrm/json_container.hpp>
+
+#include <cmath>
+#include <limits>
+
+namespace osrm
+{
+namespace json
+{
+
+// Make sure we don't have inf and NaN values
+template <typename T> T clamp_float(T d)
+{
+ if (std::isnan(d) || std::numeric_limits<T>::infinity() == d)
+ {
+ return std::numeric_limits<T>::max();
+ }
+ if (-std::numeric_limits<T>::infinity() == d)
+ {
+ return std::numeric_limits<T>::lowest();
+ }
+
+ return d;
+}
+
+template <typename... Args> osrm::json::Array make_array(Args... args)
+{
+ osrm::json::Array a;
+ append_to_container(a.values, args...);
+ return a;
+}
+
+template <typename T> osrm::json::Array make_array(const std::vector<T> &vector)
+{
+ osrm::json::Array a;
+ 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<bool> &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; }
+
+template <typename... Keys>
+osrm::json::Value &get(osrm::json::Value &value, const char *key, Keys... keys)
+{
+ using recursive_object_t = mapbox::util::recursive_wrapper<osrm::json::Object>;
+ return get(value.get<recursive_object_t>().get().values[key], keys...);
+}
+
+template <typename... Keys>
+osrm::json::Value &get(osrm::json::Value &value, unsigned key, Keys... keys)
+{
+ using recursive_array_t = mapbox::util::recursive_wrapper<osrm::json::Array>;
+ return get(value.get<recursive_array_t>().get().values[key], keys...);
+}
+
+} // namespace json
+} // namespace osrm
+#endif // JSON_UTIL_HPP
diff --git a/3party/osrm/osrm-backend/Util/LuaUtil.h b/3party/osrm/osrm-backend/util/lua_util.hpp
index 5c502c956a..af6277c59b 100644..100755
--- a/3party/osrm/osrm-backend/Util/LuaUtil.h
+++ b/3party/osrm/osrm-backend/util/lua_util.hpp
@@ -1,6 +1,6 @@
/*
-Copyright (c) 2013, 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,
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef LUA_UTIL_H
-#define LUA_UTIL_H
+#ifndef LUA_UTIL_HPP
+#define LUA_UTIL_HPP
extern "C" {
#include <lua.h>
@@ -63,4 +63,4 @@ inline void luaAddScriptFolderToLoadPath(lua_State *lua_state, const char *file_
luaL_dostring(lua_state, lua_code.c_str());
}
-#endif // LUA_UTIL_H
+#endif // LUA_UTIL_HPP
diff --git a/3party/osrm/osrm-backend/Util/make_unique.hpp b/3party/osrm/osrm-backend/util/make_unique.hpp
index 07786feaac..83e2301948 100644..100755
--- a/3party/osrm/osrm-backend/Util/make_unique.hpp
+++ b/3party/osrm/osrm-backend/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,
@@ -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<T>
-template <class T, class... Types> std::unique_ptr<T> make_unique(Types &&... Args)
+/// \brief Constructs a `new T()` with the given args and returns a
+/// `unique_ptr<T>` which owns the object.
+///
+/// Example:
+///
+/// auto p = make_unique<int>();
+/// auto p = make_unique<std::tuple<int, int>>(0, 1);
+template <class T, class... Args>
+typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
+make_unique(Args &&... args)
{
- return (std::unique_ptr<T>(new T(std::forward<Types>(Args)...)));
+ return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
-// make_unique<T[]>
-template <class T> std::unique_ptr<T[]> make_unique(std::size_t Size)
+/// \brief Constructs a `new T[n]` with the given args and returns a
+/// `unique_ptr<T[]>` which owns the object.
+///
+/// \param n size of the new array.
+///
+/// Example:
+///
+/// auto p = make_unique<int[]>(2); // value-initializes the array with 0's.
+template <class T>
+typename std::enable_if<std::is_array<T>::value && std::extent<T>::value == 0,
+ std::unique_ptr<T>>::type
+make_unique(size_t n)
{
- return (std::unique_ptr<T>(new T[Size]()));
+ return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]());
}
-// make_unique<T[N]> disallowed
-template <class T, class... Types>
-typename std::enable_if<std::extent<T>::value != 0, void>::type make_unique(Types &&...) = delete;
+/// This function isn't used and is only here to provide better compile errors.
+template <class T, class... Args>
+typename std::enable_if<std::extent<T>::value != 0>::type make_unique(Args &&...) = delete;
}
-
-#endif //MAKE_UNIQUE_H_
+#endif // MAKE_UNIQUE_H_
diff --git a/3party/osrm/osrm-backend/util/matching_debug_info.hpp b/3party/osrm/osrm-backend/util/matching_debug_info.hpp
new file mode 100755
index 0000000000..faf878e3f9
--- /dev/null
+++ b/3party/osrm/osrm-backend/util/matching_debug_info.hpp
@@ -0,0 +1,155 @@
+/*
+
+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 MATCHING_DEBUG_INFO_HPP
+#define MATCHING_DEBUG_INFO_HPP
+
+#include "json_logger.hpp"
+#include "json_util.hpp"
+#include "../data_structures/hidden_markov_model.hpp"
+
+#include <osrm/coordinate.hpp>
+
+// 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 <class CandidateLists> 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<mapbox::util::recursive_wrapper<osrm::json::Array>>()
+ .get()
+ .values.push_back(transistion);
+ }
+
+ void set_viterbi(const std::vector<std::vector<double>> &viterbi,
+ const std::vector<std::vector<bool>> &pruned,
+ const std::vector<std::vector<bool>> &suspicious)
+ {
+ // 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<unsigned>(pruned[t][s_prime]);
+ osrm::json::get(*object, "states", t, s_prime, "suspicious") =
+ static_cast<unsigned>(suspicious[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<bool> &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
diff --git a/3party/osrm/osrm-backend/Util/MercatorUtil.h b/3party/osrm/osrm-backend/util/mercator.cpp
index b4a15b779c..0ccd999814 100644..100755
--- a/3party/osrm/osrm-backend/Util/MercatorUtil.h
+++ b/3party/osrm/osrm-backend/util/mercator.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -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 <cmath>
-inline double y2lat(const double a)
+double mercator::y2lat(const double value) noexcept
{
- 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);
}
-inline double lat2y(const double a)
+double mercator::lat2y(const double latitude) noexcept
{
- 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.));
}
-
-#endif // MERCATOR_UTIL_H
diff --git a/3party/osrm/osrm-backend/util/mercator.hpp b/3party/osrm/osrm-backend/util/mercator.hpp
new file mode 100755
index 0000000000..e994c84996
--- /dev/null
+++ b/3party/osrm/osrm-backend/util/mercator.hpp
@@ -0,0 +1,38 @@
+/*
+
+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 MERCATOR_HPP
+#define MERCATOR_HPP
+
+struct mercator
+{
+ static double y2lat(const double value) noexcept;
+
+ static double lat2y(const double latitude) noexcept;
+};
+
+#endif // MERCATOR_HPP
diff --git a/3party/osrm/osrm-backend/util/osrm_exception.cpp b/3party/osrm/osrm-backend/util/osrm_exception.cpp
new file mode 100755
index 0000000000..9738b8e36b
--- /dev/null
+++ b/3party/osrm/osrm-backend/util/osrm_exception.cpp
@@ -0,0 +1,43 @@
+/*
+
+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 "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/3party/osrm/osrm-backend/Util/OSRMException.h b/3party/osrm/osrm-backend/util/osrm_exception.hpp
index f4f4290e35..e9a01381ee 100644..100755
--- a/3party/osrm/osrm-backend/Util/OSRMException.h
+++ b/3party/osrm/osrm-backend/util/osrm_exception.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,22 +25,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef OSRM_EXCEPTION_H
-#define OSRM_EXCEPTION_H
+#ifndef OSRM_EXCEPTION_HPP
+#define OSRM_EXCEPTION_HPP
#include <exception>
#include <string>
-class OSRMException : public std::exception
+namespace osrm
+{
+class exception final : public std::exception
{
public:
- explicit OSRMException(const char *message) : message(message) {}
- explicit OSRMException(const std::string &message) : message(message) {}
- virtual ~OSRMException() throw() {}
+ explicit exception(const char *message) : message(message) {}
+ explicit exception(const std::string &message) : message(message) {}
private:
- virtual const char *what() const throw() { return message.c_str(); }
+ // 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_H */
+}
+#endif /* OSRM_EXCEPTION_HPP */
diff --git a/3party/osrm/osrm-backend/util/range_algorithms.hpp b/3party/osrm/osrm-backend/util/range_algorithms.hpp
new file mode 100755
index 0000000000..4d01d29c89
--- /dev/null
+++ b/3party/osrm/osrm-backend/util/range_algorithms.hpp
@@ -0,0 +1,49 @@
+/*
+
+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 RANGE_ALGORITHMS_HPP
+#define RANGE_ALGORITHMS_HPP
+
+#include <algorithm>
+
+namespace osrm
+{
+
+template <class Container>
+auto max_element(const Container &c) -> decltype(std::max_element(c.begin(), c.end()))
+{
+ return std::max_element(c.begin(), c.end());
+}
+
+template <class Container>
+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/3party/osrm/osrm-backend/Util/ProgramOptions.h b/3party/osrm/osrm-backend/util/routed_options.hpp
index 47f69376a0..046ab71b31 100644..100755
--- a/3party/osrm/osrm-backend/Util/ProgramOptions.h
+++ b/3party/osrm/osrm-backend/util/routed_options.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,22 +25,21 @@ 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 "GitDescription.h"
-#include "IniFileUtil.h"
-#include "OSRMException.h"
+#include "git_sha.hpp"
+#include "ini_file.hpp"
+#include "osrm_exception.hpp"
#include "simple_logger.hpp"
-#include <osrm/ServerPaths.h>
-
#include <boost/any.hpp>
#include <boost/program_options.hpp>
+#include <osrm/server_paths.hpp>
+
#include <fstream>
#include <string>
-
const static unsigned INIT_OK_START_ENGINE = 0;
const static unsigned INIT_OK_DO_NOT_START_ENGINE = 1;
const static unsigned INIT_FAILED = -1;
@@ -60,8 +59,6 @@ inline void populate_base_path(ServerPaths &server_paths)
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["enodesdata"] = base_string + ".nodeData";
- 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";
@@ -90,49 +87,49 @@ inline void populate_base_path(ServerPaths &server_paths)
SimpleLogger().Write() << "not a regular file";
}
- throw OSRMException(".hsgr not found: " + path_iterator->second.string());
+ 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 OSRMException(".nodes not found");
+ 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 OSRMException(".edges not found");
+ 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 OSRMException(".geometry not found");
+ 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 OSRMException(".ramIndex not found");
+ 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 OSRMException(".fileIndex not found");
+ 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 OSRMException(".namesIndex not found");
+ throw osrm::exception(".namesIndex not found");
}
SimpleLogger().Write() << "HSGR file:\t" << server_paths["hsgrdata"];
@@ -153,64 +150,59 @@ 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,
+ 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");
generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")(
- "config,c",
- boost::program_options::value<boost::filesystem::path>(&paths["config"])
- ->default_value("server.ini"),
+ "config,c", boost::program_options::value<boost::filesystem::path>(&paths["config"])
+ ->default_value("server.ini"),
"Path to a configuration file")(
- "trial",
- boost::program_options::value<bool>(&trial)->implicit_value(true),
+ "trial", boost::program_options::value<bool>(&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<boost::filesystem::path>(&paths["hsgrdata"]),
+ "hsgrdata", boost::program_options::value<boost::filesystem::path>(&paths["hsgrdata"]),
".hsgr file")("nodesdata",
boost::program_options::value<boost::filesystem::path>(&paths["nodesdata"]),
".nodes file")(
- "edgesdata",
- boost::program_options::value<boost::filesystem::path>(&paths["edgesdata"]),
+ "edgesdata", boost::program_options::value<boost::filesystem::path>(&paths["edgesdata"]),
".edges file")("geometry",
boost::program_options::value<boost::filesystem::path>(&paths["geometries"]),
".geometry file")(
- "ramindex",
- boost::program_options::value<boost::filesystem::path>(&paths["ramindex"]),
+ "ramindex", boost::program_options::value<boost::filesystem::path>(&paths["ramindex"]),
".ramIndex file")(
- "fileindex",
- boost::program_options::value<boost::filesystem::path>(&paths["fileindex"]),
+ "fileindex", boost::program_options::value<boost::filesystem::path>(&paths["fileindex"]),
"File index file")(
- "namesdata",
- boost::program_options::value<boost::filesystem::path>(&paths["namesdata"]),
+ "namesdata", boost::program_options::value<boost::filesystem::path>(&paths["namesdata"]),
".names file")("timestamp",
boost::program_options::value<boost::filesystem::path>(&paths["timestamp"]),
".timestamp file")(
- "ip,i",
- boost::program_options::value<std::string>(&ip_address)->default_value("0.0.0.0"),
- "IP address")(
- "port,p", boost::program_options::value<int>(&ip_port)->default_value(5000), "TCP/IP port")(
- "threads,t",
- boost::program_options::value<int>(&requested_num_threads)->default_value(8),
+ "ip,i", boost::program_options::value<std::string>(&ip_address)->default_value("0.0.0.0"),
+ "IP address")("port,p", boost::program_options::value<int>(&ip_port)->default_value(5000),
+ "TCP/IP port")(
+ "threads,t", boost::program_options::value<int>(&requested_num_threads)->default_value(8),
"Number of threads to use")(
- "sharedmemory,s",
+ "shared-memory,s",
boost::program_options::value<bool>(&use_shared_memory)->implicit_value(true),
"Load data from shared memory")(
- "borders",
- boost::program_options::value<boost::filesystem::path>(&paths["borders"]),
- "Borders folder");
+ "max-table-size,m",
+ boost::program_options::value<int>(&max_locations_distance_table)->default_value(100),
+ "Max. locations supported in distance table query")(
+ "max-matching-size,m",
+ boost::program_options::value<int>(&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
boost::program_options::options_description hidden_options("Hidden options");
hidden_options.add_options()(
- "base,b",
- boost::program_options::value<boost::filesystem::path>(&paths["base"]),
+ "base,b", boost::program_options::value<boost::filesystem::path>(&paths["base"]),
"base path to .osrm file");
// positional option
@@ -256,7 +248,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);
@@ -266,7 +258,7 @@ inline unsigned GenerateServerProgramOptions(const int argc,
if (1 > requested_num_threads)
{
- throw OSRMException("Number of threads must be a positive number");
+ throw osrm::exception("Number of threads must be a positive number");
}
if (!use_shared_memory && option_variables.count("base"))
@@ -277,8 +269,17 @@ inline unsigned GenerateServerProgramOptions(const int argc,
{
return INIT_OK_START_ENGINE;
}
+ if (1 > max_locations_distance_table)
+ {
+ 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;
}
-#endif /* PROGRAM_OPTIONS_H */
+#endif // ROUTED_OPTIONS_HPP
diff --git a/3party/osrm/osrm-backend/Util/simple_logger.cpp b/3party/osrm/osrm-backend/util/simple_logger.cpp
index 5442f54c15..e3f4f8ed06 100644..100755
--- a/3party/osrm/osrm-backend/Util/simple_logger.cpp
+++ b/3party/osrm/osrm-backend/util/simple_logger.cpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -26,13 +26,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "simple_logger.hpp"
-
-#include "OSRMException.h"
-
-#include <boost/assert.hpp>
-
-#include <cstdio>
-
#ifdef _MSC_VER
#include <io.h>
#define isatty _isatty
@@ -40,17 +33,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#else
#include <unistd.h>
#endif
-
-#include <ostream>
+#include <cstdio>
#include <iostream>
#include <mutex>
+#include <string>
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"};
@@ -74,38 +67,30 @@ SimpleLogger::SimpleLogger() : level(logINFO) {}
std::mutex &SimpleLogger::get_mutex()
{
- static std::mutex m;
- return m;
+ static std::mutex mtx;
+ return mtx;
}
-std::ostringstream &SimpleLogger::Write(LogLevel l)
+std::ostringstream &SimpleLogger::Write(LogLevel lvl) noexcept
{
std::lock_guard<std::mutex> lock(get_mutex());
- try
+ level = lvl;
+ os << "[";
+ switch (level)
{
- level = l;
- 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 OSRMException
- throw OSRMException(std::string(e.what()) + ", getting ostringstream");
+ break;
+ default: // logINFO:
+ os << "info";
+ break;
}
+ os << "] ";
return os;
}
@@ -127,7 +112,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/3party/osrm/osrm-backend/Util/simple_logger.hpp b/3party/osrm/osrm-backend/util/simple_logger.hpp
index 2f7d1ed79b..df61a9deb1 100644..100755
--- a/3party/osrm/osrm-backend/Util/simple_logger.hpp
+++ b/3party/osrm/osrm-backend/util/simple_logger.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -64,11 +64,11 @@ class SimpleLogger
virtual ~SimpleLogger();
std::mutex &get_mutex();
- std::ostringstream &Write(LogLevel l = logINFO);
+ std::ostringstream &Write(LogLevel l = logINFO) noexcept;
private:
- LogLevel level;
std::ostringstream os;
+ LogLevel level;
};
#endif /* SIMPLE_LOGGER_HPP */
diff --git a/3party/osrm/osrm-backend/Util/StdHashExtensions.h b/3party/osrm/osrm-backend/util/std_hash.hpp
index 0d310d3c39..9e78fcce4e 100644..100755
--- a/3party/osrm/osrm-backend/Util/StdHashExtensions.h
+++ b/3party/osrm/osrm-backend/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,
@@ -25,37 +25,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef STD_HASH_EXTENSIONS_H
-#define STD_HASH_EXTENSIONS_H
+#ifndef STD_HASH_HPP
+#define STD_HASH_HPP
#include <functional>
// 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<typename T>
-void hash_combine(std::size_t &seed, const T& val)
+template <typename T> void hash_combine(std::size_t &seed, const T &val)
{
seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
-template<typename T>
-void hash_val(std::size_t &seed, const T& val)
-{
- hash_combine(seed, val);
-}
+template <typename T> void hash_val(std::size_t &seed, const T &val) { hash_combine(seed, val); }
-template<typename T, typename ... Types>
-void hash_val(std::size_t &seed, const T& val, const Types& ... args)
+template <typename T, typename... Types>
+void hash_val(std::size_t &seed, const T &val, const Types &... args)
{
hash_combine(seed, val);
- hash_val(seed, args ...);
+ hash_val(seed, args...);
}
-template<typename ... Types>
-std::size_t hash_val(const Types&... args)
+template <typename... Types> std::size_t hash_val(const Types &... args)
{
std::size_t seed = 0;
hash_val(seed, args...);
@@ -74,4 +69,4 @@ template <typename T1, typename T2> struct hash<std::pair<T1, T2>>
};
}
-#endif // STD_HASH_EXTENSIONS_H
+#endif // STD_HASH_HPP
diff --git a/3party/osrm/osrm-backend/Util/StringUtil.h b/3party/osrm/osrm-backend/util/string_util.hpp
index 3c9375ca73..3bfce00329 100644..100755
--- a/3party/osrm/osrm-backend/Util/StringUtil.h
+++ b/3party/osrm/osrm-backend/util/string_util.hpp
@@ -1,6 +1,6 @@
/*
-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,
@@ -25,13 +25,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef STRINGUTIL_H
-#define STRINGUTIL_H
+#ifndef STRING_UTIL_HPP
+#define STRING_UTIL_HPP
#include <boost/algorithm/string.hpp>
-#include <cstdio>
#include <cctype>
+
+#include <random>
#include <string>
#include <vector>
@@ -40,32 +41,43 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// work with negative values to prevent overflowing when taking -value
template <int length, int precision> static inline char *printInt(char *buffer, int value)
{
- bool minus = true;
- if (value > 0)
+ static_assert(length > 0, "length must be positive");
+ static_assert(precision > 0, "precision must be positive");
+
+ const bool minus = [&value]
{
- minus = false;
- value = -value;
- }
+ if (value >= 0)
+ {
+ value = -value;
+ return false;
+ }
+ return true;
+ }();
+
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;
@@ -76,13 +88,14 @@ 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)
{
+ // escape and skip reallocations if possible
std::string output;
- output.reserve(input.size());
- for (auto iter = input.begin(); iter != input.end(); ++iter)
+ output.reserve(input.size() + 4); // +4 assumes two backslashes on avg
+ for (const char letter : input)
{
- switch (iter[0])
+ switch (letter)
{
case '\\':
output += "\\\\";
@@ -109,23 +122,19 @@ inline std::string EscapeJSONString(const std::string &input)
output += "\\t";
break;
default:
- output += *iter;
+ output.append(1, letter);
break;
}
}
return output;
}
-static std::string originals[] = {"&", "\"", "<", ">", "'", "[", "]", "\\"};
-static std::string entities[] = {
- "&amp;", "&quot;", "&lt;", "&gt;", "&#39;", "&91;", "&93;", " &#92;"};
-
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]))
@@ -146,26 +155,4 @@ inline std::size_t URIDecode(const std::string &input, std::string &output)
inline std::size_t URIDecodeInPlace(std::string &URI) { return URIDecode(URI, URI); }
-// TODO: remove after switch to libosmium
-inline bool StringStartsWith(const std::string &input, const std::string &prefix)
-{
- return boost::starts_with(input, prefix);
-}
-
-inline std::string GetRandomString()
-{
- std::string s;
- s.resize(128);
- static const char alphanum[] = "0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz";
-
- for (int i = 0; i < 127; ++i)
- {
- s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
- }
- s[127] = 0;
- return s;
-}
-
-#endif // STRINGUTIL_H
+#endif // STRING_UTIL_HPP
diff --git a/3party/osrm/osrm-backend/util/timing_util.hpp b/3party/osrm/osrm-backend/util/timing_util.hpp
new file mode 100755
index 0000000000..c0c59c8a66
--- /dev/null
+++ b/3party/osrm/osrm-backend/util/timing_util.hpp
@@ -0,0 +1,90 @@
+/*
+
+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.
+
+*/
+
+#ifndef TIMING_UTIL_HPP
+#define TIMING_UTIL_HPP
+
+#include <atomic>
+#include <chrono>
+#include <cstdint>
+#include <mutex>
+#include <unordered_map>
+
+struct GlobalTimer
+{
+ GlobalTimer() : time(0) {}
+ std::atomic<uint64_t> time;
+};
+
+class GlobalTimerFactory
+{
+ public:
+ static GlobalTimerFactory &get()
+ {
+ static GlobalTimerFactory instance;
+ return instance;
+ }
+
+ GlobalTimer &getGlobalTimer(const std::string &name)
+ {
+ std::lock_guard<std::mutex> lock(map_mutex);
+ return timer_map[name];
+ }
+
+ private:
+ std::mutex map_mutex;
+ std::unordered_map<std::string, GlobalTimer> 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<double>(_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<std::chrono::nanoseconds>(_X##_stop - _X##_start).count()
+#define TIMER_USEC(_X) \
+ std::chrono::duration_cast<std::chrono::microseconds>(_X##_stop - _X##_start).count()
+#define TIMER_MSEC(_X) \
+ (0.000001 * \
+ std::chrono::duration_cast<std::chrono::nanoseconds>(_X##_stop - _X##_start).count())
+#define TIMER_SEC(_X) \
+ (0.000001 * \
+ std::chrono::duration_cast<std::chrono::microseconds>(_X##_stop - _X##_start).count())
+#define TIMER_MIN(_X) \
+ std::chrono::duration_cast<std::chrono::minutes>(_X##_stop - _X##_start).count()
+
+#endif // TIMING_UTIL_HPP
diff --git a/3party/osrm/osrm-backend/util/trigonometry_table.hpp b/3party/osrm/osrm-backend/util/trigonometry_table.hpp
new file mode 100755
index 0000000000..234a94e56c
--- /dev/null
+++ b/3party/osrm/osrm-backend/util/trigonometry_table.hpp
@@ -0,0 +1,448 @@
+/*
+
+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 TRIGONOMETRY_TABLE_HPP
+#define TRIGONOMETRY_TABLE_HPP
+
+#include "../typedefs.h"
+#include <cmath>
+
+#include <limits>
+
+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<double>::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/3party/osrm/osrm-backend/util/xml_renderer.hpp b/3party/osrm/osrm-backend/util/xml_renderer.hpp
new file mode 100755
index 0000000000..4ef1e5dc09
--- /dev/null
+++ b/3party/osrm/osrm-backend/util/xml_renderer.hpp
@@ -0,0 +1,142 @@
+/*
+
+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.
+
+*/
+
+#ifndef XML_RENDERER_HPP
+#define XML_RENDERER_HPP
+
+#include "cast.hpp"
+
+#include <osrm/json_container.hpp>
+
+namespace osrm
+{
+namespace json
+{
+
+struct XMLToArrayRenderer : mapbox::util::static_visitor<>
+{
+ explicit XMLToArrayRenderer(std::vector<char> &_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<Value>::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<char> &out;
+};
+
+template <class JSONObject> inline void xml_render(std::vector<char> &out, const JSONObject &object)
+{
+ Value value = object;
+ mapbox::util::apply_visitor(XMLToArrayRenderer(out), value);
+}
+
+template <class JSONObject> inline void gpx_render(std::vector<char> &out, const JSONObject &object)
+{
+ // add header
+
+ const std::string header{
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><gpx creator=\"OSRM Routing Engine\""
+ " version=\"1.1\" xmlns=\"http://www.topografix.com/GPX/1/1\" xmlns:xsi=\"http:"
+ "//www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.topogr"
+ "afix.com/GPX/1/1 gpx.xsd\"><metadata><copyright author=\"Project OSRM\"><lice"
+ "nse>Data (c) OpenStreetMap contributors (ODbL)</license></copyright></metadat"
+ "a><rte>"};
+ out.insert(out.end(), header.begin(), header.end());
+
+ xml_render(out, object);
+
+ const std::string footer{"</rte></gpx>"};
+ out.insert(out.end(), footer.begin(), footer.end());
+}
+} // namespace json
+} // namespace osrm
+#endif // XML_RENDERER_HPP