/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include"nsVersionComparator.h"
#include <stdlib.h> #include <string.h> #include <stdint.h> #include <errno.h> #include"mozilla/CheckedInt.h" #ifdefined(XP_WIN) # if !defined(UPDATER_NO_STRING_GLUE_STL) # include <wchar.h> # include "nsString.h" # endif # include "nsAlgorithm.h" #endif
struct VersionPart {
int32_t numA;
constchar* strB; // NOT null-terminated, can be a null pointer
uint32_t strBlen;
int32_t numC;
char* extraD; // null-terminated
};
#ifdef XP_WIN struct VersionPartW {
int32_t numA;
wchar_t* strB; // NOT null-terminated, can be a null pointer
uint32_t strBlen;
// Different platforms seem to disagree on what to return when the value // is out of range so we ensure that it is always what we want it to be. // We choose 0 firstly because that is the default when the number doesn't // exist at all and also because it would be easier to recover from should // you somehow end up in a situation where an old version is invalid. It is // much easier to create a version either larger or smaller than 0, much // harder to do the same with INT_MAX. if (errno != 0) { return 0;
}
mozilla::CheckedInt<int32_t> result = result_long; if (!result.isValid()) { return 0;
}
return result.value();
}
/** * Parse a version part into a number and "extra text". * * @returns A pointer to the next versionpart, or null if none.
*/ staticchar* ParseVP(char* aPart, VersionPart& aResult) { char* dot;
if (!*aResult.extraD) {
aResult.extraD = nullptr;
}
}
}
}
if (dot) {
++dot;
if (!*dot) {
dot = nullptr;
}
}
return dot;
} #endif
// compare two null-terminated strings, which may be null pointers static int32_t ns_strcmp(constchar* aStr1, constchar* aStr2) { // any string is *before* no string if (!aStr1) { return aStr2 != 0;
}
if (!aStr2) { return -1;
}
return strcmp(aStr1, aStr2);
}
// compare two length-specified string, which may be null pointers static int32_t ns_strnncmp(constchar* aStr1, uint32_t aLen1, constchar* aStr2,
uint32_t aLen2) { // any string is *before* no string if (!aStr1) { return aStr2 != 0;
}
if (!aStr2) { return -1;
}
for (; aLen1 && aLen2; --aLen1, --aLen2, ++aStr1, ++aStr2) { if (*aStr1 < *aStr2) { return -1;
}
if (*aStr1 > *aStr2) { return 1;
}
}
if (aLen1 == 0) { return aLen2 == 0 ? 0 : -1;
}
return 1;
}
// compare two int32_t static int32_t ns_cmp(int32_t aNum1, int32_t aNum2) { if (aNum1 < aNum2) { return -1;
}
return aNum1 != aNum2;
}
/** * Compares two VersionParts
*/ static int32_t CompareVP(VersionPart& aVer1, VersionPart& aVer2) {
int32_t r = ns_cmp(aVer1.numA, aVer2.numA); if (r) { return r;
}
r = ns_strnncmp(aVer1.strB, aVer1.strBlen, aVer2.strB, aVer2.strBlen); if (r) { return r;
}
r = ns_cmp(aVer1.numC, aVer2.numC); if (r) { return r;
}
return ns_strcmp(aVer1.extraD, aVer2.extraD);
}
/** * Compares two VersionParts
*/ #ifdef XP_WIN static int32_t CompareVP(VersionPartW& aVer1, VersionPartW& aVer2) {
int32_t r = ns_cmp(aVer1.numA, aVer2.numA); if (r) { return r;
}
r = wcsncmp(aVer1.strB, aVer2.strB, XPCOM_MIN(aVer1.strBlen, aVer2.strBlen)); if (r) { return r;
}
r = ns_cmp(aVer1.numC, aVer2.numC); if (r) { return r;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.