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