#pragma once


#include <cstdlib>
#include <cstdio>


namespace min
{

void memcpy(__restrict void* dst, __restrict void* src, size_t siz)
{
  for (int i = 0; i < siz; ++i)
    ((char*)dst)[i] = ((char*)src)[i];
}

// Cut-down simple vector
template <typename T>
class vector
{
  public:
    vector()
    {
      m_data = (T*)malloc(512 * sizeof(T));
      m_size = 0;
    }
    ~vector()
    {
      free(m_data);
    }
    void resize(size_t a_newSize)
    {
      m_data = (T*)realloc((void*)m_data, a_newSize * sizeof(T));
      m_size = a_newSize;
    }
    size_t size() const
    {
      return m_size;
    }
    T* data() const
    {
      return m_data;
    }
    void emplace_back(uint32_t a_item)
    {
      resize(m_size + 1);
      m_data[m_size - 1] = a_item;
    }
    const T& operator[](size_t a_index) const
    {
      return m_data[a_index];
    }
    T& operator[](size_t a_index)
    {
      return m_data[a_index];
    }
    vector& operator=(const vector& a_rhs)
    {
      free(m_data);
      m_size = a_rhs.m_size;
      m_data = (T*)malloc(m_size * sizeof(T));
      memcpy(m_data, a_rhs.m_data, m_size * sizeof(T));
      return *this;
    }
  private:
    size_t   m_size;
    T*       m_data;
};


class istream
{
  public:
    virtual void read(char* a_buf, size_t a_siz) = 0;
    virtual bool eof() = 0;
};


class ifstream : public istream
{
  public:
    ifstream(const char* a_fileName)
    {
      m_file = fopen(a_fileName, "rb");
    }
    bool is_open()
    {
      return m_file != NULL;
    }
    void read(char* a_buf, size_t a_siz) override
    {
      fread(a_buf, a_siz, 1, m_file);
    }
    bool eof() override
    {
      return feof(m_file);
    }
  private:
    FILE* m_file;
};


}

