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