// Copied from https://github.com/llvm/llvm-project/blob/3d3ef9d073e1e27ea57480b371b7f5a9f5642ed2/llvm/include/llvm/Object/Archive.h

//===- 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);

  StringRef SymbolTable;
  StringRef StringTable;

private:
  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
