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