| 737 | }; |
| 738 | |
| 739 | class string : public schema |
| 740 | { |
| 741 | std::pair<bool, size_t> maxLength_{false, 0}; |
| 742 | std::pair<bool, size_t> minLength_{false, 0}; |
| 743 | |
| 744 | #ifndef NO_STD_REGEX |
| 745 | std::pair<bool, REGEX_NAMESPACE::regex> pattern_{false, REGEX_NAMESPACE::regex()}; |
| 746 | std::string patternString_; |
| 747 | #endif |
| 748 | |
| 749 | std::pair<bool, std::string> format_; |
| 750 | std::tuple<bool, std::string, std::string> content_{false, "", ""}; |
| 751 | |
| 752 | std::size_t utf8_length(const std::string &s) const |
| 753 | { |
| 754 | size_t len = 0; |
| 755 | for (auto c : s) |
| 756 | if ((c & 0xc0) != 0x80) |
| 757 | len++; |
| 758 | return len; |
| 759 | } |
| 760 | |
| 761 | void validate(const json::json_pointer &ptr, const json &instance, json_patch &, error_handler &e) const override |
| 762 | { |
| 763 | if (minLength_.first) { |
| 764 | if (utf8_length(instance.get<std::string>()) < minLength_.second) { |
| 765 | std::ostringstream s; |
| 766 | s << "instance is too short as per minLength:" << minLength_.second; |
| 767 | e.error(ptr, instance, s.str()); |
| 768 | } |
| 769 | } |
| 770 | |
| 771 | if (maxLength_.first) { |
| 772 | if (utf8_length(instance.get<std::string>()) > maxLength_.second) { |
| 773 | std::ostringstream s; |
| 774 | s << "instance is too long as per maxLength: " << maxLength_.second; |
| 775 | e.error(ptr, instance, s.str()); |
| 776 | } |
| 777 | } |
| 778 | |
| 779 | if (std::get<0>(content_)) { |
| 780 | if (root_->content_check() == nullptr) |
| 781 | e.error(ptr, instance, std::string("a content checker was not provided but a contentEncoding or contentMediaType for this string have been present: '") + std::get<1>(content_) + "' '" + std::get<2>(content_) + "'"); |
| 782 | else { |
| 783 | try { |
| 784 | root_->content_check()(std::get<1>(content_), std::get<2>(content_), instance); |
| 785 | } catch (const std::exception &ex) { |
| 786 | e.error(ptr, instance, std::string("content-checking failed: ") + ex.what()); |
| 787 | } |
| 788 | } |
| 789 | } else if (instance.type() == json::value_t::binary) { |
| 790 | e.error(ptr, instance, "expected string, but get binary data"); |
| 791 | } |
| 792 | |
| 793 | if (instance.type() != json::value_t::string) { |
| 794 | return; // next checks only for strings |
| 795 | } |
| 796 |
no outgoing calls