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
This commit is contained in:
Daniel J. Hofmann 2016-12-15 18:27:09 +01:00
parent b1f1c26703
commit c277b95f03
13 changed files with 219 additions and 144 deletions

View File

@ -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());
}
}

View File

@ -76,7 +76,7 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade
util::ShM<util::Coordinate, true>::vector m_coordinate_list;
util::PackedVector<OSMNodeID, true> m_osmnodeid_list;
util::ShM<GeometryID, true>::vector m_via_geometry_list;
util::ShM<unsigned, true>::vector m_name_ID_list;
util::ShM<NameID, true>::vector m_name_ID_list;
util::ShM<LaneDataID, true>::vector m_lane_data_id;
util::ShM<extractor::guidance::TurnInstruction, true>::vector m_turn_instruction_list;
util::ShM<extractor::TravelMode, true>::vector m_travel_mode_list;
@ -89,7 +89,7 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade
util::ShM<EdgeWeight, true>::vector m_geometry_fwd_weight_list;
util::ShM<EdgeWeight, true>::vector m_geometry_rev_weight_list;
util::ShM<bool, true>::vector m_is_core_node;
util::ShM<uint8_t, true>::vector m_datasource_list;
util::ShM<DatasourceID, true>::vector m_datasource_list;
util::ShM<std::uint32_t, true>::vector m_lane_description_offsets;
util::ShM<extractor::guidance::TurnLaneType::Mask, true>::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<unsigned>(memory_block, storage::DataLayout::NAME_ID_LIST);
util::ShM<unsigned, true>::vector name_id_list(
data_layout.GetBlockPtr<NameID>(memory_block, storage::DataLayout::NAME_ID_LIST);
util::ShM<NameID, true>::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<uint8_t>(memory_block, storage::DataLayout::DATASOURCES_LIST);
util::ShM<uint8_t, true>::vector datasources_list(
auto datasources_list_ptr = data_layout.GetBlockPtr<DatasourceID>(
memory_block, storage::DataLayout::DATASOURCES_LIST);
util::ShM<DatasourceID, true>::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<unsigned>::max() == name_id)
if (std::numeric_limits<NameID>::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<uint8_t>
virtual std::vector<DatasourceID>
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<uint8_t> result_datasources;
std::vector<DatasourceID> 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<uint8_t>
virtual std::vector<DatasourceID>
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<uint8_t> result_datasources;
std::vector<DatasourceID> 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; }

View File

@ -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<EdgeID>;
class BaseDataFacade
@ -74,10 +76,10 @@ class BaseDataFacade
const std::function<bool(EdgeData)> 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<NodeID> 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<uint8_t> GetUncompressedForwardDatasources(const EdgeID id) const = 0;
virtual std::vector<uint8_t> GetUncompressedReverseDatasources(const EdgeID id) const = 0;
virtual std::vector<DatasourceID> GetUncompressedForwardDatasources(const EdgeID id) const = 0;
virtual std::vector<DatasourceID> 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<RTreeLeaf> 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;

View File

@ -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();
}
};

View File

@ -105,10 +105,10 @@ inline std::vector<RouteStep> 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<RouteStep> 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<RouteStep> 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<RouteStep> 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,

View File

@ -4,6 +4,8 @@
#include <string>
#include <unordered_set>
#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<std::string> suffix_set;
// Store lower-cased strings in SuffixTable and a set of StringViews for quick membership
// checks.
//
// Why not uset<StringView>? StringView is non-owning, the vector<string> holds the string
// contents, the set<StringView> only holds [first,last) pointers into the vector.
//
// Then why not simply uset<string>? 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<std::string> suffixes;
std::unordered_set<util::StringView> suffix_set;
};
} /* namespace extractor */

View File

@ -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

View File

@ -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 <string>
@ -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

View File

@ -0,0 +1,34 @@
#ifndef OSRM_STRING_VIEW_HPP
#define OSRM_STRING_VIEW_HPP
#include <boost/functional/hash.hpp>
#include <boost/utility/string_ref.hpp>
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 */

View File

@ -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<const datafacade::BaseDat
std::unordered_map<int, std::size_t> line_int_offsets;
// Same idea for street names - one lookup table for names for all features
std::vector<std::string> names;
std::unordered_map<std::string, std::size_t> name_offsets;
std::vector<util::StringView> names;
std::unordered_map<util::StringView, std::size_t> name_offsets;
// And again for integer values used by points.
std::vector<int> used_point_ints;
@ -714,14 +715,15 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDat
reverse_datasource_vector[reverse_datasource_vector.size() -
edge.fwd_segment_position - 1];
std::string name = facade->GetNameForID(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_ptr<const datafacade::BaseDat
util::vector_tile::VARIANT_TAG);
// Attribute value 1 == string type
values_writer.add_string(util::vector_tile::VARIANT_TYPE_STRING,
facade->GetDatasourceName(i));
facade->GetDatasourceName(i).to_string());
}
for (auto value : used_line_ints)
{
@ -892,7 +894,8 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDat
protozero::pbf_writer values_writer(line_layer_writer,
util::vector_tile::VARIANT_TAG);
// Attribute value 1 == string type
values_writer.add_string(util::vector_tile::VARIANT_TYPE_STRING, name);
values_writer.add_string(
util::vector_tile::VARIANT_TYPE_STRING, name.data(), name.size());
}
}

View File

@ -1,7 +1,9 @@
#include "extractor/suffix_table.hpp"
#include "extractor/scripting_environment.hpp"
#include <algorithm>
#include <iterator>
#include <boost/algorithm/string.hpp>
namespace osrm
@ -11,13 +13,22 @@ namespace extractor
SuffixTable::SuffixTable(ScriptingEnvironment &scripting_environment)
{
std::vector<std::string> 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;
}

View File

@ -1,9 +1,10 @@
#include "util/name_table.hpp"
#include "storage/io.hpp"
#include "util/exception.hpp"
#include "util/log.hpp"
#include <algorithm>
#include <fstream>
#include <iterator>
#include <limits>
#include <boost/filesystem/fstream.hpp>
@ -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<unsigned>::max() == name_id)
if (std::numeric_limits<NameID>::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

View File

@ -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<uint8_t> GetUncompressedForwardDatasources(const EdgeID /*id*/) const override
std::vector<DatasourceID> GetUncompressedForwardDatasources(const EdgeID /*id*/) const override
{
return {};
}
std::vector<uint8_t> GetUncompressedReverseDatasources(const EdgeID /*id*/) const override
std::vector<DatasourceID> 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; }