10a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor//===- VersionTuple.cpp - Version Number Handling ---------------*- C++ -*-===//
20a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor//
30a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor//                     The LLVM Compiler Infrastructure
40a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor//
50a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor// This file is distributed under the University of Illinois Open Source
60a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor// License. See LICENSE.TXT for details.
70a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor//
80a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor//===----------------------------------------------------------------------===//
90a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor//
100a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor// This file implements the VersionTuple class, which represents a version in
110a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor// the form major[.minor[.subminor]].
120a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor//
130a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor//===----------------------------------------------------------------------===//
140a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor#include "clang/Basic/VersionTuple.h"
150a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor#include "llvm/Support/raw_ostream.h"
160a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor
170a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregorusing namespace clang;
180a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor
190a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregorstd::string VersionTuple::getAsString() const {
200a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor  std::string Result;
210a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor  {
220a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor    llvm::raw_string_ostream Out(Result);
230a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor    Out << *this;
240a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor  }
250a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor  return Result;
260a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor}
270a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor
285f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerraw_ostream& clang::operator<<(raw_ostream &Out,
290a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor                                     const VersionTuple &V) {
300a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor  Out << V.getMajor();
31dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie  if (Optional<unsigned> Minor = V.getMinor())
32176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    Out << (V.usesUnderscores() ? '_' : '.') << *Minor;
33dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie  if (Optional<unsigned> Subminor = V.getSubminor())
34176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    Out << (V.usesUnderscores() ? '_' : '.') << *Subminor;
353ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  if (Optional<unsigned> Build = V.getBuild())
363ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    Out << (V.usesUnderscores() ? '_' : '.') << *Build;
370a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor  return Out;
380a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor}
39260611a32535c851237926bfcf78869b13c07d5bJohn McCall
40260611a32535c851237926bfcf78869b13c07d5bJohn McCallstatic bool parseInt(StringRef &input, unsigned &value) {
41260611a32535c851237926bfcf78869b13c07d5bJohn McCall  assert(value == 0);
42260611a32535c851237926bfcf78869b13c07d5bJohn McCall  if (input.empty()) return true;
43260611a32535c851237926bfcf78869b13c07d5bJohn McCall
44260611a32535c851237926bfcf78869b13c07d5bJohn McCall  char next = input[0];
45260611a32535c851237926bfcf78869b13c07d5bJohn McCall  input = input.substr(1);
46260611a32535c851237926bfcf78869b13c07d5bJohn McCall  if (next < '0' || next > '9') return true;
47260611a32535c851237926bfcf78869b13c07d5bJohn McCall  value = (unsigned) (next - '0');
48260611a32535c851237926bfcf78869b13c07d5bJohn McCall
49260611a32535c851237926bfcf78869b13c07d5bJohn McCall  while (!input.empty()) {
50260611a32535c851237926bfcf78869b13c07d5bJohn McCall    next = input[0];
51260611a32535c851237926bfcf78869b13c07d5bJohn McCall    if (next < '0' || next > '9') return false;
52260611a32535c851237926bfcf78869b13c07d5bJohn McCall    input = input.substr(1);
53260611a32535c851237926bfcf78869b13c07d5bJohn McCall    value = value * 10 + (unsigned) (next - '0');
54260611a32535c851237926bfcf78869b13c07d5bJohn McCall  }
55260611a32535c851237926bfcf78869b13c07d5bJohn McCall
56260611a32535c851237926bfcf78869b13c07d5bJohn McCall  return false;
57260611a32535c851237926bfcf78869b13c07d5bJohn McCall}
58260611a32535c851237926bfcf78869b13c07d5bJohn McCall
59260611a32535c851237926bfcf78869b13c07d5bJohn McCallbool VersionTuple::tryParse(StringRef input) {
603ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  unsigned major = 0, minor = 0, micro = 0, build = 0;
61260611a32535c851237926bfcf78869b13c07d5bJohn McCall
62260611a32535c851237926bfcf78869b13c07d5bJohn McCall  // Parse the major version, [0-9]+
63260611a32535c851237926bfcf78869b13c07d5bJohn McCall  if (parseInt(input, major)) return true;
64260611a32535c851237926bfcf78869b13c07d5bJohn McCall
65260611a32535c851237926bfcf78869b13c07d5bJohn McCall  if (input.empty()) {
66260611a32535c851237926bfcf78869b13c07d5bJohn McCall    *this = VersionTuple(major);
67260611a32535c851237926bfcf78869b13c07d5bJohn McCall    return false;
68260611a32535c851237926bfcf78869b13c07d5bJohn McCall  }
69260611a32535c851237926bfcf78869b13c07d5bJohn McCall
70260611a32535c851237926bfcf78869b13c07d5bJohn McCall  // If we're not done, parse the minor version, \.[0-9]+
71260611a32535c851237926bfcf78869b13c07d5bJohn McCall  if (input[0] != '.') return true;
72260611a32535c851237926bfcf78869b13c07d5bJohn McCall  input = input.substr(1);
73260611a32535c851237926bfcf78869b13c07d5bJohn McCall  if (parseInt(input, minor)) return true;
74260611a32535c851237926bfcf78869b13c07d5bJohn McCall
75260611a32535c851237926bfcf78869b13c07d5bJohn McCall  if (input.empty()) {
76260611a32535c851237926bfcf78869b13c07d5bJohn McCall    *this = VersionTuple(major, minor);
77260611a32535c851237926bfcf78869b13c07d5bJohn McCall    return false;
78260611a32535c851237926bfcf78869b13c07d5bJohn McCall  }
79260611a32535c851237926bfcf78869b13c07d5bJohn McCall
80260611a32535c851237926bfcf78869b13c07d5bJohn McCall  // If we're not done, parse the micro version, \.[0-9]+
81260611a32535c851237926bfcf78869b13c07d5bJohn McCall  if (input[0] != '.') return true;
82260611a32535c851237926bfcf78869b13c07d5bJohn McCall  input = input.substr(1);
83260611a32535c851237926bfcf78869b13c07d5bJohn McCall  if (parseInt(input, micro)) return true;
84260611a32535c851237926bfcf78869b13c07d5bJohn McCall
853ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  if (input.empty()) {
863ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    *this = VersionTuple(major, minor, micro);
873ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    return false;
883ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  }
893ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
903ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // If we're not done, parse the micro version, \.[0-9]+
913ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  if (input[0] != '.') return true;
923ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  input = input.substr(1);
933ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  if (parseInt(input, build)) return true;
943ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
95260611a32535c851237926bfcf78869b13c07d5bJohn McCall  // If we have characters left over, it's an error.
96260611a32535c851237926bfcf78869b13c07d5bJohn McCall  if (!input.empty()) return true;
97260611a32535c851237926bfcf78869b13c07d5bJohn McCall
983ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  *this = VersionTuple(major, minor, micro, build);
99260611a32535c851237926bfcf78869b13c07d5bJohn McCall  return false;
100260611a32535c851237926bfcf78869b13c07d5bJohn McCall}
101