std::u32string StringToUTF32(const StringView str) { if (str.empty()) { return std::u32string(); } const wchar* begin = &str[0]; const wchar* end = begin + str.length(); if (const auto length = detail::CountCodePoints(begin, end)) { std::u32string result(length.value(), L'\0'); while (begin != end) { const auto ch = *begin++; if (!IsUTF16Surrogate(ch)) { result.push_back(ch); } else { result.push_back(SurrogateToUTF32(ch, *begin++)); } } return result; } else { return std::u32string(); } }
void Write(StringView data) { NEPTOOLS_CHECK(SinkOverflow, offset+buf_put+data.length() <= size, "Sink overflow during write"); auto cp = std::min(data.length(), size_t(buf_size - buf_put)); memcpy(buf+buf_put, data.data(), cp); data.remove_prefix(cp); buf_put += cp; if (!data.empty()) Write_(data); }
void ExtractProtocol::execute(Pos data, size_t size, Pos & res_data, size_t & res_size) { res_data = data; res_size = 0; StringView scheme = getURLScheme(StringView(data, size)); Pos pos = data + scheme.size(); if (scheme.empty() || (data + size) - pos < 4) return; if (pos[0] == ':') res_size = pos - data; }
bool AbstractParser::evalSpecialCommandMap(StringView args) { if (args.empty()) return false; auto first = args.takeFirstWord(); auto &map = m_specialCommandMap; const std::string key = first.toQString().toStdString(); auto it = map.find(key); if (it == map.end()) return false; // REVISIT: add # of calls to the record? ParserRecord &rec = it->second; const auto qs = QString::fromStdString(rec.fullCommand); const auto matched = std::vector<StringView>{StringView{qs}}; return rec.callback(matched, args); }
inline bool requiresNameAnnounced(const StringView &from_name, const StringView &from_ref, const StringView &from_pronunciation, const StringView &from_exits, const StringView &to_name, const StringView &to_ref, const StringView &to_pronunciation, const StringView &to_exits, const SuffixTable &suffix_table) { // first is empty and the second is not if ((from_name.empty() && from_ref.empty()) && !(to_name.empty() && to_ref.empty())) return true; // FIXME, handle in profile to begin with? // Input for this function should be a struct separating streetname, suffix (e.g. road, // boulevard, North, West ...), and a list of references // check similarity of names const auto names_are_empty = from_name.empty() && to_name.empty(); const auto name_is_contained = boost::starts_with(from_name, to_name) || boost::starts_with(to_name, from_name); const auto checkForPrefixOrSuffixChange = [](const StringView &first, const StringView &second, const SuffixTable &suffix_table) { std::string first_prefix, first_suffix, second_prefix, second_suffix; std::tie(first_prefix, first_suffix, second_prefix, second_suffix) = decompose(first, second); const auto checkTable = [&](const std::string &str) { return str.empty() || suffix_table.isSuffix(str); }; return checkTable(first_prefix) && checkTable(first_suffix) && checkTable(second_prefix) && checkTable(second_suffix); }; const auto is_suffix_change = checkForPrefixOrSuffixChange(from_name, to_name, suffix_table); const auto names_are_equal = from_name == to_name || name_is_contained || is_suffix_change; const auto name_is_removed = !from_name.empty() && to_name.empty(); // references are contained in one another const auto refs_are_empty = from_ref.empty() && to_ref.empty(); const auto ref_is_contained = from_ref.empty() || to_ref.empty() || (from_ref.find(to_ref) != std::string::npos || to_ref.find(from_ref) != std::string::npos); const auto ref_is_removed = !from_ref.empty() && to_ref.empty(); const auto obvious_change = (names_are_empty && refs_are_empty) || (names_are_equal && ref_is_contained) || (names_are_equal && refs_are_empty) || (ref_is_contained && name_is_removed) || (names_are_equal && ref_is_removed) || is_suffix_change; const auto needs_announce = // " (Ref)" -> "Name " and reverse (from_name.empty() && !from_ref.empty() && !to_name.empty() && to_ref.empty()) || (!from_name.empty() && from_ref.empty() && to_name.empty() && !to_ref.empty()); const auto pronunciation_changes = from_pronunciation != to_pronunciation; // when exiting onto ramps, we need to be careful about exit numbers. These can often be only // assigned to the first part of the ramp // // a . . b . c . . d // ` e . . f // // could assign the exit number to `be` when exiting `abcd` instead of the full ramp. // // Issuing a new-name instruction here would result in the turn assuming the short segment to be // irrelevant and remove the exit number in a collapse scenario. We don't want to issue any // instruction from be-ef, since we only loose the exit number. So we want to make sure that we // don't just loose an exit number, when exits change const auto exits_change = from_exits != to_exits; const auto looses_exit = (names_are_equal && !from_exits.empty() && to_exits.empty()); return !obvious_change || needs_announce || pronunciation_changes || (exits_change && !looses_exit); }