Commit 04c9b5ec authored by Daniel Pfeifer's avatar Daniel Pfeifer
Browse files

cmVersionComparison: Add Debian and RPM style version comparison

parent 5913e69f
Pipeline #62622 passed with stage
......@@ -39,6 +39,123 @@ int cm_vercmp_dot_decimal(const char* lhss, const char* rhss)
return 0;
}
int cm_vercmp_deb(const char* str1, const char* str2)
{
int r, c1, c2;
for (;;) {
c1 = *str1++;
c2 = *str2++;
if (isdigit(c1) && isdigit(c2)) {
while (c1 == '0') {
c1 = *str1++;
}
while (c2 == '0') {
c2 = *str2++;
}
r = 0;
while (isdigit(c1) && isdigit(c2)) {
if (!r) {
r = c1 - c2;
}
c1 = *str1++;
c2 = *str2++;
}
if (isdigit(c1)) {
return 1;
}
if (isdigit(c2)) {
return -1;
}
if (r) {
return r < 0 ? -1 : 1;
}
}
c1 = c1 == '~' ? -1 : !c1 || isalnum(c1) ? c1 : c1 + 256;
c2 = c2 == '~' ? -1 : !c2 || isalnum(c2) ? c2 : c2 + 256;
r = c1 - c2;
if (r) {
return r < 0 ? -1 : 1;
}
if (!c1) {
return 0;
}
}
}
int cm_vercmp_rpm(const char* str1, const char* str2)
{
int r = 0;
const char *end1, *end2;
for (;;) {
while (*str1 && !isalnum(*str1) && *str1 != '~') {
str1++;
}
while (*str2 && !isalnum(*str2) && *str2 != '~') {
str2++;
}
if (*str1 && *str1 == '~') {
if (*str2 && *str2 == '~') {
str1++;
str2++;
continue;
}
return -1;
}
if (*str2 && *str2 == '~') {
return 1;
}
if (!*str1 || !*str2) {
break;
}
if (isdigit(*str1) || isdigit(*str1)) {
while (*str1 == '0' && isdigit(str1[1])) {
str1++;
}
while (*str2 == '0' && isdigit(str2[1])) {
str2++;
}
for (end1 = str1; isdigit(*end1);) {
end1++;
}
for (end2 = str2; isdigit(*end2);) {
end2++;
}
r = (end1 - str1) - (end2 - str2);
if (!r) {
r = strncmp(str1, str2, end1 - str1);
}
if (r) {
return r > 0 ? 1 : -1;
}
} else {
for (end1 = str1; isalpha(*end1);) {
end1++;
}
for (end2 = str2; isalpha(*end2);) {
end2++;
}
r = (end1 - str1) - (end2 - str2);
if (r > 0) {
r = strncmp(str1, str2, end2 - str2);
return r >= 0 ? 1 : -1;
}
if (r < 0) {
r = strncmp(str1, str2, end1 - str1);
return r <= 0 ? -1 : 1;
}
r = strncmp(str1, str2, end1 - str1);
if (r) {
return r > 0 ? 1 : -1;
}
}
str1 = end1;
str2 = end2;
}
return *str1 ? 1 : *str2 ? -1 : 0;
}
typedef int (*cm_vercmp_fun)(const char*, const char*);
bool cm_match(cm_vercmp_fun vercmp_fun, const char* lhss, Operator op,
const char* rhss)
......@@ -151,6 +268,26 @@ bool Match(std::string const& lhs, Operator op, std::string const& rhs)
return cm_match(cm_vercmp_dot_decimal, lhs.c_str(), op, rhs.c_str());
}
int CompareDEB(std::string const& lhs, std::string const& rhs)
{
return cm_vercmp_deb(lhs.c_str(), rhs.c_str());
}
bool MatchDEB(std::string const& lhs, Operator op, std::string const& rhs)
{
return cm_match(cm_vercmp_deb, lhs.c_str(), op, rhs.c_str());
}
int CompareRPM(std::string const& lhs, std::string const& rhs)
{
return cm_vercmp_rpm(lhs.c_str(), rhs.c_str());
}
bool MatchRPM(std::string const& lhs, Operator op, std::string const& rhs)
{
return cm_match(cm_vercmp_rpm, lhs.c_str(), op, rhs.c_str());
}
int strverscmp(std::string const& lhs, std::string const& rhs)
{
return cm_strverscmp(lhs.c_str(), rhs.c_str());
......
......@@ -34,6 +34,18 @@ struct CompareGreater
}
};
/**
* Debian type version compare.
*/
int CompareDEB(std::string const& lhs, std::string const& rhs);
bool MatchDEB(std::string const& lhs, Operator op, std::string const& rhs);
/**
* RPM type version compare.
*/
int CompareRPM(std::string const& lhs, std::string const& rhs);
bool MatchRPM(std::string const& lhs, Operator op, std::string const& rhs);
/**
* Compare two ASCII strings using natural versioning order.
* Non-numerical characters are compared directly.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment