xref: /llvm-project/llvm/lib/TextAPI/PackedVersion.cpp (revision f9fe6032cd6fd0814a15dfddf3116494ffa46ac7)
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