1*591312c5SZachary Turner //===- DebugStringTableSubsection.cpp - CodeView String Table ---*- C++ -*-===//
2*591312c5SZachary Turner //
3*591312c5SZachary Turner //                     The LLVM Compiler Infrastructure
4*591312c5SZachary Turner //
5*591312c5SZachary Turner // This file is distributed under the University of Illinois Open Source
6*591312c5SZachary Turner // License. See LICENSE.TXT for details.
7*591312c5SZachary Turner //
8*591312c5SZachary Turner //===----------------------------------------------------------------------===//
9*591312c5SZachary Turner 
10*591312c5SZachary Turner #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
11*591312c5SZachary Turner 
12*591312c5SZachary Turner #include "llvm/Support/BinaryStream.h"
13*591312c5SZachary Turner #include "llvm/Support/BinaryStreamReader.h"
14*591312c5SZachary Turner #include "llvm/Support/BinaryStreamWriter.h"
15*591312c5SZachary Turner 
16*591312c5SZachary Turner using namespace llvm;
17*591312c5SZachary Turner using namespace llvm::codeview;
18*591312c5SZachary Turner 
19*591312c5SZachary Turner DebugStringTableSubsectionRef::DebugStringTableSubsectionRef()
20*591312c5SZachary Turner     : DebugSubsectionRef(DebugSubsectionKind::StringTable) {}
21*591312c5SZachary Turner 
22*591312c5SZachary Turner Error DebugStringTableSubsectionRef::initialize(BinaryStreamRef Contents) {
23*591312c5SZachary Turner   Stream = Contents;
24*591312c5SZachary Turner   return Error::success();
25*591312c5SZachary Turner }
26*591312c5SZachary Turner 
27*591312c5SZachary Turner Expected<StringRef>
28*591312c5SZachary Turner DebugStringTableSubsectionRef::getString(uint32_t Offset) const {
29*591312c5SZachary Turner   BinaryStreamReader Reader(Stream);
30*591312c5SZachary Turner   Reader.setOffset(Offset);
31*591312c5SZachary Turner   StringRef Result;
32*591312c5SZachary Turner   if (auto EC = Reader.readCString(Result))
33*591312c5SZachary Turner     return std::move(EC);
34*591312c5SZachary Turner   return Result;
35*591312c5SZachary Turner }
36*591312c5SZachary Turner 
37*591312c5SZachary Turner DebugStringTableSubsection::DebugStringTableSubsection()
38*591312c5SZachary Turner     : DebugSubsection(DebugSubsectionKind::StringTable) {}
39*591312c5SZachary Turner 
40*591312c5SZachary Turner uint32_t DebugStringTableSubsection::insert(StringRef S) {
41*591312c5SZachary Turner   auto P = Strings.insert({S, StringSize});
42*591312c5SZachary Turner 
43*591312c5SZachary Turner   // If a given string didn't exist in the string table, we want to increment
44*591312c5SZachary Turner   // the string table size.
45*591312c5SZachary Turner   if (P.second)
46*591312c5SZachary Turner     StringSize += S.size() + 1; // +1 for '\0'
47*591312c5SZachary Turner   return P.first->second;
48*591312c5SZachary Turner }
49*591312c5SZachary Turner 
50*591312c5SZachary Turner uint32_t DebugStringTableSubsection::calculateSerializedSize() const {
51*591312c5SZachary Turner   return StringSize;
52*591312c5SZachary Turner }
53*591312c5SZachary Turner 
54*591312c5SZachary Turner Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const {
55*591312c5SZachary Turner   assert(Writer.bytesRemaining() == StringSize);
56*591312c5SZachary Turner   uint32_t MaxOffset = 1;
57*591312c5SZachary Turner 
58*591312c5SZachary Turner   for (auto &Pair : Strings) {
59*591312c5SZachary Turner     StringRef S = Pair.getKey();
60*591312c5SZachary Turner     uint32_t Offset = Pair.getValue();
61*591312c5SZachary Turner     Writer.setOffset(Offset);
62*591312c5SZachary Turner     if (auto EC = Writer.writeCString(S))
63*591312c5SZachary Turner       return EC;
64*591312c5SZachary Turner     MaxOffset = std::max<uint32_t>(MaxOffset, Offset + S.size() + 1);
65*591312c5SZachary Turner   }
66*591312c5SZachary Turner 
67*591312c5SZachary Turner   Writer.setOffset(MaxOffset);
68*591312c5SZachary Turner   assert(Writer.bytesRemaining() == 0);
69*591312c5SZachary Turner   return Error::success();
70*591312c5SZachary Turner }
71*591312c5SZachary Turner 
72*591312c5SZachary Turner uint32_t DebugStringTableSubsection::size() const { return Strings.size(); }
73*591312c5SZachary Turner 
74*591312c5SZachary Turner uint32_t DebugStringTableSubsection::getStringId(StringRef S) const {
75*591312c5SZachary Turner   auto P = Strings.find(S);
76*591312c5SZachary Turner   assert(P != Strings.end());
77*591312c5SZachary Turner   return P->second;
78*591312c5SZachary Turner }
79