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 14#include "llvm/Support/VersionTuple.h" 15#include "llvm/ADT/StringRef.h" 16#include "llvm/Support/raw_ostream.h" 17#include <cassert> 18 19using namespace llvm; 20 21std::string VersionTuple::getAsString() const { 22 std::string Result; 23 { 24 llvm::raw_string_ostream Out(Result); 25 Out << *this; 26 } 27 return Result; 28} 29 30raw_ostream &llvm::operator<<(raw_ostream &Out, const VersionTuple &V) { 31 Out << V.getMajor(); 32 if (Optional<unsigned> Minor = V.getMinor()) 33 Out << '.' << *Minor; 34 if (Optional<unsigned> Subminor = V.getSubminor()) 35 Out << '.' << *Subminor; 36 if (Optional<unsigned> Build = V.getBuild()) 37 Out << '.' << *Build; 38 return Out; 39} 40 41static bool parseInt(StringRef &input, unsigned &value) { 42 assert(value == 0); 43 if (input.empty()) 44 return true; 45 46 char next = input[0]; 47 input = input.substr(1); 48 if (next < '0' || next > '9') 49 return true; 50 value = (unsigned)(next - '0'); 51 52 while (!input.empty()) { 53 next = input[0]; 54 if (next < '0' || next > '9') 55 return false; 56 input = input.substr(1); 57 value = value * 10 + (unsigned)(next - '0'); 58 } 59 60 return false; 61} 62 63bool VersionTuple::tryParse(StringRef input) { 64 unsigned major = 0, minor = 0, micro = 0, build = 0; 65 66 // Parse the major version, [0-9]+ 67 if (parseInt(input, major)) 68 return true; 69 70 if (input.empty()) { 71 *this = VersionTuple(major); 72 return false; 73 } 74 75 // If we're not done, parse the minor version, \.[0-9]+ 76 if (input[0] != '.') 77 return true; 78 input = input.substr(1); 79 if (parseInt(input, minor)) 80 return true; 81 82 if (input.empty()) { 83 *this = VersionTuple(major, minor); 84 return false; 85 } 86 87 // If we're not done, parse the micro version, \.[0-9]+ 88 if (input[0] != '.') 89 return true; 90 input = input.substr(1); 91 if (parseInt(input, micro)) 92 return true; 93 94 if (input.empty()) { 95 *this = VersionTuple(major, minor, micro); 96 return false; 97 } 98 99 // If we're not done, parse the micro version, \.[0-9]+ 100 if (input[0] != '.') 101 return true; 102 input = input.substr(1); 103 if (parseInt(input, build)) 104 return true; 105 106 // If we have characters left over, it's an error. 107 if (!input.empty()) 108 return true; 109 110 *this = VersionTuple(major, minor, micro, build); 111 return false; 112} 113