xref: /freebsd/contrib/llvm-project/llvm/lib/TextAPI/PackedVersion.cpp (revision 20917cac7bcf216225a7b66f7b3a56f3764c5acc)
1  //===- PackedVersion.cpp --------------------------------------------------===//
2  //
3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  // See https://llvm.org/LICENSE.txt for license information.
5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  //
7  //===----------------------------------------------------------------------===//
8  //
9  // Implements the Mach-O packed version.
10  //
11  //===----------------------------------------------------------------------===//
12  
13  #include "llvm/TextAPI/PackedVersion.h"
14  #include "llvm/ADT/SmallString.h"
15  #include "llvm/ADT/SmallVector.h"
16  #include "llvm/ADT/StringExtras.h"
17  #include "llvm/Support/Format.h"
18  #include "llvm/Support/raw_ostream.h"
19  
20  namespace llvm {
21  namespace MachO {
22  
23  bool PackedVersion::parse32(StringRef Str) {
24    Version = 0;
25  
26    if (Str.empty())
27      return false;
28  
29    SmallVector<StringRef, 3> Parts;
30    SplitString(Str, Parts, ".");
31  
32    if (Parts.size() > 3)
33      return false;
34  
35    unsigned long long Num;
36    if (getAsUnsignedInteger(Parts[0], 10, Num))
37      return false;
38  
39    if (Num > UINT16_MAX)
40      return false;
41  
42    Version = Num << 16;
43  
44    for (unsigned i = 1, ShiftNum = 8; i < Parts.size(); ++i, ShiftNum -= 8) {
45      if (getAsUnsignedInteger(Parts[i], 10, Num))
46        return false;
47  
48      if (Num > UINT8_MAX)
49        return false;
50  
51      Version |= (Num << ShiftNum);
52    }
53  
54    return true;
55  }
56  
57  std::pair<bool, bool> PackedVersion::parse64(StringRef Str) {
58    bool Truncated = false;
59    Version = 0;
60  
61    if (Str.empty())
62      return std::make_pair(false, Truncated);
63  
64    SmallVector<StringRef, 5> Parts;
65    SplitString(Str, Parts, ".");
66  
67    if (Parts.size() > 5)
68      return std::make_pair(false, Truncated);
69  
70    unsigned long long Num;
71    if (getAsUnsignedInteger(Parts[0], 10, Num))
72      return std::make_pair(false, Truncated);
73  
74    if (Num > 0xFFFFFFULL)
75      return std::make_pair(false, Truncated);
76  
77    if (Num > 0xFFFFULL) {
78      Num = 0xFFFFULL;
79      Truncated = true;
80    }
81    Version = Num << 16;
82  
83    for (unsigned i = 1, ShiftNum = 8; i < Parts.size() && i < 3;
84         ++i, ShiftNum -= 8) {
85      if (getAsUnsignedInteger(Parts[i], 10, Num))
86        return std::make_pair(false, Truncated);
87  
88      if (Num > 0x3FFULL)
89        return std::make_pair(false, Truncated);
90  
91      if (Num > 0xFFULL) {
92        Num = 0xFFULL;
93        Truncated = true;
94      }
95      Version |= (Num << ShiftNum);
96    }
97  
98    if (Parts.size() > 3)
99      Truncated = true;
100  
101    return std::make_pair(true, Truncated);
102  }
103  
104  void PackedVersion::print(raw_ostream &OS) const {
105    OS << format("%d", getMajor());
106    if (getMinor() || getSubminor())
107      OS << format(".%d", getMinor());
108    if (getSubminor())
109      OS << format(".%d", getSubminor());
110  }
111  
112  } // end namespace MachO.
113  } // end namespace llvm.
114