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