xref: /src/contrib/llvm-project/llvm/lib/TextAPI/PackedVersion.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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