You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.167
Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
parent
e19d552987
commit
b084638f15
187
external/llvm/tools/dsymutil/CFBundle.cpp
vendored
187
external/llvm/tools/dsymutil/CFBundle.cpp
vendored
@ -1,187 +0,0 @@
|
||||
//===- tools/dsymutil/CFBundle.cpp - CFBundle helper ------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CFBundle.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <assert.h>
|
||||
#include <glob.h>
|
||||
#include <memory>
|
||||
#endif
|
||||
|
||||
namespace llvm {
|
||||
namespace dsymutil {
|
||||
|
||||
#ifdef __APPLE__
|
||||
/// Deleter that calls CFRelease rather than deleting the pointer.
|
||||
template <typename T> struct CFDeleter {
|
||||
void operator()(T *P) {
|
||||
if (P)
|
||||
::CFRelease(P);
|
||||
}
|
||||
};
|
||||
|
||||
/// This helper owns any CoreFoundation pointer and will call CFRelease() on
|
||||
/// any valid pointer it owns unless that pointer is explicitly released using
|
||||
/// the release() member function.
|
||||
template <typename T>
|
||||
using CFReleaser =
|
||||
std::unique_ptr<typename std::remove_pointer<T>::type,
|
||||
CFDeleter<typename std::remove_pointer<T>::type>>;
|
||||
|
||||
/// RAII wrapper around CFBundleRef.
|
||||
class CFString : public CFReleaser<CFStringRef> {
|
||||
public:
|
||||
CFString(CFStringRef CFStr = nullptr) : CFReleaser<CFStringRef>(CFStr) {}
|
||||
|
||||
const char *UTF8(std::string &Str) const {
|
||||
return CFString::UTF8(get(), Str);
|
||||
}
|
||||
|
||||
CFIndex GetLength() const {
|
||||
if (CFStringRef Str = get())
|
||||
return CFStringGetLength(Str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *UTF8(CFStringRef CFStr, std::string &Str);
|
||||
};
|
||||
|
||||
/// Static function that puts a copy of the UTF-8 contents of CFStringRef into
|
||||
/// std::string and returns the C string pointer that is contained in the
|
||||
/// std::string when successful, nullptr otherwise.
|
||||
///
|
||||
/// This allows the std::string parameter to own the extracted string, and also
|
||||
/// allows that string to be returned as a C string pointer that can be used.
|
||||
const char *CFString::UTF8(CFStringRef CFStr, std::string &Str) {
|
||||
if (!CFStr)
|
||||
return nullptr;
|
||||
|
||||
const CFStringEncoding Encoding = kCFStringEncodingUTF8;
|
||||
CFIndex MaxUTF8StrLength = CFStringGetLength(CFStr);
|
||||
MaxUTF8StrLength =
|
||||
CFStringGetMaximumSizeForEncoding(MaxUTF8StrLength, Encoding);
|
||||
if (MaxUTF8StrLength > 0) {
|
||||
Str.resize(MaxUTF8StrLength);
|
||||
if (!Str.empty() &&
|
||||
CFStringGetCString(CFStr, &Str[0], Str.size(), Encoding)) {
|
||||
Str.resize(strlen(Str.c_str()));
|
||||
return Str.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// RAII wrapper around CFBundleRef.
|
||||
class CFBundle : public CFReleaser<CFBundleRef> {
|
||||
public:
|
||||
CFBundle(StringRef Path) : CFReleaser<CFBundleRef>() { SetFromPath(Path); }
|
||||
|
||||
CFBundle(CFURLRef Url)
|
||||
: CFReleaser<CFBundleRef>(Url ? ::CFBundleCreate(nullptr, Url)
|
||||
: nullptr) {}
|
||||
|
||||
/// Return the bundle identifier.
|
||||
CFStringRef GetIdentifier() const {
|
||||
if (CFBundleRef bundle = get())
|
||||
return ::CFBundleGetIdentifier(bundle);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Return value for key.
|
||||
CFTypeRef GetValueForInfoDictionaryKey(CFStringRef key) const {
|
||||
if (CFBundleRef bundle = get())
|
||||
return ::CFBundleGetValueForInfoDictionaryKey(bundle, key);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Helper to initialize this instance with a new bundle created from the
|
||||
/// given path. This function will recursively remove components from the
|
||||
/// path in its search for the nearest Info.plist.
|
||||
void SetFromPath(StringRef Path);
|
||||
};
|
||||
|
||||
void CFBundle::SetFromPath(StringRef Path) {
|
||||
// Start from an empty/invalid CFBundle.
|
||||
reset();
|
||||
|
||||
if (Path.empty() || !sys::fs::exists(Path))
|
||||
return;
|
||||
|
||||
SmallString<256> RealPath;
|
||||
sys::fs::real_path(Path, RealPath, /*expand_tilde*/ true);
|
||||
|
||||
do {
|
||||
// Create a CFURL from the current path and use it to create a CFBundle.
|
||||
CFReleaser<CFURLRef> BundleURL(::CFURLCreateFromFileSystemRepresentation(
|
||||
kCFAllocatorDefault, (const UInt8 *)RealPath.data(), RealPath.size(),
|
||||
false));
|
||||
reset(::CFBundleCreate(kCFAllocatorDefault, BundleURL.get()));
|
||||
|
||||
// If we have a valid bundle and find its identifier we are done.
|
||||
if (get() != nullptr) {
|
||||
if (GetIdentifier() != nullptr)
|
||||
return;
|
||||
reset();
|
||||
}
|
||||
|
||||
// Remove the last component of the path and try again until there's
|
||||
// nothing left but the root.
|
||||
sys::path::remove_filename(RealPath);
|
||||
} while (RealPath != sys::path::root_name(RealPath));
|
||||
}
|
||||
#endif
|
||||
|
||||
/// On Darwin, try and find the original executable's Info.plist to extract
|
||||
/// information about the bundle. Return default values on other platforms.
|
||||
CFBundleInfo getBundleInfo(StringRef ExePath) {
|
||||
CFBundleInfo BundleInfo;
|
||||
|
||||
#ifdef __APPLE__
|
||||
auto PrintError = [&](CFTypeID TypeID) {
|
||||
CFString TypeIDCFStr(::CFCopyTypeIDDescription(TypeID));
|
||||
std::string TypeIDStr;
|
||||
errs() << "The Info.plist key \"CFBundleShortVersionString\" is"
|
||||
<< "a " << TypeIDCFStr.UTF8(TypeIDStr)
|
||||
<< ", but it should be a string in: " << ExePath << ".\n";
|
||||
};
|
||||
|
||||
CFBundle Bundle(ExePath);
|
||||
if (CFStringRef BundleID = Bundle.GetIdentifier()) {
|
||||
CFString::UTF8(BundleID, BundleInfo.IDStr);
|
||||
if (CFTypeRef TypeRef =
|
||||
Bundle.GetValueForInfoDictionaryKey(CFSTR("CFBundleVersion"))) {
|
||||
CFTypeID TypeID = ::CFGetTypeID(TypeRef);
|
||||
if (TypeID == ::CFStringGetTypeID())
|
||||
CFString::UTF8((CFStringRef)TypeRef, BundleInfo.VersionStr);
|
||||
else
|
||||
PrintError(TypeID);
|
||||
}
|
||||
if (CFTypeRef TypeRef = Bundle.GetValueForInfoDictionaryKey(
|
||||
CFSTR("CFBundleShortVersionString"))) {
|
||||
CFTypeID TypeID = ::CFGetTypeID(TypeRef);
|
||||
if (TypeID == ::CFStringGetTypeID())
|
||||
CFString::UTF8((CFStringRef)TypeRef, BundleInfo.ShortVersionStr);
|
||||
else
|
||||
PrintError(TypeID);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return BundleInfo;
|
||||
}
|
||||
|
||||
} // end namespace dsymutil
|
||||
} // end namespace llvm
|
Reference in New Issue
Block a user