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
getStringPool()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 '/'
transformPath(StringRef Path)31 std::string llvm::logicalview::transformPath(StringRef Path) {
32 std::string Name(Path);
33 llvm::transform(Name, Name.begin(), tolower);
34 llvm::replace(Name, '\\', '/');
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 // '/', '\', '<', '>', '.', ':', '%', '*', '?', '|', '"', ' '.
flattenedFilePath(StringRef Path)48 std::string llvm::logicalview::flattenedFilePath(StringRef Path) {
49 std::string Name(Path);
50 llvm::transform(Name, 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
getAllLexicalIndexes(StringRef Name)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
getInnerComponent(StringRef Name)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
getAllLexicalComponents(StringRef Name)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
getScopedName(const LVStringRefs & Components,StringRef BaseName)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