| //===-- 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; |
| } |