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 28226633Sdimraw_ostream& clang::operator<<(raw_ostream &Out, 29221339Sdim const VersionTuple &V) { 30221339Sdim Out << V.getMajor(); 31249423Sdim if (Optional<unsigned> Minor = V.getMinor()) 32221339Sdim Out << '.' << *Minor; 33249423Sdim if (Optional<unsigned> Subminor = V.getSubminor()) 34221339Sdim Out << '.' << *Subminor; 35221339Sdim return Out; 36221339Sdim} 37239462Sdim 38239462Sdimstatic bool parseInt(StringRef &input, unsigned &value) { 39239462Sdim assert(value == 0); 40239462Sdim if (input.empty()) return true; 41239462Sdim 42239462Sdim char next = input[0]; 43239462Sdim input = input.substr(1); 44239462Sdim if (next < '0' || next > '9') return true; 45239462Sdim value = (unsigned) (next - '0'); 46239462Sdim 47239462Sdim while (!input.empty()) { 48239462Sdim next = input[0]; 49239462Sdim if (next < '0' || next > '9') return false; 50239462Sdim input = input.substr(1); 51239462Sdim value = value * 10 + (unsigned) (next - '0'); 52239462Sdim } 53239462Sdim 54239462Sdim return false; 55239462Sdim} 56239462Sdim 57239462Sdimbool VersionTuple::tryParse(StringRef input) { 58239462Sdim unsigned major = 0, minor = 0, micro = 0; 59239462Sdim 60239462Sdim // Parse the major version, [0-9]+ 61239462Sdim if (parseInt(input, major)) return true; 62239462Sdim 63239462Sdim if (input.empty()) { 64239462Sdim *this = VersionTuple(major); 65239462Sdim return false; 66239462Sdim } 67239462Sdim 68239462Sdim // If we're not done, parse the minor version, \.[0-9]+ 69239462Sdim if (input[0] != '.') return true; 70239462Sdim input = input.substr(1); 71239462Sdim if (parseInt(input, minor)) return true; 72239462Sdim 73239462Sdim if (input.empty()) { 74239462Sdim *this = VersionTuple(major, minor); 75239462Sdim return false; 76239462Sdim } 77239462Sdim 78239462Sdim // If we're not done, parse the micro version, \.[0-9]+ 79239462Sdim if (input[0] != '.') return true; 80239462Sdim input = input.substr(1); 81239462Sdim if (parseInt(input, micro)) return true; 82239462Sdim 83239462Sdim // If we have characters left over, it's an error. 84239462Sdim if (!input.empty()) return true; 85239462Sdim 86239462Sdim *this = VersionTuple(major, minor, micro); 87239462Sdim return false; 88239462Sdim} 89