/*****
 NAME
 	cnetstream.m - source code for CNetSClient
 VERSION
 	$Id$
 CHANGELOG
 	$Log$
 */

#include <coconut/gnet/cnetstream.h>
#include <coconut/cconststr.h>
#include <coconut/cstring.h>
#include <coconut/cmemory.h>
#include <coconut/cerror.h>
#include <coconut/cmessage.h>
#include <coconut/csystem.h>

#define	BUF_UNIT		512

@implementation CNetStream

+ (void) getCanonicalName: (GTcpSocket *) socket to: (id <PConstStr>) str
{
	GInetAddr *	addr ;
	gchar *		name ;

	addr = gnet_tcp_socket_get_inetaddr(socket) ;
	if(addr){
		name = gnet_inetaddr_get_canonical_name(addr) ;
		[str setPtr: name copy: FALSE free: TRUE] ;
		gnet_inetaddr_delete(addr) ;
	} else 
		[str setPtr: ""] ;
}

- init
{
	stream_channel = NULL ; 
	canonical_name = [[CConstStr alloc] init] ;
	[CSystem checkPtr: canonical_name] ;
	return [super init] ;
}

- (void) dealloc
{
	[canonical_name release] ;
	[super dealloc] ;
}

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

- (id <PError>) closeChannel
{
	if(stream_channel){
		g_io_channel_unref(stream_channel) ;
		return nil ;
	} else
		return [CError can_not_close] ;
}

- (io_status_t) putChar: (utf8_char) c
{
	GIOError	err ;
	err = gnet_io_channel_writen(stream_channel,&c,sizeof(utf8_char),NULL);
	return err == G_IO_ERROR_NONE ? io_status_normal : io_status_error ;
}

- (io_status_t) putStr: (id <PBasicStr>) str
{
	GIOError	err ;
	guint		len ;

	err = gnet_io_channel_writen(stream_channel, (gpointer) [str ptr], 
	  [str length], &len);
	return err == G_IO_ERROR_NONE ? io_status_normal : io_status_error ;
}

- (io_status_t) putPtr: (const utf8_char *) ptr length: (u_int) len
{
	GIOError	err ;
	guint		res ;

	err = gnet_io_channel_writen(stream_channel, (gpointer) ptr, len, &res);
	return err == G_IO_ERROR_NONE ? io_status_normal : io_status_error ;
}

- (io_status_t) putPtr: (const utf8_char *) ptr 
{
	GIOError	err ;
	guint		res ;

	err = gnet_io_channel_writen(stream_channel, (gpointer) ptr,
	  strlen(ptr), &res);
	return err == G_IO_ERROR_NONE ? io_status_normal : io_status_error ;
}

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

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

- (int) getChar
{
	GIOError	err ;
	gchar		c ;
	guint		res ;

	err = gnet_io_channel_readn(stream_channel, &c, sizeof(gchar), &res) ;
	return err == G_IO_ERROR_NONE ? c : EOF ;
}

- (id <PConstStr>) getLine
{
	id <PConstStr>	str ;
	GIOError	err ;
	gchar *		buf ;
	guint 		size ;

	err = gnet_io_channel_readline_strdup(stream_channel, &buf, &size) ;
	if(err != G_IO_ERROR_NONE){
		[CMessage message: error_message code: (int) can_not_read_err 
		  format: "fail to getLine in CNetStream"] ;
		return nil ;
	}
	str = [CConstStr newConstStr: buf copy: FALSE free: TRUE] ;
	[CSystem checkPtr: str] ;
	return str ;
}

- (open_t) accessMode
{
	return read_write_open ;
}

- (boolean) isReadable
{
	return TRUE ;
}

- (boolean) isWritable
{
	return TRUE ;
}

- (io_status_t) flush
{
	return io_status_normal ;
}

- (io_status_t) rewind
{
	return io_status_error ;
}

@end

