xref: /freebsd/contrib/llvm-project/llvm/lib/Support/VersionTuple.cpp (revision 7a65641922f404b84e9a249d48593de84d8e8d17)
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  
19  using namespace llvm;
20  
21  std::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  
30  raw_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  
41  static 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  
63  bool 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