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