1 //===- StringToOffsetTable.h - Emit a big concatenated string ---*- C++ -*-===// 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 #ifndef LLVM_TABLEGEN_STRINGTOOFFSETTABLE_H 10 #define LLVM_TABLEGEN_STRINGTOOFFSETTABLE_H 11 12 #include "llvm/ADT/SmallString.h" 13 #include "llvm/ADT/StringExtras.h" 14 #include "llvm/ADT/StringMap.h" 15 #include "llvm/Support/raw_ostream.h" 16 #include <cctype> 17 18 namespace llvm { 19 20 /// StringToOffsetTable - This class uniques a bunch of nul-terminated strings 21 /// and keeps track of their offset in a massive contiguous string allocation. 22 /// It can then output this string blob and use indexes into the string to 23 /// reference each piece. 24 class StringToOffsetTable { 25 StringMap<unsigned> StringOffset; 26 std::string AggregateString; 27 28 public: 29 bool Empty() const { return StringOffset.empty(); } 30 31 unsigned GetOrAddStringOffset(StringRef Str, bool appendZero = true) { 32 auto IterBool = 33 StringOffset.insert(std::make_pair(Str, AggregateString.size())); 34 if (IterBool.second) { 35 // Add the string to the aggregate if this is the first time found. 36 AggregateString.append(Str.begin(), Str.end()); 37 if (appendZero) 38 AggregateString += '\0'; 39 } 40 41 return IterBool.first->second; 42 } 43 44 void EmitString(raw_ostream &O) { 45 // Escape the string. 46 SmallString<256> Str; 47 raw_svector_ostream(Str).write_escaped(AggregateString); 48 AggregateString = std::string(Str); 49 50 O << " \""; 51 unsigned CharsPrinted = 0; 52 for (unsigned i = 0, e = AggregateString.size(); i != e; ++i) { 53 if (CharsPrinted > 70) { 54 O << "\"\n \""; 55 CharsPrinted = 0; 56 } 57 O << AggregateString[i]; 58 ++CharsPrinted; 59 60 // Print escape sequences all together. 61 if (AggregateString[i] != '\\') 62 continue; 63 64 assert(i + 1 < AggregateString.size() && "Incomplete escape sequence!"); 65 if (isdigit(AggregateString[i + 1])) { 66 assert(isdigit(AggregateString[i + 2]) && 67 isdigit(AggregateString[i + 3]) && 68 "Expected 3 digit octal escape!"); 69 O << AggregateString[++i]; 70 O << AggregateString[++i]; 71 O << AggregateString[++i]; 72 CharsPrinted += 3; 73 } else { 74 O << AggregateString[++i]; 75 ++CharsPrinted; 76 } 77 } 78 O << "\""; 79 } 80 81 /// Emit the string using character literals. MSVC has a limitation that 82 /// string literals cannot be longer than 64K. 83 void EmitCharArray(raw_ostream &O) { 84 assert(AggregateString.find(')') == std::string::npos && 85 "can't emit raw string with closing parens"); 86 int Count = 0; 87 O << ' '; 88 for (char C : AggregateString) { 89 O << " \'"; 90 O.write_escaped(StringRef(&C, 1)); 91 O << "\',"; 92 Count++; 93 if (Count > 14) { 94 O << "\n "; 95 Count = 0; 96 } 97 } 98 O << '\n'; 99 } 100 }; 101 102 } // end namespace llvm 103 104 #endif 105