@@ -7,34 +7,55 @@ namespace ada::checkers {
7
7
8
8
// TODO: Refactor this to not use `std::vector` but use pointer arithmetic for performance.
9
9
bool ends_in_a_number (const std::string_view input) noexcept {
10
- // Let parts be the result of strictly splitting input on U+002E (.).
11
- std::vector<std::string> parts = ada::helpers::split_string_view (input, ' .' , false );
12
-
13
- if (parts.empty ()) {
10
+ if (input.empty ()) {
14
11
return false ;
15
12
}
16
13
14
+ size_t parts_count = std::count (input.begin (), input.end (), ' .' );
15
+
16
+ if (parts_count > 0 ) { parts_count++; }
17
+
18
+ static const std::string delimiter = " ." ;
19
+ std::string_view::iterator pointer_start = input.begin ();
20
+ std::string_view::iterator pointer_end = input.end ();
21
+
17
22
// If the last item in parts is the empty string, then:
18
- if (parts .back (). empty () ) {
23
+ if (input .back () == ' . ' ) {
19
24
// If parts’s size is 1, then return false.
20
- if (parts. size () == 1 ) {
25
+ if (parts_count == 1 ) {
21
26
return false ;
22
27
}
23
28
24
29
// Remove the last item from parts.
25
- parts.pop_back ();
30
+ pointer_end--;
31
+ parts_count--;
32
+ }
33
+
34
+ if (std::distance (pointer_start, pointer_end) == 0 ) {
35
+ return false ;
26
36
}
27
37
28
- // Let last be the last item in parts.
29
- std::string_view last = parts.back ();
38
+ if (parts_count > 1 ) {
39
+ pointer_start = std::find_end (pointer_start, pointer_end, delimiter.begin (), delimiter.end ());
40
+
41
+ if (pointer_start == pointer_end) {
42
+ return false ;
43
+ }
44
+
45
+ pointer_start++;
46
+ }
47
+
48
+ if (std::distance (pointer_start, pointer_end) == 0 ) {
49
+ return false ;
50
+ }
30
51
31
52
// If last is non-empty and contains only ASCII digits, then return true.
32
- if (!last. empty () && std::all_of (last. begin (), last. end () , ::isdigit)) {
53
+ if (std::all_of (pointer_start, pointer_end , ::isdigit)) {
33
54
return true ;
34
55
}
35
56
36
57
// If parsing last as an IPv4 number does not return failure, then return true.
37
- return ada::parser::parse_ipv4_number (last). has_value ( );
58
+ return is_ipv4_number_valid ( std::string (pointer_start, pointer_end) );
38
59
}
39
60
40
61
// A Windows drive letter is two code points, of which the first is an ASCII alpha
@@ -48,5 +69,30 @@ namespace ada::checkers {
48
69
return is_windows_drive_letter (input) && input[1 ] == ' :' ;
49
70
}
50
71
72
+ // This function assumes the input is not empty.
73
+ ada_really_inline constexpr bool is_ipv4_number_valid (const std::string_view input) noexcept {
74
+ // The first two code points are either "0X" or "0x", then:
75
+ if (input.length () >= 2 && input[0 ] == ' 0' && (input[1 ] == ' X' || input[1 ] == ' x' )) {
76
+ if (input.length () == 2 ) {
77
+ return true ;
78
+ }
79
+
80
+ // Remove the first two code points from input.
81
+ // If input contains a code point that is not a radix-R digit, then return failure.
82
+ return input.find_first_not_of (" 0123456789abcdefABCDEF" , 2 ) == std::string_view::npos;
83
+ }
84
+ // Otherwise, if the first code point is U+0030 (0), then:
85
+ else if (input[0 ] == ' 0' ) {
86
+ if (input.length () == 1 ) {
87
+ return true ;
88
+ }
89
+
90
+ // Remove the first code point from input.
91
+ // If input contains a code point that is not a radix-R digit, then return failure.
92
+ return input.find_first_not_of (" 01234567" , 1 ) == std::string_view::npos;
93
+ }
94
+
95
+ return std::all_of (input.begin (), input.end (), ::isdigit);
96
+ }
51
97
52
98
} // namespace ada::checkers
0 commit comments