//===- Archive.h - ar archive file format -----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares the ar archive file format class.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_OBJECT_ARCHIVE_H
#define LLVM_OBJECT_ARCHIVE_H

#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/fallible_iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Object/Binary.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cassert>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>

namespace llvm {

template <typename T> class Optional;

namespace object {

const char ArchiveMagic[] = "!<arch>\n";
const char ThinArchiveMagic[] = "!<thin>\n";
const char BigArchiveMagic[] = "<bigaf>\n";

class Archive;

class AbstractArchiveMemberHeader {
protected:
  AbstractArchiveMemberHeader(const Archive *Parent) : Parent(Parent){};

public:
  friend class Archive;
  virtual std::unique_ptr<AbstractArchiveMemberHeader> clone() const = 0;
  virtual ~AbstractArchiveMemberHeader() = default;

  /// Get the name without looking up long names.
  virtual Expected<StringRef> getRawName() const = 0;
  virtual StringRef getRawAccessMode() const = 0;
  virtual StringRef getRawLastModified() const = 0;
  virtual StringRef getRawUID() const = 0;
  virtual StringRef getRawGID() const = 0;

  /// Get the name looking up long names.
  virtual Expected<StringRef> getName(uint64_t Size) const = 0;
  virtual Expected<uint64_t> getSize() const = 0;
  virtual uint64_t getOffset() const = 0;

  /// Get next file member location.
  virtual Expected<const char *> getNextChildLoc() const = 0;
  virtual Expected<bool> isThin() const = 0;

  Expected<sys::fs::perms> getAccessMode() const;
  Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const;
  Expected<unsigned> getUID() const;
  Expected<unsigned> getGID() const;

  /// Returns the size in bytes of the format-defined member header of the
  /// concrete archive type.
  virtual uint64_t getSizeOf() const = 0;

  const Archive *Parent;
};

template <typename T>
class CommonArchiveMemberHeader : public AbstractArchiveMemberHeader {
public:
  CommonArchiveMemberHeader(const Archive *Parent, const T *RawHeaderPtr)
      : AbstractArchiveMemberHeader(Parent), ArMemHdr(RawHeaderPtr){};
  StringRef getRawAccessMode() const override;
  StringRef getRawLastModified() const override;
  StringRef getRawUID() const override;
  StringRef getRawGID() const override;

  uint64_t getOffset() const override;
  uint64_t getSizeOf() const override { return sizeof(T); }

  T const *ArMemHdr;
};

struct UnixArMemHdrType {
  char Name[16];
  char LastModified[12];
  char UID[6];
  char GID[6];
  char AccessMode[8];
  char Size[10]; ///< Size of data, not including header or padding.
  char Terminator[2];
};

class ArchiveMemberHeader : public CommonArchiveMemberHeader<UnixArMemHdrType> {
public:
  ArchiveMemberHeader(const Archive *Parent, const char *RawHeaderPtr,
                      uint64_t Size, Error *Err);

  std::unique_ptr<AbstractArchiveMemberHeader> clone() const override {
    return std::make_unique<ArchiveMemberHeader>(*this);
  }

  Expected<StringRef> getRawName() const override;

  Expected<StringRef> getName(uint64_t Size) const override;
  Expected<uint64_t> getSize() const override;
  Expected<const char *> getNextChildLoc() const override;
  Expected<bool> isThin() const override;
};

// File Member Header
struct BigArMemHdrType {
  char Size[20];       // File member size in decimal
  char NextOffset[20]; // Next member offset in decimal
  char PrevOffset[20]; // Previous member offset in decimal
  char LastModified[12];
  char UID[12];
  char GID[12];
  char AccessMode[12];
  char NameLen[4]; // File member name length in decimal
  union {
    char Name[2]; // Start of member name
    char Terminator[2];
  };
};

// Define file member header of AIX big archive.
class BigArchiveMemberHeader
    : public CommonArchiveMemberHeader<BigArMemHdrType> {

public:
  BigArchiveMemberHeader(Archive const *Parent, const char *RawHeaderPtr,
                         uint64_t Size, Error *Err);
  std::unique_ptr<AbstractArchiveMemberHeader> clone() const override {
    return std::make_unique<BigArchiveMemberHeader>(*this);
  }

  Expected<StringRef> getRawName() const override;
  Expected<uint64_t> getRawNameSize() const;

  Expected<StringRef> getName(uint64_t Size) const override;
  Expected<uint64_t> getSize() const override;
  Expected<const char *> getNextChildLoc() const override;
  Expected<uint64_t> getNextOffset() const;
  Expected<bool> isThin() const override { return false; }
};

class Archive : public Binary {
  virtual void anchor();

public:
  class Child {
    friend Archive;
    friend AbstractArchiveMemberHeader;

    const Archive *Parent;
    std::unique_ptr<AbstractArchiveMemberHeader> Header;
    /// Includes header but not padding byte.
    StringRef Data;
    /// Offset from Data to the start of the file.
    uint16_t StartOfFile;

    Expected<bool> isThinMember() const;

  public:
    Child(const Archive *Parent, const char *Start, Error *Err);
    Child(const Archive *Parent, StringRef Data, uint16_t StartOfFile);

    Child(const Child &C)
        : Parent(C.Parent), Data(C.Data), StartOfFile(C.StartOfFile) {
      if (C.Header)
        Header = C.Header->clone();
    }

    Child(Child &&C) {
      Parent = std::move(C.Parent);
      Header = std::move(C.Header);
      Data = C.Data;
      StartOfFile = C.StartOfFile;
    }

    Child &operator=(Child &&C) noexcept {
      if (&C == this)
        return *this;

      Parent = std::move(C.Parent);
      Header = std::move(C.Header);
      Data = C.Data;
      StartOfFile = C.StartOfFile;

      return *this;
    }

    Child &operator=(const Child &C) {
      if (&C == this)
        return *this;

      Parent = C.Parent;
      if (C.Header)
        Header = C.Header->clone();
      Data = C.Data;
      StartOfFile = C.StartOfFile;

      return *this;
    }

    bool operator==(const Child &other) const {
      assert(!Parent || !other.Parent || Parent == other.Parent);
      return Data.begin() == other.Data.begin();
    }

    const Archive *getParent() const { return Parent; }
    Expected<Child> getNext() const;

    Expected<StringRef> getName() const;
    Expected<std::string> getFullName() const;
    Expected<StringRef> getRawName() const { return Header->getRawName(); }

    Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const {
      return Header->getLastModified();
    }

    StringRef getRawLastModified() const {
      return Header->getRawLastModified();
    }

    Expected<unsigned> getUID() const { return Header->getUID(); }
    Expected<unsigned> getGID() const { return Header->getGID(); }

    Expected<sys::fs::perms> getAccessMode() const {
      return Header->getAccessMode();
    }

    /// \return the size of the archive member without the header or padding.
    Expected<uint64_t> getSize() const;
    /// \return the size in the archive header for this member.
    Expected<uint64_t> getRawSize() const;

    Expected<StringRef> getBuffer() const;
    uint64_t getChildOffset() const;
    uint64_t getDataOffset() const { return getChildOffset() + StartOfFile; }

    Expected<MemoryBufferRef> getMemoryBufferRef() const;

    Expected<std::unique_ptr<Binary>>
    getAsBinary(LLVMContext *Context = nullptr) const;
  };

  class ChildFallibleIterator {
    Child C;

  public:
    ChildFallibleIterator() : C(Child(nullptr, nullptr, nullptr)) {}
    ChildFallibleIterator(const Child &C) : C(C) {}

    const Child *operator->() const { return &C; }
    const Child &operator*() const { return C; }

    bool operator==(const ChildFallibleIterator &other) const {
      // Ignore errors here: If an error occurred during increment then getNext
      // will have been set to child_end(), and the following comparison should
      // do the right thing.
      return C == other.C;
    }

    bool operator!=(const ChildFallibleIterator &other) const {
      return !(*this == other);
    }

    Error inc() {
      auto NextChild = C.getNext();
      if (!NextChild)
        return NextChild.takeError();
      C = std::move(*NextChild);
      return Error::success();
    }
  };

  using child_iterator = fallible_iterator<ChildFallibleIterator>;

  class Symbol {
    const Archive *Parent;
    uint32_t SymbolIndex;
    uint32_t StringIndex; // Extra index to the string.

  public:
    Symbol(const Archive *p, uint32_t symi, uint32_t stri)
        : Parent(p), SymbolIndex(symi), StringIndex(stri) {}

    bool operator==(const Symbol &other) const {
      return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex);
    }

    StringRef getName() const;
    Expected<Child> getMember() const;
    Symbol getNext() const;
  };

  class symbol_iterator {
    Symbol symbol;

  public:
    symbol_iterator(const Symbol &s) : symbol(s) {}

    const Symbol *operator->() const { return &symbol; }
    const Symbol &operator*() const { return symbol; }

    bool operator==(const symbol_iterator &other) const {
      return symbol == other.symbol;
    }

    bool operator!=(const symbol_iterator &other) const {
      return !(*this == other);
    }

    symbol_iterator &operator++() { // Preincrement
      symbol = symbol.getNext();
      return *this;
    }
  };

  Archive(MemoryBufferRef Source, Error &Err);
  static Expected<std::unique_ptr<Archive>> create(MemoryBufferRef Source);

  /// Size field is 10 decimal digits long
  static const uint64_t MaxMemberSize = 9999999999;

  enum Kind { K_GNU, K_GNU64, K_BSD, K_DARWIN, K_DARWIN64, K_COFF, K_AIXBIG };

  Kind kind() const { return (Kind)Format; }
  bool isThin() const { return IsThin; }
  static object::Archive::Kind getDefaultKindForHost();

  child_iterator child_begin(Error &Err, bool SkipInternal = true) const;
  child_iterator child_end() const;
  iterator_range<child_iterator> children(Error &Err,
                                          bool SkipInternal = true) const {
    return make_range(child_begin(Err, SkipInternal), child_end());
  }

  symbol_iterator symbol_begin() const;
  symbol_iterator symbol_end() const;
  iterator_range<symbol_iterator> symbols() const {
    return make_range(symbol_begin(), symbol_end());
  }

  static bool classof(Binary const *v) { return v->isArchive(); }

  // check if a symbol is in the archive
  Expected<Optional<Child>> findSym(StringRef name) const;

  virtual bool isEmpty() const;
  bool hasSymbolTable() const;
  StringRef getSymbolTable() const { return SymbolTable; }
  StringRef getStringTable() const { return StringTable; }
  uint32_t getNumberOfSymbols() const;
  virtual uint64_t getFirstChildOffset() const { return getArchiveMagicLen(); }

  std::vector<std::unique_ptr<MemoryBuffer>> takeThinBuffers() {
    return std::move(ThinBuffers);
  }

  std::unique_ptr<AbstractArchiveMemberHeader>
  createArchiveMemberHeader(const char *RawHeaderPtr, uint64_t Size,
                            Error *Err) const;

protected:
  uint64_t getArchiveMagicLen() const;
  void setFirstRegular(const Child &C);

private:
  StringRef SymbolTable;
  StringRef StringTable;

  StringRef FirstRegularData;
  uint16_t FirstRegularStartOfFile = -1;

  unsigned Format : 3;
  unsigned IsThin : 1;
  mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers;
};

class BigArchive : public Archive {
public:
  /// Fixed-Length Header.
  struct FixLenHdr {
    char Magic[sizeof(BigArchiveMagic) - 1]; ///< Big archive magic string.
    char MemOffset[20];                      ///< Offset to member table.
    char GlobSymOffset[20];                  ///< Offset to global symbol table.
    char
        GlobSym64Offset[20]; ///< Offset global symbol table for 64-bit objects.
    char FirstChildOffset[20]; ///< Offset to first archive member.
    char LastChildOffset[20];  ///< Offset to last archive member.
    char FreeOffset[20];       ///< Offset to first mem on free list.
  };

  const FixLenHdr *ArFixLenHdr;
  uint64_t FirstChildOffset = 0;
  uint64_t LastChildOffset = 0;

public:
  BigArchive(MemoryBufferRef Source, Error &Err);
  uint64_t getFirstChildOffset() const override { return FirstChildOffset; }
  uint64_t getLastChildOffset() const { return LastChildOffset; }
  bool isEmpty() const override {
    return Data.getBufferSize() == sizeof(FixLenHdr);
  };
};

} // end namespace object
} // end namespace llvm

#endif // LLVM_OBJECT_ARCHIVE_H
