/*****
 NAME
 	cboolean.m - header file for CBoolean class
 VERSION
 	$Id$
 CHANGELOG
 	$Log$
 */

#include <coconut/cboolean.h>
#include <coconut/csystem.h>
#include <coconut/cstring.h>
#include <coconut/cerror.h>
#include <coconut/ptext.h>
#include <coconut/dconststr.h>
#include <string.h>

@implementation CBoolean

+ (id <PError>) strToBoolean: (const char *) str to: (boolean *) result
{
	static const char * true_list[] = {"true", "yes", NULL} ;
	static const char * false_list[] = {"false", "no", NULL} ;
	const char ** list ;
	const char * item ;

	/* check true */
	for(list = true_list ; (item = *list) != NULL ; list++){
		if(strcasecmp(str, item) == 0){
			*result = TRUE ;
			return nil ;
		}
	}
	/* check false */
	for(list = false_list ; (item = *list) != NULL ; list++){
		if(strcasecmp(str, item) == 0){
			*result = FALSE ;
			return nil ;
		}
	}
	/* not matched */
	return [CError illegal_format] ;
}

+ (const char *) booleanToStr: (boolean) value
{
	return value ? TRUE_STR : FALSE_STR ;
}

+ (id <PNumber>) newBoolean: (boolean) val
{
	id <PNumber>	newbool ;
	newbool = [[CBoolean alloc] init] ;
	g_assert(newbool != nil) ;
	[newbool setBoolean: val] ;
	return newbool ;
}

- init
{
	boolean_value = FALSE ;
	return [super init] ;
}

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

- (valtype_t) type
{
	return boolean_value ;
}

- setObject: (id <PNumber>) obj
{
	boolean_value = [obj booleanNum] ;
	return nil ;
}

- setBoolean: (boolean) value
{
	boolean_value = value ;
	return nil ;
}

- setInt: (int) value
{
	boolean_value = value ? TRUE : FALSE ;
	return nil ;
}

- setReal: (double) value
{
	boolean_value = value != (double) 0.0 ? TRUE : FALSE ;
	return nil ;
}

- (boolean) booleanNum
{
	return boolean_value ;
}

- (int) intNum
{
	return boolean_value ? 1 : 0 ;
}

- (double) realNum
{
	return boolean_value ? 1.0 : 0.0 ;
}

- (id <PNumber>) addObject: (id <PNumber>) obj
{
	if([obj booleanNum])
		boolean_value = TRUE ;
	return self ;
}

- (id <PNumber>) addBoolean: (boolean) value 
{
	if(value)
		boolean_value = TRUE ;
	return self ;
}

- (id <PNumber>) addInt: (int) value 
{
	if(value)
		boolean_value = TRUE ;
	return self ;
}

- (id <PNumber>) addReal: (double) value 
{
	if(value != 0.0)
		boolean_value = TRUE ;
	return self ;
}

- (id <PNumber>) duplicate
{
	return [CBoolean newBoolean: boolean_value] ;
}

- (id <PString>) toString
{
	id <PString>	newstr ;

	newstr = [[CString alloc] init] ;
	[CSystem checkPtr: newstr] ;
	[newstr setFormat: "((boolean) %s)",  boolean_value ? TRUE_STR : 
	  FALSE_STR] ;
	return newstr ;
}

#define	INTDIFF(A, B)		(((int) A) - ((int) B))
- (int) compare: (id <PNumber>) src
{
	int	delta ;

	if((delta = INTDIFF(valtype_boolean, [src type])) != 0)
		return delta ;
	delta = INTDIFF(boolean_value, [src booleanNum]) ;
	return delta ;
}

- (u_int) hashkey
{
	return (((int) valtype_boolean) << 8) + boolean_value ;
}

#define	STREAM	((id <PIndentStream>) stream)
- print: (id) stream
{
	io_status_t	stat ;
	stat = [STREAM putPtr: boolean_value ? TRUE_STR : FALSE_STR] ;
	return stat == io_status_normal ? nil : [CError can_not_happen] ;
}

@end

