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