int string::compare(const std::u32string & s) const noexcept
{
    size_type sz = size();
    size_type len = s.size();
    size_type n = std::min(sz, len);
    
    auto pos = cbegin();
    auto spos = s.cbegin();
    for ( ; n; pos++, spos++ )
    {
        if ( traits_type::lt(*pos, *spos) )
            return -1;
        if ( traits_type::lt(*spos, *pos) )
            return 1;
    }
    
    if ( sz < len )
        return -1;
    if ( sz > len )
        return 1;
    return 0;
}
// static
bool EditableMapObject::ValidateName(string const & name)
{
  if (name.empty())
    return true;

  if (strings::IsASCIIString(name))
    return regex_match(name, regex(R"(^[ A-Za-z0-9.,?!@#$%&()\-\+:;"'`]+$)"));

  std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter;

  std::u32string u32name;
  try
  {
    u32name = converter.from_bytes(name);
  }
  catch (std::range_error const &)
  {
    // Cannot convert, for ex. it is possible for some emoji.
    return false;
  }

  std::u32string const excludedSymbols = U"^~§><{}[]*=_±\n\t\r\v\f|√•÷׶°";

  for (auto const ch : u32name)
  {
    // Exclude arrows, mathematical symbols, borders, geometric shapes.
    if (ch >= U'\U00002190' && ch <= U'\U00002BFF')
      return false;
    // Exclude format controls, musical symbols, emoticons, ornamental and pictographs,
    // ancient and exotic alphabets.
    if (ch >= U'\U0000FFF0' && ch <= U'\U0001F9FF')
      return false;

    if (find(excludedSymbols.cbegin(), excludedSymbols.cend(), ch) != excludedSymbols.cend())
      return false;
  }
  return true;
}
int string::compare(size_type pos1, size_type n1, const std::u32string& str,
                    size_type pos2, size_type n2) const
{
    if ( n1 == 0 && n2 > 0 )
        return -1;
    
    size_type sz = (n1 == npos ? size() - pos1 : n1);
    size_type len = (n2 == npos ? str.size() - pos2 : n2);
    size_type n = std::min(sz, len);
    
    auto pos = cbegin()+pos1;
    auto spos = str.cbegin();
    for ( ; n; pos++, spos++ )
    {
        if ( traits_type::lt(*pos, *spos) )
            return -1;
        if ( traits_type::lt(*spos, *pos) )
            return 1;
    }
    
    if ( sz < len )
        return -1;
    if ( sz > len )
        return 1;
    return 0;
}