Bladeren bron

feat: implement draft03 format phone numbers according to E.123 format

Sam Jaffe 2 weken geleden
bovenliggende
commit
f22fb02f21
1 gewijzigde bestanden met toevoegingen van 29 en 1 verwijderingen
  1. 29 1
      include/jvalidate/format.h

+ 29 - 1
include/jvalidate/format.h

@@ -1,4 +1,5 @@
 #pragma once
+#include <cstdio>
 #include <jvalidate/_macro.h>
 
 #include <cctype>
@@ -49,6 +50,12 @@ template <typename CharT = char> bool email(std::basic_string_view<CharT> em);
 }
 
 namespace jvalidate::format::detail {
+inline bool is_dec(std::string_view s, size_t min = 0, size_t max = std::string_view::npos) {
+  constexpr char const * g_dec_digits = "0123456789";
+  return s.find_first_not_of(g_dec_digits) == std::string::npos && s.size() >= min &&
+         s.size() <= max;
+}
+
 inline bool is_hex(std::string_view s) {
   constexpr char const * g_hex_digits = "0123456789ABCDEFabcdef";
   return s.find_first_not_of(g_hex_digits) == std::string::npos;
@@ -248,6 +255,9 @@ inline bool utc_millisec(std::string_view utc) {
 }
 
 inline bool css_2_1_color(std::string_view color) {
+  if (color.empty()) {
+    return false;
+  }
   constexpr char const * g_hex_digits = "0123456789ABCDEFabcdef";
   if (color[0] == '#') {
     return color.size() <= 7 && detail::is_hex(color.substr(1));
@@ -257,6 +267,24 @@ inline bool css_2_1_color(std::string_view color) {
       "green",  "navy", "blue",   "aqua",   "teal",  "black",  "silver",  "gray"};
   return g_color_codes.contains(color);
 }
+
+inline bool e_123_phone(std::string_view phone) {
+  // https://support.secureauth.com/hc/en-us/articles/360036402211-Regular-Expressions-for-ITU-E-123-and-E-164-phone-number-formats
+  if (phone.empty()) {
+    return false;
+  }
+  if (phone[0] != '+') {
+    constexpr size_t g_usa_phone_tokens = 3;
+    char area[4], head[4], tail[5];
+    return sscanf(phone.data(), "(%3s) %3s %4s", area, head, tail) == g_usa_phone_tokens &&
+           detail::is_dec(area, 3) && detail::is_dec(head, 3) && detail::is_dec(tail, 4);
+  }
+  char tok0[4], tok1[4], tok2[4], tok3[5];
+  constexpr size_t g_i18n_phone_tokens = 4;
+  return sscanf(phone.data(), "+%3s %3s %3s %4s", tok0, tok1, tok2, tok3) == g_i18n_phone_tokens &&
+         detail::is_dec(tok0, 1, 3) && detail::is_dec(tok1, 2, 3) && detail::is_dec(tok2, 2, 3) &&
+         detail::is_dec(tok3, 4);
+}
 }
 
 namespace jvalidate::format {
@@ -715,7 +743,7 @@ private:
       {"utc-millisec", &format::draft03::utc_millisec},
       {"color", &format::draft03::css_2_1_color},
       {"style", nullptr},
-      {"phone", nullptr},
+      {"phone", &format::draft03::e_123_phone},
       {"uri", &format::uri},
       {"email", &format::email},
       {"ip-address", &format::ipv4},