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