Home | History | Annotate | Line # | Download | only in TableGen
      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.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