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