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