1221339Sdim//===- VersionTuple.cpp - Version Number Handling ---------------*- C++ -*-===// 2221339Sdim// 3221339Sdim// The LLVM Compiler Infrastructure 4221339Sdim// 5221339Sdim// This file is distributed under the University of Illinois Open Source 6221339Sdim// License. See LICENSE.TXT for details. 7221339Sdim// 8221339Sdim//===----------------------------------------------------------------------===// 9221339Sdim// 10221339Sdim// This file implements the VersionTuple class, which represents a version in 11221339Sdim// the form major[.minor[.subminor]]. 12221339Sdim// 13221339Sdim//===----------------------------------------------------------------------===// 14221339Sdim#include "clang/Basic/VersionTuple.h" 15221339Sdim#include "llvm/Support/raw_ostream.h" 16221339Sdim 17221339Sdimusing namespace clang; 18221339Sdim 19221339Sdimstd::string VersionTuple::getAsString() const { 20221339Sdim std::string Result; 21221339Sdim { 22221339Sdim llvm::raw_string_ostream Out(Result); 23221339Sdim Out << *this; 24221339Sdim } 25221339Sdim return Result; 26221339Sdim} 27221339Sdim 28226890Sdimraw_ostream& clang::operator<<(raw_ostream &Out, 29221339Sdim const VersionTuple &V) { 30221339Sdim Out << V.getMajor(); 31252723Sdim if (Optional<unsigned> Minor = V.getMinor()) 32221339Sdim Out << '.' << *Minor; 33252723Sdim if (Optional<unsigned> Subminor = V.getSubminor()) 34221339Sdim Out << '.' << *Subminor; 35221339Sdim return Out; 36221339Sdim} 37245431Sdim 38245431Sdimstatic bool parseInt(StringRef &input, unsigned &value) { 39245431Sdim assert(value == 0); 40245431Sdim if (input.empty()) return true; 41245431Sdim 42245431Sdim char next = input[0]; 43245431Sdim input = input.substr(1); 44245431Sdim if (next < '0' || next > '9') return true; 45245431Sdim value = (unsigned) (next - '0'); 46245431Sdim 47245431Sdim while (!input.empty()) { 48245431Sdim next = input[0]; 49245431Sdim if (next < '0' || next > '9') return false; 50245431Sdim input = input.substr(1); 51245431Sdim value = value * 10 + (unsigned) (next - '0'); 52245431Sdim } 53245431Sdim 54245431Sdim return false; 55245431Sdim} 56245431Sdim 57245431Sdimbool VersionTuple::tryParse(StringRef input) { 58245431Sdim unsigned major = 0, minor = 0, micro = 0; 59245431Sdim 60245431Sdim // Parse the major version, [0-9]+ 61245431Sdim if (parseInt(input, major)) return true; 62245431Sdim 63245431Sdim if (input.empty()) { 64245431Sdim *this = VersionTuple(major); 65245431Sdim return false; 66245431Sdim } 67245431Sdim 68245431Sdim // If we're not done, parse the minor version, \.[0-9]+ 69245431Sdim if (input[0] != '.') return true; 70245431Sdim input = input.substr(1); 71245431Sdim if (parseInt(input, minor)) return true; 72245431Sdim 73245431Sdim if (input.empty()) { 74245431Sdim *this = VersionTuple(major, minor); 75245431Sdim return false; 76245431Sdim } 77245431Sdim 78245431Sdim // If we're not done, parse the micro version, \.[0-9]+ 79245431Sdim if (input[0] != '.') return true; 80245431Sdim input = input.substr(1); 81245431Sdim if (parseInt(input, micro)) return true; 82245431Sdim 83245431Sdim // If we have characters left over, it's an error. 84245431Sdim if (!input.empty()) return true; 85245431Sdim 86245431Sdim *this = VersionTuple(major, minor, micro); 87245431Sdim return false; 88245431Sdim} 89