/*

cls_2: Curl Like Syntax
Yauheni A. Akhotnikau (C) 2001-2003
eao197@yahoo.com
-------------------------------------------------

Permission is granted to anyone to use this software for any purpose on any
computer system, and to redistribute it freely, subject to the following
restrictions:

1. This software is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

2. The origin of this software must not be misrepresented, either by
   explicit claim or by omission.

3. Altered versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

-------------------------------------------------

*/
#include <cassert>
#include <cstring>

#include <cls_2/std_cpp/h/is_ios.hpp>

namespace cls_2 {

namespace std_cpp {

static char	g_chars_to_ignore[] = "\r";
static char g_eol_chars[] = "\n";

static bool
is_eol( char ch ) {
	return ( 0 != strchr( g_eol_chars, ch ) );
}

static bool
is_char_must_be_ignored( char ch ) {
	return ( 0 != strchr( g_chars_to_ignore, ch ) );
}

//
// is_ios_t
//

const size_t	c_file_buffer_capacity = 2048;
is_ios_t::is_ios_t(
	std::istream & stream ) :
	m_stream( stream ),
	m_size( 0 ),
	m_pos( 0 ),
	m_line( 1 ) {

	m_buf.set( new char[ c_file_buffer_capacity ],
		c_file_buffer_capacity );
}

is_ios_t::~is_ios_t( void ) {
}

unsigned int
is_ios_t::query_line() const {
	return m_line;
}

int
is_ios_t::get( char & ch ) {
	register char cur = 0;
	register int err;
	while( 1 ) {
		if( e_ok == ( err = lo_get_ch( cur ) ) ) {
			if( cur && !is_char_must_be_ignored( cur ) ) {
				ch = cur;
				return e_ok;
			}
		}
		else
			return err;
	}
}

void
is_ios_t::back() {
	lo_back_ch();
}

int
is_ios_t::lo_get_ch( char & ch ) {
	if( m_pos == m_size ) {
		m_pos = 0;
		m_size = 0;

		if( m_stream.eof() )
			return e_eof;
		else if( !m_stream.good() )
			return e_error;

		m_stream.read( m_buf.query(), m_buf.size() );
		m_size = m_stream.gcount();
		if( !m_size ) {
			return e_eof;
		}
	}
	ch = *(m_buf.query() + m_pos++);

	if( is_eol( ch ) )
		++m_line;

	return e_ok;
}

void
is_ios_t::lo_back_ch( void ) {
	if( is_eol( m_buf.query()[ m_pos ] ) )
		--m_line;
	m_pos--;
}

} /* namespace std_cpp */

} /* namespace cls_2 */
