static
| 629 | |
| 630 | // static |
| 631 | bool EditableMapObject::ValidateLevel(string const & level) |
| 632 | { |
| 633 | if (level.empty()) |
| 634 | return true; |
| 635 | |
| 636 | if (strings::CountChar(level) > kMaximumOsmChars) |
| 637 | return false; |
| 638 | |
| 639 | if (level.front() == ';' || level.back() == ';' || level.find(";;") != std::string::npos) |
| 640 | return false; |
| 641 | |
| 642 | // validate ";" separated values separately |
| 643 | vector<std::string_view> const tokenizedValues = strings::Tokenize(level, ";"); |
| 644 | |
| 645 | for (std::string_view const & value : tokenizedValues) |
| 646 | { |
| 647 | auto const isValidNumber = [](std::string_view const & s) |
| 648 | { |
| 649 | auto constexpr kMinBuildingLevel = -9; |
| 650 | double valueDouble; |
| 651 | return strings::to_double(s, valueDouble) && valueDouble > kMinBuildingLevel && |
| 652 | valueDouble <= kMaximumLevelsEditableByUsers; |
| 653 | }; |
| 654 | |
| 655 | // Check for simple value (e.g. "42") |
| 656 | if (!isValidNumber(value)) |
| 657 | { |
| 658 | // Check for range (e.g. "-3-12") |
| 659 | size_t rangeSymbol = value.find('-', 1); // skip first as it could be a negative sign |
| 660 | if (rangeSymbol == std::string::npos) |
| 661 | return false; |
| 662 | |
| 663 | std::string_view from = value.substr(0, rangeSymbol); |
| 664 | std::string_view to = value.substr(rangeSymbol + 1, value.size()); |
| 665 | |
| 666 | if (!isValidNumber(from) || !isValidNumber(to)) |
| 667 | return false; |
| 668 | } |
| 669 | |
| 670 | // Forbid leading zero (e.g. "04") |
| 671 | if (value.front() == '0' && value.size() >= 2 && value[1] != '.') |
| 672 | return false; |
| 673 | } |
| 674 | |
| 675 | return true; |
| 676 | } |
| 677 | |
| 678 | // static |
| 679 | bool EditableMapObject::ValidateName(string const & name) |