@@ -11,6 +11,7 @@ namespace version_weaver {
11
11
static constexpr size_t MAX_VERSION_LENGTH = 256 ;
12
12
13
13
bool validate (std::string_view version);
14
+
14
15
bool satisfies (std::string_view version, std::string_view range);
15
16
std::string coerce (std::string_view version);
16
17
std::string minimum (std::string_view range);
@@ -58,32 +59,81 @@ enum ParseError {
58
59
// This will return a cleaned and trimmed semver version.
59
60
// If the provided version is not valid a null will be returned.
60
61
// This does not work for ranges.
61
- std::expected<Version, ParseError> clean (std::string_view range );
62
+ std::expected<Version, ParseError> clean (std::string_view input );
62
63
63
64
std::expected<Version, ParseError> parse (std::string_view version);
64
65
} // namespace version_weaver
65
66
66
- inline bool operator !=(const version_weaver::Version& first,
67
- const version_weaver::Version& second) {
68
- if (first.major != second.major ) return first.major != second.major ;
69
- if (first.minor != second.minor ) return first.minor != second.minor ;
70
- return first.patch != second.patch ;
71
- }
72
- inline bool operator ==(const version_weaver::Version& first,
73
- const version_weaver::Version& second) {
74
- if (first.major != second.major ) return first.major == second.major ;
75
- if (first.minor != second.minor ) return first.minor == second.minor ;
76
- return first.patch == second.patch ;
77
- }
67
+ // https://semver.org/#spec-item-11
78
68
inline auto operator <=>(const version_weaver::Version& first,
79
69
const version_weaver::Version& second) {
70
+ auto number_string_compare = [](std::string_view first,
71
+ std::string_view second) {
72
+ if (first.size () > second.size ()) {
73
+ return std::strong_ordering::greater;
74
+ } else if (first.size () < second.size ()) {
75
+ return std::strong_ordering::less;
76
+ }
77
+ for (size_t i = 0 ; i < first.size (); i++) {
78
+ if (first[i] > second[i]) {
79
+ return std::strong_ordering::greater;
80
+ } else if (first[i] < second[i]) {
81
+ return std::strong_ordering::less;
82
+ }
83
+ }
84
+ return std::strong_ordering::equal;
85
+ };
80
86
if (first.major != second.major ) {
81
- return first.major <=> second.major ;
87
+ return number_string_compare ( first.major , second.major ) ;
82
88
}
83
89
if (first.minor != second.minor ) {
84
- return first.minor <=> second.minor ;
90
+ return number_string_compare (first.minor , second.minor );
91
+ }
92
+ if (first.patch != second.patch ) {
93
+ return number_string_compare (first.patch , second.patch );
94
+ }
95
+ if (second.pre_release .has_value () && !first.pre_release .has_value ()) {
96
+ return std::strong_ordering::greater;
97
+ }
98
+ if (first.pre_release .has_value () && !second.pre_release .has_value ()) {
99
+ return std::strong_ordering::less;
100
+ }
101
+ if (!first.pre_release .has_value () && !second.pre_release .has_value ()) {
102
+ return std::strong_ordering::equal;
103
+ }
104
+ if (first.pre_release .value () == second.pre_release .value ()) {
105
+ return std::strong_ordering::equal;
106
+ }
107
+ auto only_digits = [](std::string_view first) {
108
+ for (auto c : first) {
109
+ if (c < ' 0' || c > ' 9' ) {
110
+ return false ;
111
+ }
112
+ }
113
+ return true ;
114
+ };
115
+ bool first_numeric = only_digits (first.pre_release .value ());
116
+ bool second_numeric = only_digits (second.pre_release .value ());
117
+ if (first_numeric && !second_numeric) {
118
+ return std::strong_ordering::greater;
119
+ }
120
+ if (!first_numeric && second_numeric) {
121
+ return std::strong_ordering::less;
122
+ }
123
+ if (first_numeric && second_numeric) {
124
+ return number_string_compare (first.pre_release .value (),
125
+ second.pre_release .value ());
126
+ }
127
+ size_t min_size = std::min (first.pre_release .value ().size (),
128
+ second.pre_release .value ().size ());
129
+ for (size_t i = 0 ; i < min_size; i++) {
130
+ if (first.pre_release .value ()[i] > second.pre_release .value ()[i]) {
131
+ return std::strong_ordering::greater;
132
+ } else if (first.pre_release .value ()[i] < second.pre_release .value ()[i]) {
133
+ return std::strong_ordering::less;
134
+ }
85
135
}
86
- return first.patch <=> second.patch ;
136
+ return first.pre_release . value (). size () <=> second.pre_release . value (). size () ;
87
137
}
88
138
89
- #endif // VERSION_WEAVER_H
139
+ #endif // VERSION_WEAVER_H
0 commit comments