//===- NamedStreamMap.cpp - PDB Named Stream Map ----------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h"

#include "llvm/ADT/SparseBitVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/PDB/Native/HashTable.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/Error.h"
#include <algorithm>
#include <cstdint>

using namespace llvm;
using namespace llvm::pdb;

// FIXME: This shouldn't be necessary, but if we insert the strings in any
// other order, cvdump cannot read the generated name map.  This suggests that
// we may be using the wrong hash function.  A closer inspection of the cvdump
// source code may reveal something, but for now this at least makes us work,
// even if only by accident.
static constexpr const char *OrderedStreamNames[] = {"/LinkInfo", "/names",
                                                     "/src/headerblock"};

NamedStreamMap::NamedStreamMap() = default;

Error NamedStreamMap::load(BinaryStreamReader &Stream) {
  Mapping.clear();
  FinalizedHashTable.clear();
  FinalizedInfo.reset();

  uint32_t StringBufferSize;
  if (auto EC = Stream.readInteger(StringBufferSize))
    return joinErrors(std::move(EC),
                      make_error<RawError>(raw_error_code::corrupt_file,
                                           "Expected string buffer size"));

  BinaryStreamRef StringsBuffer;
  if (auto EC = Stream.readStreamRef(StringsBuffer, StringBufferSize))
    return EC;

  HashTable OffsetIndexMap;
  if (auto EC = OffsetIndexMap.load(Stream))
    return EC;

  uint32_t NameOffset;
  uint32_t NameIndex;
  for (const auto &Entry : OffsetIndexMap) {
    std::tie(NameOffset, NameIndex) = Entry;

    // Compute the offset of the start of the string relative to the stream.
    BinaryStreamReader NameReader(StringsBuffer);
    NameReader.setOffset(NameOffset);
    // Pump out our c-string from the stream.
    StringRef Str;
    if (auto EC = NameReader.readCString(Str))
      return joinErrors(std::move(EC),
                        make_error<RawError>(raw_error_code::corrupt_file,
                                             "Expected name map name"));

    // Add this to a string-map from name to stream number.
    Mapping.insert({Str, NameIndex});
  }

  return Error::success();
}

Error NamedStreamMap::commit(BinaryStreamWriter &Writer) const {
  assert(FinalizedInfo.hasValue());

  // The first field is the number of bytes of string data.
  if (auto EC = Writer.writeInteger(FinalizedInfo->StringDataBytes))
    return EC;

  for (const auto &Name : OrderedStreamNames) {
    auto Item = Mapping.find(Name);
    assert(Item != Mapping.end());
    if (auto EC = Writer.writeCString(Item->getKey()))
      return EC;
  }

  // And finally the Offset Index map.
  if (auto EC = FinalizedHashTable.commit(Writer))
    return EC;

  return Error::success();
}

uint32_t NamedStreamMap::finalize() {
  if (FinalizedInfo.hasValue())
    return FinalizedInfo->SerializedLength;

  // Build the finalized hash table.
  FinalizedHashTable.clear();
  FinalizedInfo.emplace();

  for (const auto &Name : OrderedStreamNames) {
    auto Item = Mapping.find(Name);
    assert(Item != Mapping.end());
    FinalizedHashTable.set(FinalizedInfo->StringDataBytes, Item->getValue());
    FinalizedInfo->StringDataBytes += Item->getKeyLength() + 1;
  }

  // Number of bytes of string data.
  FinalizedInfo->SerializedLength += sizeof(support::ulittle32_t);
  // Followed by that many actual bytes of string data.
  FinalizedInfo->SerializedLength += FinalizedInfo->StringDataBytes;
  // Followed by the mapping from Offset to Index.
  FinalizedInfo->SerializedLength +=
      FinalizedHashTable.calculateSerializedLength();
  return FinalizedInfo->SerializedLength;
}

iterator_range<StringMapConstIterator<uint32_t>>
NamedStreamMap::entries() const {
  return make_range<StringMapConstIterator<uint32_t>>(Mapping.begin(),
                                                      Mapping.end());
}

uint32_t NamedStreamMap::size() const { return Mapping.size(); }

bool NamedStreamMap::get(StringRef Stream, uint32_t &StreamNo) const {
  auto Iter = Mapping.find(Stream);
  if (Iter == Mapping.end())
    return false;
  StreamNo = Iter->second;
  return true;
}

void NamedStreamMap::set(StringRef Stream, uint32_t StreamNo) {
  FinalizedInfo.reset();
  Mapping[Stream] = StreamNo;
}

void NamedStreamMap::remove(StringRef Stream) {
  FinalizedInfo.reset();
  Mapping.erase(Stream);
}
