/*
 * This file is part of the Owl Positioning System (OwlPS) project.
 * It is subject to the copyright notice and license terms in the
 * COPYRIGHT.t2t file found in the top-level directory of this
 * distribution and at
 *   https://code.lm7.fr/mcy/owlps/src/master/COPYRIGHT.t2t
 * No part of the OwlPS Project, including this file, may be copied,
 * modified, propagated, or distributed except according to the terms
 * contained in the COPYRIGHT.t2t file; the COPYRIGHT.t2t file must be
 * distributed along with this file, either separately or by replacing
 * this notice by the COPYRIGHT.t2t file's contents.
 */


#include "textfilereader.hh"
#include "posexcept.hh"

#include <iostream>

using namespace std ;



/* *** Constructors *** */


/**
 * @param _file_name The name of the file to open.
 * @throw error_opening_input_file if the file cannot be opened.
 */
TextFileReader::TextFileReader(const string &_file_name):
  file_name(_file_name), current_line_nb(0)
{
  if (file_name == "-")
    {
      file_buf = file.rdbuf() ;
      file.std::ios::rdbuf(std::cin.rdbuf()) ;
    }
  else
    {
      file.open(file_name.c_str()) ;
      if (! file)
        throw error_opening_input_file(file_name) ;
    }
}


TextFileReader::~TextFileReader()
{
  if (file_name == "-")
    file.std::ios::rdbuf(file_buf) ;
  else
    file.close() ;
}



/* *** Operations *** */


/**
 * Blank lines or lines containing only blank characters are skipped.
 * Tabs and spaces at the begining of a line are deleted.
 * If the first non-blank character of a line is a #, then the line is
 * skipped (note that comments at the end of a line are *not* handled).
 * @param[out] text Output argument; unchanged in case of error.
 * @returns `false` in case of error, `true` else.
 */
bool TextFileReader::read_nonblank_line(string &text)
{
  string line ;
  string::size_type first_non_blank = 0 ;

  do
    if (! read_line(line))
      return false ;
  while ((first_non_blank = line.find_first_not_of(" \t"))
         == string::npos || line.at(first_non_blank) == '#') ;

  line.erase(0, first_non_blank) ;
  text = line ;

  return true ;
}


/**
 * @param[out] text The string read.
 * @returns `true` in case of success, `false` in case of error.
 */
bool TextFileReader::read_line(string &text)
{
  if (eof_close())
    return false ;

  getline(file, text) ;
  ++current_line_nb ;
  return true ;
}


/**
 * Tests if #file is opened and there is something more to
 * read. If the end of file is reached, the stream is closed.
 * @returns `true` if the end of file is reached or if the file is
 * already closed.
 * @returns `false` if there is something more to read.
 */
bool TextFileReader::eof_close()
{
  if (file)
    return false ;

  if (file.eof())
    {
      file.close() ;
      return true ;
    }

  return false ;
}
