From c277b95f039dd42153f540dc6552d7ef3d0faf7a Mon Sep 17 00:00:00 2001 From: "Daniel J. Hofmann" Date: Thu, 15 Dec 2016 18:27:09 +0100 Subject: [PATCH] Implements Zero-Copy String Views onto Contiguous Memory, resolves #3265. - http://www.boost.org/doc/libs/1_61_0/libs/utility/doc/html/string_ref.html - http://en.cppreference.com/w/cpp/string/basic_string_view --- include/engine/api/base_api.hpp | 5 +- .../contiguous_internalmem_datafacade.hpp | 87 ++++++++++--------- include/engine/datafacade/datafacade_base.hpp | 28 +++--- include/engine/guidance/assemble_leg.hpp | 4 +- include/engine/guidance/assemble_steps.hpp | 32 +++---- include/extractor/suffix_table.hpp | 15 +++- include/util/guidance/name_announcements.hpp | 26 +++--- include/util/name_table.hpp | 8 +- include/util/string_view.hpp | 34 ++++++++ src/engine/plugins/tile.cpp | 15 ++-- src/extractor/suffix_table.cpp | 19 +++- src/util/name_table.cpp | 52 +++++------ unit_tests/mocks/mock_datafacade.hpp | 38 ++++---- 13 files changed, 219 insertions(+), 144 deletions(-) create mode 100644 include/util/string_view.hpp diff --git a/include/engine/api/base_api.hpp b/include/engine/api/base_api.hpp index 7bbbf6cb3..672ddf594 100644 --- a/include/engine/api/base_api.hpp +++ b/include/engine/api/base_api.hpp @@ -51,12 +51,13 @@ class BaseAPI if (parameters.generate_hints) { return json::makeWaypoint(phantom.location, - facade.GetNameForID(phantom.name_id), + facade.GetNameForID(phantom.name_id).to_string(), Hint{phantom, facade.GetCheckSum()}); } else { - return json::makeWaypoint(phantom.location, facade.GetNameForID(phantom.name_id)); + return json::makeWaypoint(phantom.location, + facade.GetNameForID(phantom.name_id).to_string()); } } diff --git a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp index 8da10a6b4..5a08ab9b9 100644 --- a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp +++ b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp @@ -76,7 +76,7 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade util::ShM::vector m_coordinate_list; util::PackedVector m_osmnodeid_list; util::ShM::vector m_via_geometry_list; - util::ShM::vector m_name_ID_list; + util::ShM::vector m_name_ID_list; util::ShM::vector m_lane_data_id; util::ShM::vector m_turn_instruction_list; util::ShM::vector m_travel_mode_list; @@ -89,7 +89,7 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade util::ShM::vector m_geometry_fwd_weight_list; util::ShM::vector m_geometry_rev_weight_list; util::ShM::vector m_is_core_node; - util::ShM::vector m_datasource_list; + util::ShM::vector m_datasource_list; util::ShM::vector m_lane_description_offsets; util::ShM::vector m_lane_description_masks; @@ -231,8 +231,8 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade m_turn_instruction_list = std::move(turn_instruction_list); const auto name_id_list_ptr = - data_layout.GetBlockPtr(memory_block, storage::DataLayout::NAME_ID_LIST); - util::ShM::vector name_id_list( + data_layout.GetBlockPtr(memory_block, storage::DataLayout::NAME_ID_LIST); + util::ShM::vector name_id_list( name_id_list_ptr, data_layout.num_entries[storage::DataLayout::NAME_ID_LIST]); m_name_ID_list = std::move(name_id_list); @@ -340,9 +340,9 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST]); m_geometry_rev_weight_list = std::move(geometry_rev_weight_list); - auto datasources_list_ptr = - data_layout.GetBlockPtr(memory_block, storage::DataLayout::DATASOURCES_LIST); - util::ShM::vector datasources_list( + auto datasources_list_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::DATASOURCES_LIST); + util::ShM::vector datasources_list( datasources_list_ptr, data_layout.num_entries[storage::DataLayout::DATASOURCES_LIST]); m_datasource_list = std::move(datasources_list); @@ -482,7 +482,7 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade return m_coordinate_list[id]; } - OSMNodeID GetOSMNodeIDOfNode(const unsigned id) const override final + OSMNodeID GetOSMNodeIDOfNode(const NodeID id) const override final { return m_osmnodeid_list.at(id); } @@ -583,18 +583,18 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade return result_weights; } - virtual GeometryID GetGeometryIndexForEdgeID(const unsigned id) const override final + virtual GeometryID GetGeometryIndexForEdgeID(const EdgeID id) const override final { return m_via_geometry_list.at(id); } extractor::guidance::TurnInstruction - GetTurnInstructionForEdgeID(const unsigned id) const override final + GetTurnInstructionForEdgeID(const EdgeID id) const override final { return m_turn_instruction_list.at(id); } - extractor::TravelMode GetTravelModeForEdgeID(const unsigned id) const override final + extractor::TravelMode GetTravelModeForEdgeID(const EdgeID id) const override final { return m_travel_mode_list.at(id); } @@ -716,56 +716,59 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade unsigned GetCheckSum() const override final { return m_check_sum; } - unsigned GetNameIndexFromEdgeID(const unsigned id) const override final + NameID GetNameIndexFromEdgeID(const EdgeID id) const override final { return m_name_ID_list.at(id); } - std::string GetNameForID(const unsigned name_id) const override final + StringView GetNameForID(const NameID id) const override final { - if (std::numeric_limits::max() == name_id) + if (std::numeric_limits::max() == id) { return ""; } - auto range = m_name_table->GetRange(name_id); - std::string result; - result.reserve(range.size()); - if (range.begin() != range.end()) + auto range = m_name_table->GetRange(id); + + if (range.begin() == range.end()) { - result.resize(range.back() - range.front() + 1); - std::copy(m_names_char_list.begin() + range.front(), - m_names_char_list.begin() + range.back() + 1, - result.begin()); + return ""; } - return result; + + auto first = m_names_char_list.begin() + range.front(); + auto last = m_names_char_list.begin() + range.back() + 1u; + // These iterators are useless: they're InputIterators onto a contiguous block of memory. + // Deref to get to the first element, then Addressof to get the memory address of the it. + const std::size_t len = &*last - &*first; + + return StringView{&*first, len}; } - std::string GetRefForID(const unsigned name_id) const override final + StringView GetRefForID(const NameID id) const override final { // We store the ref after the name, destination and pronunciation of a street. // We do this to get around the street length limit of 255 which would hit // if we concatenate these. Order (see extractor_callbacks): // name (0), destination (1), pronunciation (2), ref (3) - return GetNameForID(name_id + 3); + return GetNameForID(id + 3); } - std::string GetPronunciationForID(const unsigned name_id) const override final + StringView GetPronunciationForID(const NameID id) const override final { // We store the pronunciation after the name and destination of a street. // We do this to get around the street length limit of 255 which would hit // if we concatenate these. Order (see extractor_callbacks): // name (0), destination (1), pronunciation (2), ref (3) - return GetNameForID(name_id + 2); + return GetNameForID(id + 2); } - std::string GetDestinationsForID(const unsigned name_id) const override final + StringView GetDestinationsForID(const NameID id) const override final { // We store the destination after the name of a street. // We do this to get around the street length limit of 255 which would hit // if we concatenate these. Order (see extractor_callbacks): // name (0), destination (1), pronunciation (2), ref (3) - return GetNameForID(name_id + 1); + return GetNameForID(id + 1); } bool IsCoreNode(const NodeID id) const override final @@ -782,7 +785,7 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade // Returns the data source ids that were used to supply the edge // weights. - virtual std::vector + virtual std::vector GetUncompressedForwardDatasources(const EdgeID id) const override final { /* @@ -797,7 +800,7 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade const unsigned begin = m_geometry_indices.at(id) + 1; const unsigned end = m_geometry_indices.at(id + 1); - std::vector result_datasources; + std::vector result_datasources; result_datasources.resize(end - begin); // If there was no datasource info, return an array of 0's. @@ -820,7 +823,7 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade // Returns the data source ids that were used to supply the edge // weights. - virtual std::vector + virtual std::vector GetUncompressedReverseDatasources(const EdgeID id) const override final { /* @@ -835,7 +838,7 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade const unsigned begin = m_geometry_indices.at(id); const unsigned end = m_geometry_indices.at(id + 1) - 1; - std::vector result_datasources; + std::vector result_datasources; result_datasources.resize(end - begin); // If there was no datasource info, return an array of 0's. @@ -856,19 +859,19 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade return result_datasources; } - virtual std::string GetDatasourceName(const uint8_t datasource_name_id) const override final + StringView GetDatasourceName(const DatasourceID id) const override final { BOOST_ASSERT(m_datasource_name_offsets.size() >= 1); - BOOST_ASSERT(m_datasource_name_offsets.size() > datasource_name_id); + BOOST_ASSERT(m_datasource_name_offsets.size() > id); - std::string result; - result.reserve(m_datasource_name_lengths[datasource_name_id]); - std::copy(m_datasource_name_data.begin() + m_datasource_name_offsets[datasource_name_id], - m_datasource_name_data.begin() + m_datasource_name_offsets[datasource_name_id] + - m_datasource_name_lengths[datasource_name_id], - std::back_inserter(result)); + auto first = m_datasource_name_data.begin() + m_datasource_name_offsets[id]; + auto last = m_datasource_name_data.begin() + m_datasource_name_offsets[id] + + m_datasource_name_lengths[id]; + // These iterators are useless: they're InputIterators onto a contiguous block of memory. + // Deref to get to the first element, then Addressof to get the memory address of the it. + const std::size_t len = &*last - &*first; - return result; + return StringView{&*first, len}; } std::string GetTimestamp() const override final { return m_timestamp; } diff --git a/include/engine/datafacade/datafacade_base.hpp b/include/engine/datafacade/datafacade_base.hpp index 61df241af..b738f12f9 100644 --- a/include/engine/datafacade/datafacade_base.hpp +++ b/include/engine/datafacade/datafacade_base.hpp @@ -17,6 +17,7 @@ #include "util/guidance/turn_lanes.hpp" #include "util/integer_range.hpp" #include "util/string_util.hpp" +#include "util/string_view.hpp" #include "util/typedefs.hpp" #include "osrm/coordinate.hpp" @@ -34,6 +35,7 @@ namespace engine namespace datafacade { +using StringView = util::StringView; using EdgeRange = util::range; class BaseDataFacade @@ -74,10 +76,10 @@ class BaseDataFacade const std::function filter) const = 0; // node and edge information access - virtual util::Coordinate GetCoordinateOfNode(const unsigned id) const = 0; - virtual OSMNodeID GetOSMNodeIDOfNode(const unsigned id) const = 0; + virtual util::Coordinate GetCoordinateOfNode(const NodeID id) const = 0; + virtual OSMNodeID GetOSMNodeIDOfNode(const NodeID id) const = 0; - virtual GeometryID GetGeometryIndexForEdgeID(const unsigned id) const = 0; + virtual GeometryID GetGeometryIndexForEdgeID(const EdgeID id) const = 0; virtual std::vector GetUncompressedForwardGeometry(const EdgeID id) const = 0; @@ -91,16 +93,16 @@ class BaseDataFacade // Returns the data source ids that were used to supply the edge // weights. Will return an empty array when only the base profile is used. - virtual std::vector GetUncompressedForwardDatasources(const EdgeID id) const = 0; - virtual std::vector GetUncompressedReverseDatasources(const EdgeID id) const = 0; + virtual std::vector GetUncompressedForwardDatasources(const EdgeID id) const = 0; + virtual std::vector GetUncompressedReverseDatasources(const EdgeID id) const = 0; // Gets the name of a datasource - virtual std::string GetDatasourceName(const uint8_t datasource_name_id) const = 0; + virtual StringView GetDatasourceName(const DatasourceID id) const = 0; virtual extractor::guidance::TurnInstruction - GetTurnInstructionForEdgeID(const unsigned id) const = 0; + GetTurnInstructionForEdgeID(const EdgeID id) const = 0; - virtual extractor::TravelMode GetTravelModeForEdgeID(const unsigned id) const = 0; + virtual extractor::TravelMode GetTravelModeForEdgeID(const EdgeID id) const = 0; virtual std::vector GetEdgesInBox(const util::Coordinate south_west, const util::Coordinate north_east) const = 0; @@ -157,15 +159,15 @@ class BaseDataFacade virtual bool IsCoreNode(const NodeID id) const = 0; - virtual unsigned GetNameIndexFromEdgeID(const unsigned id) const = 0; + virtual NameID GetNameIndexFromEdgeID(const EdgeID id) const = 0; - virtual std::string GetNameForID(const unsigned name_id) const = 0; + virtual StringView GetNameForID(const NameID id) const = 0; - virtual std::string GetRefForID(const unsigned name_id) const = 0; + virtual StringView GetRefForID(const NameID id) const = 0; - virtual std::string GetPronunciationForID(const unsigned name_id) const = 0; + virtual StringView GetPronunciationForID(const NameID id) const = 0; - virtual std::string GetDestinationsForID(const unsigned name_id) const = 0; + virtual StringView GetDestinationsForID(const NameID id) const = 0; virtual std::size_t GetCoreSize() const = 0; diff --git a/include/engine/guidance/assemble_leg.hpp b/include/engine/guidance/assemble_leg.hpp index f2f8ad92d..edffcf55c 100644 --- a/include/engine/guidance/assemble_leg.hpp +++ b/include/engine/guidance/assemble_leg.hpp @@ -186,11 +186,11 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade, const auto name_id_to_string = [&](const NameID name_id) { const auto name = facade.GetNameForID(name_id); if (!name.empty()) - return name; + return name.to_string(); else { const auto ref = facade.GetRefForID(name_id); - return ref; + return ref.to_string(); } }; diff --git a/include/engine/guidance/assemble_steps.hpp b/include/engine/guidance/assemble_steps.hpp index a6bed757c..d62ae5dd0 100644 --- a/include/engine/guidance/assemble_steps.hpp +++ b/include/engine/guidance/assemble_steps.hpp @@ -105,10 +105,10 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa const auto distance = leg_geometry.segment_distances[segment_index]; steps.push_back(RouteStep{step_name_id, - std::move(name), - std::move(ref), - std::move(pronunciation), - std::move(destinations), + name.to_string(), + ref.to_string(), + pronunciation.to_string(), + destinations.to_string(), NO_ROTARY_NAME, NO_ROTARY_NAME, segment_duration / 10.0, @@ -179,10 +179,10 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa const int duration = segment_duration + target_duration; BOOST_ASSERT(duration >= 0); steps.push_back(RouteStep{step_name_id, - facade.GetNameForID(step_name_id), - facade.GetRefForID(step_name_id), - facade.GetPronunciationForID(step_name_id), - facade.GetDestinationsForID(step_name_id), + facade.GetNameForID(step_name_id).to_string(), + facade.GetRefForID(step_name_id).to_string(), + facade.GetPronunciationForID(step_name_id).to_string(), + facade.GetDestinationsForID(step_name_id).to_string(), NO_ROTARY_NAME, NO_ROTARY_NAME, duration / 10., @@ -206,10 +206,10 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa BOOST_ASSERT(duration >= 0); steps.push_back(RouteStep{source_node.name_id, - facade.GetNameForID(source_node.name_id), - facade.GetRefForID(source_node.name_id), - facade.GetPronunciationForID(source_node.name_id), - facade.GetDestinationsForID(source_node.name_id), + facade.GetNameForID(source_node.name_id).to_string(), + facade.GetRefForID(source_node.name_id).to_string(), + facade.GetPronunciationForID(source_node.name_id).to_string(), + facade.GetDestinationsForID(source_node.name_id).to_string(), NO_ROTARY_NAME, NO_ROTARY_NAME, duration / 10., @@ -243,10 +243,10 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa BOOST_ASSERT(!leg_geometry.locations.empty()); steps.push_back(RouteStep{target_node.name_id, - facade.GetNameForID(target_node.name_id), - facade.GetRefForID(target_node.name_id), - facade.GetPronunciationForID(target_node.name_id), - facade.GetDestinationsForID(target_node.name_id), + facade.GetNameForID(target_node.name_id).to_string(), + facade.GetRefForID(target_node.name_id).to_string(), + facade.GetPronunciationForID(target_node.name_id).to_string(), + facade.GetDestinationsForID(target_node.name_id).to_string(), NO_ROTARY_NAME, NO_ROTARY_NAME, ZERO_DURATION, diff --git a/include/extractor/suffix_table.hpp b/include/extractor/suffix_table.hpp index 7785a5e14..5d16fe6b7 100644 --- a/include/extractor/suffix_table.hpp +++ b/include/extractor/suffix_table.hpp @@ -4,6 +4,8 @@ #include #include +#include "util/string_view.hpp" + namespace osrm { namespace extractor @@ -21,9 +23,20 @@ class SuffixTable final // check whether a string is part of the know suffix list bool isSuffix(const std::string &possible_suffix) const; + bool isSuffix(util::StringView possible_suffix) const; private: - std::unordered_set suffix_set; + // Store lower-cased strings in SuffixTable and a set of StringViews for quick membership + // checks. + // + // Why not uset? StringView is non-owning, the vector holds the string + // contents, the set only holds [first,last) pointers into the vector. + // + // Then why not simply uset? Because membership tests against StringView keys would + // require us to first convert StringViews into strings (allocation), do the membership, + // and destroy the StringView again. + std::vector suffixes; + std::unordered_set suffix_set; }; } /* namespace extractor */ diff --git a/include/util/guidance/name_announcements.hpp b/include/util/guidance/name_announcements.hpp index ea0ad049a..098a7b80a 100644 --- a/include/util/guidance/name_announcements.hpp +++ b/include/util/guidance/name_announcements.hpp @@ -159,13 +159,14 @@ inline bool requiresNameAnnounced(const NameID from_name_id, if (from_name_id == to_name_id) return false; else - return requiresNameAnnounced(name_table.GetNameForID(from_name_id), - name_table.GetRefForID(from_name_id), - name_table.GetPronunciationForID(from_name_id), - name_table.GetNameForID(to_name_id), - name_table.GetRefForID(to_name_id), - name_table.GetPronunciationForID(to_name_id), + return requiresNameAnnounced(name_table.GetNameForID(from_name_id).to_string(), + name_table.GetRefForID(from_name_id).to_string(), + name_table.GetPronunciationForID(from_name_id).to_string(), + name_table.GetNameForID(to_name_id).to_string(), + name_table.GetRefForID(to_name_id).to_string(), + name_table.GetPronunciationForID(to_name_id).to_string(), suffix_table); + // FIXME: converts StringViews to strings since the name change heuristics mutates in place } inline bool requiresNameAnnounced(const NameID from_name_id, @@ -175,12 +176,13 @@ inline bool requiresNameAnnounced(const NameID from_name_id, if (from_name_id == to_name_id) return false; else - return requiresNameAnnounced(name_table.GetNameForID(from_name_id), - name_table.GetRefForID(from_name_id), - name_table.GetPronunciationForID(from_name_id), - name_table.GetNameForID(to_name_id), - name_table.GetRefForID(to_name_id), - name_table.GetPronunciationForID(to_name_id)); + return requiresNameAnnounced(name_table.GetNameForID(from_name_id).to_string(), + name_table.GetRefForID(from_name_id).to_string(), + name_table.GetPronunciationForID(from_name_id).to_string(), + name_table.GetNameForID(to_name_id).to_string(), + name_table.GetRefForID(to_name_id).to_string(), + name_table.GetPronunciationForID(to_name_id).to_string()); + // FIXME: converts StringViews to strings since the name change heuristics mutates in place } } // namespace guidance diff --git a/include/util/name_table.hpp b/include/util/name_table.hpp index e07e17fb2..07d10db53 100644 --- a/include/util/name_table.hpp +++ b/include/util/name_table.hpp @@ -3,6 +3,8 @@ #include "util/range_table.hpp" #include "util/shared_memory_vector_wrapper.hpp" +#include "util/string_view.hpp" +#include "util/typedefs.hpp" #include @@ -28,9 +30,9 @@ class NameTable // The following functions are a subset of what is available. // See the data facades for they provide full access to this serialized string data. // (at time of writing this: get{Name,Ref,Pronunciation,Destinations}ForID(name_id);) - std::string GetNameForID(const unsigned name_id) const; - std::string GetRefForID(const unsigned name_id) const; - std::string GetPronunciationForID(const unsigned name_id) const; + util::StringView GetNameForID(const NameID id) const; + util::StringView GetRefForID(const NameID id) const; + util::StringView GetPronunciationForID(const NameID id) const; }; } // namespace util } // namespace osrm diff --git a/include/util/string_view.hpp b/include/util/string_view.hpp new file mode 100644 index 000000000..c7ab0df3d --- /dev/null +++ b/include/util/string_view.hpp @@ -0,0 +1,34 @@ +#ifndef OSRM_STRING_VIEW_HPP +#define OSRM_STRING_VIEW_HPP + +#include +#include + +namespace osrm +{ +namespace util +{ +// Convenience typedef: boost::string_ref, boost::string_view or C++17's string_view +using StringView = boost::string_ref; + +} // namespace util +} // namespace osrm + +// Specializing hash<> for user-defined type in std namespace, this is standard conforming. +namespace std +{ +template <> struct hash<::osrm::util::StringView> final +{ + std::size_t operator()(::osrm::util::StringView v) const noexcept + { + // Bring into scope and call un-qualified for ADL: + // remember we want to be able to switch impl. above. + using std::begin; + using std::end; + + return boost::hash_range(begin(v), end(v)); + } +}; +} // namespace std + +#endif /* OSRM_STRING_VIEW_HPP */ diff --git a/src/engine/plugins/tile.cpp b/src/engine/plugins/tile.cpp index e77ba1e06..e3cb1ee5f 100644 --- a/src/engine/plugins/tile.cpp +++ b/src/engine/plugins/tile.cpp @@ -3,6 +3,7 @@ #include "engine/plugins/plugin_base.hpp" #include "util/coordinate_calculation.hpp" +#include "util/string_view.hpp" #include "util/vector_tile.hpp" #include "util/web_mercator.hpp" @@ -287,8 +288,8 @@ Status TilePlugin::HandleRequest(const std::shared_ptr line_int_offsets; // Same idea for street names - one lookup table for names for all features - std::vector names; - std::unordered_map name_offsets; + std::vector names; + std::unordered_map name_offsets; // And again for integer values used by points. std::vector used_point_ints; @@ -714,14 +715,15 @@ Status TilePlugin::HandleRequest(const std::shared_ptrGetNameForID(edge.name_id); + auto name = facade->GetNameForID(edge.name_id); + const auto name_offset = [&name, &names, &name_offsets]() { auto iter = name_offsets.find(name); if (iter == name_offsets.end()) { auto offset = names.size(); name_offsets[name] = offset; - names.push_back(std::move(name)); + names.push_back(name); return offset; } return iter->second; @@ -873,7 +875,7 @@ Status TilePlugin::HandleRequest(const std::shared_ptrGetDatasourceName(i)); + facade->GetDatasourceName(i).to_string()); } for (auto value : used_line_ints) { @@ -892,7 +894,8 @@ Status TilePlugin::HandleRequest(const std::shared_ptr +#include + #include namespace osrm @@ -11,13 +13,22 @@ namespace extractor SuffixTable::SuffixTable(ScriptingEnvironment &scripting_environment) { - std::vector suffixes_vector = scripting_environment.GetNameSuffixList(); - for (auto &suffix : suffixes_vector) + suffixes = scripting_environment.GetNameSuffixList(); + + for (auto &suffix : suffixes) boost::algorithm::to_lower(suffix); - suffix_set.insert(std::begin(suffixes_vector), std::end(suffixes_vector)); + + auto into = std::inserter(suffix_set, end(suffix_set)); + auto to_view = [](const auto &s) { return util::StringView{s}; }; + std::transform(begin(suffixes), end(suffixes), into, to_view); } bool SuffixTable::isSuffix(const std::string &possible_suffix) const +{ + return isSuffix(util::StringView{possible_suffix}); +} + +bool SuffixTable::isSuffix(util::StringView possible_suffix) const { return suffix_set.count(possible_suffix) > 0; } diff --git a/src/util/name_table.cpp b/src/util/name_table.cpp index 082ac8571..2b3b2b216 100644 --- a/src/util/name_table.cpp +++ b/src/util/name_table.cpp @@ -1,9 +1,10 @@ #include "util/name_table.hpp" +#include "storage/io.hpp" #include "util/exception.hpp" #include "util/log.hpp" #include -#include +#include #include #include @@ -18,11 +19,9 @@ NameTable::NameTable(const std::string &filename) storage::io::FileReader name_stream_file_reader(filename, storage::io::FileReader::HasNoFingerprint); - // name_stream >> m_name_table; - m_name_table.ReadARangeTable(name_stream_file_reader); - unsigned number_of_chars = name_stream_file_reader.ReadElementCount32(); + const auto number_of_chars = name_stream_file_reader.ReadElementCount32(); m_names_char_list.resize(number_of_chars + 1); //+1 gives sentinel element m_names_char_list.back() = 0; @@ -37,58 +36,59 @@ NameTable::NameTable(const std::string &filename) } } -std::string NameTable::GetNameForID(const unsigned name_id) const +StringView NameTable::GetNameForID(const NameID id) const { - if (std::numeric_limits::max() == name_id) + if (std::numeric_limits::max() == id) { - return ""; + return {}; } - auto range = m_name_table.GetRange(name_id); - std::string result; - result.reserve(range.size()); - if (range.begin() != range.end()) + auto range = m_name_table.GetRange(id); + + if (range.begin() == range.end()) { - result.resize(range.back() - range.front() + 1); - std::copy(m_names_char_list.begin() + range.front(), - m_names_char_list.begin() + range.back() + 1, - result.begin()); + return {}; } - return result; + + auto first = begin(m_names_char_list) + range.front(); + auto last = begin(m_names_char_list) + range.back() + 1; + const std::size_t len = last - first; + + return StringView{&*first, len}; } -std::string NameTable::GetRefForID(const unsigned name_id) const +StringView NameTable::GetRefForID(const NameID id) const { - // Way string data is stored in blocks based on `name_id` as follows: + // Way string data is stored in blocks based on `id` as follows: // // | name | destination | pronunciation | ref | // ^ ^ // [range) - // ^ name_id + 3 + // ^ id + 3 // - // `name_id + offset` gives us the range of chars. + // `id + offset` gives us the range of chars. // // Offset 0 is name, 1 is destination, 2 is pronunciation, 3 is ref. // See datafacades and extractor callbacks for details. const constexpr auto OFFSET_REF = 3u; - return GetNameForID(name_id + OFFSET_REF); + return GetNameForID(id + OFFSET_REF); } -std::string NameTable::GetPronunciationForID(const unsigned name_id) const +StringView NameTable::GetPronunciationForID(const NameID id) const { - // Way string data is stored in blocks based on `name_id` as follows: + // Way string data is stored in blocks based on `id` as follows: // // | name | destination | pronunciation | ref | // ^ ^ // [range) - // ^ name_id + 2 + // ^ id + 2 // - // `name_id + offset` gives us the range of chars. + // `id + offset` gives us the range of chars. // // Offset 0 is name, 1 is destination, 2 is pronunciation, 3 is ref. // See datafacades and extractor callbacks for details. const constexpr auto OFFSET_PRONUNCIATION = 2u; - return GetNameForID(name_id + OFFSET_PRONUNCIATION); + return GetNameForID(id + OFFSET_PRONUNCIATION); } } // namespace util diff --git a/unit_tests/mocks/mock_datafacade.hpp b/unit_tests/mocks/mock_datafacade.hpp index 6eb1d8a8f..eac95222f 100644 --- a/unit_tests/mocks/mock_datafacade.hpp +++ b/unit_tests/mocks/mock_datafacade.hpp @@ -19,6 +19,8 @@ namespace test class MockDataFacade final : public engine::datafacade::BaseDataFacade { + using StringView = util::StringView; + private: EdgeData foo; @@ -56,13 +58,13 @@ class MockDataFacade final : public engine::datafacade::BaseDataFacade { return SPECIAL_EDGEID; } - util::Coordinate GetCoordinateOfNode(const unsigned /* id */) const override + util::Coordinate GetCoordinateOfNode(const NodeID /* id */) const override { return {util::FixedLongitude{0}, util::FixedLatitude{0}}; } - OSMNodeID GetOSMNodeIDOfNode(const unsigned /* id */) const override { return OSMNodeID{0}; } - bool EdgeIsCompressed(const unsigned /* id */) const { return false; } - GeometryID GetGeometryIndexForEdgeID(const unsigned /* id */) const override + OSMNodeID GetOSMNodeIDOfNode(const NodeID /* id */) const override { return OSMNodeID{0}; } + bool EdgeIsCompressed(const EdgeID /* id */) const { return false; } + GeometryID GetGeometryIndexForEdgeID(const EdgeID /* id */) const override { return GeometryID{SPECIAL_GEOMETRYID, false}; } @@ -88,24 +90,23 @@ class MockDataFacade final : public engine::datafacade::BaseDataFacade result_weights[0] = 1; return result_weights; } - std::vector GetUncompressedForwardDatasources(const EdgeID /*id*/) const override + std::vector GetUncompressedForwardDatasources(const EdgeID /*id*/) const override { return {}; } - std::vector GetUncompressedReverseDatasources(const EdgeID /*id*/) const override + std::vector GetUncompressedReverseDatasources(const EdgeID /*id*/) const override { return {}; } - std::string GetDatasourceName(const uint8_t /*datasource_name_id*/) const override - { - return ""; - } + + StringView GetDatasourceName(const DatasourceID) const override final { return {}; } + extractor::guidance::TurnInstruction - GetTurnInstructionForEdgeID(const unsigned /* id */) const override + GetTurnInstructionForEdgeID(const EdgeID /* id */) const override { return extractor::guidance::TurnInstruction::NO_TURN(); } - extractor::TravelMode GetTravelModeForEdgeID(const unsigned /* id */) const override + extractor::TravelMode GetTravelModeForEdgeID(const EdgeID /* id */) const override { return TRAVEL_MODE_INACCESSIBLE; } @@ -198,11 +199,14 @@ class MockDataFacade final : public engine::datafacade::BaseDataFacade unsigned GetCheckSum() const override { return 0; } bool IsCoreNode(const NodeID /* id */) const override { return false; } - unsigned GetNameIndexFromEdgeID(const unsigned /* id */) const override { return 0; } - std::string GetNameForID(const unsigned /* name_id */) const override { return ""; } - std::string GetRefForID(const unsigned /* name_id */) const override { return ""; } - std::string GetPronunciationForID(const unsigned /* name_id */) const override { return ""; } - std::string GetDestinationsForID(const unsigned /* name_id */) const override { return ""; } + + NameID GetNameIndexFromEdgeID(const EdgeID /* id */) const override { return 0; } + + StringView GetNameForID(const NameID) const override final { return {}; } + StringView GetRefForID(const NameID) const override final { return {}; } + StringView GetPronunciationForID(const NameID) const override final { return {}; } + StringView GetDestinationsForID(const NameID) const override final { return {}; } + std::size_t GetCoreSize() const override { return 0; } std::string GetTimestamp() const override { return ""; } bool GetContinueStraightDefault() const override { return true; }