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