10116d04dSCyndy Ishida //===- PackedVersion.cpp --------------------------------------------------===//
20116d04dSCyndy Ishida //
30116d04dSCyndy Ishida // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40116d04dSCyndy Ishida // See https://llvm.org/LICENSE.txt for license information.
50116d04dSCyndy Ishida // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60116d04dSCyndy Ishida //
70116d04dSCyndy Ishida //===----------------------------------------------------------------------===//
80116d04dSCyndy Ishida //
90116d04dSCyndy Ishida // Implements the Mach-O packed version.
100116d04dSCyndy Ishida //
110116d04dSCyndy Ishida //===----------------------------------------------------------------------===//
120116d04dSCyndy Ishida
130116d04dSCyndy Ishida #include "llvm/TextAPI/PackedVersion.h"
140116d04dSCyndy Ishida #include "llvm/ADT/SmallVector.h"
150116d04dSCyndy Ishida #include "llvm/ADT/StringExtras.h"
160116d04dSCyndy Ishida #include "llvm/Support/Format.h"
170116d04dSCyndy Ishida #include "llvm/Support/raw_ostream.h"
180116d04dSCyndy Ishida
190116d04dSCyndy Ishida namespace llvm {
200116d04dSCyndy Ishida namespace MachO {
210116d04dSCyndy Ishida
parse32(StringRef Str)220116d04dSCyndy Ishida bool PackedVersion::parse32(StringRef Str) {
230116d04dSCyndy Ishida Version = 0;
240116d04dSCyndy Ishida
250116d04dSCyndy Ishida if (Str.empty())
260116d04dSCyndy Ishida return false;
270116d04dSCyndy Ishida
280116d04dSCyndy Ishida SmallVector<StringRef, 3> Parts;
290116d04dSCyndy Ishida SplitString(Str, Parts, ".");
300116d04dSCyndy Ishida
31*f9fe6032SCyndy Ishida if (Parts.size() > 3 || Parts.empty())
320116d04dSCyndy Ishida return false;
330116d04dSCyndy Ishida
340116d04dSCyndy Ishida unsigned long long Num;
350116d04dSCyndy Ishida if (getAsUnsignedInteger(Parts[0], 10, Num))
360116d04dSCyndy Ishida return false;
370116d04dSCyndy Ishida
380116d04dSCyndy Ishida if (Num > UINT16_MAX)
390116d04dSCyndy Ishida return false;
400116d04dSCyndy Ishida
410116d04dSCyndy Ishida Version = Num << 16;
420116d04dSCyndy Ishida
430116d04dSCyndy Ishida for (unsigned i = 1, ShiftNum = 8; i < Parts.size(); ++i, ShiftNum -= 8) {
440116d04dSCyndy Ishida if (getAsUnsignedInteger(Parts[i], 10, Num))
450116d04dSCyndy Ishida return false;
460116d04dSCyndy Ishida
470116d04dSCyndy Ishida if (Num > UINT8_MAX)
480116d04dSCyndy Ishida return false;
490116d04dSCyndy Ishida
500116d04dSCyndy Ishida Version |= (Num << ShiftNum);
510116d04dSCyndy Ishida }
520116d04dSCyndy Ishida
530116d04dSCyndy Ishida return true;
540116d04dSCyndy Ishida }
550116d04dSCyndy Ishida
parse64(StringRef Str)560116d04dSCyndy Ishida std::pair<bool, bool> PackedVersion::parse64(StringRef Str) {
570116d04dSCyndy Ishida bool Truncated = false;
580116d04dSCyndy Ishida Version = 0;
590116d04dSCyndy Ishida
600116d04dSCyndy Ishida if (Str.empty())
610116d04dSCyndy Ishida return std::make_pair(false, Truncated);
620116d04dSCyndy Ishida
630116d04dSCyndy Ishida SmallVector<StringRef, 5> Parts;
640116d04dSCyndy Ishida SplitString(Str, Parts, ".");
650116d04dSCyndy Ishida
66*f9fe6032SCyndy Ishida if (Parts.size() > 5 || Parts.empty())
670116d04dSCyndy Ishida return std::make_pair(false, Truncated);
680116d04dSCyndy Ishida
690116d04dSCyndy Ishida unsigned long long Num;
700116d04dSCyndy Ishida if (getAsUnsignedInteger(Parts[0], 10, Num))
710116d04dSCyndy Ishida return std::make_pair(false, Truncated);
720116d04dSCyndy Ishida
730116d04dSCyndy Ishida if (Num > 0xFFFFFFULL)
740116d04dSCyndy Ishida return std::make_pair(false, Truncated);
750116d04dSCyndy Ishida
760116d04dSCyndy Ishida if (Num > 0xFFFFULL) {
770116d04dSCyndy Ishida Num = 0xFFFFULL;
780116d04dSCyndy Ishida Truncated = true;
790116d04dSCyndy Ishida }
800116d04dSCyndy Ishida Version = Num << 16;
810116d04dSCyndy Ishida
820116d04dSCyndy Ishida for (unsigned i = 1, ShiftNum = 8; i < Parts.size() && i < 3;
830116d04dSCyndy Ishida ++i, ShiftNum -= 8) {
840116d04dSCyndy Ishida if (getAsUnsignedInteger(Parts[i], 10, Num))
850116d04dSCyndy Ishida return std::make_pair(false, Truncated);
860116d04dSCyndy Ishida
870116d04dSCyndy Ishida if (Num > 0x3FFULL)
880116d04dSCyndy Ishida return std::make_pair(false, Truncated);
890116d04dSCyndy Ishida
900116d04dSCyndy Ishida if (Num > 0xFFULL) {
910116d04dSCyndy Ishida Num = 0xFFULL;
920116d04dSCyndy Ishida Truncated = true;
930116d04dSCyndy Ishida }
940116d04dSCyndy Ishida Version |= (Num << ShiftNum);
950116d04dSCyndy Ishida }
960116d04dSCyndy Ishida
970116d04dSCyndy Ishida if (Parts.size() > 3)
980116d04dSCyndy Ishida Truncated = true;
990116d04dSCyndy Ishida
1000116d04dSCyndy Ishida return std::make_pair(true, Truncated);
1010116d04dSCyndy Ishida }
1020116d04dSCyndy Ishida
operator std::string() const103d6f9b97bSCyndy Ishida PackedVersion::operator std::string() const {
104d6f9b97bSCyndy Ishida SmallString<32> Str;
105d6f9b97bSCyndy Ishida raw_svector_ostream OS(Str);
106d6f9b97bSCyndy Ishida print(OS);
107d6f9b97bSCyndy Ishida return std::string(Str);
108d6f9b97bSCyndy Ishida }
109d6f9b97bSCyndy Ishida
print(raw_ostream & OS) const1100116d04dSCyndy Ishida void PackedVersion::print(raw_ostream &OS) const {
1110116d04dSCyndy Ishida OS << format("%d", getMajor());
1120116d04dSCyndy Ishida if (getMinor() || getSubminor())
1130116d04dSCyndy Ishida OS << format(".%d", getMinor());
1140116d04dSCyndy Ishida if (getSubminor())
1150116d04dSCyndy Ishida OS << format(".%d", getSubminor());
1160116d04dSCyndy Ishida }
1170116d04dSCyndy Ishida
1180116d04dSCyndy Ishida } // end namespace MachO.
1190116d04dSCyndy Ishida } // end namespace llvm.
120