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