1 //===- VersionTuple.cpp - Version Number Handling ---------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the VersionTuple class, which represents a version in 10 // the form major[.minor[.subminor]]. 11 // 12 //===----------------------------------------------------------------------===// 13 #include "llvm/Support/VersionTuple.h" 14 #include "llvm/Support/raw_ostream.h" 15 16 using namespace llvm; 17 18 std::string VersionTuple::getAsString() const { 19 std::string Result; 20 { 21 llvm::raw_string_ostream Out(Result); 22 Out << *this; 23 } 24 return Result; 25 } 26 27 raw_ostream &llvm::operator<<(raw_ostream &Out, const VersionTuple &V) { 28 Out << V.getMajor(); 29 if (Optional<unsigned> Minor = V.getMinor()) 30 Out << '.' << *Minor; 31 if (Optional<unsigned> Subminor = V.getSubminor()) 32 Out << '.' << *Subminor; 33 if (Optional<unsigned> Build = V.getBuild()) 34 Out << '.' << *Build; 35 return Out; 36 } 37 38 static bool parseInt(StringRef &input, unsigned &value) { 39 assert(value == 0); 40 if (input.empty()) 41 return true; 42 43 char next = input[0]; 44 input = input.substr(1); 45 if (next < '0' || next > '9') 46 return true; 47 value = (unsigned)(next - '0'); 48 49 while (!input.empty()) { 50 next = input[0]; 51 if (next < '0' || next > '9') 52 return false; 53 input = input.substr(1); 54 value = value * 10 + (unsigned)(next - '0'); 55 } 56 57 return false; 58 } 59 60 bool VersionTuple::tryParse(StringRef input) { 61 unsigned major = 0, minor = 0, micro = 0, build = 0; 62 63 // Parse the major version, [0-9]+ 64 if (parseInt(input, major)) 65 return true; 66 67 if (input.empty()) { 68 *this = VersionTuple(major); 69 return false; 70 } 71 72 // If we're not done, parse the minor version, \.[0-9]+ 73 if (input[0] != '.') 74 return true; 75 input = input.substr(1); 76 if (parseInt(input, minor)) 77 return true; 78 79 if (input.empty()) { 80 *this = VersionTuple(major, minor); 81 return false; 82 } 83 84 // If we're not done, parse the micro version, \.[0-9]+ 85 if (input[0] != '.') 86 return true; 87 input = input.substr(1); 88 if (parseInt(input, micro)) 89 return true; 90 91 if (input.empty()) { 92 *this = VersionTuple(major, minor, micro); 93 return false; 94 } 95 96 // If we're not done, parse the micro version, \.[0-9]+ 97 if (input[0] != '.') 98 return true; 99 input = input.substr(1); 100 if (parseInt(input, build)) 101 return true; 102 103 // If we have characters left over, it's an error. 104 if (!input.empty()) 105 return true; 106 107 *this = VersionTuple(major, minor, micro, build); 108 return false; 109 } 110