/*****
 NAME
 	ciostream.m - source code for CIOStream class
 VERSION
 	$Id$
 CHANGELOG
 	$Log$
 */

#include <coconut/ciostream.h>
#include <coconut/cconststr.h>
#include <coconut/cstring.h>
#include <coconut/csystem.h>
#include <coconut/cerror.h>
#include <unistd.h>
#include <errno.h>

@implementation CIOStream

- init
{
	io_channel = NULL ;
	access_mode = not_open ;
	return [super init] ;
}

- retain
{
	if(io_channel)
		g_io_channel_ref(io_channel) ;
	return [super retain] ;
}

- (void) dealloc
{
	id <PError> err ;
	err = [self closeChannel] ;
	g_assert(err == no_error) ;
	[super dealloc] ;
}

- (id <PError>) openChannel: (GIOChannel *) channel
{
	io_channel = channel ;
	return io_channel ? nil : [CError can_not_happen] ;
}

- (id <PError>) closeChannel
{
	gint	fd ;

	/* WARNING: this method is copied from "closeChannel" method for
	     CIOStream class (in "ciostrem.m"). You have to update
	     both methods when you edit this.
	 */

	/* dispose the channel */
	access_mode = not_open ;
	if(io_channel){
		/* flush the buffer */
		[self flush] ;

		fd = g_io_channel_unix_get_fd(io_channel) ;
		g_io_channel_unref(io_channel) ;
		io_channel = NULL ;
		/* the io_channel will be disposed by above function
		  g_free(io_channel) ; io_channel = NULL ;
		 */
	} 
	return nil ;
}

- (id <PConstStr>) getLine
{
	id <PConstStr>	result ;
	io_status_t	stat ;
	gchar *		str ;

	stat = g_io_channel_read_line(io_channel,&str,NULL,NULL,ERROR_NULL);
	if(stat == io_status_normal){
		result = [[CConstStr alloc] initConstStr: str copy: FALSE
		  free: TRUE] ;
	} else
		result = nil ;
	return result ;
}

- (io_status_t) putChar: (utf8_char) c
{
	io_status_t	stat ;
	gchar		ch ;
	gsize		ressize ;

	ch = c ;
	stat = g_io_channel_write_chars(io_channel, &ch, sizeof(gchar),  
	  &ressize, NULL) ;
	return stat ;
}

- (io_status_t) putPtr: (const utf8_char *) ptr length: (u_int) len
{
	io_status_t	stat ;
	gsize		ressize ;

	if(ptr && len>0)
		stat = g_io_channel_write_chars(io_channel, ptr, len, &ressize,
		  NULL) ;
	else
		stat = io_status_normal ;
	return stat ;
}

- (io_status_t) putPtr: (const utf8_char *) ptr 
{
	io_status_t	stat ;
	gsize		ressize ;
	if(ptr){
		/* the length "-1" means the "ptr" is null terminated string */
		stat = g_io_channel_write_chars(io_channel, ptr, -1, &ressize, 
		  NULL) ;
	} else 
		stat = io_status_normal ;
	return stat ;
}

- (io_status_t) putStr: (id <PBasicStr>) str
{
	io_status_t	stat ;
	gsize		ressize ;
	stat = g_io_channel_write_chars(io_channel, [str ptr], [str length], 
	  &ressize, NULL) ;
	return stat ;
}

- (io_status_t) putFormat: (const utf8_char *) form, ...
{
	id <PString>	str ;
	va_list		args ;
	io_status_t	stat ;

	str = [[CString alloc] init] ;
	  va_start(args, form) ;
	    [str setFormat: form valist: args] ;
	  va_end(args) ;
	  stat = [self putStr: str];
	[str release] ;
	return stat ;
}

- (open_t) accessMode
{
	return access_mode ;
}

- (boolean) isReadable
{
	return IS_READABLE_OPEN(access_mode) ;
}

- (boolean) isWritable
{
	return IS_WRITABLE_OPEN(access_mode) ;
}

- (io_status_t) flush
{
	GIOStatus	stat ;
	if(io_channel)
		stat = g_io_channel_flush(io_channel, NULL) ;
	else
		stat = io_status_normal ;
	return stat ;
}

- (io_status_t) rewind
{
	GIOStatus	stat ;
	stat = g_io_channel_seek_position(io_channel,0,G_SEEK_SET,ERROR_NULL) ;
	return stat ;
}

@end

