blob: d22b136632148d01dde59bcccd09d5d2788022b9 [file] [log] [blame]
//===-- LVSupport.cpp -----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This implements the supporting functions.
//
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/LogicalView/Core/LVSupport.h"
#include "llvm/Support/FormatVariadic.h"
using namespace llvm;
using namespace llvm::logicalview;
#define DEBUG_TYPE "Support"
namespace {
// Unique string pool instance used by all logical readers.
LVStringPool StringPool;
} // namespace
LVStringPool &llvm::logicalview::getStringPool() { return StringPool; }
// Perform the following transformations to the given 'Path':
// - all characters to lowercase.
// - '\\' into '/' (Platform independent).
// - '//' into '/'
std::string llvm::logicalview::transformPath(StringRef Path) {
std::string Name(Path);
llvm::transform(Name, Name.begin(), tolower);
llvm::replace(Name, '\\', '/');
// Remove all duplicate slashes.
size_t Pos = 0;
while ((Pos = Name.find("//", Pos)) != std::string::npos)
Name.erase(Pos, 1);
return Name;
}
// Convert the given 'Path' to lowercase and change any matching character
// from 'CharSet' into '_'.
// The characters in 'CharSet' are:
// '/', '\', '<', '>', '.', ':', '%', '*', '?', '|', '"', ' '.
std::string llvm::logicalview::flattenedFilePath(StringRef Path) {
std::string Name(Path);
llvm::transform(Name, Name.begin(), tolower);
const char *CharSet = "/\\<>.:%*?|\" ";
char *Input = Name.data();
while (Input && *Input) {
Input = strpbrk(Input, CharSet);
if (Input)
*Input++ = '_';
};
return Name;
}
using LexicalEntry = std::pair<size_t, size_t>;
using LexicalIndexes = SmallVector<LexicalEntry, 10>;
static LexicalIndexes getAllLexicalIndexes(StringRef Name) {
if (Name.empty())
return {};
size_t AngleCount = 0;
size_t ColonSeen = 0;
size_t Current = 0;
LexicalIndexes Indexes;
#ifndef NDEBUG
auto PrintLexicalEntry = [&]() {
LexicalEntry Entry = Indexes.back();
llvm::dbgs() << formatv(
"'{0}:{1}', '{2}'\n", Entry.first, Entry.second,
Name.substr(Entry.first, Entry.second - Entry.first + 1));
};
#endif
size_t Length = Name.size();
for (size_t Index = 0; Index < Length; ++Index) {
LLVM_DEBUG({
llvm::dbgs() << formatv("Index: '{0}', Char: '{1}'\n", Index,
Name[Index]);
});
switch (Name[Index]) {
case '<':
++AngleCount;
break;
case '>':
--AngleCount;
break;
case ':':
++ColonSeen;
break;
}
if (ColonSeen == 2) {
if (!AngleCount) {
Indexes.push_back(LexicalEntry(Current, Index - 2));
Current = Index + 1;
LLVM_DEBUG({ PrintLexicalEntry(); });
}
ColonSeen = 0;
continue;
}
}
// Store last component.
Indexes.push_back(LexicalEntry(Current, Length - 1));
LLVM_DEBUG({ PrintLexicalEntry(); });
return Indexes;
}
LVLexicalComponent llvm::logicalview::getInnerComponent(StringRef Name) {
if (Name.empty())
return {};
LexicalIndexes Indexes = getAllLexicalIndexes(Name);
if (Indexes.size() == 1)
return std::make_tuple(StringRef(), Name);
LexicalEntry BeginEntry = Indexes.front();
LexicalEntry EndEntry = Indexes[Indexes.size() - 2];
StringRef Outer =
Name.substr(BeginEntry.first, EndEntry.second - BeginEntry.first + 1);
LexicalEntry LastEntry = Indexes.back();
StringRef Inner =
Name.substr(LastEntry.first, LastEntry.second - LastEntry.first + 1);
return std::make_tuple(Outer, Inner);
}
LVStringRefs llvm::logicalview::getAllLexicalComponents(StringRef Name) {
if (Name.empty())
return {};
LexicalIndexes Indexes = getAllLexicalIndexes(Name);
LVStringRefs Components;
for (const LexicalEntry &Entry : Indexes)
Components.push_back(
Name.substr(Entry.first, Entry.second - Entry.first + 1));
return Components;
}
std::string llvm::logicalview::getScopedName(const LVStringRefs &Components,
StringRef BaseName) {
if (Components.empty())
return {};
std::string Name(BaseName);
raw_string_ostream Stream(Name);
if (BaseName.size())
Stream << "::";
Stream << Components[0];
for (LVStringRefs::size_type Index = 1; Index < Components.size(); ++Index)
Stream << "::" << Components[Index];
return Name;
}