1 //===-- LVSupport.cpp -----------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This implements the supporting functions. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/DebugInfo/LogicalView/Core/LVSupport.h" 14 #include "llvm/Support/FormatAdapters.h" 15 #include "llvm/Support/FormatVariadic.h" 16 #include <iomanip> 17 18 using namespace llvm; 19 using namespace llvm::logicalview; 20 21 #define DEBUG_TYPE "Support" 22 23 namespace { 24 // Unique string pool instance used by all logical readers. 25 LVStringPool StringPool; 26 } // namespace 27 LVStringPool &llvm::logicalview::getStringPool() { return StringPool; } 28 29 // Perform the following transformations to the given 'Path': 30 // - all characters to lowercase. 31 // - '\\' into '/' (Platform independent). 32 // - '//' into '/' 33 std::string llvm::logicalview::transformPath(StringRef Path) { 34 std::string Name(Path); 35 std::transform(Name.begin(), Name.end(), Name.begin(), tolower); 36 std::replace(Name.begin(), Name.end(), '\\', '/'); 37 38 // Remove all duplicate slashes. 39 size_t Pos = 0; 40 while ((Pos = Name.find("//", Pos)) != std::string::npos) 41 Name.erase(Pos, 1); 42 43 return Name; 44 } 45 46 // Convert the given 'Path' to lowercase and change any matching character 47 // from 'CharSet' into '_'. 48 // The characters in 'CharSet' are: 49 // '/', '\', '<', '>', '.', ':', '%', '*', '?', '|', '"', ' '. 50 std::string llvm::logicalview::flattenedFilePath(StringRef Path) { 51 std::string Name(Path); 52 std::transform(Name.begin(), Name.end(), Name.begin(), tolower); 53 54 const char *CharSet = "/\\<>.:%*?|\" "; 55 char *Input = Name.data(); 56 while (Input && *Input) { 57 Input = strpbrk(Input, CharSet); 58 if (Input) 59 *Input++ = '_'; 60 }; 61 return Name; 62 } 63 64 using LexicalEntry = std::pair<size_t, size_t>; 65 using LexicalIndexes = SmallVector<LexicalEntry, 10>; 66 67 static LexicalIndexes getAllLexicalIndexes(StringRef Name) { 68 if (Name.empty()) 69 return {}; 70 71 size_t AngleCount = 0; 72 size_t ColonSeen = 0; 73 size_t Current = 0; 74 75 LexicalIndexes Indexes; 76 77 #ifndef NDEBUG 78 auto PrintLexicalEntry = [&]() { 79 LexicalEntry Entry = Indexes.back(); 80 llvm::dbgs() << formatv( 81 "'{0}:{1}', '{2}'\n", Entry.first, Entry.second, 82 Name.substr(Entry.first, Entry.second - Entry.first + 1)); 83 }; 84 #endif 85 86 size_t Length = Name.size(); 87 for (size_t Index = 0; Index < Length; ++Index) { 88 LLVM_DEBUG({ 89 llvm::dbgs() << formatv("Index: '{0}', Char: '{1}'\n", Index, 90 Name[Index]); 91 }); 92 switch (Name[Index]) { 93 case '<': 94 ++AngleCount; 95 break; 96 case '>': 97 --AngleCount; 98 break; 99 case ':': 100 ++ColonSeen; 101 break; 102 } 103 if (ColonSeen == 2) { 104 if (!AngleCount) { 105 Indexes.push_back(LexicalEntry(Current, Index - 2)); 106 Current = Index + 1; 107 LLVM_DEBUG({ PrintLexicalEntry(); }); 108 } 109 ColonSeen = 0; 110 continue; 111 } 112 } 113 114 // Store last component. 115 Indexes.push_back(LexicalEntry(Current, Length - 1)); 116 LLVM_DEBUG({ PrintLexicalEntry(); }); 117 return Indexes; 118 } 119 120 LVLexicalComponent llvm::logicalview::getInnerComponent(StringRef Name) { 121 if (Name.empty()) 122 return {}; 123 124 LexicalIndexes Indexes = getAllLexicalIndexes(Name); 125 if (Indexes.size() == 1) 126 return std::make_tuple(StringRef(), Name); 127 128 LexicalEntry BeginEntry = Indexes.front(); 129 LexicalEntry EndEntry = Indexes[Indexes.size() - 2]; 130 StringRef Outer = 131 Name.substr(BeginEntry.first, EndEntry.second - BeginEntry.first + 1); 132 133 LexicalEntry LastEntry = Indexes.back(); 134 StringRef Inner = 135 Name.substr(LastEntry.first, LastEntry.second - LastEntry.first + 1); 136 137 return std::make_tuple(Outer, Inner); 138 } 139 140 LVStringRefs llvm::logicalview::getAllLexicalComponents(StringRef Name) { 141 if (Name.empty()) 142 return {}; 143 144 LexicalIndexes Indexes = getAllLexicalIndexes(Name); 145 LVStringRefs Components; 146 for (const LexicalEntry &Entry : Indexes) 147 Components.push_back( 148 Name.substr(Entry.first, Entry.second - Entry.first + 1)); 149 150 return Components; 151 } 152 153 std::string llvm::logicalview::getScopedName(const LVStringRefs &Components, 154 StringRef BaseName) { 155 if (Components.empty()) 156 return {}; 157 std::string Name(BaseName); 158 raw_string_ostream Stream(Name); 159 if (BaseName.size()) 160 Stream << "::"; 161 Stream << Components[0]; 162 for (LVStringRefs::size_type Index = 1; Index < Components.size(); ++Index) 163 Stream << "::" << Components[Index]; 164 return Name; 165 } 166