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