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