/* ========================================================================== *
 *  File wrapper for safer file operations.
 *
 *  Author: Firas Safadi (fsafadi@ulg.ac.be)
 * ========================================================================== */

#pragma once

#include "util.h"

class File
{
public:
  template <typename T> friend File& operator>>(File& file, T& t);
  template <typename T> friend File& operator<<(File& file, T& t);

  static void endl(File& file);

  File(char* path, std::ios::openmode mode = std::ios::in) { open(path, mode); }
  File() {}
  ~File() {}

  void open(char* path, std::ios::openmode mode = std::ios::in);
  void close();

protected:
  std::fstream stream;

private:
};

inline void File::endl(File& file)
{
  file.stream << std::endl;

  if (!file.stream)
    error("Error writing file");
}

inline void File::open(char* path, std::ios::openmode mode)
{
  stream.open(path, mode);

  if (!stream)
    error("Error opening file");
}

inline void File::close()
{
  stream.close();

  if (!stream)
    error("Error closing file");
}

template <typename T>
inline File& operator>>(File& file, T& t)
{
  file.stream >> t;

  if (!file.stream)
    error("Error reading file");

  return file;
}

template <typename T>
inline File& operator<<(File& file, T& t)
{
  file.stream << t;

  if (!file.stream)
    error("Error writing file");

  return file;
}

inline File& operator<<(File& file, void (*endl)(File&))
{
  endl(file);

  return file;
}
