xref: /freebsd/contrib/llvm-project/llvm/include/llvm/TableGen/StringToOffsetTable.h (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
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