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