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