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