@@ -11,6 +11,7 @@ namespace version_weaver {
1111static constexpr size_t MAX_VERSION_LENGTH = 256 ;
1212
1313bool validate (std::string_view version);
14+
1415bool satisfies (std::string_view version, std::string_view range);
1516std::string coerce (std::string_view version);
1617std::string minimum (std::string_view range);
@@ -58,32 +59,81 @@ enum ParseError {
5859// This will return a cleaned and trimmed semver version.
5960// If the provided version is not valid a null will be returned.
6061// 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 );
6263
6364std::expected<Version, ParseError> parse (std::string_view version);
6465} // namespace version_weaver
6566
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
7868inline auto operator <=>(const version_weaver::Version& first,
7969 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+ };
8086 if (first.major != second.major ) {
81- return first.major <=> second.major ;
87+ return number_string_compare ( first.major , second.major ) ;
8288 }
8389 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+ }
85135 }
86- return first.patch <=> second.patch ;
136+ return first.pre_release . value (). size () <=> second.pre_release . value (). size () ;
87137}
88138
89- #endif // VERSION_WEAVER_H
139+ #endif // VERSION_WEAVER_H
0 commit comments