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 TBLGEN_STRING_TO_OFFSET_TABLE_H
11#define TBLGEN_STRING_TO_OFFSET_TABLE_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
19namespace 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.
25class StringToOffsetTable {
26  StringMap<unsigned> StringOffset;
27  std::string AggregateString;
28
29public:
30  unsigned GetOrAddStringOffset(StringRef Str, bool appendZero = true) {
31    StringMapEntry<unsigned> &Entry = StringOffset.GetOrCreateValue(Str, -1U);
32    if (Entry.getValue() == -1U) {
33      // Add the string to the aggregate if this is the first time found.
34      Entry.setValue(AggregateString.size());
35      AggregateString.append(Str.begin(), Str.end());
36      if (appendZero)
37        AggregateString += '\0';
38    }
39
40    return Entry.getValue();
41  }
42
43  void EmitString(raw_ostream &O) {
44    // Escape the string.
45    SmallString<256> Str;
46    raw_svector_ostream(Str).write_escaped(AggregateString);
47    AggregateString = Str.str();
48
49    O << "    \"";
50    unsigned CharsPrinted = 0;
51    for (unsigned i = 0, e = AggregateString.size(); i != e; ++i) {
52      if (CharsPrinted > 70) {
53        O << "\"\n    \"";
54        CharsPrinted = 0;
55      }
56      O << AggregateString[i];
57      ++CharsPrinted;
58
59      // Print escape sequences all together.
60      if (AggregateString[i] != '\\')
61        continue;
62
63      assert(i+1 < AggregateString.size() && "Incomplete escape sequence!");
64      if (isdigit(AggregateString[i+1])) {
65        assert(isdigit(AggregateString[i+2]) &&
66               isdigit(AggregateString[i+3]) &&
67               "Expected 3 digit octal escape!");
68        O << AggregateString[++i];
69        O << AggregateString[++i];
70        O << AggregateString[++i];
71        CharsPrinted += 3;
72      } else {
73        O << AggregateString[++i];
74        ++CharsPrinted;
75      }
76    }
77    O << "\"";
78  }
79};
80
81} // end namespace llvm
82
83#endif
84