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