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/SmallString.h" 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/ADT/StringExtras.h" 17 #include "llvm/Support/Format.h" 18 #include "llvm/Support/raw_ostream.h" 19 20 namespace llvm { 21 namespace MachO { 22 23 bool PackedVersion::parse32(StringRef Str) { 24 Version = 0; 25 26 if (Str.empty()) 27 return false; 28 29 SmallVector<StringRef, 3> Parts; 30 SplitString(Str, Parts, "."); 31 32 if (Parts.size() > 3) 33 return false; 34 35 unsigned long long Num; 36 if (getAsUnsignedInteger(Parts[0], 10, Num)) 37 return false; 38 39 if (Num > UINT16_MAX) 40 return false; 41 42 Version = Num << 16; 43 44 for (unsigned i = 1, ShiftNum = 8; i < Parts.size(); ++i, ShiftNum -= 8) { 45 if (getAsUnsignedInteger(Parts[i], 10, Num)) 46 return false; 47 48 if (Num > UINT8_MAX) 49 return false; 50 51 Version |= (Num << ShiftNum); 52 } 53 54 return true; 55 } 56 57 std::pair<bool, bool> PackedVersion::parse64(StringRef Str) { 58 bool Truncated = false; 59 Version = 0; 60 61 if (Str.empty()) 62 return std::make_pair(false, Truncated); 63 64 SmallVector<StringRef, 5> Parts; 65 SplitString(Str, Parts, "."); 66 67 if (Parts.size() > 5) 68 return std::make_pair(false, Truncated); 69 70 unsigned long long Num; 71 if (getAsUnsignedInteger(Parts[0], 10, Num)) 72 return std::make_pair(false, Truncated); 73 74 if (Num > 0xFFFFFFULL) 75 return std::make_pair(false, Truncated); 76 77 if (Num > 0xFFFFULL) { 78 Num = 0xFFFFULL; 79 Truncated = true; 80 } 81 Version = Num << 16; 82 83 for (unsigned i = 1, ShiftNum = 8; i < Parts.size() && i < 3; 84 ++i, ShiftNum -= 8) { 85 if (getAsUnsignedInteger(Parts[i], 10, Num)) 86 return std::make_pair(false, Truncated); 87 88 if (Num > 0x3FFULL) 89 return std::make_pair(false, Truncated); 90 91 if (Num > 0xFFULL) { 92 Num = 0xFFULL; 93 Truncated = true; 94 } 95 Version |= (Num << ShiftNum); 96 } 97 98 if (Parts.size() > 3) 99 Truncated = true; 100 101 return std::make_pair(true, Truncated); 102 } 103 104 void PackedVersion::print(raw_ostream &OS) const { 105 OS << format("%d", getMajor()); 106 if (getMinor() || getSubminor()) 107 OS << format(".%d", getMinor()); 108 if (getSubminor()) 109 OS << format(".%d", getSubminor()); 110 } 111 112 } // end namespace MachO. 113 } // end namespace llvm. 114