xref: /netbsd-src/external/apache2/llvm/dist/llvm/lib/Support/VersionTuple.cpp (revision 82d56013d7b633d116a93943de88e08335357a7c)
17330f729Sjoerg //===- VersionTuple.cpp - Version Number Handling ---------------*- C++ -*-===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file implements the VersionTuple class, which represents a version in
107330f729Sjoerg // the form major[.minor[.subminor]].
117330f729Sjoerg //
127330f729Sjoerg //===----------------------------------------------------------------------===//
13*82d56013Sjoerg 
147330f729Sjoerg #include "llvm/Support/VersionTuple.h"
15*82d56013Sjoerg #include "llvm/ADT/StringRef.h"
167330f729Sjoerg #include "llvm/Support/raw_ostream.h"
17*82d56013Sjoerg #include <cassert>
187330f729Sjoerg 
197330f729Sjoerg using namespace llvm;
207330f729Sjoerg 
getAsString() const217330f729Sjoerg std::string VersionTuple::getAsString() const {
227330f729Sjoerg   std::string Result;
237330f729Sjoerg   {
247330f729Sjoerg     llvm::raw_string_ostream Out(Result);
257330f729Sjoerg     Out << *this;
267330f729Sjoerg   }
277330f729Sjoerg   return Result;
287330f729Sjoerg }
297330f729Sjoerg 
operator <<(raw_ostream & Out,const VersionTuple & V)307330f729Sjoerg raw_ostream &llvm::operator<<(raw_ostream &Out, const VersionTuple &V) {
317330f729Sjoerg   Out << V.getMajor();
327330f729Sjoerg   if (Optional<unsigned> Minor = V.getMinor())
337330f729Sjoerg     Out << '.' << *Minor;
347330f729Sjoerg   if (Optional<unsigned> Subminor = V.getSubminor())
357330f729Sjoerg     Out << '.' << *Subminor;
367330f729Sjoerg   if (Optional<unsigned> Build = V.getBuild())
377330f729Sjoerg     Out << '.' << *Build;
387330f729Sjoerg   return Out;
397330f729Sjoerg }
407330f729Sjoerg 
parseInt(StringRef & input,unsigned & value)417330f729Sjoerg static bool parseInt(StringRef &input, unsigned &value) {
427330f729Sjoerg   assert(value == 0);
437330f729Sjoerg   if (input.empty())
447330f729Sjoerg     return true;
457330f729Sjoerg 
467330f729Sjoerg   char next = input[0];
477330f729Sjoerg   input = input.substr(1);
487330f729Sjoerg   if (next < '0' || next > '9')
497330f729Sjoerg     return true;
507330f729Sjoerg   value = (unsigned)(next - '0');
517330f729Sjoerg 
527330f729Sjoerg   while (!input.empty()) {
537330f729Sjoerg     next = input[0];
547330f729Sjoerg     if (next < '0' || next > '9')
557330f729Sjoerg       return false;
567330f729Sjoerg     input = input.substr(1);
577330f729Sjoerg     value = value * 10 + (unsigned)(next - '0');
587330f729Sjoerg   }
597330f729Sjoerg 
607330f729Sjoerg   return false;
617330f729Sjoerg }
627330f729Sjoerg 
tryParse(StringRef input)637330f729Sjoerg bool VersionTuple::tryParse(StringRef input) {
647330f729Sjoerg   unsigned major = 0, minor = 0, micro = 0, build = 0;
657330f729Sjoerg 
667330f729Sjoerg   // Parse the major version, [0-9]+
677330f729Sjoerg   if (parseInt(input, major))
687330f729Sjoerg     return true;
697330f729Sjoerg 
707330f729Sjoerg   if (input.empty()) {
717330f729Sjoerg     *this = VersionTuple(major);
727330f729Sjoerg     return false;
737330f729Sjoerg   }
747330f729Sjoerg 
757330f729Sjoerg   // If we're not done, parse the minor version, \.[0-9]+
767330f729Sjoerg   if (input[0] != '.')
777330f729Sjoerg     return true;
787330f729Sjoerg   input = input.substr(1);
797330f729Sjoerg   if (parseInt(input, minor))
807330f729Sjoerg     return true;
817330f729Sjoerg 
827330f729Sjoerg   if (input.empty()) {
837330f729Sjoerg     *this = VersionTuple(major, minor);
847330f729Sjoerg     return false;
857330f729Sjoerg   }
867330f729Sjoerg 
877330f729Sjoerg   // If we're not done, parse the micro version, \.[0-9]+
887330f729Sjoerg   if (input[0] != '.')
897330f729Sjoerg     return true;
907330f729Sjoerg   input = input.substr(1);
917330f729Sjoerg   if (parseInt(input, micro))
927330f729Sjoerg     return true;
937330f729Sjoerg 
947330f729Sjoerg   if (input.empty()) {
957330f729Sjoerg     *this = VersionTuple(major, minor, micro);
967330f729Sjoerg     return false;
977330f729Sjoerg   }
987330f729Sjoerg 
997330f729Sjoerg   // If we're not done, parse the micro version, \.[0-9]+
1007330f729Sjoerg   if (input[0] != '.')
1017330f729Sjoerg     return true;
1027330f729Sjoerg   input = input.substr(1);
1037330f729Sjoerg   if (parseInt(input, build))
1047330f729Sjoerg     return true;
1057330f729Sjoerg 
1067330f729Sjoerg   // If we have characters left over, it's an error.
1077330f729Sjoerg   if (!input.empty())
1087330f729Sjoerg     return true;
1097330f729Sjoerg 
1107330f729Sjoerg   *this = VersionTuple(major, minor, micro, build);
1117330f729Sjoerg   return false;
1127330f729Sjoerg }
113