From 05d73706a1d9868d75a3ae26849050dc6549f57b Mon Sep 17 00:00:00 2001 From: Nathan Varner Date: Tue, 7 Mar 2023 02:28:28 -0500 Subject: [PATCH] [routing] Recognize empty lane directions as none Needed for: #1404 Signed-off-by: Nathan Varner --- .../routing_tests/turns_generator_test.cpp | 23 +++++++++++++++++++ routing/turns.cpp | 20 ++++++++++++---- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/routing/routing_tests/turns_generator_test.cpp b/routing/routing_tests/turns_generator_test.cpp index 5b5c3b0269..694e51355d 100644 --- a/routing/routing_tests/turns_generator_test.cpp +++ b/routing/routing_tests/turns_generator_test.cpp @@ -108,6 +108,18 @@ UNIT_TEST(TestParseSingleLane) TEST(ParseSingleLane("left", ';', result), ()); TEST_EQUAL(result.size(), 1, ()); TEST_EQUAL(result[0], LaneWay::Left, ()); + + TEST(ParseSingleLane("left;", ';', result), ()); + TSingleLane expected3 = {LaneWay::Left, LaneWay::None}; + TEST_EQUAL(result, expected3, ()); + + TEST(ParseSingleLane(";", ';', result), ()); + TSingleLane expected4 = {LaneWay::None, LaneWay::None}; + TEST_EQUAL(result, expected4, ()); + + TEST(ParseSingleLane("", ';', result), ()); + TSingleLane expected5 = {LaneWay::None}; + TEST_EQUAL(result, expected5, ()); } UNIT_TEST(TestParseLanes) @@ -162,6 +174,17 @@ UNIT_TEST(TestParseLanes) vector const expected7 = { {LaneWay::Left}, {LaneWay::Left}, {LaneWay::Through}, {LaneWay::Through}, {LaneWay::Right}}; TEST_EQUAL(result, expected7, ()); + + TEST(ParseLanes("|||||slight_right", result), ()); + vector const expected8 = { + {LaneWay::None}, + {LaneWay::None}, + {LaneWay::None}, + {LaneWay::None}, + {LaneWay::None}, + {LaneWay::SlightRight} + }; + TEST_EQUAL(result, expected8, ()); } UNIT_TEST(TestFixupTurns) diff --git a/routing/turns.cpp b/routing/turns.cpp index 12b69754f7..536d2e27d5 100644 --- a/routing/turns.cpp +++ b/routing/turns.cpp @@ -22,8 +22,14 @@ namespace { /// The order is important. Starting with the most frequent tokens according to /// taginfo.openstreetmap.org we minimize the number of the comparisons in ParseSingleLane(). -array, static_cast(LaneWay::Count)> const g_laneWayNames = { - {{LaneWay::Through, "through"}, +/// +/// A `none` lane can be represented either as "none" or as "". That means both "none" and "" +/// should be considered names, even though they refer to the same thing. As a result, +/// `LaneWay::None` appears twice in this array, which is one longer than the number of +/// enum values. +array, static_cast(LaneWay::Count) + 1> const g_laneWayNames = { + {{LaneWay::None, ""}, + {LaneWay::Through, "through"}, {LaneWay::Left, "left"}, {LaneWay::Right, "right"}, {LaneWay::None, "none"}, @@ -34,7 +40,7 @@ array, static_cast(LaneWay::Count)> const g_ {LaneWay::SlightRight, "slight_right"}, {LaneWay::SharpRight, "sharp_right"}, {LaneWay::Reverse, "reverse"}}}; -static_assert(g_laneWayNames.size() == static_cast(LaneWay::Count), +static_assert(g_laneWayNames.size() == static_cast(LaneWay::Count) + 1, "Check the size of g_laneWayNames"); array, static_cast(CarDirection::Count)> const @@ -298,7 +304,13 @@ void SplitLanes(string const & lanesString, char delimiter, vector & lan bool ParseSingleLane(string const & laneString, char delimiter, TSingleLane & lane) { lane.clear(); - istringstream laneStream(laneString); + // When `laneString` ends with "" representing none, for example, in "right;", + // `getline` will not read any characters, so it exits the loop and does not + // handle the "". So, we add a delimiter to the end of `laneString`. Nonempty + // final tokens consume the delimiter and act as expected, and empty final tokens + // read a the delimiter, so `getline` sets `token` to the empty string rather than + // exiting the loop. + istringstream laneStream(laneString + delimiter); string token; while (getline(laneStream, token, delimiter)) {