// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file.
// Parses the |numbers| vector representing the different numbers // inside the version string and constructs a vector of valid integers. It stops // when it reaches an invalid item (including the wildcard character). |parsed| // is the resulting integer vector. Function returns true if all numbers were // parsed successfully, false otherwise. bool ParseVersionNumbers(StringPiece version_str,
std::vector<uint32_t>* parsed) {
std::vector<StringPiece> numbers =
SplitStringPiece(version_str, ".", KEEP_WHITESPACE, SPLIT_WANT_ALL); if (numbers.empty()) returnfalse;
for (auto it = numbers.begin(); it != numbers.end(); ++it) { if (StartsWith(*it, "+", CompareCase::SENSITIVE)) returnfalse;
unsignedint num; if (!StringToUint(*it, &num)) returnfalse;
// This throws out leading zeros for the first item only. if (it == numbers.begin() && NumberToString(num) != *it) returnfalse;
// StringToUint returns unsigned int but Version fields are uint32_t.
static_assert(sizeof (uint32_t) == sizeof (unsignedint), "uint32_t must be same as unsigned int");
parsed->push_back(num);
} returntrue;
}
// Compares version components in |components1| with components in // |components2|. Returns -1, 0 or 1 if |components1| is less than, equal to, // or greater than |components2|, respectively. int CompareVersionComponents(const std::vector<uint32_t>& components1, const std::vector<uint32_t>& components2) { const size_t count = std::min(components1.size(), components2.size()); for (size_t i = 0; i < count; ++i) { if (components1[i] > components2[i]) return 1; if (components1[i] < components2[i]) return -1;
} if (components1.size() > components2.size()) { for (size_t i = count; i < components1.size(); ++i) { if (components1[i] > 0) return 1;
}
} elseif (components1.size() < components2.size()) { for (size_t i = count; i < components2.size(); ++i) { if (components2[i] > 0) return -1;
}
} return 0;
}
} // namespace
Version::Version() = default;
Version::Version(const Version& other) = default;
Version::~Version() = default;
Version::Version(StringPiece version_str) {
std::vector<uint32_t> parsed; if (!ParseVersionNumbers(version_str, &parsed)) return;
Version version(version_string); return version.IsValid();
}
int Version::CompareToWildcardString(StringPiece wildcard_string) const {
DCHECK(IsValid());
DCHECK(Version::IsValidWildcardString(wildcard_string));
// Default behavior if the string doesn't end with a wildcard. if (!EndsWith(wildcard_string, ".*", CompareCase::SENSITIVE)) {
Version version(wildcard_string);
DCHECK(version.IsValid()); return CompareTo(version);
}
std::vector<uint32_t> parsed; constbool success = ParseVersionNumbers(
wildcard_string.substr(0, wildcard_string.length() - 2), &parsed);
DCHECK(success); constint comparison = CompareVersionComponents(components_, parsed); // If the version is smaller than the wildcard version's |parsed| vector, // then the wildcard has no effect (e.g. comparing 1.2.3 and 1.3.*) and the // version is still smaller. Same logic for equality (e.g. comparing 1.2.2 to // 1.2.2.* is 0 regardless of the wildcard). Under this logic, // 1.2.0.0.0.0 compared to 1.2.* is 0. if (comparison == -1 || comparison == 0) return comparison;
// Catch the case where the digits of |parsed| are found in |components_|, // which means that the two are equal since |parsed| has a trailing "*". // (e.g. 1.2.3 vs. 1.2.* will return 0). All other cases return 1 since // components is greater (e.g. 3.2.3 vs 1.*).
DCHECK_GT(parsed.size(), 0UL); const size_t min_num_comp = std::min(components_.size(), parsed.size()); for (size_t i = 0; i < min_num_comp; ++i) { if (components_[i] != parsed[i]) return 1;
} return 0;
}
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 und die Messung sind noch experimentell.