|  | //===- VersionTuple.cpp - Version Number Handling ---------------*- C++ -*-===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This file implements the VersionTuple class, which represents a version in | 
|  | // the form major[.minor[.subminor]]. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | #include "llvm/Support/VersionTuple.h" | 
|  | #include "llvm/Support/raw_ostream.h" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | std::string VersionTuple::getAsString() const { | 
|  | std::string Result; | 
|  | { | 
|  | llvm::raw_string_ostream Out(Result); | 
|  | Out << *this; | 
|  | } | 
|  | return Result; | 
|  | } | 
|  |  | 
|  | raw_ostream &llvm::operator<<(raw_ostream &Out, const VersionTuple &V) { | 
|  | Out << V.getMajor(); | 
|  | if (Optional<unsigned> Minor = V.getMinor()) | 
|  | Out << '.' << *Minor; | 
|  | if (Optional<unsigned> Subminor = V.getSubminor()) | 
|  | Out << '.' << *Subminor; | 
|  | if (Optional<unsigned> Build = V.getBuild()) | 
|  | Out << '.' << *Build; | 
|  | return Out; | 
|  | } | 
|  |  | 
|  | static bool parseInt(StringRef &input, unsigned &value) { | 
|  | assert(value == 0); | 
|  | if (input.empty()) | 
|  | return true; | 
|  |  | 
|  | char next = input[0]; | 
|  | input = input.substr(1); | 
|  | if (next < '0' || next > '9') | 
|  | return true; | 
|  | value = (unsigned)(next - '0'); | 
|  |  | 
|  | while (!input.empty()) { | 
|  | next = input[0]; | 
|  | if (next < '0' || next > '9') | 
|  | return false; | 
|  | input = input.substr(1); | 
|  | value = value * 10 + (unsigned)(next - '0'); | 
|  | } | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool VersionTuple::tryParse(StringRef input) { | 
|  | unsigned major = 0, minor = 0, micro = 0, build = 0; | 
|  |  | 
|  | // Parse the major version, [0-9]+ | 
|  | if (parseInt(input, major)) | 
|  | return true; | 
|  |  | 
|  | if (input.empty()) { | 
|  | *this = VersionTuple(major); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // If we're not done, parse the minor version, \.[0-9]+ | 
|  | if (input[0] != '.') | 
|  | return true; | 
|  | input = input.substr(1); | 
|  | if (parseInt(input, minor)) | 
|  | return true; | 
|  |  | 
|  | if (input.empty()) { | 
|  | *this = VersionTuple(major, minor); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // If we're not done, parse the micro version, \.[0-9]+ | 
|  | if (input[0] != '.') | 
|  | return true; | 
|  | input = input.substr(1); | 
|  | if (parseInt(input, micro)) | 
|  | return true; | 
|  |  | 
|  | if (input.empty()) { | 
|  | *this = VersionTuple(major, minor, micro); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // If we're not done, parse the micro version, \.[0-9]+ | 
|  | if (input[0] != '.') | 
|  | return true; | 
|  | input = input.substr(1); | 
|  | if (parseInt(input, build)) | 
|  | return true; | 
|  |  | 
|  | // If we have characters left over, it's an error. | 
|  | if (!input.empty()) | 
|  | return true; | 
|  |  | 
|  | *this = VersionTuple(major, minor, micro, build); | 
|  | return false; | 
|  | } |