StringToOffsetTable.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- StringToOffsetTable.h - Emit a big concatenated string ---*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_TABLEGEN_STRINGTOOFFSETTABLE_H
  14. #define LLVM_TABLEGEN_STRINGTOOFFSETTABLE_H
  15. #include "llvm/ADT/SmallString.h"
  16. #include "llvm/ADT/StringExtras.h"
  17. #include "llvm/ADT/StringMap.h"
  18. #include "llvm/Support/raw_ostream.h"
  19. #include <cctype>
  20. namespace llvm {
  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. public:
  29. bool Empty() const { return StringOffset.empty(); }
  30. unsigned GetOrAddStringOffset(StringRef Str, bool appendZero = true) {
  31. auto IterBool =
  32. StringOffset.insert(std::make_pair(Str, AggregateString.size()));
  33. if (IterBool.second) {
  34. // Add the string to the aggregate if this is the first time found.
  35. AggregateString.append(Str.begin(), Str.end());
  36. if (appendZero)
  37. AggregateString += '\0';
  38. }
  39. return IterBool.first->second;
  40. }
  41. void EmitString(raw_ostream &O) {
  42. // Escape the string.
  43. SmallString<256> Str;
  44. raw_svector_ostream(Str).write_escaped(AggregateString);
  45. AggregateString = std::string(Str.str());
  46. O << " \"";
  47. unsigned CharsPrinted = 0;
  48. for (unsigned i = 0, e = AggregateString.size(); i != e; ++i) {
  49. if (CharsPrinted > 70) {
  50. O << "\"\n \"";
  51. CharsPrinted = 0;
  52. }
  53. O << AggregateString[i];
  54. ++CharsPrinted;
  55. // Print escape sequences all together.
  56. if (AggregateString[i] != '\\')
  57. continue;
  58. assert(i + 1 < AggregateString.size() && "Incomplete escape sequence!");
  59. if (isdigit(AggregateString[i + 1])) {
  60. assert(isdigit(AggregateString[i + 2]) &&
  61. isdigit(AggregateString[i + 3]) &&
  62. "Expected 3 digit octal escape!");
  63. O << AggregateString[++i];
  64. O << AggregateString[++i];
  65. O << AggregateString[++i];
  66. CharsPrinted += 3;
  67. } else {
  68. O << AggregateString[++i];
  69. ++CharsPrinted;
  70. }
  71. }
  72. O << "\"";
  73. }
  74. /// Emit the string using character literals. MSVC has a limitation that
  75. /// string literals cannot be longer than 64K.
  76. void EmitCharArray(raw_ostream &O) {
  77. assert(AggregateString.find(')') == std::string::npos &&
  78. "can't emit raw string with closing parens");
  79. int Count = 0;
  80. O << ' ';
  81. for (char C : AggregateString) {
  82. O << " \'";
  83. O.write_escaped(StringRef(&C, 1));
  84. O << "\',";
  85. Count++;
  86. if (Count > 14) {
  87. O << "\n ";
  88. Count = 0;
  89. }
  90. }
  91. O << '\n';
  92. }
  93. };
  94. } // end namespace llvm
  95. #endif
  96. #ifdef __GNUC__
  97. #pragma GCC diagnostic pop
  98. #endif