From 296ce69fe0b6d56e0429ec892d1ccc2066782d19 Mon Sep 17 00:00:00 2001
From: Alexander Borsuk <me@alex.bio>
Date: Fri, 7 Jun 2024 00:13:32 +0200
Subject: [PATCH] [C++20] Use starts_with and ends_with

Signed-off-by: Alexander Borsuk <me@alex.bio>
---
 base/base_tests/string_utils_test.cpp         | 60 +++--------------
 base/string_utils.cpp                         | 28 +-------
 base/string_utils.hpp                         |  5 --
 coding/url.cpp                                |  2 +-
 drape_frontend/color_constants.cpp            |  2 +-
 feature_list/feature_list.cpp                 |  4 +-
 ge0/geo_url_parser.cpp                        |  4 +-
 ge0/parser.cpp                                |  2 +-
 generator/descriptions_section_builder.cpp    |  2 +-
 .../generator_integration_tests/helpers.cpp   |  3 +-
 .../towns_tests.cpp                           |  2 +-
 .../test_with_custom_mwms.cpp                 |  2 +-
 generator/generator_tool/generator_tool.cpp   |  4 +-
 generator/maxspeeds_parser.cpp                |  4 +-
 generator/osm2meta.cpp                        | 17 ++---
 generator/osm2type.cpp                        |  2 +-
 generator/relation_tags.cpp                   |  6 +-
 indexer/categories_holder.cpp                 |  2 +-
 indexer/editable_map_object.cpp               |  2 +-
 indexer/feature_decl.cpp                      |  2 +-
 indexer/feature_meta.cpp                      |  4 +-
 indexer/road_shields_parser.cpp               |  2 +-
 indexer/validate_and_format_contacts.cpp      | 65 +++++++++----------
 map/bookmark_helpers.cpp                      |  2 +-
 map/framework.cpp                             |  2 +-
 map/map_tests/kmz_unarchive_test.cpp          |  2 +-
 map/mwm_url.cpp                               |  4 +-
 map/transit/transit_display.cpp               |  8 +--
 platform/local_country_file_utils.cpp         | 16 ++---
 platform/platform.cpp                         | 24 ++++---
 platform/platform.hpp                         |  2 +-
 platform/platform_android.cpp                 |  4 +-
 qt/place_page_dialog_user.cpp                 |  2 +-
 .../absent_regions_finder_tests.cpp           |  2 +-
 routing/speed_camera_prohibition.cpp          |  2 +-
 routing/turns_tts_text_i18n.cpp               | 12 ++--
 search/doc_vec.cpp                            |  6 +-
 .../search_quality_tests/real_mwm_tests.cpp   |  2 +-
 .../search_quality_tool.cpp                   |  2 +-
 storage/country_info_getter.cpp               |  3 +-
 storage/storage.cpp                           |  3 +-
 testing/testingmain.cpp                       | 25 ++++---
 42 files changed, 131 insertions(+), 218 deletions(-)

diff --git a/base/base_tests/string_utils_test.cpp b/base/base_tests/string_utils_test.cpp
index bddeb2366f..18ea0456c5 100644
--- a/base/base_tests/string_utils_test.cpp
+++ b/base/base_tests/string_utils_test.cpp
@@ -881,19 +881,7 @@ UNIT_TEST(StartsWith)
 {
   using namespace strings;
 
-  TEST(StartsWith(std::string(), ""), ());
-
-  std::string s("xyz");
-  TEST(StartsWith(s, ""), ());
-  TEST(StartsWith(s, "x"), ());
-  TEST(StartsWith(s, 'x'), ());
-  TEST(!StartsWith(s, 'z'), ());
-  TEST(StartsWith(s, "xyz"), ());
-  TEST(!StartsWith(s, "xyzabc"), ());
-  TEST(!StartsWith(s, "ayz"), ());
-  TEST(!StartsWith(s, "axy"), ());
-
-  UniString const us = MakeUniString(s);
+  UniString const us = MakeUniString("xyz");
   TEST(StartsWith(us, UniString()), ());
   TEST(StartsWith(us, MakeUniString("x")), ());
   TEST(StartsWith(us, MakeUniString("xyz")), ());
@@ -905,43 +893,15 @@ UNIT_TEST(StartsWith)
 UNIT_TEST(EndsWith)
 {
   using namespace strings;
-  {
-    TEST(EndsWith(std::string(), ""), ());
-  }
-  {
-    std::string const s("xyz");
-    TEST(EndsWith(s, ""), ());
-    TEST(EndsWith(s, "z"), ());
-    TEST(EndsWith(s, 'z'), ());
-    TEST(!EndsWith(s, 'x'), ());
-    TEST(EndsWith(s, "yz"), ());
-    TEST(EndsWith(s, "xyz"), ());
-    TEST(!EndsWith(s, "abcxyz"), ());
-    TEST(!EndsWith(s, "ayz"), ());
-    TEST(!EndsWith(s, "axyz"), ());
-  }
-  {
-    auto const s = MakeUniString("zюя");
-    TEST(EndsWith(s, MakeUniString("")), ());
-    TEST(EndsWith(s, MakeUniString("я")), ());
-    TEST(EndsWith(s, MakeUniString("юя")), ());
-    TEST(EndsWith(s, MakeUniString("zюя")), ());
-    TEST(!EndsWith(s, MakeUniString("абвгдzюя")), ());
-    TEST(!EndsWith(s, MakeUniString("aюя")), ());
-    TEST(!EndsWith(s, MakeUniString("1zюя")), ());
-  }
-  {
-    std::string const s("abcd");
-    TEST(EndsWith(s, std::string_view{""}), ());
-    TEST(EndsWith(s, std::string_view{"d"}), ());
-    TEST(EndsWith(s, std::string_view{"bcd"}), ());
-    TEST(EndsWith(s, std::string_view{"abcd"}), ());
-    TEST(!EndsWith(s, std::string_view{"dd"}), ());
-    TEST(!EndsWith(s, std::string_view{"c\""}), ());
-    TEST(!EndsWith(s, std::string_view{"cde"}), ());
-    TEST(!EndsWith(s, std::string_view{"abcde"}), ());
-    TEST(!EndsWith(s, std::string_view{"0abcd"}), ());
-  }
+
+  auto const s = MakeUniString("zюя");
+  TEST(EndsWith(s, MakeUniString("")), ());
+  TEST(EndsWith(s, MakeUniString("я")), ());
+  TEST(EndsWith(s, MakeUniString("юя")), ());
+  TEST(EndsWith(s, MakeUniString("zюя")), ());
+  TEST(!EndsWith(s, MakeUniString("абвгдzюя")), ());
+  TEST(!EndsWith(s, MakeUniString("aюя")), ());
+  TEST(!EndsWith(s, MakeUniString("1zюя")), ());
 }
 
 UNIT_TEST(EatPrefix_EatSuffix)
diff --git a/base/string_utils.cpp b/base/string_utils.cpp
index 01e7d245be..076ad4459a 100644
--- a/base/string_utils.cpp
+++ b/base/string_utils.cpp
@@ -339,16 +339,6 @@ bool StartsWith(UniString const & s, UniString const & p)
   return StartsWith(s.begin(), s.end(), p.begin(), p.end());
 }
 
-bool StartsWith(std::string_view s1, std::string_view s2)
-{
-  return (s1.compare(0, s2.length(), s2) == 0);
-}
-
-bool StartsWith(std::string const & s, std::string::value_type c)
-{
-  return s.empty() ? false : s.front() == c;
-}
-
 bool EndsWith(UniString const & s1, UniString const & s2)
 {
   if (s1.size() < s2.size())
@@ -357,23 +347,9 @@ bool EndsWith(UniString const & s1, UniString const & s2)
   return std::equal(s1.end() - s2.size(), s1.end(), s2.begin());
 }
 
-bool EndsWith(std::string_view s1, std::string_view s2)
-{
-  size_t const n = s1.size();
-  size_t const m = s2.size();
-  if (n < m)
-    return false;
-  return (s1.compare(n - m, m, s2) == 0);
-}
-
-bool EndsWith(std::string const & s, std::string::value_type c)
-{
-  return s.empty() ? false : s.back() == c;
-}
-
 bool EatPrefix(std::string & s, std::string const & prefix)
 {
-  if (!StartsWith(s, prefix))
+  if (!s.starts_with(prefix))
     return false;
 
   CHECK_LESS_OR_EQUAL(prefix.size(), s.size(), ());
@@ -383,7 +359,7 @@ bool EatPrefix(std::string & s, std::string const & prefix)
 
 bool EatSuffix(std::string & s, std::string const & suffix)
 {
-  if (!EndsWith(s, suffix))
+  if (!s.ends_with(suffix))
     return false;
 
   CHECK_LESS_OR_EQUAL(suffix.size(), s.size(), ());
diff --git a/base/string_utils.hpp b/base/string_utils.hpp
index 27c666b9d0..ce8f59eb83 100644
--- a/base/string_utils.hpp
+++ b/base/string_utils.hpp
@@ -593,12 +593,7 @@ bool StartsWith(IterT1 beg, IterT1 end, IterT2 begPrefix, IterT2 endPrefix)
 }
 
 bool StartsWith(UniString const & s, UniString const & p);
-bool StartsWith(std::string_view s1, std::string_view s2);
-bool StartsWith(std::string const & s, std::string::value_type c);
-
 bool EndsWith(UniString const & s1, UniString const & s2);
-bool EndsWith(std::string_view s1, std::string_view s2);
-bool EndsWith(std::string const & s, std::string::value_type c);
 
 // If |s| starts with |prefix|, deletes it from |s| and returns true.
 // Otherwise, leaves |s| unmodified and returns false.
diff --git a/coding/url.cpp b/coding/url.cpp
index 310f3fccc3..acc2bc7d66 100644
--- a/coding/url.cpp
+++ b/coding/url.cpp
@@ -19,7 +19,7 @@ Url::Url(std::string const & url)
 
 Url Url::FromString(std::string const & url)
 {
-  bool const hasProtocol = strings::StartsWith(url, "http://") || strings::StartsWith(url, "https://");
+  bool const hasProtocol = url.starts_with("http://") || url.starts_with("https://");
   return Url(hasProtocol ? url : "https://" + url);
 }
 
diff --git a/drape_frontend/color_constants.cpp b/drape_frontend/color_constants.cpp
index 0b835719a3..487b8f39b7 100644
--- a/drape_frontend/color_constants.cpp
+++ b/drape_frontend/color_constants.cpp
@@ -117,7 +117,7 @@ ColorConstant GetTransitTextColorName(ColorConstant const & localName)
 
 bool IsTransitColor(ColorConstant const & constant)
 {
-  return strings::StartsWith(constant, kTransitColorPrefix);
+  return constant.starts_with(kTransitColorPrefix);
 }
 
 dp::Color GetColorConstant(ColorConstant const & constant)
diff --git a/feature_list/feature_list.cpp b/feature_list/feature_list.cpp
index ad85839b8e..b41700b24b 100644
--- a/feature_list/feature_list.cpp
+++ b/feature_list/feature_list.cpp
@@ -269,7 +269,7 @@ public:
     string const wikipedia(meta.Get(feature::Metadata::FMD_WIKIPEDIA));
     string const wikimedia_commons(meta.Get(feature::Metadata::FMD_WIKIMEDIA_COMMONS));
     string const floor(meta.Get(feature::Metadata::FMD_LEVEL));
-    string const fee = strings::EndsWith(category, "-fee") ? "yes" : "";
+    string const fee = category.ends_with("-fee") ? "yes" : "";
     string const atm = HasAtm(f) ? "yes" : "";
 
     vector<string> columns = {
@@ -365,7 +365,7 @@ int main(int argc, char ** argv)
   {
     if (mwmInfo->GetType() != MwmInfo::COUNTRY)
       continue;
-    if (argc > 3 && !strings::StartsWith(mwmInfo->GetCountryName() + DATA_FILE_EXTENSION, argv[3]))
+    if (argc > 3 && !(mwmInfo->GetCountryName() + DATA_FILE_EXTENSION).starts_with(argv[3]))
       continue;
     LOG(LINFO, ("Processing", mwmInfo->GetCountryName()));
     string osmToFeatureFile = base::JoinPath(
diff --git a/ge0/geo_url_parser.cpp b/ge0/geo_url_parser.cpp
index a844837afe..78f46ae463 100644
--- a/ge0/geo_url_parser.cpp
+++ b/ge0/geo_url_parser.cpp
@@ -173,7 +173,7 @@ bool GeoParser::Parse(std::string const & raw, GeoURLInfo & info) const
   /*
    * Check that URI starts with geo:
    */
-  if (!strings::StartsWith(raw, "geo:"))
+  if (!raw.starts_with("geo:"))
     return false;
 
   /*
@@ -365,7 +365,7 @@ bool GeoURLInfo::SetLon(double x)
 
 bool UnifiedParser::Parse(std::string const & raw, GeoURLInfo & res)
 {
-  if (strings::StartsWith(raw, "geo:"))
+  if (raw.starts_with("geo:"))
     return m_geoParser.Parse(raw, res);
 
   url::Url url(raw);
diff --git a/ge0/parser.cpp b/ge0/parser.cpp
index 4175090606..569c58a38b 100644
--- a/ge0/parser.cpp
+++ b/ge0/parser.cpp
@@ -41,7 +41,7 @@ bool Ge0Parser::Parse(std::string const & url, Result & result)
 
   for (auto prefix : kGe0Prefixes)
   {
-    if (strings::StartsWith(url, prefix))
+    if (url.starts_with(prefix))
       return ParseAfterPrefix(url, prefix.size(), result);
   }
 
diff --git a/generator/descriptions_section_builder.cpp b/generator/descriptions_section_builder.cpp
index 9fa11ed36f..4cb267be07 100644
--- a/generator/descriptions_section_builder.cpp
+++ b/generator/descriptions_section_builder.cpp
@@ -144,7 +144,7 @@ std::string DescriptionsCollector::MakePathForWikipedia(std::string const & wiki
   strings::Trim(wikipediaUrl);
   strings::ReplaceFirst(wikipediaUrl, "http://", "");
   strings::ReplaceFirst(wikipediaUrl, "https://", "");
-  if (strings::EndsWith(wikipediaUrl, "/"))
+  if (wikipediaUrl.ends_with('/'))
     wikipediaUrl.pop_back();
 
   return base::JoinPath(wikipediaDir, wikipediaUrl);
diff --git a/generator/generator_integration_tests/helpers.cpp b/generator/generator_integration_tests/helpers.cpp
index 9e24b6a000..ce39bab2bd 100644
--- a/generator/generator_integration_tests/helpers.cpp
+++ b/generator/generator_integration_tests/helpers.cpp
@@ -7,7 +7,6 @@
 
 #include "base/assert.hpp"
 #include "base/file_name_utils.hpp"
-#include "base/string_utils.hpp"
 
 namespace generator_integration_tests
 {
@@ -22,7 +21,7 @@ void DecompressZipArchive(std::string const & src, std::string const & dst)
   for (auto const & p : files)
   {
     auto const output = base::JoinPath(dst, p.first);
-    if (strings::EndsWith(output, base::GetNativeSeparator()))
+    if (output.ends_with(base::GetNativeSeparator()))
     {
       if (!plaftorm.MkDirRecursively(output))
         MYTHROW(MkDirFailure, (output));
diff --git a/generator/generator_integration_tests/towns_tests.cpp b/generator/generator_integration_tests/towns_tests.cpp
index abe65f3833..954c2f84cc 100644
--- a/generator/generator_integration_tests/towns_tests.cpp
+++ b/generator/generator_integration_tests/towns_tests.cpp
@@ -50,7 +50,7 @@ class TestAffiliation : public feature::AffiliationInterface
 
   bool HasCountryByName(std::string const & name) const override
   {
-    return !strings::StartsWith(name, "World");
+    return !name.starts_with("World");
   }
 };
 } // namespace
diff --git a/generator/generator_tests_support/test_with_custom_mwms.cpp b/generator/generator_tests_support/test_with_custom_mwms.cpp
index 85b044e7a5..3776676a06 100644
--- a/generator/generator_tests_support/test_with_custom_mwms.cpp
+++ b/generator/generator_tests_support/test_with_custom_mwms.cpp
@@ -86,7 +86,7 @@ void TestWithCustomMwms::RegisterLocalMapsByPrefix(std::string const & prefix)
 {
   RegisterLocalMapsImpl([&](std::string const & name)
   {
-    return strings::StartsWith(name, prefix);
+    return name.starts_with(prefix);
   });
 }
 
diff --git a/generator/generator_tool/generator_tool.cpp b/generator/generator_tool/generator_tool.cpp
index 82af930723..a18d26a173 100644
--- a/generator/generator_tool/generator_tool.cpp
+++ b/generator/generator_tool/generator_tool.cpp
@@ -377,12 +377,12 @@ MAIN_WITH_ERROR_HANDLING([](int argc, char ** argv)
       if (!FLAGS_uk_postcodes_dataset.empty() || !FLAGS_us_postcodes_dataset.empty())
       {
         bool res = true;
-        if (!FLAGS_uk_postcodes_dataset.empty() && strings::StartsWith(country, "UK_"))
+        if (!FLAGS_uk_postcodes_dataset.empty() && country.starts_with("UK_"))
         {
           res = indexer::BuildPostcodePoints(path, country, indexer::PostcodePointsDatasetType::UK,
                                              FLAGS_uk_postcodes_dataset, true /*forceRebuild*/);
         }
-        else if (!FLAGS_us_postcodes_dataset.empty() && strings::StartsWith(country, "US_"))
+        else if (!FLAGS_us_postcodes_dataset.empty() && country.starts_with("US_"))
         {
           res = indexer::BuildPostcodePoints(path, country, indexer::PostcodePointsDatasetType::US,
                                              FLAGS_us_postcodes_dataset, true /*forceRebuild*/);
diff --git a/generator/maxspeeds_parser.cpp b/generator/maxspeeds_parser.cpp
index e27502117f..928f61d881 100644
--- a/generator/maxspeeds_parser.cpp
+++ b/generator/maxspeeds_parser.cpp
@@ -176,7 +176,7 @@ bool ParseMaxspeedTag(std::string const & maxspeedValue, routing::SpeedInUnits &
   while (i < maxspeedValue.size() && isspace(maxspeedValue[i]))
     ++i;
 
-  if (maxspeedValue.size() == i || strings::StartsWith(maxspeedValue.substr(i), "kmh"))
+  if (maxspeedValue.size() == i || maxspeedValue.substr(i).starts_with("kmh"))
   {
     uint64_t kmph = 0;
     if (!strings::to_uint64(speedStr.c_str(), kmph) || kmph == 0 || kmph > std::numeric_limits<uint16_t>::max())
@@ -187,7 +187,7 @@ bool ParseMaxspeedTag(std::string const & maxspeedValue, routing::SpeedInUnits &
     return true;
   }
 
-  if (strings::StartsWith(maxspeedValue.substr(i), "mph"))
+  if (maxspeedValue.substr(i).starts_with("mph"))
   {
     uint64_t mph = 0;
     if (!strings::to_uint64(speedStr.c_str(), mph) || mph == 0 || mph > std::numeric_limits<uint16_t>::max())
diff --git a/generator/osm2meta.cpp b/generator/osm2meta.cpp
index b79182617e..1d0a89f715 100644
--- a/generator/osm2meta.cpp
+++ b/generator/osm2meta.cpp
@@ -286,22 +286,17 @@ std::string MetadataTagProcessorImpl::ValidateAndFormat_wikipedia(std::string v)
 
 std::string MetadataTagProcessorImpl::ValidateAndFormat_wikimedia_commons(std::string v)
 {
-
   // Putting the full wikimedia url to this tag is incorrect according to:
   // https://wiki.openstreetmap.org/wiki/Key:wikimedia_commons
   // But it happens often enough that we should guard against it.
   strings::ReplaceFirst(v, "https://commons.wikimedia.org/wiki/", "");
   strings::ReplaceFirst(v, "https://commons.m.wikimedia.org/wiki/", "");
 
-  if (strings::StartsWith(v, "File:") || strings::StartsWith(v, "Category:"))
-  {
+  if (v.starts_with("File:") || v.starts_with("Category:"))
     return v;
-  }
-  else
-  {
-    LOG(LDEBUG, ("Invalid Wikimedia Commons tag value:", v));
-    return {};
-  }
+
+  LOG(LDEBUG, ("Invalid Wikimedia Commons tag value:", v));
+  return {};
 }
 
 std::string MetadataTagProcessorImpl::ValidateAndFormat_airport_iata(std::string const & v) const
@@ -394,7 +389,7 @@ std::string MetadataTagProcessorImpl::ValidateAndFormat_duration(std::string con
   size_t pos = 0;
   std::optional<uint32_t> op;
 
-  if (strings::StartsWith(v, "PT"))
+  if (v.starts_with("PT"))
   {
     if (v.size() < 4)
       return {};
@@ -474,7 +469,7 @@ void MetadataTagProcessor::operator()(std::string const & k, std::string const &
     return std::string_view();
   };
 
-  if (strings::StartsWith(k, "description"))
+  if (k.starts_with("description"))
   {
     // Separate description tags processing.
     int8_t langIdx = StringUtf8Multilang::kDefaultCode;
diff --git a/generator/osm2type.cpp b/generator/osm2type.cpp
index 2012d46078..ba972d3886 100644
--- a/generator/osm2type.cpp
+++ b/generator/osm2type.cpp
@@ -1084,7 +1084,7 @@ void PostprocessElement(OsmElement * p, FeatureBuilderParams & params)
       {
         for (auto const & prefix : disusedPrefix)
         {
-          if (strings::StartsWith(tag.m_key, prefix))
+          if (tag.m_key.starts_with(prefix))
           {
             params.ClearPOIAttribs();
             goto exit;
diff --git a/generator/relation_tags.cpp b/generator/relation_tags.cpp
index 717e6bb660..825f005d21 100644
--- a/generator/relation_tags.cpp
+++ b/generator/relation_tags.cpp
@@ -59,7 +59,7 @@ void RelationTagsNode::Process(RelationElement const & e)
     // - used in routing information
     // - used in building addresses matching
     if (p.first == "network" || p.first == "operator" || p.first == "route" ||
-        p.first == "maxspeed" || strings::StartsWith(p.first, "addr:"))
+        p.first == "maxspeed" || p.first.starts_with("addr:"))
     {
       if (!Base::IsKeyTagExists(p.first))
         Base::AddCustomTag(p);
@@ -189,8 +189,8 @@ void RelationTagsWay::Process(RelationElement const & e)
       Base::AddCustomTag("addr:street", p.second);
 
     // All "name" tags should be skipped.
-    if (strings::StartsWith(p.first, "name") || strings::StartsWith(p.first, "int_name") ||
-        strings::StartsWith(p.first, "old_name") || strings::StartsWith(p.first, "alt_name"))
+    if (p.first.starts_with("name") || p.first.starts_with("int_name") ||
+        p.first.starts_with("old_name") || p.first.starts_with("alt_name"))
     {
       continue;
     }
diff --git a/indexer/categories_holder.cpp b/indexer/categories_holder.cpp
index d53594c354..ddc9ed1e34 100644
--- a/indexer/categories_holder.cpp
+++ b/indexer/categories_holder.cpp
@@ -78,7 +78,7 @@ void ProcessName(CategoriesHolder::Category::Name name, std::vector<std::string>
 
   FillPrefixLengthToSuggest(name);
 
-  if (strings::StartsWith(name.m_name, "U+") && !ParseEmoji(name))
+  if (name.m_name.starts_with("U+") && !ParseEmoji(name))
     return;
 
   if (groups.size() == 1 && types.empty())
diff --git a/indexer/editable_map_object.cpp b/indexer/editable_map_object.cpp
index fddf8b246d..3822b3b536 100644
--- a/indexer/editable_map_object.cpp
+++ b/indexer/editable_map_object.cpp
@@ -530,7 +530,7 @@ bool EditableMapObject::ValidateLevel(string const & level)
     return false;
 
   // Allowing only half-levels.
-  if (level.find('.') != string::npos && !strings::EndsWith(level, ".5"))
+  if (level.find('.') != string::npos && !level.ends_with(".5"))
     return false;
 
   // Forbid "04" and "0.".
diff --git a/indexer/feature_decl.cpp b/indexer/feature_decl.cpp
index cc9911eac1..3b5cc18dd3 100644
--- a/indexer/feature_decl.cpp
+++ b/indexer/feature_decl.cpp
@@ -43,7 +43,7 @@ bool FeatureID::IsEqualCountry(base::StringIL const & lst) const
   auto const & name = m_mwmId.GetInfo()->GetCountryName();
   for (char const * e : lst)
   {
-    if (strings::StartsWith(name, e))
+    if (name.starts_with(e))
       return true;
   }
   return false;
diff --git a/indexer/feature_meta.cpp b/indexer/feature_meta.cpp
index ec53c7a72e..f57ac1d655 100644
--- a/indexer/feature_meta.cpp
+++ b/indexer/feature_meta.cpp
@@ -69,7 +69,7 @@ bool Metadata::TypeFromString(string_view k, Metadata::EType & outType)
     outType = Metadata::EType::FMD_FAX_NUMBER;
   else if (k == "stars")
     outType = Metadata::FMD_STARS;
-  else if (strings::StartsWith(k, "operator"))
+  else if (k.starts_with("operator"))
     outType = Metadata::FMD_OPERATOR;
   else if (k == "url" || k == "website" || k == "contact:website")
     outType = Metadata::FMD_WEBSITE;
@@ -124,7 +124,7 @@ bool Metadata::TypeFromString(string_view k, Metadata::EType & outType)
     outType = Metadata::FMD_LEVEL;
   else if (k == "iata")
     outType = Metadata::FMD_AIRPORT_IATA;
-  else if (strings::StartsWith(k, "brand"))
+  else if (k.starts_with("brand"))
     outType = Metadata::FMD_BRAND;
   else if (k == "duration")
     outType = Metadata::FMD_DURATION;
diff --git a/indexer/road_shields_parser.cpp b/indexer/road_shields_parser.cpp
index d89d6dc326..ece14d368e 100644
--- a/indexer/road_shields_parser.cpp
+++ b/indexer/road_shields_parser.cpp
@@ -96,7 +96,7 @@ public:
   RoadShieldType FindNetworkShield(std::string network) const
   {
     // Special processing for US state highways, to not duplicate the table.
-    if (network.size() == 5 && strings::StartsWith(network, "US:"))
+    if (network.size() == 5 && network.starts_with("US:"))
     {
       if (base::IsExist(kStatesCode, network.substr(3)))
         return RoadShieldType::Generic_White;
diff --git a/indexer/validate_and_format_contacts.cpp b/indexer/validate_and_format_contacts.cpp
index f544a452bb..13027f4cda 100644
--- a/indexer/validate_and_format_contacts.cpp
+++ b/indexer/validate_and_format_contacts.cpp
@@ -51,16 +51,16 @@ constexpr string_view kHttps{"https://"};
 
 size_t GetProtocolNameLength(string const & website)
 {
-  if (strings::StartsWith(website, kHttp))
-    return kHttp.size();
-  if (strings::StartsWith(website, kHttps))
+  if (website.starts_with(kHttps))
     return kHttps.size();
+  if (website.starts_with(kHttp))
+    return kHttp.size();
   return 0;
 }
 
 bool IsProtocolSpecified(string const & website)
 {
-  return strings::StartsWith(website, kHttp) || strings::StartsWith(website, kHttps);
+  return 0 != GetProtocolNameLength(website);
 }
 
 // TODO: Current implementation looks only for restricted symbols from ASCII block ignoring
@@ -111,19 +111,19 @@ string ValidateAndFormat_facebook(string const & facebookPage)
       return facebookPage;
   }
 
-  // facebookPage is not a valid username it must be an URL.
+  // facebookPage is not a valid username it must be a URL.
   if (!ValidateWebsite(facebookPage))
     return {};
 
   url::Url const url = url::Url::FromString(facebookPage);
   string const domain = strings::MakeLowerCase(url.GetHost());
   // Check Facebook domain name.
-  if (strings::StartsWith(domain, kFacebookDot) || strings::StartsWith(domain, kFbDot) ||
+  if (domain.starts_with(kFacebookDot) || domain.starts_with(kFbDot) ||
       domain.find(".facebook.") != string::npos || domain.find(".fb.") != string::npos)
   {
     auto webPath = url.GetPath();
     // In case of https://www.facebook.com/profile.php?id=100085707580841 extract only ID.
-    if (strings::StartsWith(webPath, kProfilePhp))
+    if (webPath.starts_with(kProfilePhp))
     {
       std::string const * id = url.GetParamValue("id");
       return (id ? *id : std::string());
@@ -155,7 +155,7 @@ string ValidateAndFormat_instagram(string const & instagramPage)
   url::Url const url = url::Url::FromString(instagramPage);
   string const domain = strings::MakeLowerCase(url.GetHost());
   // Check Instagram domain name: "instagram.com" or "*.instagram.com".
-  if (domain == kInstagramCom || strings::EndsWith(domain, kDotInstagramCom))
+  if (domain == kInstagramCom || domain.ends_with(kDotInstagramCom))
   {
     auto webPath = url.GetPath();
     // Strip last '/' symbol.
@@ -184,7 +184,7 @@ string ValidateAndFormat_twitter(string const & twitterPage)
   url::Url const url = url::Url::FromString(twitterPage);
   string const domain = strings::MakeLowerCase(url.GetHost());
   // Check Twitter domain name: "twitter.com" or "*.twitter.com".
-  if (domain == kTwitterCom || strings::EndsWith(domain, kDotTwitterCom))
+  if (domain == kTwitterCom || domain.ends_with(kDotTwitterCom))
   {
     auto webPath = url.GetPath();
 
@@ -222,11 +222,11 @@ string ValidateAndFormat_vk(string const & vkPage)
   if (!ValidateWebsite(vkPage))
     return {};
 
-  url::Url const url = url::Url::FromString(vkPage);
-  string const domain = strings::MakeLowerCase(url.GetHost());
+  auto const url = url::Url::FromString(vkPage);
+  auto const domain = strings::MakeLowerCase(url.GetHost());
   // Check VK domain name: "vk.com" or "vkontakte.ru" or "*.vk.com" or "*.vkontakte.ru".
-  if (domain == kVkCom || strings::EndsWith(domain, kDotVkCom) ||
-      domain == kVkontakteRu || strings::EndsWith(domain, kDotVkontakteRu))
+  if (domain == kVkCom || domain.ends_with(kDotVkCom) ||
+      domain == kVkontakteRu || domain.ends_with(kDotVkontakteRu))
   {
     auto webPath = url.GetPath();
     // Strip last '/' symbol.
@@ -244,7 +244,7 @@ string stripAtSymbol(string const & lineId)
     return lineId;
   if (lineId.front() == '@')
     return lineId.substr(1);
-  if (strings::StartsWith(lineId, "%40"))
+  if (lineId.starts_with("%40"))
     return lineId.substr(3);
   return lineId;
 }
@@ -257,7 +257,7 @@ string ValidateAndFormat_contactLine(string const & linePage)
   {
     // Check that linePage contains valid page name.
     // Rules are defined here: https://help.line.me/line/?contentId=10009904
-    // The page name must be between 4 and 20 characters. Should contains alphanumeric characters
+    // The page name must be between 4 and 20 characters. Should contain alphanumeric characters
     // and symbols '.', '-', and '_'
 
     string linePageClean = stripAtSymbol(linePage);
@@ -284,36 +284,33 @@ string ValidateAndFormat_contactLine(string const & linePage)
     string lineId = url.GetPath();
     return stripAtSymbol(lineId);
   }
-  else if (domain == kLineMe || strings::EndsWith(domain, kDotLineMe))
+  else if (domain == kLineMe || domain.ends_with(kDotLineMe))
   {
     auto webPath = url.GetPath();
-    if (strings::StartsWith(webPath, "R/ti/p/"))
+    if (webPath.starts_with("R/ti/p/"))
     {
       // Parse https://line.me/R/ti/p/{LINE ID}
       string lineId = webPath.substr(7, webPath.length());
       return stripAtSymbol(lineId);
     }
-    else if (strings::StartsWith(webPath, "ti/p/"))
+    if (webPath.starts_with("ti/p/"))
     {
       // Parse https://line.me/ti/p/{LINE ID}
       string lineId = webPath.substr(5, webPath.length());
       return stripAtSymbol(lineId);
     }
-    else if (strings::StartsWith(webPath, "R/home/public/main") || strings::StartsWith(webPath, "R/home/public/profile"))
+    if (webPath.starts_with("R/home/public/main") || webPath.starts_with("R/home/public/profile"))
     {
       // Parse https://line.me/R/home/public/main?id={LINE ID without @}
       // and https://line.me/R/home/public/profile?id={LINE ID without @}
       std::string const * id = url.GetParamValue("id");
       return (id ? *id : std::string());
     }
-    else
-    {
-      if (strings::StartsWith(linePage, kHttp))
-        return linePage.substr(7);
-      if (strings::StartsWith(linePage, kHttps))
-        return linePage.substr(8);
-      return linePage;
-    }
+    if (linePage.starts_with(kHttp))
+      return linePage.substr(7);
+    if (linePage.starts_with(kHttps))
+      return linePage.substr(8);
+    return linePage;
   }
 
   return {};
@@ -361,7 +358,7 @@ bool ValidateFacebookPage(string const & page)
 
   string const domain = strings::MakeLowerCase(url::Url::FromString(page).GetHost());
   // Validate domain name: "facebook.*" or "fb.*" or "*.facebook.*" or "*.fb.*".
-  return (strings::StartsWith(domain, kFacebookDot) || strings::StartsWith(domain, kFbDot) ||
+  return (domain.starts_with(kFacebookDot) || domain.starts_with(kFbDot) ||
           domain.find(".facebook.") != string::npos || domain.find(".fb.") != string::npos);
 }
 
@@ -378,7 +375,7 @@ bool ValidateInstagramPage(string const & page)
     return false;
 
   string const domain = strings::MakeLowerCase(url::Url::FromString(page).GetHost());
-  return domain == kInstagramCom || strings::EndsWith(domain, kDotInstagramCom);
+  return domain == kInstagramCom || domain.ends_with(kDotInstagramCom);
 }
 
 bool ValidateTwitterPage(string const & page)
@@ -390,7 +387,7 @@ bool ValidateTwitterPage(string const & page)
     return regex_match(page, s_twitterRegex); // Rules are defined here: https://stackoverflow.com/q/11361044
 
   string const domain = strings::MakeLowerCase(url::Url::FromString(page).GetHost());
-  return domain == kTwitterCom || strings::EndsWith(domain, kDotTwitterCom);
+  return domain == kTwitterCom || domain.ends_with(kDotTwitterCom);
 }
 
 bool ValidateVkPage(string const & page)
@@ -423,8 +420,8 @@ bool ValidateVkPage(string const & page)
     return false;
 
   string const domain = strings::MakeLowerCase(url::Url::FromString(page).GetHost());
-  return domain == kVkCom || strings::EndsWith(domain, kDotVkCom)
-         || domain == kVkontakteRu || strings::EndsWith(domain, kDotVkontakteRu);
+  return domain == kVkCom || domain.ends_with(kDotVkCom)
+         || domain == kVkontakteRu || domain.ends_with(kDotVkontakteRu);
 }
 
 bool ValidateLinePage(string const & page)
@@ -435,7 +432,7 @@ bool ValidateLinePage(string const & page)
   {
     // Check that linePage contains valid page name.
     // Rules are defined here: https://help.line.me/line/?contentId=10009904
-    // The page name must be between 4 and 20 characters. Should contains alphanumeric characters
+    // The page name must be between 4 and 20 characters. Should contain alphanumeric characters
     // and symbols '.', '-', and '_'
 
     if (regex_match(stripAtSymbol(page), s_lineRegex))
@@ -447,7 +444,7 @@ bool ValidateLinePage(string const & page)
 
   string const domain = strings::MakeLowerCase(url::Url::FromString(page).GetHost());
   // Check Line domain name.
-  return (domain == kLineMe || strings::EndsWith(domain, kDotLineMe));
+  return (domain == kLineMe || domain.ends_with(kDotLineMe));
 }
 
 bool isSocialContactTag(string_view tag)
diff --git a/map/bookmark_helpers.cpp b/map/bookmark_helpers.cpp
index 43b470a42d..5b70a46a60 100644
--- a/map/bookmark_helpers.cpp
+++ b/map/bookmark_helpers.cpp
@@ -248,7 +248,7 @@ std::string GetLowercaseFileExt(std::string const & filePath)
 std::string GenerateUniqueFileName(std::string const & path, std::string name, std::string_view ext)
 {
   // Remove extension, if file name already contains it.
-  if (strings::EndsWith(name, ext))
+  if (name.ends_with(ext))
     name.resize(name.size() - ext.size());
 
   size_t counter = 1;
diff --git a/map/framework.cpp b/map/framework.cpp
index 27420039bf..2d53bacd7f 100644
--- a/map/framework.cpp
+++ b/map/framework.cpp
@@ -111,7 +111,7 @@ size_t constexpr kMaxTrafficCacheSizeBytes = 64 /* Mb */ * 1024 * 1024;
 bool ParseSetGpsTrackMinAccuracyCommand(string const & query)
 {
   char const kGpsAccuracy[] = "?gpstrackaccuracy:";
-  if (!strings::StartsWith(query, kGpsAccuracy))
+  if (!query.starts_with(kGpsAccuracy))
     return false;
 
   size_t const end = query.find(';', sizeof(kGpsAccuracy) - 1);
diff --git a/map/map_tests/kmz_unarchive_test.cpp b/map/map_tests/kmz_unarchive_test.cpp
index 07eb5fbee7..aa1f3cc925 100644
--- a/map/map_tests/kmz_unarchive_test.cpp
+++ b/map/map_tests/kmz_unarchive_test.cpp
@@ -16,7 +16,7 @@ UNIT_TEST(KMZ_UnzipTest)
   TEST(!filePath.empty(), ());
   SCOPE_GUARD(fileGuard, std::bind(&base::DeleteFileX, filePath));
 
-  TEST(strings::EndsWith(filePath, "doc.kml"), (filePath));
+  TEST(filePath.ends_with("doc.kml"), (filePath));
 
   auto const kmlData = LoadKmlFile(filePath, KmlFileType::Text);
   TEST(kmlData != nullptr, ());
diff --git a/map/mwm_url.cpp b/map/mwm_url.cpp
index 033495896d..d968f3e8c5 100644
--- a/map/mwm_url.cpp
+++ b/map/mwm_url.cpp
@@ -94,12 +94,12 @@ std::tuple<size_t, bool> FindUrlPrefix(std::string const & url)
 {
   for (auto const prefix : ge0::Ge0Parser::kGe0Prefixes)
   {
-    if (strings::StartsWith(url, prefix))
+    if (url.starts_with(prefix))
       return {prefix.size(), true};
   }
   for (auto const prefix : kLegacyMwmPrefixes)
   {
-    if (strings::StartsWith(url, prefix))
+    if (url.starts_with(prefix))
       return {prefix.size(), false};
   }
   return {std::string::npos, false};
diff --git a/map/transit/transit_display.cpp b/map/transit/transit_display.cpp
index caf4343fb4..799f4ef063 100644
--- a/map/transit/transit_display.cpp
+++ b/map/transit/transit_display.cpp
@@ -530,8 +530,8 @@ void TransitRouteDisplay::AddGateSubwayForSubroute(routing::RouteSegment const &
     auto const fid = FeatureID(ssp.m_mwmId, gate.m_featureId);
     auto const & featureInfo = ssp.m_displayInfo.m_features.at(fid);
     auto symbolName = featureInfo.m_gateSymbolName;
-    if (strings::EndsWith(symbolName, "-s") || strings::EndsWith(symbolName, "-m") ||
-        strings::EndsWith(symbolName, "-l"))
+    if (symbolName.ends_with("-s") || symbolName.ends_with("-m") ||
+        symbolName.ends_with("-l"))
     {
       symbolName = symbolName.substr(0, symbolName.rfind('-'));
     }
@@ -582,8 +582,8 @@ void TransitRouteDisplay::AddGatePTForSubroute(routing::RouteSegment const & seg
     auto const fid = FeatureID(ssp.m_mwmId, gate.m_featureId);
     auto const & featureInfo = ssp.m_displayInfo.m_features.at(fid);
     auto symbolName = featureInfo.m_gateSymbolName;
-    if (strings::EndsWith(symbolName, "-s") || strings::EndsWith(symbolName, "-m") ||
-        strings::EndsWith(symbolName, "-l"))
+    if (symbolName.ends_with("-s") || symbolName.ends_with("-m") ||
+        symbolName.ends_with("-l"))
     {
       symbolName = symbolName.substr(0, symbolName.rfind('-'));
     }
diff --git a/platform/local_country_file_utils.cpp b/platform/local_country_file_utils.cpp
index 973fcd5918..e068f2e939 100644
--- a/platform/local_country_file_utils.cpp
+++ b/platform/local_country_file_utils.cpp
@@ -48,8 +48,7 @@ bool IsDownloaderFile(string const & name)
 
 bool IsDiffFile(string const & name)
 {
-  return strings::EndsWith(name, DIFF_FILE_EXTENSION) ||
-         strings::EndsWith(name, DIFF_APPLYING_FILE_EXTENSION);
+  return name.ends_with(DIFF_FILE_EXTENSION) || name.ends_with(DIFF_APPLYING_FILE_EXTENSION);
 }
 
 /*
@@ -92,9 +91,8 @@ void FindAllDiffsInDirectory(string const & dir, vector<LocalCountryFile> & diff
   {
     string name = fileWithType.first;
 
-    auto const isDiffReady =
-        strings::EndsWith(name, strings::to_string(DIFF_FILE_EXTENSION) + READY_FILE_EXTENSION);
-    auto const isDiff = strings::EndsWith(name, DIFF_FILE_EXTENSION);
+    auto const isDiffReady = name.ends_with(DIFF_FILE_EXTENSION READY_FILE_EXTENSION);
+    auto const isDiff = name.ends_with(DIFF_FILE_EXTENSION);
 
     if (!isDiff && !isDiffReady)
       continue;
@@ -129,7 +127,7 @@ void DeleteDownloaderFilesForCountry(int64_t version, string const & dataDir,
   {
     string const path = GetFileDownloadPath(version, dataDir, countryFile,
                                             static_cast<MapFileType>(type));
-    ASSERT(strings::EndsWith(path, READY_FILE_EXTENSION), ());
+    ASSERT(path.ends_with(READY_FILE_EXTENSION), ());
     Platform::RemoveFileIfExists(path);
     Platform::RemoveFileIfExists(path + RESUME_FILE_EXTENSION);
     Platform::RemoveFileIfExists(path + DOWNLOADING_FILE_EXTENSION);
@@ -166,7 +164,7 @@ size_t FindAllLocalMapsInDirectoryAndCleanup(string const & directory, int64_t v
       continue;
     }
 
-    if (!strings::EndsWith(name, DATA_FILE_EXTENSION))
+    if (!name.ends_with(DATA_FILE_EXTENSION))
       continue;
 
     // Remove DATA_FILE_EXTENSION and use base name as a country file name.
@@ -397,8 +395,8 @@ void CountryIndexes::GetIndexesExts(vector<string> & exts)
 // static
 bool CountryIndexes::IsIndexFile(string const & file)
 {
-  return strings::EndsWith(file, kBitsExt) || strings::EndsWith(file, kNodesExt) ||
-         strings::EndsWith(file, kOffsetsExt);
+  return file.ends_with(kBitsExt) || file.ends_with(kNodesExt) ||
+         file.ends_with(kOffsetsExt);
 }
 
 // static
diff --git a/platform/platform.cpp b/platform/platform.cpp
index de62b9f333..9f898a1d80 100644
--- a/platform/platform.cpp
+++ b/platform/platform.cpp
@@ -1,7 +1,6 @@
 #include "platform/platform.hpp"
 
 #include "coding/internal/file_data.hpp"
-#include "coding/writer.hpp"
 
 #include "base/file_name_utils.hpp"
 #include "base/logging.hpp"
@@ -289,16 +288,15 @@ void Platform::SetResourceDir(std::string const & path)
 // static
 bool Platform::MkDirChecked(std::string const & dirName)
 {
-  Platform::EError const ret = MkDir(dirName);
-  switch (ret)
+  switch (EError const ret = MkDir(dirName))
   {
-  case Platform::ERR_OK: return true;
-  case Platform::ERR_FILE_ALREADY_EXISTS:
+  case ERR_OK: return true;
+  case ERR_FILE_ALREADY_EXISTS:
   {
-    Platform::EFileType type;
+    EFileType type;
     if (!GetFileTypeChecked(dirName, type))
       return false;
-    if (type != EFileType::Directory)
+    if (type != Directory)
     {
       LOG(LERROR, (dirName, "exists, but not a dirName:", type));
       return false;
@@ -312,16 +310,16 @@ bool Platform::MkDirChecked(std::string const & dirName)
 // static
 bool Platform::MkDirRecursively(std::string const & dirName)
 {
+  CHECK(!dirName.empty(), ());
+
   std::string::value_type const sep[] = { base::GetNativeSeparator(), 0};
-  std::string path = strings::StartsWith(dirName, sep) ? sep : ".";
-  auto const tokens = strings::Tokenize(dirName, sep);
-  for (auto const & t : tokens)
+  std::string path = dirName.starts_with(sep[0]) ? sep : ".";
+  for (auto const & t : strings::Tokenize(dirName, sep))
   {
     path = base::JoinPath(path, std::string{t});
     if (!IsFileExistsByFullPath(path))
     {
-      auto const ret = MkDir(path);
-      switch (ret)
+      switch (MkDir(path))
       {
       case ERR_OK: break;
       case ERR_FILE_ALREADY_EXISTS:
@@ -338,7 +336,7 @@ bool Platform::MkDirRecursively(std::string const & dirName)
   return true;
 }
 
-unsigned Platform::CpuCores() const
+unsigned Platform::CpuCores()
 {
   unsigned const cores = std::thread::hardware_concurrency();
   return cores > 0 ? cores : 1;
diff --git a/platform/platform.hpp b/platform/platform.hpp
index 939d17498a..457e08d9e8 100644
--- a/platform/platform.hpp
+++ b/platform/platform.hpp
@@ -251,7 +251,7 @@ public:
 
   // Please note, that number of active cores can vary at runtime.
   // DO NOT assume for the same return value between calls.
-  unsigned CpuCores() const;
+  static unsigned CpuCores() ;
 
   void GetFontNames(FilesList & res) const;
 
diff --git a/platform/platform_android.cpp b/platform/platform_android.cpp
index 7982a1e98d..31ec9a3448 100644
--- a/platform/platform_android.cpp
+++ b/platform/platform_android.cpp
@@ -66,7 +66,7 @@ unique_ptr<ModelReader> Platform::GetReader(string const & file, string searchSc
 
       if (ext == DATA_FILE_EXTENSION)
       {
-        if (strings::StartsWith(file, WORLD_COASTS_FILE_NAME) || strings::StartsWith(file, WORLD_FILE_NAME))
+        if (file.starts_with(WORLD_COASTS_FILE_NAME) || file.starts_with(WORLD_FILE_NAME))
           searchScope = "wsr";
         else
           searchScope = "w";
@@ -209,7 +209,7 @@ void Platform::GetSystemFontNames(FilesList & res) const
     string name(entry);
     if (name != "Roboto-Medium.ttf" && name != "Roboto-Regular.ttf")
     {
-      if (!strings::StartsWith(name, "NotoNaskh") && !strings::StartsWith(name, "NotoSans"))
+      if (!name.starts_with("NotoNaskh") && !name.starts_with("NotoSans"))
         return;
 
       if (name.find("-Regular") == string::npos)
diff --git a/qt/place_page_dialog_user.cpp b/qt/place_page_dialog_user.cpp
index 76118f12bd..b792cf305b 100644
--- a/qt/place_page_dialog_user.cpp
+++ b/qt/place_page_dialog_user.cpp
@@ -41,7 +41,7 @@ std::string getShortDescription(const std::string & description)
 std::string_view stripSchemeFromURI(std::string_view uri) {
   for (std::string_view prefix : {"https://", "http://"})
   {
-    if (strings::StartsWith(uri, prefix))
+    if (uri.starts_with(prefix))
       return uri.substr(prefix.size());
   }
   return uri;
diff --git a/routing/routing_integration_tests/absent_regions_finder_tests.cpp b/routing/routing_integration_tests/absent_regions_finder_tests.cpp
index ee11acc5dc..d3614a08d7 100644
--- a/routing/routing_integration_tests/absent_regions_finder_tests.cpp
+++ b/routing/routing_integration_tests/absent_regions_finder_tests.cpp
@@ -309,7 +309,7 @@ UNIT_CLASS_TEST(TestAbsentRegionsFinder, Russia_SPB_Pechory)
 
   /// @todo Optimal should not include Estonia.
   for (auto const & rgn : GetRegions(checkpoints))
-    TEST(!strings::StartsWith(rgn, "Estonia"), ());
+    TEST(!rgn.starts_with("Estonia"), ());
 }
 
 } // namespace absent_regions_finder_tests
diff --git a/routing/speed_camera_prohibition.cpp b/routing/speed_camera_prohibition.cpp
index f221bd7b27..a49b8d09c8 100644
--- a/routing/speed_camera_prohibition.cpp
+++ b/routing/speed_camera_prohibition.cpp
@@ -20,7 +20,7 @@ std::vector<std::string> kSpeedCamerasPartlyProhibitedCountries = {
 bool IsMwmContained(platform::CountryFile const & mwm, std::vector<std::string> const & countryList)
 {
   return std::any_of(countryList.cbegin(), countryList.cend(), [&mwm](auto const & country) {
-    return strings::StartsWith(mwm.GetName(), country);
+    return mwm.GetName().starts_with(country);
   });
 }
 }  // namespace
diff --git a/routing/turns_tts_text_i18n.cpp b/routing/turns_tts_text_i18n.cpp
index 1557ead96e..e1157c37c2 100644
--- a/routing/turns_tts_text_i18n.cpp
+++ b/routing/turns_tts_text_i18n.cpp
@@ -106,20 +106,20 @@ uint8_t CategorizeHungarianAcronymsAndNumbers(std::string const & hungarianStrin
   // Compare the end of our string with the views above. The order is chosen
   // in priority of what would most likely cause an ending vowel sound change.
   for (auto myCase : specialCaseFront)
-    if (strings::EndsWith(hungarianString, myCase))
+    if (hungarianString.ends_with(myCase))
       return 1;
   for (auto myCase : specialCaseBack)
-    if (strings::EndsWith(hungarianString, myCase))
+    if (hungarianString.ends_with(myCase))
       return 2;
-  if (strings::EndsWith(hungarianString, "100"))
+  if (hungarianString.ends_with("100"))
     return 2;
   for (auto myCase : frontNames)
-    if (strings::EndsWith(hungarianString, myCase))
+    if (hungarianString.ends_with(myCase))
       return 1;
   for (auto myCase : backNames)
-    if (strings::EndsWith(hungarianString, myCase))
+    if (hungarianString.ends_with(myCase))
       return 2;
-  if (strings::EndsWith(hungarianString, " "))
+  if (hungarianString.ends_with(' '))
     return 2;
 
   LOG(LWARNING, ("Unable to find Hungarian front/back for", hungarianString));
diff --git a/search/doc_vec.cpp b/search/doc_vec.cpp
index 2663f59279..96ba289a8b 100644
--- a/search/doc_vec.cpp
+++ b/search/doc_vec.cpp
@@ -1,13 +1,11 @@
 #include "search/doc_vec.hpp"
 
-#include "base/logging.hpp"
-
 #include <limits>
 
-using namespace std;
-
 namespace search
 {
+using namespace std;
+
 namespace
 {
 // Accumulates frequencies of equal tokens in |tfs|. Result is sorted
diff --git a/search/search_quality/search_quality_tests/real_mwm_tests.cpp b/search/search_quality/search_quality_tests/real_mwm_tests.cpp
index 829d84a50c..b72729e09d 100644
--- a/search/search_quality/search_quality_tests/real_mwm_tests.cpp
+++ b/search/search_quality/search_quality_tests/real_mwm_tests.cpp
@@ -108,7 +108,7 @@ public:
     {
       auto const it = std::find_if(prefixes.begin(), prefixes.end(), [name = r.GetString()](char const * prefix)
       {
-        return strings::StartsWith(name, prefix);
+        return name.starts_with(prefix);
       });
 
       TEST(it != prefixes.end(), (r));
diff --git a/search/search_quality/search_quality_tool/search_quality_tool.cpp b/search/search_quality/search_quality_tool/search_quality_tool.cpp
index f82b1f1fce..f8774c901f 100644
--- a/search/search_quality/search_quality_tool/search_quality_tool.cpp
+++ b/search/search_quality/search_quality_tool/search_quality_tool.cpp
@@ -94,7 +94,7 @@ struct CompletenessQuery
 
     string mwmName = parts[0].substr(0, idx);
     string const kMwmSuffix = ".mwm";
-    if (!strings::EndsWith(mwmName, kMwmSuffix))
+    if (!mwmName.ends_with(kMwmSuffix))
       MYTHROW(MalformedQueryException, ("Bad mwm name:", s));
 
     string const featureIdStr = parts[0].substr(idx + 1);
diff --git a/storage/country_info_getter.cpp b/storage/country_info_getter.cpp
index 099ff3b8b2..0ed1c660e7 100644
--- a/storage/country_info_getter.cpp
+++ b/storage/country_info_getter.cpp
@@ -8,7 +8,6 @@
 #include "coding/geometry_coding.hpp"
 #include "coding/read_write_utils.hpp"
 
-#include "geometry/latlon.hpp"
 #include "geometry/mercator.hpp"
 #include "geometry/region2d.hpp"
 
@@ -187,7 +186,7 @@ void CountryInfoGetter::ForEachCountry(std::string const & prefix, ToDo && toDo)
 {
   for (auto const & country : m_countries)
   {
-    if (strings::StartsWith(country.m_countryId, prefix.c_str()))
+    if (country.m_countryId.starts_with(prefix))
       toDo(country);
   }
 }
diff --git a/storage/storage.cpp b/storage/storage.cpp
index 38706af06c..208efc4661 100644
--- a/storage/storage.cpp
+++ b/storage/storage.cpp
@@ -14,7 +14,6 @@
 #include "platform/preferred_languages.hpp"
 #include "platform/settings.hpp"
 
-#include "coding/file_reader.hpp"
 #include "coding/file_writer.hpp"
 #include "coding/internal/file_data.hpp"
 #include "coding/sha1.hpp"
@@ -1349,7 +1348,7 @@ bool Storage::IsCountryLeaf(CountryTree::Node const & node)
 
 bool Storage::IsWorldCountryID(CountryId const & country)
 {
-  return strings::StartsWith(country, WORLD_FILE_NAME);
+  return country.starts_with(WORLD_FILE_NAME);
 }
 
 /*
diff --git a/testing/testingmain.cpp b/testing/testingmain.cpp
index 4b5ecde11e..db4f2a6b8f 100644
--- a/testing/testingmain.cpp
+++ b/testing/testingmain.cpp
@@ -2,8 +2,6 @@
 #include "testing/testregister.hpp"
 
 #include "base/logging.hpp"
-#include "base/scope_guard.hpp"
-#include "base/string_utils.hpp"
 #include "base/timer.hpp"
 #include "base/waiter.hpp"
 
@@ -19,6 +17,7 @@
 #include <vector>
 
 #ifdef WITH_GL_MOCK
+# include "base/scope_guard.hpp"
 # include "drape/drape_tests/gl_mock_functions.hpp"
 #endif
 
@@ -123,18 +122,18 @@ void ParseOptions(int argc, char * argv[], CommandLineOptions & options)
 {
   for (int i = 1; i < argc; ++i)
   {
-    char const * const arg = argv[i];
-    if (strings::StartsWith(arg, kFilterOption))
-      options.m_filterRegExp = arg + sizeof(kFilterOption) - 1;
-    if (strings::StartsWith(arg, kSuppressOption))
-      options.m_suppressRegExp = arg + sizeof(kSuppressOption) - 1;
-    if (strings::StartsWith(arg, kDataPathOptions))
-      options.m_dataPath = arg + sizeof(kDataPathOptions) - 1;
-    if (strings::StartsWith(arg, kResourcePathOptions))
-      options.m_resourcePath = arg + sizeof(kResourcePathOptions) - 1;
-    if (strcmp(arg, kHelpOption) == 0)
+    std::string_view const arg = argv[i];
+    if (arg.starts_with(kFilterOption))
+      options.m_filterRegExp = argv[i] + sizeof(kFilterOption) - 1;
+    if (arg.starts_with(kSuppressOption))
+      options.m_suppressRegExp = argv[i] + sizeof(kSuppressOption) - 1;
+    if (arg.starts_with(kDataPathOptions))
+      options.m_dataPath = argv[i] + sizeof(kDataPathOptions) - 1;
+    if (arg.starts_with(kResourcePathOptions))
+      options.m_resourcePath = argv[i] + sizeof(kResourcePathOptions) - 1;
+    if (arg == kHelpOption)
       options.m_help = true;
-    if (strcmp(arg, kListAllTestsOption) == 0)
+    if (arg == kListAllTestsOption)
       options.m_listTests = true;
   }
 #ifndef OMIM_UNIT_TEST_DISABLE_PLATFORM_INIT