VersionTuple.cpp revision 341825
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
17using namespace llvm;
18
19std::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
28raw_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
39static 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
61bool 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