1f4a2713aSLionel Sambuc //===- VersionTuple.cpp - Version Number Handling ---------------*- C++ -*-===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file implements the VersionTuple class, which represents a version in
11f4a2713aSLionel Sambuc // the form major[.minor[.subminor]].
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc #include "clang/Basic/VersionTuple.h"
15f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
16f4a2713aSLionel Sambuc
17f4a2713aSLionel Sambuc using namespace clang;
18f4a2713aSLionel Sambuc
getAsString() const19f4a2713aSLionel Sambuc std::string VersionTuple::getAsString() const {
20f4a2713aSLionel Sambuc std::string Result;
21f4a2713aSLionel Sambuc {
22f4a2713aSLionel Sambuc llvm::raw_string_ostream Out(Result);
23f4a2713aSLionel Sambuc Out << *this;
24f4a2713aSLionel Sambuc }
25f4a2713aSLionel Sambuc return Result;
26f4a2713aSLionel Sambuc }
27f4a2713aSLionel Sambuc
operator <<(raw_ostream & Out,const VersionTuple & V)28f4a2713aSLionel Sambuc raw_ostream& clang::operator<<(raw_ostream &Out,
29f4a2713aSLionel Sambuc const VersionTuple &V) {
30f4a2713aSLionel Sambuc Out << V.getMajor();
31f4a2713aSLionel Sambuc if (Optional<unsigned> Minor = V.getMinor())
32*0a6a1f1dSLionel Sambuc Out << (V.usesUnderscores() ? '_' : '.') << *Minor;
33f4a2713aSLionel Sambuc if (Optional<unsigned> Subminor = V.getSubminor())
34*0a6a1f1dSLionel Sambuc Out << (V.usesUnderscores() ? '_' : '.') << *Subminor;
35f4a2713aSLionel Sambuc return Out;
36f4a2713aSLionel Sambuc }
37f4a2713aSLionel Sambuc
parseInt(StringRef & input,unsigned & value)38f4a2713aSLionel Sambuc static bool parseInt(StringRef &input, unsigned &value) {
39f4a2713aSLionel Sambuc assert(value == 0);
40f4a2713aSLionel Sambuc if (input.empty()) return true;
41f4a2713aSLionel Sambuc
42f4a2713aSLionel Sambuc char next = input[0];
43f4a2713aSLionel Sambuc input = input.substr(1);
44f4a2713aSLionel Sambuc if (next < '0' || next > '9') return true;
45f4a2713aSLionel Sambuc value = (unsigned) (next - '0');
46f4a2713aSLionel Sambuc
47f4a2713aSLionel Sambuc while (!input.empty()) {
48f4a2713aSLionel Sambuc next = input[0];
49f4a2713aSLionel Sambuc if (next < '0' || next > '9') return false;
50f4a2713aSLionel Sambuc input = input.substr(1);
51f4a2713aSLionel Sambuc value = value * 10 + (unsigned) (next - '0');
52f4a2713aSLionel Sambuc }
53f4a2713aSLionel Sambuc
54f4a2713aSLionel Sambuc return false;
55f4a2713aSLionel Sambuc }
56f4a2713aSLionel Sambuc
tryParse(StringRef input)57f4a2713aSLionel Sambuc bool VersionTuple::tryParse(StringRef input) {
58f4a2713aSLionel Sambuc unsigned major = 0, minor = 0, micro = 0;
59f4a2713aSLionel Sambuc
60f4a2713aSLionel Sambuc // Parse the major version, [0-9]+
61f4a2713aSLionel Sambuc if (parseInt(input, major)) return true;
62f4a2713aSLionel Sambuc
63f4a2713aSLionel Sambuc if (input.empty()) {
64f4a2713aSLionel Sambuc *this = VersionTuple(major);
65f4a2713aSLionel Sambuc return false;
66f4a2713aSLionel Sambuc }
67f4a2713aSLionel Sambuc
68f4a2713aSLionel Sambuc // If we're not done, parse the minor version, \.[0-9]+
69f4a2713aSLionel Sambuc if (input[0] != '.') return true;
70f4a2713aSLionel Sambuc input = input.substr(1);
71f4a2713aSLionel Sambuc if (parseInt(input, minor)) return true;
72f4a2713aSLionel Sambuc
73f4a2713aSLionel Sambuc if (input.empty()) {
74f4a2713aSLionel Sambuc *this = VersionTuple(major, minor);
75f4a2713aSLionel Sambuc return false;
76f4a2713aSLionel Sambuc }
77f4a2713aSLionel Sambuc
78f4a2713aSLionel Sambuc // If we're not done, parse the micro version, \.[0-9]+
79f4a2713aSLionel Sambuc if (input[0] != '.') return true;
80f4a2713aSLionel Sambuc input = input.substr(1);
81f4a2713aSLionel Sambuc if (parseInt(input, micro)) return true;
82f4a2713aSLionel Sambuc
83f4a2713aSLionel Sambuc // If we have characters left over, it's an error.
84f4a2713aSLionel Sambuc if (!input.empty()) return true;
85f4a2713aSLionel Sambuc
86f4a2713aSLionel Sambuc *this = VersionTuple(major, minor, micro);
87f4a2713aSLionel Sambuc return false;
88f4a2713aSLionel Sambuc }
89