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 19 namespace llvm { 20 namespace MachO { 21 22 bool PackedVersion::parse32(StringRef Str) { 23 Version = 0; 24 25 if (Str.empty()) 26 return false; 27 28 SmallVector<StringRef, 3> Parts; 29 SplitString(Str, Parts, "."); 30 31 if (Parts.size() > 3) 32 return false; 33 34 unsigned long long Num; 35 if (getAsUnsignedInteger(Parts[0], 10, 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(Parts[i], 10, 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 56 std::pair<bool, bool> PackedVersion::parse64(StringRef Str) { 57 bool Truncated = false; 58 Version = 0; 59 60 if (Str.empty()) 61 return std::make_pair(false, Truncated); 62 63 SmallVector<StringRef, 5> Parts; 64 SplitString(Str, Parts, "."); 65 66 if (Parts.size() > 5) 67 return std::make_pair(false, Truncated); 68 69 unsigned long long Num; 70 if (getAsUnsignedInteger(Parts[0], 10, Num)) 71 return std::make_pair(false, Truncated); 72 73 if (Num > 0xFFFFFFULL) 74 return std::make_pair(false, 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(Parts[i], 10, Num)) 85 return std::make_pair(false, Truncated); 86 87 if (Num > 0x3FFULL) 88 return std::make_pair(false, 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(true, Truncated); 101 } 102 103 PackedVersion::operator std::string() const { 104 SmallString<32> Str; 105 raw_svector_ostream OS(Str); 106 print(OS); 107 return std::string(Str); 108 } 109 110 void PackedVersion::print(raw_ostream &OS) const { 111 OS << format("%d", getMajor()); 112 if (getMinor() || getSubminor()) 113 OS << format(".%d", getMinor()); 114 if (getSubminor()) 115 OS << format(".%d", getSubminor()); 116 } 117 118 } // end namespace MachO. 119 } // end namespace llvm. 120