Home | History | Annotate | Download | only in Basic
      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 "clang/Basic/VersionTuple.h"
     15 #include "llvm/Support/raw_ostream.h"
     16 
     17 using namespace clang;
     18 
     19 std::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 
     28 raw_ostream& clang::operator<<(raw_ostream &Out,
     29                                      const VersionTuple &V) {
     30   Out << V.getMajor();
     31   if (Optional<unsigned> Minor = V.getMinor())
     32     Out << (V.usesUnderscores() ? '_' : '.') << *Minor;
     33   if (Optional<unsigned> Subminor = V.getSubminor())
     34     Out << (V.usesUnderscores() ? '_' : '.') << *Subminor;
     35   if (Optional<unsigned> Build = V.getBuild())
     36     Out << (V.usesUnderscores() ? '_' : '.') << *Build;
     37   return Out;
     38 }
     39 
     40 static bool parseInt(StringRef &input, unsigned &value) {
     41   assert(value == 0);
     42   if (input.empty()) return true;
     43 
     44   char next = input[0];
     45   input = input.substr(1);
     46   if (next < '0' || next > '9') return true;
     47   value = (unsigned) (next - '0');
     48 
     49   while (!input.empty()) {
     50     next = input[0];
     51     if (next < '0' || next > '9') return false;
     52     input = input.substr(1);
     53     value = value * 10 + (unsigned) (next - '0');
     54   }
     55 
     56   return false;
     57 }
     58 
     59 bool VersionTuple::tryParse(StringRef input) {
     60   unsigned major = 0, minor = 0, micro = 0, build = 0;
     61 
     62   // Parse the major version, [0-9]+
     63   if (parseInt(input, major)) return true;
     64 
     65   if (input.empty()) {
     66     *this = VersionTuple(major);
     67     return false;
     68   }
     69 
     70   // If we're not done, parse the minor version, \.[0-9]+
     71   if (input[0] != '.') return true;
     72   input = input.substr(1);
     73   if (parseInt(input, minor)) return true;
     74 
     75   if (input.empty()) {
     76     *this = VersionTuple(major, minor);
     77     return false;
     78   }
     79 
     80   // If we're not done, parse the micro version, \.[0-9]+
     81   if (input[0] != '.') return true;
     82   input = input.substr(1);
     83   if (parseInt(input, micro)) return true;
     84 
     85   if (input.empty()) {
     86     *this = VersionTuple(major, minor, micro);
     87     return false;
     88   }
     89 
     90   // If we're not done, parse the micro version, \.[0-9]+
     91   if (input[0] != '.') return true;
     92   input = input.substr(1);
     93   if (parseInt(input, build)) return true;
     94 
     95   // If we have characters left over, it's an error.
     96   if (!input.empty()) return true;
     97 
     98   *this = VersionTuple(major, minor, micro, build);
     99   return false;
    100 }
    101