StringToOffsetTable.h 3.1 KB

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