/*
 * Copyright 2016 WebAssembly Community Group participants
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef WABT_STREAM_H_
#define WABT_STREAM_H_

#include <cassert>
#include <memory>
#include <vector>

#include "src/common.h"

namespace wabt {

/* whether to display the ASCII characters in the debug output for
 * write_memory */
enum class PrintChars {
  No = 0,
  Yes = 1,
};

class Stream {
 public:
  explicit Stream(Stream* log_stream = nullptr);
  virtual ~Stream() = default;

  size_t offset() { return offset_; }
  Result result() { return result_; }

  void set_log_stream(Stream* stream) {
    assert(stream);
    log_stream_ = stream;
  }

  Stream& log_stream() {
    assert(log_stream_);
    return *log_stream_;
  }

  bool has_log_stream() const { return log_stream_ != nullptr; }

  void ClearOffset() { offset_ = 0; }
  void AddOffset(ssize_t delta);

  void WriteData(const void* src,
                 size_t size,
                 const char* desc = nullptr,
                 PrintChars = PrintChars::No);

  template <typename T>
  void WriteData(const std::vector<T> src,
                 const char* desc,
                 PrintChars print_chars = PrintChars::No) {
    if (!src.empty()) {
      WriteData(src.data(), src.size() * sizeof(T), desc, print_chars);
    }
  }

  void WriteDataAt(size_t offset,
                   const void* src,
                   size_t size,
                   const char* desc = nullptr,
                   PrintChars = PrintChars::No);

  void MoveData(size_t dst_offset, size_t src_offset, size_t size);

  void Truncate(size_t size);

  void WABT_PRINTF_FORMAT(2, 3) Writef(const char* format, ...);

  // Specified as uint32_t instead of uint8_t so we can check if the value
  // given is in range before wrapping.
  void WriteU8(uint32_t value,
               const char* desc = nullptr,
               PrintChars print_chars = PrintChars::No) {
    assert(value <= UINT8_MAX);
    Write(static_cast<uint8_t>(value), desc, print_chars);
  }
  void WriteU32(uint32_t value,
                const char* desc = nullptr,
                PrintChars print_chars = PrintChars::No) {
    Write(value, desc, print_chars);
  }
  void WriteU64(uint64_t value,
                const char* desc = nullptr,
                PrintChars print_chars = PrintChars::No) {
    Write(value, desc, print_chars);
  }
  void WriteU128(v128 value,
                 const char* desc = nullptr,
                 PrintChars print_chars = PrintChars::No) {
    Write(value, desc, print_chars);
  }

  void WriteChar(char c,
                 const char* desc = nullptr,
                 PrintChars print_chars = PrintChars::No) {
    WriteU8(static_cast<unsigned char>(c), desc, print_chars);
  }

  // Dump memory as text, similar to the xxd format.
  void WriteMemoryDump(const void* start,
                       size_t size,
                       size_t offset = 0,
                       PrintChars print_chars = PrintChars::No,
                       const char* prefix = nullptr,
                       const char* desc = nullptr);

  // Convenience functions for writing enums.
  template <typename T>
  void WriteU8Enum(T value,
                   const char* desc = nullptr,
                   PrintChars print_chars = PrintChars::No) {
    WriteU8(static_cast<uint32_t>(value), desc, print_chars);
  }

  virtual void Flush() {}

 protected:
  virtual Result WriteDataImpl(size_t offset,
                               const void* data,
                               size_t size) = 0;
  virtual Result MoveDataImpl(size_t dst_offset,
                              size_t src_offset,
                              size_t size) = 0;
  virtual Result TruncateImpl(size_t size) = 0;

 private:
  template <typename T>
  void Write(const T& data, const char* desc, PrintChars print_chars) {
#if WABT_BIG_ENDIAN
    char tmp[sizeof(T)];
    memcpy(tmp, &data, sizeof(tmp));
    SwapBytesSized(tmp, sizeof(tmp));
    WriteData(tmp, sizeof(tmp), desc, print_chars);
#else
    WriteData(&data, sizeof(data), desc, print_chars);
#endif
  }

  size_t offset_;
  Result result_;
  // Not owned. If non-null, log all writes to this stream.
  Stream* log_stream_;
};

struct OutputBuffer {
  Result WriteToFile(string_view filename) const;

  void clear() { data.clear(); }
  size_t size() const { return data.size(); }

  std::vector<uint8_t> data;
};

class MemoryStream : public Stream {
 public:
  WABT_DISALLOW_COPY_AND_ASSIGN(MemoryStream);
  explicit MemoryStream(Stream* log_stream = nullptr);
  explicit MemoryStream(std::unique_ptr<OutputBuffer>&&,
                        Stream* log_stream = nullptr);

  OutputBuffer& output_buffer() { return *buf_; }
  std::unique_ptr<OutputBuffer> ReleaseOutputBuffer();

  void Clear();

  Result WriteToFile(string_view filename) {
    return buf_->WriteToFile(filename);
  }

 protected:
  Result WriteDataImpl(size_t offset, const void* data, size_t size) override;
  Result MoveDataImpl(size_t dst_offset,
                      size_t src_offset,
                      size_t size) override;
  Result TruncateImpl(size_t size) override;

 private:
  std::unique_ptr<OutputBuffer> buf_;
};

class FileStream : public Stream {
 public:
  WABT_DISALLOW_COPY_AND_ASSIGN(FileStream);
  explicit FileStream(string_view filename, Stream* log_stream = nullptr);
  explicit FileStream(FILE*, Stream* log_stream = nullptr);
  FileStream(FileStream&&);
  FileStream& operator=(FileStream&&);
  ~FileStream() override;

  static std::unique_ptr<FileStream> CreateStdout();
  static std::unique_ptr<FileStream> CreateStderr();

  bool is_open() const { return file_ != nullptr; }

  void Flush() override;

 protected:
  Result WriteDataImpl(size_t offset, const void* data, size_t size) override;
  Result MoveDataImpl(size_t dst_offset,
                      size_t src_offset,
                      size_t size) override;
  Result TruncateImpl(size_t size) override;

 private:
  FILE* file_;
  size_t offset_;
  bool should_close_;
};

}  // namespace wabt

#endif /* WABT_STREAM_H_ */
