mirror of
https://github.com/overte-org/overte.git
synced 2025-04-26 07:16:25 +02:00
164 lines
4.1 KiB
C++
Executable file
164 lines
4.1 KiB
C++
Executable file
#include "fvversioncomparator.h"
|
|
#include <string>
|
|
#include <algorithm>
|
|
#include <cctype>
|
|
|
|
//
|
|
// Clone of Sparkle's SUStandardVersionComparator.m, so here's original author's
|
|
// copyright too:
|
|
//
|
|
// Copyright 2007 Andy Matuschak. All rights reserved.
|
|
//
|
|
// Everything's the same except for TypeOfCharacter()
|
|
// (because who knows how Foundation does isdigit() and such.)
|
|
//
|
|
|
|
|
|
FvVersionComparator::FvVersionComparator()
|
|
{
|
|
// noop
|
|
}
|
|
|
|
FvVersionComparator::CharacterType FvVersionComparator::TypeOfCharacter(std::string character)
|
|
{
|
|
if (character == ".") {
|
|
return kSeparatorType;
|
|
} else if (isdigit(character[0])) {
|
|
return kNumberType;
|
|
} else if (isspace(character[0])) {
|
|
return kSeparatorType;
|
|
} else if (ispunct(character[0])) {
|
|
return kSeparatorType;
|
|
} else {
|
|
return kStringType;
|
|
}
|
|
|
|
}
|
|
|
|
std::vector<std::string> FvVersionComparator::SplitVersionString(std::string version)
|
|
{
|
|
std::string character;
|
|
std::string s;
|
|
unsigned long i = 0, n = 0;
|
|
CharacterType oldType, newType;
|
|
std::vector<std::string> parts;
|
|
|
|
if (version.length() == 0) {
|
|
// Nothing to do here
|
|
return parts;
|
|
}
|
|
|
|
s = version.substr(0, 1);
|
|
oldType = TypeOfCharacter(s);
|
|
n = version.length() - 1;
|
|
for (i = 1; i <= n; ++i) {
|
|
character = version.substr(i, 1)[0];
|
|
newType = TypeOfCharacter(character);
|
|
if (oldType != newType || oldType == kSeparatorType) {
|
|
// We've reached a new segment
|
|
std::string aPart = s;
|
|
parts.push_back(aPart);
|
|
s = character;
|
|
} else {
|
|
// Add character to string and continue
|
|
s.append(character);
|
|
}
|
|
oldType = newType;
|
|
}
|
|
|
|
// Add the last part onto the array
|
|
parts.push_back(s);
|
|
return parts;
|
|
}
|
|
|
|
|
|
FvVersionComparator::ComparatorResult FvVersionComparator::CompareVersions(std::string versionA,
|
|
std::string versionB)
|
|
{
|
|
std::vector<std::string> partsA = SplitVersionString(versionA);
|
|
std::vector<std::string> partsB = SplitVersionString(versionB);
|
|
|
|
std::string partA = std::string(""), partB = std::string("");
|
|
unsigned long i = 0, n = 0;
|
|
int intA, intB;
|
|
CharacterType typeA, typeB;
|
|
|
|
n = std::min(partsA.size(), partsB.size());
|
|
for (i = 0; i < n; ++i) {
|
|
partA = partsA.at(i);
|
|
partB = partsB.at(i);
|
|
|
|
typeA = TypeOfCharacter(partA);
|
|
typeB = TypeOfCharacter(partB);
|
|
|
|
// Compare types
|
|
if (typeA == typeB) {
|
|
// Same type; we can compare
|
|
if (typeA == kNumberType) {
|
|
intA = atoi(partA.c_str());
|
|
intB = atoi(partB.c_str());
|
|
|
|
if (intA > intB) {
|
|
return kDescending;
|
|
} else if (intA < intB) {
|
|
return kAscending;
|
|
}
|
|
} else if (typeA == kStringType) {
|
|
short result = partA.compare(partB);
|
|
switch (result) {
|
|
case -1: return kAscending; break;
|
|
case 1: return kDescending; break;
|
|
case 0: /* do nothing */ break;
|
|
};
|
|
}
|
|
} else {
|
|
// Not the same type? Now we have to do some validity checking
|
|
if (typeA != kStringType && typeB == kStringType) {
|
|
// typeA wins
|
|
return kDescending;
|
|
} else if (typeA == kStringType && typeB != kStringType) {
|
|
// typeB wins
|
|
return kAscending;
|
|
} else {
|
|
// One is a number and the other is a period. The period is invalid
|
|
if (typeA == kNumberType) {
|
|
return kDescending;
|
|
} else {
|
|
return kAscending;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// The versions are equal up to the point where they both still have parts
|
|
// Lets check to see if one is larger than the other
|
|
if (partsA.size() != partsB.size()) {
|
|
// Yep. Lets get the next part of the larger
|
|
// n holds the index of the part we want.
|
|
std::string missingPart = std::string("");
|
|
CharacterType missingType;
|
|
ComparatorResult shorterResult, largerResult;
|
|
|
|
if (partsA.size() > partsB.size()) {
|
|
missingPart = partsA.at(n);
|
|
shorterResult = kAscending;
|
|
largerResult = kDescending;
|
|
} else {
|
|
missingPart = partsB.at(n);
|
|
shorterResult = kDescending;
|
|
largerResult = kAscending;
|
|
}
|
|
|
|
missingType = TypeOfCharacter(missingPart);
|
|
// Check the type
|
|
if (missingType == kStringType) {
|
|
// It's a string. Shorter version wins
|
|
return shorterResult;
|
|
} else {
|
|
// It's a number/period. Larger version wins
|
|
return largerResult;
|
|
}
|
|
}
|
|
|
|
// The 2 strings are identical
|
|
return kSame;
|
|
}
|