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
getAsString() const18 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
operator <<(raw_ostream & Out,const VersionTuple & V)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
parseInt(StringRef & input,unsigned & value)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
tryParse(StringRef input)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