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