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